* [PATCH 2/7] phylib: fix generic phy driver probe
2012-11-18 12:49 ` [PATCH 1/7] driver: introduce device_probe to manully probe a device Jean-Christophe PLAGNIOL-VILLARD
@ 2012-11-18 12:49 ` Jean-Christophe PLAGNIOL-VILLARD
2012-11-18 12:49 ` [PATCH 3/7] mdio_bus: fix match Jean-Christophe PLAGNIOL-VILLARD
` (4 subsequent siblings)
5 siblings, 0 replies; 9+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2012-11-18 12:49 UTC (permalink / raw)
To: barebox
the generic phy driver is used if no driver are found
Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
---
drivers/net/phy/Kconfig | 8 ++------
drivers/net/phy/Makefile | 1 -
drivers/net/phy/generic.c | 36 ------------------------------------
drivers/net/phy/phy.c | 34 ++++++++++++++++++++++++++++++++--
4 files changed, 34 insertions(+), 45 deletions(-)
delete mode 100644 drivers/net/phy/generic.c
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 616b539..3f7c150 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -8,15 +8,11 @@ if PHYLIB
comment "MII PHY device drivers"
-config GENERIC_PHY
- bool "Drivers for the Generic PHYs"
- default y
-
-endif
-
config SMSC_PHY
bool "Drivers for SMSC PHYs"
---help---
Currently supports the LAN83C185, LAN8187 and LAN8700 PHYs
+endif
+
endmenu
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index 0caeb70..dfc709a 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -1,3 +1,2 @@
obj-y += phy.o mdio_bus.o
-obj-$(CONFIG_GENERIC_PHY) += generic.o
obj-$(CONFIG_SMSC_PHY) += smsc.o
diff --git a/drivers/net/phy/generic.c b/drivers/net/phy/generic.c
deleted file mode 100644
index 3f5f127..0000000
--- a/drivers/net/phy/generic.c
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2009 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307 USA
- *
- */
-
-#include <common.h>
-#include <linux/phy.h>
-#include <init.h>
-
-static struct phy_driver generic_phy = {
- .drv.name = "Generic PHY",
- .phy_id = PHY_ANY_UID,
- .phy_id_mask = PHY_ANY_UID,
- .features = 0,
-};
-
-static int generic_phy_register(void)
-{
- return phy_driver_register(&generic_phy);
-}
-device_initcall(generic_phy_register);
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 4478d9f..2fd0440 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -19,6 +19,7 @@
#include <common.h>
#include <driver.h>
+#include <init.h>
#include <net.h>
#include <malloc.h>
#include <linux/phy.h>
@@ -27,6 +28,7 @@
#define PHY_AN_TIMEOUT 10
+static struct phy_driver genphy_driver;
static int genphy_config_init(struct phy_device *phydev);
int phy_update_status(struct phy_device *dev)
@@ -142,6 +144,21 @@ struct phy_device *get_phy_device(struct mii_bus *bus, int addr)
return dev;
}
+static int phy_register_device(struct phy_device* dev)
+{
+ int ret;
+
+ ret = register_device(&dev->dev);
+ if (ret)
+ return ret;
+
+ if (dev->dev.driver)
+ return 0;
+
+ dev->dev.driver = &genphy_driver.drv;
+ return device_probe(&dev->dev);
+}
+
/* Automatically gets and returns the PHY device */
int phy_device_connect(struct eth_device *edev, struct mii_bus *bus, int addr,
void (*adjust_link) (struct eth_device *edev),
@@ -164,7 +181,7 @@ int phy_device_connect(struct eth_device *edev, struct mii_bus *bus, int addr,
dev->interface = interface;
dev->dev_flags = flags;
- ret = register_device(&dev->dev);
+ ret = phy_register_device(dev);
if (ret)
goto fail;
} else {
@@ -181,7 +198,7 @@ int phy_device_connect(struct eth_device *edev, struct mii_bus *bus, int addr,
dev->interface = interface;
dev->dev_flags = flags;
- ret = register_device(&dev->dev);
+ ret = phy_register_device(dev);
if (ret)
goto fail;
@@ -597,3 +614,16 @@ int phy_drivers_register(struct phy_driver *new_driver, int n)
}
return ret;
}
+
+static struct phy_driver genphy_driver = {
+ .drv.name = "Generic PHY",
+ .phy_id = PHY_ANY_UID,
+ .phy_id_mask = PHY_ANY_UID,
+ .features = 0,
+};
+
+static int generic_phy_register(void)
+{
+ return phy_driver_register(&genphy_driver);
+}
+device_initcall(generic_phy_register);
--
1.7.10.4
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 3/7] mdio_bus: fix match
2012-11-18 12:49 ` [PATCH 1/7] driver: introduce device_probe to manully probe a device Jean-Christophe PLAGNIOL-VILLARD
2012-11-18 12:49 ` [PATCH 2/7] phylib: fix generic phy driver probe Jean-Christophe PLAGNIOL-VILLARD
@ 2012-11-18 12:49 ` Jean-Christophe PLAGNIOL-VILLARD
2012-11-18 12:49 ` [PATCH 4/7] phylib: export phy_id via param Jean-Christophe PLAGNIOL-VILLARD
` (3 subsequent siblings)
5 siblings, 0 replies; 9+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2012-11-18 12:49 UTC (permalink / raw)
To: barebox
on barebox we have the weird way the return 0 true on bus match
Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
---
drivers/net/phy/mdio_bus.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
index 35319b4..762adfe 100644
--- a/drivers/net/phy/mdio_bus.c
+++ b/drivers/net/phy/mdio_bus.c
@@ -106,7 +106,7 @@ static int mdio_bus_match(struct device_d *dev, struct driver_d *drv)
struct phy_device *phydev = to_phy_device(dev);
struct phy_driver *phydrv = to_phy_driver(drv);
- return ((phydrv->phy_id & phydrv->phy_id_mask) ==
+ return ((phydrv->phy_id & phydrv->phy_id_mask) !=
(phydev->phy_id & phydrv->phy_id_mask));
}
--
1.7.10.4
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 4/7] phylib: export phy_id via param
2012-11-18 12:49 ` [PATCH 1/7] driver: introduce device_probe to manully probe a device Jean-Christophe PLAGNIOL-VILLARD
2012-11-18 12:49 ` [PATCH 2/7] phylib: fix generic phy driver probe Jean-Christophe PLAGNIOL-VILLARD
2012-11-18 12:49 ` [PATCH 3/7] mdio_bus: fix match Jean-Christophe PLAGNIOL-VILLARD
@ 2012-11-18 12:49 ` Jean-Christophe PLAGNIOL-VILLARD
2012-11-18 12:49 ` [PATCH 5/7] phylib: introduction of forced 100Mbps Jean-Christophe PLAGNIOL-VILLARD
` (2 subsequent siblings)
5 siblings, 0 replies; 9+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2012-11-18 12:49 UTC (permalink / raw)
To: barebox
Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
---
drivers/net/phy/mdio_bus.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
index 762adfe..41c8a96 100644
--- a/drivers/net/phy/mdio_bus.c
+++ b/drivers/net/phy/mdio_bus.c
@@ -193,6 +193,9 @@ static int mdio_bus_probe(struct device_d *_dev)
sprintf(str, "%d", dev->addr);
dev_add_param_fixed(&dev->dev, "phy_addr", str);
+ sprintf(str, "0x%08x", dev->phy_id);
+ dev_add_param_fixed(&dev->dev, "phy_id", str);
+
dev->cdev.name = asprintf("phy%d", _dev->id);
dev->cdev.size = 64;
dev->cdev.ops = &phydev_ops;
--
1.7.10.4
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 5/7] phylib: introduction of forced 100Mbps
2012-11-18 12:49 ` [PATCH 1/7] driver: introduce device_probe to manully probe a device Jean-Christophe PLAGNIOL-VILLARD
` (2 preceding siblings ...)
2012-11-18 12:49 ` [PATCH 4/7] phylib: export phy_id via param Jean-Christophe PLAGNIOL-VILLARD
@ 2012-11-18 12:49 ` Jean-Christophe PLAGNIOL-VILLARD
2012-11-18 12:49 ` [PATCH 6/7] phylib: add fixup support Jean-Christophe PLAGNIOL-VILLARD
2012-11-18 12:49 ` [PATCH 7/7] phylib: add micrel support Jean-Christophe PLAGNIOL-VILLARD
5 siblings, 0 replies; 9+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2012-11-18 12:49 UTC (permalink / raw)
To: barebox
Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
---
drivers/net/phy/mdio_bus.c | 4 ++++
include/linux/phy.h | 3 ++-
2 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
index 41c8a96..3e79345 100644
--- a/drivers/net/phy/mdio_bus.c
+++ b/drivers/net/phy/mdio_bus.c
@@ -175,6 +175,10 @@ static int mdio_bus_probe(struct device_d *_dev)
dev->speed = SPEED_10;
dev->duplex = DUPLEX_FULL;
dev->autoneg = !AUTONEG_ENABLE;
+ } else if (dev->dev_flags & PHYLIB_FORCE_100) {
+ dev->speed = SPEED_100;
+ dev->duplex = DUPLEX_FULL;
+ dev->autoneg = !AUTONEG_ENABLE;
}
}
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 4f14dae..791d657 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -60,7 +60,8 @@ typedef enum {
#define MII_BUS_ID_SIZE (20 - 3)
#define PHYLIB_FORCE_10 (1 << 0)
-#define PHYLIB_FORCE_LINK (1 << 1)
+#define PHYLIB_FORCE_100 (1 << 1)
+#define PHYLIB_FORCE_LINK (1 << 2)
#define PHYLIB_CAPABLE_1000M (1 << 0)
--
1.7.10.4
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 6/7] phylib: add fixup support
2012-11-18 12:49 ` [PATCH 1/7] driver: introduce device_probe to manully probe a device Jean-Christophe PLAGNIOL-VILLARD
` (3 preceding siblings ...)
2012-11-18 12:49 ` [PATCH 5/7] phylib: introduction of forced 100Mbps Jean-Christophe PLAGNIOL-VILLARD
@ 2012-11-18 12:49 ` Jean-Christophe PLAGNIOL-VILLARD
2012-11-18 12:49 ` [PATCH 7/7] phylib: add micrel support Jean-Christophe PLAGNIOL-VILLARD
5 siblings, 0 replies; 9+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2012-11-18 12:49 UTC (permalink / raw)
To: barebox
if board need specific phy fixup they can register it and then the code will
executed only if needed
Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
---
drivers/net/phy/mdio_bus.c | 19 +++++----
drivers/net/phy/phy.c | 96 ++++++++++++++++++++++++++++++++++++++++++++
include/linux/phy.h | 18 +++++++++
3 files changed, 125 insertions(+), 8 deletions(-)
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
index 3e79345..1d20bb0 100644
--- a/drivers/net/phy/mdio_bus.c
+++ b/drivers/net/phy/mdio_bus.c
@@ -153,6 +153,7 @@ static int mdio_bus_probe(struct device_d *_dev)
struct phy_device *dev = to_phy_device(_dev);
struct phy_driver *drv = to_phy_driver(_dev->driver);
+ int ret;
char str[16];
dev->attached_dev->phydev = dev;
@@ -160,14 +161,9 @@ static int mdio_bus_probe(struct device_d *_dev)
dev_add_child(dev->dev.parent, _dev);
if (drv->probe) {
- int ret;
-
ret = drv->probe(dev);
- if (ret) {
- dev->attached_dev->phydev = NULL;
- dev->attached_dev = NULL;
- return ret;
- }
+ if (ret)
+ goto err;
}
if (dev->dev_flags) {
@@ -188,7 +184,9 @@ static int mdio_bus_probe(struct device_d *_dev)
dev->supported = drv->features;
dev->advertising = drv->features;
- drv->config_init(dev);
+ ret = phy_init_hw(dev);
+ if (ret)
+ goto err;
/* Sanitize settings based on PHY capabilities */
if ((dev->supported & SUPPORTED_Autoneg) == 0)
@@ -208,6 +206,11 @@ static int mdio_bus_probe(struct device_d *_dev)
devfs_create(&dev->cdev);
return 0;
+
+err:
+ dev->attached_dev->phydev = NULL;
+ dev->attached_dev = NULL;
+ return ret;
}
static void mdio_bus_remove(struct device_d *_dev)
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 2fd0440..59df742 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -55,6 +55,87 @@ int phy_update_status(struct phy_device *dev)
return 0;
}
+static LIST_HEAD(phy_fixup_list);
+
+/*
+ * Creates a new phy_fixup and adds it to the list
+ * @bus_id: A string which matches phydev->dev.bus_id (or PHY_ANY_ID)
+ * @phy_uid: Used to match against phydev->phy_id (the UID of the PHY)
+ * It can also be PHY_ANY_UID
+ * @phy_uid_mask: Applied to phydev->phy_id and fixup->phy_uid before
+ * comparison
+ * @run: The actual code to be run when a matching PHY is found
+ */
+int phy_register_fixup(const char *bus_id, u32 phy_uid, u32 phy_uid_mask,
+ int (*run)(struct phy_device *))
+{
+ struct phy_fixup *fixup;
+
+ fixup = kzalloc(sizeof(struct phy_fixup), GFP_KERNEL);
+ if (!fixup)
+ return -ENOMEM;
+
+ strlcpy(fixup->bus_id, bus_id, sizeof(fixup->bus_id));
+ fixup->phy_uid = phy_uid;
+ fixup->phy_uid_mask = phy_uid_mask;
+ fixup->run = run;
+
+ list_add_tail(&fixup->list, &phy_fixup_list);
+
+ return 0;
+}
+
+/* Registers a fixup to be run on any PHY with the UID in phy_uid */
+int phy_register_fixup_for_uid(u32 phy_uid, u32 phy_uid_mask,
+ int (*run)(struct phy_device *))
+{
+ return phy_register_fixup(PHY_ANY_ID, phy_uid, phy_uid_mask, run);
+}
+
+/* Registers a fixup to be run on the PHY with id string bus_id */
+int phy_register_fixup_for_id(const char *bus_id,
+ int (*run)(struct phy_device *))
+{
+ return phy_register_fixup(bus_id, PHY_ANY_UID, 0xffffffff, run);
+}
+
+/*
+ * Returns 1 if fixup matches phydev in bus_id and phy_uid.
+ * Fixups can be set to match any in one or more fields.
+ */
+static int phy_needs_fixup(struct phy_device *phydev, struct phy_fixup *fixup)
+{
+ if (strcmp(fixup->bus_id, dev_name(&phydev->dev)) != 0)
+ if (strcmp(fixup->bus_id, PHY_ANY_ID) != 0)
+ return 0;
+
+ if ((fixup->phy_uid & fixup->phy_uid_mask) !=
+ (phydev->phy_id & fixup->phy_uid_mask))
+ if (fixup->phy_uid != PHY_ANY_UID)
+ return 0;
+
+ return 1;
+}
+/* Runs any matching fixups for this phydev */
+int phy_scan_fixups(struct phy_device *phydev)
+{
+ struct phy_fixup *fixup;
+
+ list_for_each_entry(fixup, &phy_fixup_list, list) {
+ if (phy_needs_fixup(phydev, fixup)) {
+ int err;
+
+ err = fixup->run(phydev);
+
+ if (err < 0) {
+ return err;
+ }
+ }
+ }
+
+ return 0;
+}
+
struct phy_device *phy_device_create(struct mii_bus *bus, int addr, int phy_id)
{
struct phy_device *dev;
@@ -615,6 +696,21 @@ int phy_drivers_register(struct phy_driver *new_driver, int n)
return ret;
}
+int phy_init_hw(struct phy_device *phydev)
+{
+ struct phy_driver *phydrv = to_phy_driver(phydev->dev.driver);
+ int ret;
+
+ if (!phydrv || !phydrv->config_init)
+ return 0;
+
+ ret = phy_scan_fixups(phydev);
+ if (ret < 0)
+ return ret;
+
+ return phydrv->config_init(phydev);
+}
+
static struct phy_driver genphy_driver = {
.drv.name = "Generic PHY",
.phy_id = PHY_ANY_UID,
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 791d657..b39eca5 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -226,10 +226,20 @@ struct phy_driver {
#define PHY_ANY_ID "MATCH ANY PHY"
#define PHY_ANY_UID 0xffffffff
+/* A Structure for boards to register fixups with the PHY Lib */
+struct phy_fixup {
+ struct list_head list;
+ char bus_id[20];
+ u32 phy_uid;
+ u32 phy_uid_mask;
+ int (*run)(struct phy_device *phydev);
+};
+
int phy_driver_register(struct phy_driver *drv);
int phy_drivers_register(struct phy_driver *new_driver, int n);
struct phy_device *get_phy_device(struct mii_bus *bus, int addr);
int phy_init(void);
+int phy_init_hw(struct phy_device *phydev);
/**
* phy_read - Convenience function for reading a given PHY register
@@ -267,5 +277,13 @@ int genphy_config_advert(struct phy_device *phydev);
int genphy_setup_forced(struct phy_device *phydev);
int get_phy_id(struct mii_bus *bus, int addr, u32 *phy_id);
+int phy_register_fixup(const char *bus_id, u32 phy_uid, u32 phy_uid_mask,
+ int (*run)(struct phy_device *));
+int phy_register_fixup_for_id(const char *bus_id,
+ int (*run)(struct phy_device *));
+int phy_register_fixup_for_uid(u32 phy_uid, u32 phy_uid_mask,
+ int (*run)(struct phy_device *));
+int phy_scan_fixups(struct phy_device *phydev);
+
extern struct bus_type mdio_bus_type;
#endif /* __PHYDEV_H__ */
--
1.7.10.4
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 7/7] phylib: add micrel support
2012-11-18 12:49 ` [PATCH 1/7] driver: introduce device_probe to manully probe a device Jean-Christophe PLAGNIOL-VILLARD
` (4 preceding siblings ...)
2012-11-18 12:49 ` [PATCH 6/7] phylib: add fixup support Jean-Christophe PLAGNIOL-VILLARD
@ 2012-11-18 12:49 ` Jean-Christophe PLAGNIOL-VILLARD
5 siblings, 0 replies; 9+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2012-11-18 12:49 UTC (permalink / raw)
To: barebox
Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
---
drivers/net/phy/Kconfig | 5 ++
drivers/net/phy/Makefile | 1 +
drivers/net/phy/micrel.c | 174 ++++++++++++++++++++++++++++++++++++++++++++
include/linux/micrel_phy.h | 30 ++++++++
4 files changed, 210 insertions(+)
create mode 100644 drivers/net/phy/micrel.c
create mode 100644 include/linux/micrel_phy.h
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 3f7c150..c75d73d 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 dfc709a..5f8191d 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 0000000..0c6d43e
--- /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 0000000..adfe8c0
--- /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 */
--
1.7.10.4
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 9+ messages in thread