summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/ethernet/marvell/mv643xx_eth.c49
-rw-r--r--include/linux/mv643xx_eth.h2
2 files changed, 44 insertions, 7 deletions
diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c
index 707993b445d1..4389a33a2ea6 100644
--- a/drivers/net/ethernet/marvell/mv643xx_eth.c
+++ b/drivers/net/ethernet/marvell/mv643xx_eth.c
@@ -108,6 +108,7 @@ static char mv643xx_eth_driver_version[] = "1.4";
#define TXQ_COMMAND 0x0048
#define TXQ_FIX_PRIO_CONF 0x004c
#define PORT_SERIAL_CONTROL1 0x004c
+#define RGMII_EN 0x00000008
#define CLK125_BYPASS_EN 0x00000010
#define TX_BW_RATE 0x0050
#define TX_BW_MTU 0x0058
@@ -2761,6 +2762,8 @@ static int mv643xx_eth_shared_of_add_port(struct platform_device *pdev,
mv643xx_eth_property(pnp, "rx-sram-addr", ppd.rx_sram_addr);
mv643xx_eth_property(pnp, "rx-sram-size", ppd.rx_sram_size);
+ of_get_phy_mode(pnp, &ppd.interface);
+
ppd.phy_node = of_parse_phandle(pnp, "phy-handle", 0);
if (!ppd.phy_node) {
ppd.phy_addr = MV643XX_ETH_PHY_NONE;
@@ -3092,6 +3095,7 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
struct mv643xx_eth_private *mp;
struct net_device *dev;
struct phy_device *phydev = NULL;
+ u32 psc1r;
int err, irq;
pd = dev_get_platdata(&pdev->dev);
@@ -3119,14 +3123,45 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
mp->dev = dev;
- /* Kirkwood resets some registers on gated clocks. Especially
- * CLK125_BYPASS_EN must be cleared but is not available on
- * all other SoCs/System Controllers using this driver.
- */
if (of_device_is_compatible(pdev->dev.of_node,
- "marvell,kirkwood-eth-port"))
- wrlp(mp, PORT_SERIAL_CONTROL1,
- rdlp(mp, PORT_SERIAL_CONTROL1) & ~CLK125_BYPASS_EN);
+ "marvell,kirkwood-eth-port")) {
+ psc1r = rdlp(mp, PORT_SERIAL_CONTROL1);
+
+ /* Kirkwood resets some registers on gated clocks. Especially
+ * CLK125_BYPASS_EN must be cleared but is not available on
+ * all other SoCs/System Controllers using this driver.
+ */
+ psc1r &= ~CLK125_BYPASS_EN;
+
+ /* On Kirkwood with two Ethernet controllers, if both of them
+ * have RGMII_EN disabled, the first controller will be in GMII
+ * mode and the second one is effectively disabled, instead of
+ * two MII interfaces.
+ *
+ * To enable GMII in the first controller, the second one must
+ * also be configured (and may be enabled) with RGMII_EN
+ * disabled too, even though it cannot be used at all.
+ */
+ switch (pd->interface) {
+ /* Use internal to denote second controller being disabled */
+ case PHY_INTERFACE_MODE_INTERNAL:
+ case PHY_INTERFACE_MODE_MII:
+ case PHY_INTERFACE_MODE_GMII:
+ psc1r &= ~RGMII_EN;
+ break;
+ case PHY_INTERFACE_MODE_RGMII:
+ case PHY_INTERFACE_MODE_RGMII_ID:
+ case PHY_INTERFACE_MODE_RGMII_RXID:
+ case PHY_INTERFACE_MODE_RGMII_TXID:
+ psc1r |= RGMII_EN;
+ break;
+ default:
+ /* Unknown; don't touch */
+ break;
+ }
+
+ wrlp(mp, PORT_SERIAL_CONTROL1, psc1r);
+ }
/*
* Start with a default rate, and if there is a clock, allow
diff --git a/include/linux/mv643xx_eth.h b/include/linux/mv643xx_eth.h
index 3682ae75c7aa..145169be2ed8 100644
--- a/include/linux/mv643xx_eth.h
+++ b/include/linux/mv643xx_eth.h
@@ -8,6 +8,7 @@
#include <linux/mbus.h>
#include <linux/if_ether.h>
+#include <linux/phy.h>
#define MV643XX_ETH_SHARED_NAME "mv643xx_eth"
#define MV643XX_ETH_NAME "mv643xx_eth_port"
@@ -59,6 +60,7 @@ struct mv643xx_eth_platform_data {
*/
int speed;
int duplex;
+ phy_interface_t interface;
/*
* How many RX/TX queues to use.