* [PATCH 1/2] phy: add phy_drivers_register
@ 2012-11-15 9:31 Jean-Christophe PLAGNIOL-VILLARD
2012-11-15 9:31 ` [PATCH 2/2] phy: add smsc phy driver support Jean-Christophe PLAGNIOL-VILLARD
0 siblings, 1 reply; 5+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2012-11-15 9:31 UTC (permalink / raw)
To: barebox
to allow to register an array of drivers
Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
---
drivers/net/phy/phy.c | 12 ++++++++++++
include/linux/phy.h | 1 +
2 files changed, 13 insertions(+)
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index daa657f..5a4be54 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -705,6 +705,18 @@ int phy_driver_register(struct phy_driver *phydrv)
return register_driver(&phydrv->drv);
}
+int phy_drivers_register(struct phy_driver *new_driver, int n)
+{
+ int i, ret = 0;
+
+ for (i = 0; i < n; i++) {
+ ret = phy_driver_register(new_driver + i);
+ if (ret)
+ return ret;
+ }
+ return ret;
+}
+
int phy_init_hw(struct phy_device *phydev)
{
struct phy_driver *phydrv = to_phy_driver(phydev->dev.driver);
diff --git a/include/linux/phy.h b/include/linux/phy.h
index fa21984..ce6f22c 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -235,6 +235,7 @@ struct phy_fixup {
};
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);
--
1.7.10.4
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 2/2] phy: add smsc phy driver support
2012-11-15 9:31 [PATCH 1/2] phy: add phy_drivers_register Jean-Christophe PLAGNIOL-VILLARD
@ 2012-11-15 9:31 ` Jean-Christophe PLAGNIOL-VILLARD
2012-11-15 11:29 ` Sascha Hauer
` (2 more replies)
0 siblings, 3 replies; 5+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2012-11-15 9:31 UTC (permalink / raw)
To: barebox
as we to have specific phy init to fix chip issue link detection support
based on linux 3.6
Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
---
drivers/net/phy/Kconfig | 5 ++
drivers/net/phy/Makefile | 1 +
drivers/net/phy/smsc.c | 146 ++++++++++++++++++++++++++++++++++++++++++++++
include/linux/smscphy.h | 25 ++++++++
4 files changed, 177 insertions(+)
create mode 100644 drivers/net/phy/smsc.c
create mode 100644 include/linux/smscphy.h
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index b66261a..616b539 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -14,4 +14,9 @@ config GENERIC_PHY
endif
+config SMSC_PHY
+ bool "Drivers for SMSC PHYs"
+ ---help---
+ Currently supports the LAN83C185, LAN8187 and LAN8700 PHYs
+
endmenu
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index 82e90d4..0caeb70 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -1,2 +1,3 @@
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/smsc.c b/drivers/net/phy/smsc.c
new file mode 100644
index 0000000..3c201f6
--- /dev/null
+++ b/drivers/net/phy/smsc.c
@@ -0,0 +1,146 @@
+/*
+ * drivers/net/phy/smsc.c
+ *
+ * Driver for SMSC PHYs
+ *
+ * Author: Herbert Valerio Riedel
+ *
+ * Copyright (c) 2006 Herbert Valerio Riedel <hvr@gnu.org>
+ *
+ * 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 added for SMSC LAN8187 and LAN8700 by steve.glendinning@shawell.net
+ *
+ */
+
+#include <common.h>
+#include <init.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/phy.h>
+#include <linux/smscphy.h>
+
+static int smsc_phy_ack_interrupt(struct phy_device *phydev)
+{
+ int rc = phy_read (phydev, MII_LAN83C185_ISF);
+
+ return rc < 0 ? rc : 0;
+}
+
+static int smsc_phy_config_init(struct phy_device *phydev)
+{
+ int rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS);
+ if (rc < 0)
+ return rc;
+
+ /* Enable energy detect mode for this SMSC Transceivers */
+ rc = phy_write(phydev, MII_LAN83C185_CTRL_STATUS,
+ rc | MII_LAN83C185_EDPWRDOWN);
+ if (rc < 0)
+ return rc;
+
+ return smsc_phy_ack_interrupt (phydev);
+}
+
+static int lan87xx_config_init(struct phy_device *phydev)
+{
+ /*
+ * Make sure the EDPWRDOWN bit is NOT set. Setting this bit on
+ * LAN8710/LAN8720 PHY causes the PHY to misbehave, likely due
+ * to a bug on the chip.
+ *
+ * When the system is powered on with the network cable being
+ * disconnected all the way until after ifconfig ethX up is
+ * issued for the LAN port with this PHY, connecting the cable
+ * afterwards does not cause LINK change detection, while the
+ * expected behavior is the Link UP being detected.
+ */
+ int rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS);
+ if (rc < 0)
+ return rc;
+
+ rc &= ~MII_LAN83C185_EDPWRDOWN;
+
+ rc = phy_write(phydev, MII_LAN83C185_CTRL_STATUS, rc);
+ if (rc < 0)
+ return rc;
+
+ return smsc_phy_ack_interrupt(phydev);
+}
+
+static int lan911x_config_init(struct phy_device *phydev)
+{
+ return smsc_phy_ack_interrupt(phydev);
+}
+
+static struct phy_driver smsc_phy_driver[] = {
+{
+ .phy_id = 0x0007c0a0, /* OUI=0x00800f, Model#=0x0a */
+ .phy_id_mask = 0xfffffff0,
+ .drv.name = "SMSC LAN83C185",
+
+ .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause
+ | SUPPORTED_Asym_Pause),
+
+ /* basic functions */
+ .config_aneg = genphy_config_aneg,
+ .read_status = genphy_read_status,
+ .config_init = smsc_phy_config_init,
+}, {
+ .phy_id = 0x0007c0b0, /* OUI=0x00800f, Model#=0x0b */
+ .phy_id_mask = 0xfffffff0,
+ .drv.name = "SMSC LAN8187",
+
+ .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause
+ | SUPPORTED_Asym_Pause),
+
+ /* basic functions */
+ .config_aneg = genphy_config_aneg,
+ .read_status = genphy_read_status,
+ .config_init = smsc_phy_config_init,
+}, {
+ .phy_id = 0x0007c0c0, /* OUI=0x00800f, Model#=0x0c */
+ .phy_id_mask = 0xfffffff0,
+ .drv.name = "SMSC LAN8700",
+
+ .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause
+ | SUPPORTED_Asym_Pause),
+
+ /* basic functions */
+ .config_aneg = genphy_config_aneg,
+ .read_status = genphy_read_status,
+ .config_init = smsc_phy_config_init,
+}, {
+ .phy_id = 0x0007c0d0, /* OUI=0x00800f, Model#=0x0d */
+ .phy_id_mask = 0xfffffff0,
+ .drv.name = "SMSC LAN911x Internal PHY",
+
+ .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause
+ | SUPPORTED_Asym_Pause),
+
+ /* basic functions */
+ .config_aneg = genphy_config_aneg,
+ .read_status = genphy_read_status,
+ .config_init = lan911x_config_init,
+}, {
+ .phy_id = 0x0007c0f0, /* OUI=0x00800f, Model#=0x0f */
+ .phy_id_mask = 0xfffffff0,
+ .drv.name = "SMSC LAN8710/LAN8720",
+
+ .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause
+ | SUPPORTED_Asym_Pause),
+
+ /* basic functions */
+ .config_aneg = genphy_config_aneg,
+ .read_status = genphy_read_status,
+ .config_init = lan87xx_config_init,
+} };
+
+static int __init smsc_init(void)
+{
+ return phy_drivers_register(smsc_phy_driver, ARRAY_SIZE(smsc_phy_driver));
+}
+device_initcall(smsc_init);
diff --git a/include/linux/smscphy.h b/include/linux/smscphy.h
new file mode 100644
index 0000000..ce718cb
--- /dev/null
+++ b/include/linux/smscphy.h
@@ -0,0 +1,25 @@
+#ifndef __LINUX_SMSCPHY_H__
+#define __LINUX_SMSCPHY_H__
+
+#define MII_LAN83C185_ISF 29 /* Interrupt Source Flags */
+#define MII_LAN83C185_IM 30 /* Interrupt Mask */
+#define MII_LAN83C185_CTRL_STATUS 17 /* Mode/Status Register */
+
+#define MII_LAN83C185_ISF_INT1 (1<<1) /* Auto-Negotiation Page Received */
+#define MII_LAN83C185_ISF_INT2 (1<<2) /* Parallel Detection Fault */
+#define MII_LAN83C185_ISF_INT3 (1<<3) /* Auto-Negotiation LP Ack */
+#define MII_LAN83C185_ISF_INT4 (1<<4) /* Link Down */
+#define MII_LAN83C185_ISF_INT5 (1<<5) /* Remote Fault Detected */
+#define MII_LAN83C185_ISF_INT6 (1<<6) /* Auto-Negotiation complete */
+#define MII_LAN83C185_ISF_INT7 (1<<7) /* ENERGYON */
+
+#define MII_LAN83C185_ISF_INT_ALL (0x0e)
+
+#define MII_LAN83C185_ISF_INT_PHYLIB_EVENTS \
+ (MII_LAN83C185_ISF_INT6 | MII_LAN83C185_ISF_INT4 | \
+ MII_LAN83C185_ISF_INT7)
+
+#define MII_LAN83C185_EDPWRDOWN (1 << 13) /* EDPWRDOWN */
+#define MII_LAN83C185_ENERGYON (1 << 1) /* ENERGYON */
+
+#endif /* __LINUX_SMSCPHY_H__ */
--
1.7.10.4
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH 2/2] phy: add smsc phy driver support
2012-11-15 9:31 ` [PATCH 2/2] phy: add smsc phy driver support Jean-Christophe PLAGNIOL-VILLARD
@ 2012-11-15 11:29 ` Sascha Hauer
2012-11-15 11:58 ` [PATCH 1/1 v2] " Jean-Christophe PLAGNIOL-VILLARD
2012-12-08 15:05 ` [PATCH 2/2] " Sascha Hauer
2 siblings, 0 replies; 5+ messages in thread
From: Sascha Hauer @ 2012-11-15 11:29 UTC (permalink / raw)
To: Jean-Christophe PLAGNIOL-VILLARD; +Cc: barebox
On Thu, Nov 15, 2012 at 10:31:44AM +0100, Jean-Christophe PLAGNIOL-VILLARD wrote:
> as we to have specific phy init to fix chip issue link detection support
>
> based on linux 3.6
>
> Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
The driver is never used here, because the generic phy is probed first.
For this to work we somehow have to make sure that the generic phy is
probed last.
Sascha
> ---
> drivers/net/phy/Kconfig | 5 ++
> drivers/net/phy/Makefile | 1 +
> drivers/net/phy/smsc.c | 146 ++++++++++++++++++++++++++++++++++++++++++++++
> include/linux/smscphy.h | 25 ++++++++
> 4 files changed, 177 insertions(+)
> create mode 100644 drivers/net/phy/smsc.c
> create mode 100644 include/linux/smscphy.h
>
> diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
> index b66261a..616b539 100644
> --- a/drivers/net/phy/Kconfig
> +++ b/drivers/net/phy/Kconfig
> @@ -14,4 +14,9 @@ config GENERIC_PHY
>
> endif
>
> +config SMSC_PHY
> + bool "Drivers for SMSC PHYs"
> + ---help---
> + Currently supports the LAN83C185, LAN8187 and LAN8700 PHYs
> +
> endmenu
> diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
> index 82e90d4..0caeb70 100644
> --- a/drivers/net/phy/Makefile
> +++ b/drivers/net/phy/Makefile
> @@ -1,2 +1,3 @@
> 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/smsc.c b/drivers/net/phy/smsc.c
> new file mode 100644
> index 0000000..3c201f6
> --- /dev/null
> +++ b/drivers/net/phy/smsc.c
> @@ -0,0 +1,146 @@
> +/*
> + * drivers/net/phy/smsc.c
> + *
> + * Driver for SMSC PHYs
> + *
> + * Author: Herbert Valerio Riedel
> + *
> + * Copyright (c) 2006 Herbert Valerio Riedel <hvr@gnu.org>
> + *
> + * 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 added for SMSC LAN8187 and LAN8700 by steve.glendinning@shawell.net
> + *
> + */
> +
> +#include <common.h>
> +#include <init.h>
> +#include <linux/mii.h>
> +#include <linux/ethtool.h>
> +#include <linux/phy.h>
> +#include <linux/smscphy.h>
> +
> +static int smsc_phy_ack_interrupt(struct phy_device *phydev)
> +{
> + int rc = phy_read (phydev, MII_LAN83C185_ISF);
> +
> + return rc < 0 ? rc : 0;
> +}
> +
> +static int smsc_phy_config_init(struct phy_device *phydev)
> +{
> + int rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS);
> + if (rc < 0)
> + return rc;
> +
> + /* Enable energy detect mode for this SMSC Transceivers */
> + rc = phy_write(phydev, MII_LAN83C185_CTRL_STATUS,
> + rc | MII_LAN83C185_EDPWRDOWN);
> + if (rc < 0)
> + return rc;
> +
> + return smsc_phy_ack_interrupt (phydev);
> +}
> +
> +static int lan87xx_config_init(struct phy_device *phydev)
> +{
> + /*
> + * Make sure the EDPWRDOWN bit is NOT set. Setting this bit on
> + * LAN8710/LAN8720 PHY causes the PHY to misbehave, likely due
> + * to a bug on the chip.
> + *
> + * When the system is powered on with the network cable being
> + * disconnected all the way until after ifconfig ethX up is
> + * issued for the LAN port with this PHY, connecting the cable
> + * afterwards does not cause LINK change detection, while the
> + * expected behavior is the Link UP being detected.
> + */
> + int rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS);
> + if (rc < 0)
> + return rc;
> +
> + rc &= ~MII_LAN83C185_EDPWRDOWN;
> +
> + rc = phy_write(phydev, MII_LAN83C185_CTRL_STATUS, rc);
> + if (rc < 0)
> + return rc;
> +
> + return smsc_phy_ack_interrupt(phydev);
> +}
> +
> +static int lan911x_config_init(struct phy_device *phydev)
> +{
> + return smsc_phy_ack_interrupt(phydev);
> +}
> +
> +static struct phy_driver smsc_phy_driver[] = {
> +{
> + .phy_id = 0x0007c0a0, /* OUI=0x00800f, Model#=0x0a */
> + .phy_id_mask = 0xfffffff0,
> + .drv.name = "SMSC LAN83C185",
> +
> + .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause
> + | SUPPORTED_Asym_Pause),
> +
> + /* basic functions */
> + .config_aneg = genphy_config_aneg,
> + .read_status = genphy_read_status,
> + .config_init = smsc_phy_config_init,
> +}, {
> + .phy_id = 0x0007c0b0, /* OUI=0x00800f, Model#=0x0b */
> + .phy_id_mask = 0xfffffff0,
> + .drv.name = "SMSC LAN8187",
> +
> + .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause
> + | SUPPORTED_Asym_Pause),
> +
> + /* basic functions */
> + .config_aneg = genphy_config_aneg,
> + .read_status = genphy_read_status,
> + .config_init = smsc_phy_config_init,
> +}, {
> + .phy_id = 0x0007c0c0, /* OUI=0x00800f, Model#=0x0c */
> + .phy_id_mask = 0xfffffff0,
> + .drv.name = "SMSC LAN8700",
> +
> + .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause
> + | SUPPORTED_Asym_Pause),
> +
> + /* basic functions */
> + .config_aneg = genphy_config_aneg,
> + .read_status = genphy_read_status,
> + .config_init = smsc_phy_config_init,
> +}, {
> + .phy_id = 0x0007c0d0, /* OUI=0x00800f, Model#=0x0d */
> + .phy_id_mask = 0xfffffff0,
> + .drv.name = "SMSC LAN911x Internal PHY",
> +
> + .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause
> + | SUPPORTED_Asym_Pause),
> +
> + /* basic functions */
> + .config_aneg = genphy_config_aneg,
> + .read_status = genphy_read_status,
> + .config_init = lan911x_config_init,
> +}, {
> + .phy_id = 0x0007c0f0, /* OUI=0x00800f, Model#=0x0f */
> + .phy_id_mask = 0xfffffff0,
> + .drv.name = "SMSC LAN8710/LAN8720",
> +
> + .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause
> + | SUPPORTED_Asym_Pause),
> +
> + /* basic functions */
> + .config_aneg = genphy_config_aneg,
> + .read_status = genphy_read_status,
> + .config_init = lan87xx_config_init,
> +} };
> +
> +static int __init smsc_init(void)
> +{
> + return phy_drivers_register(smsc_phy_driver, ARRAY_SIZE(smsc_phy_driver));
> +}
> +device_initcall(smsc_init);
> diff --git a/include/linux/smscphy.h b/include/linux/smscphy.h
> new file mode 100644
> index 0000000..ce718cb
> --- /dev/null
> +++ b/include/linux/smscphy.h
> @@ -0,0 +1,25 @@
> +#ifndef __LINUX_SMSCPHY_H__
> +#define __LINUX_SMSCPHY_H__
> +
> +#define MII_LAN83C185_ISF 29 /* Interrupt Source Flags */
> +#define MII_LAN83C185_IM 30 /* Interrupt Mask */
> +#define MII_LAN83C185_CTRL_STATUS 17 /* Mode/Status Register */
> +
> +#define MII_LAN83C185_ISF_INT1 (1<<1) /* Auto-Negotiation Page Received */
> +#define MII_LAN83C185_ISF_INT2 (1<<2) /* Parallel Detection Fault */
> +#define MII_LAN83C185_ISF_INT3 (1<<3) /* Auto-Negotiation LP Ack */
> +#define MII_LAN83C185_ISF_INT4 (1<<4) /* Link Down */
> +#define MII_LAN83C185_ISF_INT5 (1<<5) /* Remote Fault Detected */
> +#define MII_LAN83C185_ISF_INT6 (1<<6) /* Auto-Negotiation complete */
> +#define MII_LAN83C185_ISF_INT7 (1<<7) /* ENERGYON */
> +
> +#define MII_LAN83C185_ISF_INT_ALL (0x0e)
> +
> +#define MII_LAN83C185_ISF_INT_PHYLIB_EVENTS \
> + (MII_LAN83C185_ISF_INT6 | MII_LAN83C185_ISF_INT4 | \
> + MII_LAN83C185_ISF_INT7)
> +
> +#define MII_LAN83C185_EDPWRDOWN (1 << 13) /* EDPWRDOWN */
> +#define MII_LAN83C185_ENERGYON (1 << 1) /* ENERGYON */
> +
> +#endif /* __LINUX_SMSCPHY_H__ */
> --
> 1.7.10.4
>
>
> _______________________________________________
> barebox mailing list
> barebox@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
>
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 1/1 v2] phy: add smsc phy driver support
2012-11-15 9:31 ` [PATCH 2/2] phy: add smsc phy driver support Jean-Christophe PLAGNIOL-VILLARD
2012-11-15 11:29 ` Sascha Hauer
@ 2012-11-15 11:58 ` Jean-Christophe PLAGNIOL-VILLARD
2012-12-08 15:05 ` [PATCH 2/2] " Sascha Hauer
2 siblings, 0 replies; 5+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2012-11-15 11:58 UTC (permalink / raw)
To: barebox
as we to have specific phy init to fix chip issue link detection support
based on linux 3.6
Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
---
v2:
ensure the phy driver are probe before the generic one
so register them first
Best Regards,
J.
drivers/net/phy/Kconfig | 5 ++
drivers/net/phy/Makefile | 1 +
drivers/net/phy/smsc.c | 146 ++++++++++++++++++++++++++++++++++++++++++++++
include/linux/smscphy.h | 25 ++++++++
4 files changed, 177 insertions(+)
create mode 100644 drivers/net/phy/smsc.c
create mode 100644 include/linux/smscphy.h
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index b66261a..616b539 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -14,4 +14,9 @@ config GENERIC_PHY
endif
+config SMSC_PHY
+ bool "Drivers for SMSC PHYs"
+ ---help---
+ Currently supports the LAN83C185, LAN8187 and LAN8700 PHYs
+
endmenu
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index 82e90d4..0caeb70 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -1,2 +1,3 @@
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/smsc.c b/drivers/net/phy/smsc.c
new file mode 100644
index 0000000..a318624
--- /dev/null
+++ b/drivers/net/phy/smsc.c
@@ -0,0 +1,146 @@
+/*
+ * drivers/net/phy/smsc.c
+ *
+ * Driver for SMSC PHYs
+ *
+ * Author: Herbert Valerio Riedel
+ *
+ * Copyright (c) 2006 Herbert Valerio Riedel <hvr@gnu.org>
+ *
+ * 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 added for SMSC LAN8187 and LAN8700 by steve.glendinning@shawell.net
+ *
+ */
+
+#include <common.h>
+#include <init.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/phy.h>
+#include <linux/smscphy.h>
+
+static int smsc_phy_ack_interrupt(struct phy_device *phydev)
+{
+ int rc = phy_read (phydev, MII_LAN83C185_ISF);
+
+ return rc < 0 ? rc : 0;
+}
+
+static int smsc_phy_config_init(struct phy_device *phydev)
+{
+ int rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS);
+ if (rc < 0)
+ return rc;
+
+ /* Enable energy detect mode for this SMSC Transceivers */
+ rc = phy_write(phydev, MII_LAN83C185_CTRL_STATUS,
+ rc | MII_LAN83C185_EDPWRDOWN);
+ if (rc < 0)
+ return rc;
+
+ return smsc_phy_ack_interrupt (phydev);
+}
+
+static int lan87xx_config_init(struct phy_device *phydev)
+{
+ /*
+ * Make sure the EDPWRDOWN bit is NOT set. Setting this bit on
+ * LAN8710/LAN8720 PHY causes the PHY to misbehave, likely due
+ * to a bug on the chip.
+ *
+ * When the system is powered on with the network cable being
+ * disconnected all the way until after ifconfig ethX up is
+ * issued for the LAN port with this PHY, connecting the cable
+ * afterwards does not cause LINK change detection, while the
+ * expected behavior is the Link UP being detected.
+ */
+ int rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS);
+ if (rc < 0)
+ return rc;
+
+ rc &= ~MII_LAN83C185_EDPWRDOWN;
+
+ rc = phy_write(phydev, MII_LAN83C185_CTRL_STATUS, rc);
+ if (rc < 0)
+ return rc;
+
+ return smsc_phy_ack_interrupt(phydev);
+}
+
+static int lan911x_config_init(struct phy_device *phydev)
+{
+ return smsc_phy_ack_interrupt(phydev);
+}
+
+static struct phy_driver smsc_phy_driver[] = {
+{
+ .phy_id = 0x0007c0a0, /* OUI=0x00800f, Model#=0x0a */
+ .phy_id_mask = 0xfffffff0,
+ .drv.name = "SMSC LAN83C185",
+
+ .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause
+ | SUPPORTED_Asym_Pause),
+
+ /* basic functions */
+ .config_aneg = genphy_config_aneg,
+ .read_status = genphy_read_status,
+ .config_init = smsc_phy_config_init,
+}, {
+ .phy_id = 0x0007c0b0, /* OUI=0x00800f, Model#=0x0b */
+ .phy_id_mask = 0xfffffff0,
+ .drv.name = "SMSC LAN8187",
+
+ .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause
+ | SUPPORTED_Asym_Pause),
+
+ /* basic functions */
+ .config_aneg = genphy_config_aneg,
+ .read_status = genphy_read_status,
+ .config_init = smsc_phy_config_init,
+}, {
+ .phy_id = 0x0007c0c0, /* OUI=0x00800f, Model#=0x0c */
+ .phy_id_mask = 0xfffffff0,
+ .drv.name = "SMSC LAN8700",
+
+ .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause
+ | SUPPORTED_Asym_Pause),
+
+ /* basic functions */
+ .config_aneg = genphy_config_aneg,
+ .read_status = genphy_read_status,
+ .config_init = smsc_phy_config_init,
+}, {
+ .phy_id = 0x0007c0d0, /* OUI=0x00800f, Model#=0x0d */
+ .phy_id_mask = 0xfffffff0,
+ .drv.name = "SMSC LAN911x Internal PHY",
+
+ .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause
+ | SUPPORTED_Asym_Pause),
+
+ /* basic functions */
+ .config_aneg = genphy_config_aneg,
+ .read_status = genphy_read_status,
+ .config_init = lan911x_config_init,
+}, {
+ .phy_id = 0x0007c0f0, /* OUI=0x00800f, Model#=0x0f */
+ .phy_id_mask = 0xfffffff0,
+ .drv.name = "SMSC LAN8710/LAN8720",
+
+ .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause
+ | SUPPORTED_Asym_Pause),
+
+ /* basic functions */
+ .config_aneg = genphy_config_aneg,
+ .read_status = genphy_read_status,
+ .config_init = lan87xx_config_init,
+} };
+
+static int __init smsc_init(void)
+{
+ return phy_drivers_register(smsc_phy_driver, ARRAY_SIZE(smsc_phy_driver));
+}
+fs_initcall(smsc_init);
diff --git a/include/linux/smscphy.h b/include/linux/smscphy.h
new file mode 100644
index 0000000..ce718cb
--- /dev/null
+++ b/include/linux/smscphy.h
@@ -0,0 +1,25 @@
+#ifndef __LINUX_SMSCPHY_H__
+#define __LINUX_SMSCPHY_H__
+
+#define MII_LAN83C185_ISF 29 /* Interrupt Source Flags */
+#define MII_LAN83C185_IM 30 /* Interrupt Mask */
+#define MII_LAN83C185_CTRL_STATUS 17 /* Mode/Status Register */
+
+#define MII_LAN83C185_ISF_INT1 (1<<1) /* Auto-Negotiation Page Received */
+#define MII_LAN83C185_ISF_INT2 (1<<2) /* Parallel Detection Fault */
+#define MII_LAN83C185_ISF_INT3 (1<<3) /* Auto-Negotiation LP Ack */
+#define MII_LAN83C185_ISF_INT4 (1<<4) /* Link Down */
+#define MII_LAN83C185_ISF_INT5 (1<<5) /* Remote Fault Detected */
+#define MII_LAN83C185_ISF_INT6 (1<<6) /* Auto-Negotiation complete */
+#define MII_LAN83C185_ISF_INT7 (1<<7) /* ENERGYON */
+
+#define MII_LAN83C185_ISF_INT_ALL (0x0e)
+
+#define MII_LAN83C185_ISF_INT_PHYLIB_EVENTS \
+ (MII_LAN83C185_ISF_INT6 | MII_LAN83C185_ISF_INT4 | \
+ MII_LAN83C185_ISF_INT7)
+
+#define MII_LAN83C185_EDPWRDOWN (1 << 13) /* EDPWRDOWN */
+#define MII_LAN83C185_ENERGYON (1 << 1) /* ENERGYON */
+
+#endif /* __LINUX_SMSCPHY_H__ */
--
1.7.10.4
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH 2/2] phy: add smsc phy driver support
2012-11-15 9:31 ` [PATCH 2/2] phy: add smsc phy driver support Jean-Christophe PLAGNIOL-VILLARD
2012-11-15 11:29 ` Sascha Hauer
2012-11-15 11:58 ` [PATCH 1/1 v2] " Jean-Christophe PLAGNIOL-VILLARD
@ 2012-12-08 15:05 ` Sascha Hauer
2 siblings, 0 replies; 5+ messages in thread
From: Sascha Hauer @ 2012-12-08 15:05 UTC (permalink / raw)
To: Jean-Christophe PLAGNIOL-VILLARD; +Cc: barebox
On Thu, Nov 15, 2012 at 10:31:44AM +0100, Jean-Christophe PLAGNIOL-VILLARD wrote:
> as we to have specific phy init to fix chip issue link detection support
This patch was introduced to make the LAN8720 work with phylib. When
appplying this patch I believed that...
> +
> +static int lan87xx_config_init(struct phy_device *phydev)
> +{
> + /*
> + * Make sure the EDPWRDOWN bit is NOT set. Setting this bit on
> + * LAN8710/LAN8720 PHY causes the PHY to misbehave, likely due
> + * to a bug on the chip.
> + *
> + * When the system is powered on with the network cable being
> + * disconnected all the way until after ifconfig ethX up is
> + * issued for the LAN port with this PHY, connecting the cable
> + * afterwards does not cause LINK change detection, while the
> + * expected behavior is the Link UP being detected.
> + */
> + int rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS);
> + if (rc < 0)
> + return rc;
> +
> + rc &= ~MII_LAN83C185_EDPWRDOWN;
> +
> + rc = phy_write(phydev, MII_LAN83C185_CTRL_STATUS, rc);
> + if (rc < 0)
> + return rc;
... this change was responsible to let the phy driver correctly wait for
a link. As it just turned out, this change os totally irrelevant. The
change which makes this driver work is...
> +}, {
> + .phy_id = 0x0007c0f0, /* OUI=0x00800f, Model#=0x0f */
> + .phy_id_mask = 0xfffffff0,
> + .drv.name = "SMSC LAN8710/LAN8720",
> +
> + .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause
> + | SUPPORTED_Asym_Pause),
... this one. The phy now advertises SUPPORTED_Pause and
SUPPORTED_Asym_Pause which the generic phy driver does not do. This
causes the adv != oldadv check in genphy_config_advert to become true.
genphy_config_advert then returns '1' for advertise changed, which
causes genphy_config_aneg to call genphy_restart_aneg which calls
phy_aneg_done to wait for a link.
So this patch is bogus and by accident fixes a problem. The real problem
is that current phylib does not wait (reliably) for a link. This problem still
persists and is still very annoying. I just have a USB network adapter
here which needs a three second delay after discovering it to make it
work with barebox.
We need a phy_aneg_done() before trying to do network transfers and we
need that *unconditionally*.
Jean-Christophe, you can choose where you want to have this call, but it
will go in. We are carrying these phylib regressions for several months
now.
Sascha
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2012-12-08 15:05 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-11-15 9:31 [PATCH 1/2] phy: add phy_drivers_register Jean-Christophe PLAGNIOL-VILLARD
2012-11-15 9:31 ` [PATCH 2/2] phy: add smsc phy driver support Jean-Christophe PLAGNIOL-VILLARD
2012-11-15 11:29 ` Sascha Hauer
2012-11-15 11:58 ` [PATCH 1/1 v2] " Jean-Christophe PLAGNIOL-VILLARD
2012-12-08 15:05 ` [PATCH 2/2] " Sascha Hauer
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox