@@ -239,6 +239,7 @@ struct fec_enet_private {
int mii_timeout;
uint phy_speed;
phy_interface_t phy_interface;
+ unsigned phy_type;
int link;
int full_duplex;
struct completion mdio_done;
@@ -978,6 +979,17 @@ static int fec_enet_mii_probe(struct net_device *ndev)
fep->phy_dev = NULL;
+ if (fep->phy_type == FEC_PHY_SWITCH) {
+ fep->link = 1;
+ netif_carrier_on(ndev); // always up
+
+ fep->full_duplex = 1; // full duplex
+
+ fec_restart(ndev, fep->full_duplex);
+
+ return 0;
+ }
+
/* check for attached phy */
for (phy_id = 0; (phy_id < PHY_MAX_ADDR); phy_id++) {
if ((fep->mii_bus->phy_mask & (1 << phy_id)))
@@ -1170,8 +1182,20 @@ static int fec_enet_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd)
if (!netif_running(ndev))
return -EINVAL;
- if (!phydev)
- return -ENODEV;
+ if (!phydev) {
+ // On i.mx28, this is not necessarily needed
+ // TODO: remove?
+ struct mii_ioctl_data *mii_data = if_mii(rq);
+
+ if (cmd == SIOCGMIIREG)
+ mdiobus_write(fep->mii_bus, mii_data->phy_id,
+ mii_data->reg_num, mii_data->val_in);
+ else if (cmd == SIOCSMIIREG)
+ mii_data->val_out = mdiobus_read(fep->mii_bus,
+ mii_data->phy_id, mii_data->reg_num);
+ else return -ENODEV;
+ return 0;
+ }
return phy_mii_ioctl(phydev, rq, cmd);
}
@@ -1274,7 +1298,8 @@ fec_enet_open(struct net_device *ndev)
fec_enet_free_buffers(ndev);
return ret;
}
- phy_start(fep->phy_dev);
+ if (fep->phy_type == FEC_PHY_NORMAL)
+ phy_start(fep->phy_dev);
netif_start_queue(ndev);
fep->opened = 1;
return 0;
@@ -1598,6 +1623,9 @@ fec_probe(struct platform_device *pdev)
fep->phy_interface = ret;
}
+ if (pdata)
+ fep->phy_type = pdata->phy_type;
+
fec_reset_phy(pdev);
for (i = 0; i < FEC_IRQ_NUM; i++) {
@@ -14,10 +14,15 @@
#ifndef __LINUX_FEC_H__
#define __LINUX_FEC_H__
+#define FEC_PHY_NORMAL 0
+#define FEC_PHY_SWITCH 1
+#define FEC_PHY_NONE 2
+
#include <linux/phy.h>
struct fec_platform_data {
phy_interface_t phy;
+ unsigned phy_type;
unsigned char mac[ETH_ALEN];
};