summaryrefslogtreecommitdiffstats
path: root/drivers/net/smc91111.c
diff options
context:
space:
mode:
authorRobert Jarzmik <robert.jarzmik@free.fr>2015-01-31 14:10:09 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2015-02-04 12:52:43 +0100
commita8d19f1f2f24b1021d641316c8810f68b2f0c9fd (patch)
tree9ed2e7c3a9a75fb6d696b7209841339be193a104 /drivers/net/smc91111.c
parentd6f8016ce7bc877a19c95d92e2ce1786aed78e8d (diff)
downloadbarebox-a8d19f1f2f24b1021d641316c8810f68b2f0c9fd.tar.gz
barebox-a8d19f1f2f24b1021d641316c8810f68b2f0c9fd.tar.xz
net: smc1111: extend the driver for 91c94 and 91c96 support
All the smcs family chips 91c94, 91c96, 91c100, 91c111 share almost the same behavior and register sets. The noticeable exceptions are coped with in this patch, ie : - 91c94 and 91c96 only have an internal 10 Mbps phy The registers used for phy discovery on later chips will corrupt the 91c96 state. - 91c94 and 91c96 have a control and config register quite different from their 91c1xx conterparts A platform data user defined couple of registers is introduced. If these values are 0, 91c1xx legacy behavior is assumed. Signed-off-by: Robert Jarzmik <robert.jarzmik@free.fr> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'drivers/net/smc91111.c')
-rw-r--r--drivers/net/smc91111.c38
1 files changed, 33 insertions, 5 deletions
diff --git a/drivers/net/smc91111.c b/drivers/net/smc91111.c
index 1e194e4ce1..19b1eefe32 100644
--- a/drivers/net/smc91111.c
+++ b/drivers/net/smc91111.c
@@ -451,6 +451,10 @@ struct smc91c111_priv {
void __iomem *base;
int qemu_fixup;
unsigned shift;
+ int version;
+ int revision;
+ unsigned int control_setup;
+ unsigned int config_setup;
};
#if (SMC_DEBUG > 2 )
@@ -911,6 +915,7 @@ static int smc91c111_phy_read(struct mii_bus *bus, int phyaddr, int phyreg)
static void smc91c111_reset(struct eth_device *edev)
{
struct smc91c111_priv *priv = (struct smc91c111_priv *)edev->priv;
+ int rev_vers;
/* This resets the registers mostly to defaults, but doesn't
affect EEPROM. That seems unnecessary */
@@ -926,8 +931,11 @@ static void smc91c111_reset(struct eth_device *edev)
/* Release from possible power-down state */
/* Configuration register is not affected by Soft Reset */
- SMC_outw(priv, SMC_inw(priv, CONFIG_REG) | CONFIG_EPH_POWER_EN,
- CONFIG_REG);
+ if (priv->config_setup)
+ SMC_outw(priv, priv->config_setup, CONFIG_REG);
+ else
+ SMC_outw(priv, SMC_inw(priv, CONFIG_REG) | CONFIG_EPH_POWER_EN,
+ CONFIG_REG);
SMC_SELECT_BANK(priv, 0);
@@ -940,7 +948,10 @@ static void smc91c111_reset(struct eth_device *edev)
/* set the control register */
SMC_SELECT_BANK(priv, 1);
- SMC_outw(priv, CTL_DEFAULT, CTL_REG);
+ if (priv->control_setup)
+ SMC_outw(priv, priv->control_setup, CTL_REG);
+ else
+ SMC_outw(priv, CTL_DEFAULT, CTL_REG);
/* Reset the MMU */
SMC_SELECT_BANK(priv, 2);
@@ -956,6 +967,14 @@ static void smc91c111_reset(struct eth_device *edev)
/* Disable all interrupts */
SMC_outb(priv, 0, IM_REG);
+
+ /* Check chip revision (91c94, 91c96, 91c100, ...) */
+ SMC_SELECT_BANK(priv, 3);
+ rev_vers = SMC_inb(priv, REV_REG);
+ priv->revision = (rev_vers >> 4) & 0xf;
+ priv->version = rev_vers & 0xf;
+ dev_info(edev->parent, "chip is revision=%2d, version=%2d\n",
+ priv->revision, priv->version);
}
static void smc91c111_enable(struct eth_device *edev)
@@ -975,10 +994,16 @@ static int smc91c111_eth_open(struct eth_device *edev)
/* Configure the Receive/Phy Control register */
SMC_SELECT_BANK(priv, 0);
- SMC_outw(priv, RPC_DEFAULT, RPC_REG);
+ if (priv->revision > 4)
+ SMC_outw(priv, RPC_DEFAULT, RPC_REG);
smc91c111_enable(edev);
+ if (priv->revision <= 4) {
+ dev_info(edev->parent, "force link at 10Mpbs on internal phy\n");
+ return 0;
+ }
+
ret = phy_device_connect(edev, &priv->miibus, 0, NULL,
0, PHY_INTERFACE_MODE_NA);
@@ -1390,6 +1415,8 @@ static int smc91c111_probe(struct device_d *dev)
priv->shift = pdata->addr_shift;
if (pdata->bus_width == 16)
priv->a = access_via_16bit;
+ pdata->config_setup = pdata->config_setup;
+ pdata->control_setup = pdata->control_setup;
}
edev->init = smc91c111_init_dev;
@@ -1411,7 +1438,8 @@ static int smc91c111_probe(struct device_d *dev)
smc91c111_reset(edev);
- mdiobus_register(&priv->miibus);
+ if (priv->revision > 4)
+ mdiobus_register(&priv->miibus);
eth_register(edev);
return 0;