+ struct emaclite_regs *regs = emaclite->regs;
+
+ if (mdio_wait(regs))
+ return 1;
+
+ u32 ctrl_reg = __raw_readl(®s->mdioctrl);
+ __raw_writel(XEL_MDIOADDR_OP_MASK
+ | ((phyaddress << XEL_MDIOADDR_PHYADR_SHIFT)
+ | registernum), ®s->mdioaddr);
+ __raw_writel(ctrl_reg | XEL_MDIOCTRL_MDIOSTS_MASK, ®s->mdioctrl);
+
+ if (mdio_wait(regs))
+ return 1;
+
+ /* Read data */
+ *data = __raw_readl(®s->mdiord);
+ return 0;
+}
+
+static u32 phywrite(struct xemaclite *emaclite, u32 phyaddress, u32 registernum,
+ u16 data)
+{
+ struct emaclite_regs *regs = emaclite->regs;
+
+ if (mdio_wait(regs))
+ return 1;
+
+ /*
+ * Write the PHY address, register number and clear the OP bit in the
+ * MDIO Address register and then write the value into the MDIO Write
+ * Data register. Finally, set the Status bit in the MDIO Control
+ * register to start a MDIO write transaction.
+ */
+ u32 ctrl_reg = __raw_readl(®s->mdioctrl);
+ __raw_writel(~XEL_MDIOADDR_OP_MASK
+ & ((phyaddress << XEL_MDIOADDR_PHYADR_SHIFT)
+ | registernum), ®s->mdioaddr);
+ __raw_writel(data, ®s->mdiowr);
+ __raw_writel(ctrl_reg | XEL_MDIOCTRL_MDIOSTS_MASK, ®s->mdioctrl);
+
+ if (mdio_wait(regs))
+ return 1;
+
+ return 0;
+}
+
+static void emaclite_stop(struct udevice *dev)
+{
+ debug("eth_stop\n");
+}
+
+/* Use MII register 1 (MII status register) to detect PHY */
+#define PHY_DETECT_REG 1
+
+/* Mask used to verify certain PHY features (or register contents)
+ * in the register above:
+ * 0x1000: 10Mbps full duplex support
+ * 0x0800: 10Mbps half duplex support
+ * 0x0008: Auto-negotiation support
+ */
+#define PHY_DETECT_MASK 0x1808
+
+static int setup_phy(struct udevice *dev)
+{
+ int i, ret;
+ u16 phyreg;
+ struct xemaclite *emaclite = dev_get_priv(dev);
+ struct phy_device *phydev;
+
+ u32 supported = SUPPORTED_10baseT_Half |
+ SUPPORTED_10baseT_Full |
+ SUPPORTED_100baseT_Half |
+ SUPPORTED_100baseT_Full;
+
+ if (emaclite->phyaddr != -1) {
+ phyread(emaclite, emaclite->phyaddr, PHY_DETECT_REG, &phyreg);
+ if ((phyreg != 0xFFFF) &&
+ ((phyreg & PHY_DETECT_MASK) == PHY_DETECT_MASK)) {
+ /* Found a valid PHY address */
+ debug("Default phy address %d is valid\n",
+ emaclite->phyaddr);
+ } else {
+ debug("PHY address is not setup correctly %d\n",
+ emaclite->phyaddr);
+ emaclite->phyaddr = -1;
+ }
+ }
+
+ if (emaclite->phyaddr == -1) {
+ /* detect the PHY address */
+ for (i = 31; i >= 0; i--) {
+ phyread(emaclite, i, PHY_DETECT_REG, &phyreg);
+ if ((phyreg != 0xFFFF) &&
+ ((phyreg & PHY_DETECT_MASK) == PHY_DETECT_MASK)) {
+ /* Found a valid PHY address */
+ emaclite->phyaddr = i;
+ debug("emaclite: Found valid phy address, %d\n",
+ i);
+ break;
+ }
+ }
+ }
+
+ /* interface - look at tsec */
+ phydev = phy_connect(emaclite->bus, emaclite->phyaddr, dev,
+ PHY_INTERFACE_MODE_MII);
+ /*
+ * Phy can support 1000baseT but device NOT that's why phydev->supported
+ * must be setup for 1000baseT. phydev->advertising setups what speeds
+ * will be used for autonegotiation where 1000baseT must be disabled.
+ */
+ phydev->supported = supported | SUPPORTED_1000baseT_Half |
+ SUPPORTED_1000baseT_Full;
+ phydev->advertising = supported;
+ emaclite->phydev = phydev;
+ phy_config(phydev);
+ ret = phy_startup(phydev);
+ if (ret)
+ return ret;
+
+ if (!phydev->link) {
+ printf("%s: No link.\n", phydev->dev->name);
+ return 0;
+ }
+
+ /* Do not setup anything */
+ return 1;
+}
+
+static int emaclite_start(struct udevice *dev)
+{
+ struct xemaclite *emaclite = dev_get_priv(dev);
+ struct eth_pdata *pdata = dev_get_platdata(dev);
+ struct emaclite_regs *regs = emaclite->regs;
+