net: smc911x: Inline all functions from header file
[oweals/u-boot.git] / examples / standalone / smc911x_eeprom.c
index 2c05ed902d0c55734fc6f13784eaed4de9e93105..19ad9e6297c77122587a1633b9cf25aded1fae4c 100644 (file)
 #include <console.h>
 #include <exports.h>
 #include <linux/ctype.h>
 #include <console.h>
 #include <exports.h>
 #include <linux/ctype.h>
+#include <linux/types.h>
 #include "../drivers/net/smc911x.h"
 
 #include "../drivers/net/smc911x.h"
 
+#define DRIVERNAME "smc911x"
+
+#if defined (CONFIG_SMC911X_32_BIT) && \
+       defined (CONFIG_SMC911X_16_BIT)
+#error "SMC911X: Only one of CONFIG_SMC911X_32_BIT and \
+       CONFIG_SMC911X_16_BIT shall be set"
+#endif
+
+struct chip_id {
+       u16 id;
+       char *name;
+};
+
+static const struct chip_id chip_ids[] =  {
+       { CHIP_89218, "LAN89218" },
+       { CHIP_9115, "LAN9115" },
+       { CHIP_9116, "LAN9116" },
+       { CHIP_9117, "LAN9117" },
+       { CHIP_9118, "LAN9118" },
+       { CHIP_9211, "LAN9211" },
+       { CHIP_9215, "LAN9215" },
+       { CHIP_9216, "LAN9216" },
+       { CHIP_9217, "LAN9217" },
+       { CHIP_9218, "LAN9218" },
+       { CHIP_9220, "LAN9220" },
+       { CHIP_9221, "LAN9221" },
+       { 0, NULL },
+};
+
+#if defined (CONFIG_SMC911X_32_BIT)
+static inline u32 __smc911x_reg_read(struct eth_device *dev, u32 offset)
+{
+       return *(volatile u32*)(dev->iobase + offset);
+}
+u32 smc911x_reg_read(struct eth_device *dev, u32 offset)
+       __attribute__((weak, alias("__smc911x_reg_read")));
+
+static inline void __smc911x_reg_write(struct eth_device *dev,
+                                       u32 offset, u32 val)
+{
+       *(volatile u32*)(dev->iobase + offset) = val;
+}
+void smc911x_reg_write(struct eth_device *dev, u32 offset, u32 val)
+       __attribute__((weak, alias("__smc911x_reg_write")));
+#elif defined (CONFIG_SMC911X_16_BIT)
+static inline u32 smc911x_reg_read(struct eth_device *dev, u32 offset)
+{
+       volatile u16 *addr_16 = (u16 *)(dev->iobase + offset);
+       return ((*addr_16 & 0x0000ffff) | (*(addr_16 + 1) << 16));
+}
+static inline void smc911x_reg_write(struct eth_device *dev,
+                                       u32 offset, u32 val)
+{
+       *(volatile u16 *)(dev->iobase + offset) = (u16)val;
+       *(volatile u16 *)(dev->iobase + offset + 2) = (u16)(val >> 16);
+}
+#else
+#error "SMC911X: undefined bus width"
+#endif /* CONFIG_SMC911X_16_BIT */
+
+static u32 smc911x_get_mac_csr(struct eth_device *dev, u8 reg)
+{
+       while (smc911x_reg_read(dev, MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY)
+               ;
+       smc911x_reg_write(dev, MAC_CSR_CMD,
+                       MAC_CSR_CMD_CSR_BUSY | MAC_CSR_CMD_R_NOT_W | reg);
+       while (smc911x_reg_read(dev, MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY)
+               ;
+
+       return smc911x_reg_read(dev, MAC_CSR_DATA);
+}
+
+static void smc911x_set_mac_csr(struct eth_device *dev, u8 reg, u32 data)
+{
+       while (smc911x_reg_read(dev, MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY)
+               ;
+       smc911x_reg_write(dev, MAC_CSR_DATA, data);
+       smc911x_reg_write(dev, MAC_CSR_CMD, MAC_CSR_CMD_CSR_BUSY | reg);
+       while (smc911x_reg_read(dev, MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY)
+               ;
+}
+
+static int smc911x_detect_chip(struct eth_device *dev)
+{
+       unsigned long val, i;
+
+       val = smc911x_reg_read(dev, BYTE_TEST);
+       if (val == 0xffffffff) {
+               /* Special case -- no chip present */
+               return -1;
+       } else if (val != 0x87654321) {
+               printf(DRIVERNAME ": Invalid chip endian 0x%08lx\n", val);
+               return -1;
+       }
+
+       val = smc911x_reg_read(dev, ID_REV) >> 16;
+       for (i = 0; chip_ids[i].id != 0; i++) {
+               if (chip_ids[i].id == val) break;
+       }
+       if (!chip_ids[i].id) {
+               printf(DRIVERNAME ": Unknown chip ID %04lx\n", val);
+               return -1;
+       }
+
+       dev->priv = (void *)&chip_ids[i];
+
+       return 0;
+}
+
+static void smc911x_reset(struct eth_device *dev)
+{
+       int timeout;
+
+       /*
+        *  Take out of PM setting first
+        *  Device is already wake up if PMT_CTRL_READY bit is set
+        */
+       if ((smc911x_reg_read(dev, PMT_CTRL) & PMT_CTRL_READY) == 0) {
+               /* Write to the bytetest will take out of powerdown */
+               smc911x_reg_write(dev, BYTE_TEST, 0x0);
+
+               timeout = 10;
+
+               while (timeout-- &&
+                       !(smc911x_reg_read(dev, PMT_CTRL) & PMT_CTRL_READY))
+                       udelay(10);
+               if (timeout < 0) {
+                       printf(DRIVERNAME
+                               ": timeout waiting for PM restore\n");
+                       return;
+               }
+       }
+
+       /* Disable interrupts */
+       smc911x_reg_write(dev, INT_EN, 0);
+
+       smc911x_reg_write(dev, HW_CFG, HW_CFG_SRST);
+
+       timeout = 1000;
+       while (timeout-- && smc911x_reg_read(dev, E2P_CMD) & E2P_CMD_EPC_BUSY)
+               udelay(10);
+
+       if (timeout < 0) {
+               printf(DRIVERNAME ": reset timeout\n");
+               return;
+       }
+
+       /* Reset the FIFO level and flow control settings */
+       smc911x_set_mac_csr(dev, FLOW, FLOW_FCPT | FLOW_FCEN);
+       smc911x_reg_write(dev, AFC_CFG, 0x0050287F);
+
+       /* Set to LED outputs */
+       smc911x_reg_write(dev, GPIO_CFG, 0x70070000);
+}
+
 /**
  *     smsc_ctrlc - detect press of CTRL+C (common ctrlc() isnt exported!?)
  */
 /**
  *     smsc_ctrlc - detect press of CTRL+C (common ctrlc() isnt exported!?)
  */