All of lore.kernel.org
 help / color / mirror / Atom feed
From: Angelo Dureghello <angelo70@gmail.com>
To: linux-kernel@vger.kernel.org, netdev@vger.kernel.org
Subject: [RFC PATCH] m68knommu: added dm9000 support
Date: Wed, 05 Jan 2011 17:48:36 +0100	[thread overview]
Message-ID: <4D24A0E4.1070805@gmail.com> (raw)

This patch allows to use the dm9000 network chip with a m68knommu 
big-endian cpu. From the HW point of view, the cpu data bus connected to 
the dm9000 chip should be hardware-byte-swapped, crossing the bytes 
wires (D0:7 to D24:31, etc.). In anyway, has been also added an option 
to swap the bytes in the driver, if some cpu has been wired straight 
D0:D31 to dm9000.

Signed-off-by: Angelo Dureghello <angelo70@gmail.com>
---

--- drivers/net/Kconfig.orig  2011-01-05 17:11:37.992376124 +0100
+++ drivers/net/Kconfig 2011-01-04 22:33:14.132301872 +0100
@@ -960,7 +960,7 @@ config TI_DAVINCI_EMAC

  config DM9000
    tristate "DM9000 support"
-  depends on ARM || BLACKFIN || MIPS
+  depends on COLDFIRE || ARM || BLACKFIN || MIPS
    select CRC32
    select MII
    ---help---
@@ -986,6 +986,14 @@ config DM9000_FORCE_SIMPLE_PHY_POLL
      costly MII PHY reads. Note, this will not work if the chip is
      operating with an external PHY.

+config DM9000_32BIT_SW_SWAP
+  bool "Software byte swap for 32 bit data bus"
+  depends on DM9000 && COLDFIRE
+  ---help---
+    This configuration allows to swap data bytes from the dm9000
+    driver itself, when the big endian cpu is wired straight to
+    the dm9000 32 bit data bus.
+
  config ENC28J60
    tristate "ENC28J60 support"
    depends on EXPERIMENTAL && SPI && NET_ETHERNET
@@ -3347,4 +3355,3 @@ config VMXNET3
           module will be called vmxnet3.

  endif # NETDEVICES
-


--- drivers/net/dm9000.c.orig    2010-12-30 23:19:39.747836070 +0100
+++ drivers/net/dm9000.c    2011-01-05 16:30:48.636116500 +0100
@@ -158,9 +158,17 @@ dm9000_reset(board_info_t * db)
      dev_dbg(db->dev, "resetting device\n");

      /* RESET device */
+#ifdef CONFIG_DM9000_32BIT_SW_SWAP
+    writel(DM9000_NCR, db->io_addr);
+#else
      writeb(DM9000_NCR, db->io_addr);
+#endif
      udelay(200);
+#ifdef CONFIG_DM9000_32BIT_SW_SWAP
+    writel(NCR_RST, db->io_data);
+#else
      writeb(NCR_RST, db->io_data);
+#endif
      udelay(200);
  }

@@ -170,8 +178,13 @@ dm9000_reset(board_info_t * db)
  static u8
  ior(board_info_t * db, int reg)
  {
+#ifdef CONFIG_DM9000_32BIT_SW_SWAP
+    writel(reg, db->io_addr);
+    return (u8)readl(db->io_data);
+#else
      writeb(reg, db->io_addr);
      return readb(db->io_data);
+#endif
  }

  /*
@@ -181,43 +194,72 @@ ior(board_info_t * db, int reg)
  static void
  iow(board_info_t * db, int reg, int value)
  {
+#ifdef CONFIG_DM9000_32BIT_SW_SWAP
+    writel(reg, db->io_addr);
+    writel(value, db->io_data);
+#else
      writeb(reg, db->io_addr);
      writeb(value, db->io_data);
+#endif
  }

  /* routines for sending block to chip */

  static void dm9000_outblk_8bit(void __iomem *reg, void *data, int count)
  {
+#ifdef CONFIG_DM9000_32BIT_SW_SWAP
+    writesbsw(reg, data, count);
+#else
      writesb(reg, data, count);
+#endif
  }

  static void dm9000_outblk_16bit(void __iomem *reg, void *data, int count)
  {
+#ifdef CONFIG_DM9000_32BIT_SW_SWAP
+    writeswsw(reg, data, (count+1) >> 1);
+#else
      writesw(reg, data, (count+1) >> 1);
+#endif
  }

  static void dm9000_outblk_32bit(void __iomem *reg, void *data, int count)
  {
+#ifdef CONFIG_DM9000_32BIT_SW_SWAP
+    writeslsw(reg, data, (count+3) >> 2);
+#else
      writesl(reg, data, (count+3) >> 2);
+#endif
  }

  /* input block from chip to memory */

  static void dm9000_inblk_8bit(void __iomem *reg, void *data, int count)
  {
+#ifdef CONFIG_DM9000_32BIT_SW_SWAP
+    readsbsw(reg, data, count);
+#else
      readsb(reg, data, count);
+#endif
  }


  static void dm9000_inblk_16bit(void __iomem *reg, void *data, int count)
  {
+#ifdef CONFIG_DM9000_32BIT_SW_SWAP
+    readswsw(reg, data, (count+1) >> 1);
+#else
      readsw(reg, data, (count+1) >> 1);
+#endif
  }

  static void dm9000_inblk_32bit(void __iomem *reg, void *data, int count)
  {
+#ifdef CONFIG_DM9000_32BIT_SW_SWAP
+    readslsw(reg, data, (count+3) >> 2);
+#else
      readsl(reg, data, (count+3) >> 2);
+#endif
  }

  /* dump block from chip to null */
@@ -863,8 +905,13 @@ static void dm9000_timeout(struct net_de
      netif_wake_queue(dev);

      /* Restore previous register address */
+#ifdef CONFIG_DM9000_32BIT_SW_SWAP
+    writel(reg_save, db->io_addr);
+#else
      writeb(reg_save, db->io_addr);
-    spin_unlock_irqrestore(&db->lock, flags);
+#endif
+
+    spin_unlock_irqrestore(&db->lock,flags);
  }

  static void dm9000_send_packet(struct net_device *dev,
@@ -908,7 +955,11 @@ dm9000_start_xmit(struct sk_buff *skb, s
      spin_lock_irqsave(&db->lock, flags);

      /* Move data to DM9000 TX RAM */
+#ifdef CONFIG_DM9000_32BIT_SW_SWAP
+   writel(DM9000_MWCMD, db->io_addr);
+#else
      writeb(DM9000_MWCMD, db->io_addr);
+#endif

      (db->outblk)(db->io_data, skb->data, skb->len);
      dev->stats.tx_bytes += skb->len;
@@ -981,7 +1032,11 @@ dm9000_rx(struct net_device *dev)
          ior(db, DM9000_MRCMDX);    /* Dummy read */

          /* Get most updated data */
-        rxbyte = readb(db->io_data);
+#ifdef CONFIG_DM9000_32BIT_SW_SWAP
+      rxbyte = (u8)readl(db->io_data);
+#else
+      rxbyte = readb(db->io_data);
+#endif

          /* Status check: this byte must be 0 or 1 */
          if (rxbyte & DM9000_PKT_ERR) {
@@ -996,8 +1051,13 @@ dm9000_rx(struct net_device *dev)

          /* A packet ready now & Get status/length */
          GoodPacket = true;
-        writeb(DM9000_MRCMD, db->io_addr);

+#ifdef CONFIG_DM9000_32BIT_SW_SWAP
+        writel(DM9000_MRCMD, db->io_addr);
+#else
+      writeb(DM9000_MRCMD, db->io_addr);
+#endif
+
          (db->inblk)(db->io_data, &rxhdr, sizeof(rxhdr));

          RxLen = le16_to_cpu(rxhdr.RxLen);
@@ -1077,7 +1137,7 @@ static irqreturn_t dm9000_interrupt(int
      unsigned long flags;
      u8 reg_save;

-    dm9000_dbg(db, 3, "entering %s\n", __func__);
+    //dm9000_dbg(db, 3, "entering %s\n", __func__);

      /* A real interrupt coming */

@@ -1085,7 +1145,11 @@ static irqreturn_t dm9000_interrupt(int
      spin_lock_irqsave(&db->lock, flags);

      /* Save previous register address */
-    reg_save = readb(db->io_addr);
+#ifdef CONFIG_DM9000_32BIT_SW_SWAP
+   reg_save = (u8)readl(db->io_addr);
+#else
+   reg_save = readb(db->io_addr);
+#endif

      /* Disable all interrupts */
      iow(db, DM9000_IMR, IMR_PAR);
@@ -1100,7 +1164,7 @@ static irqreturn_t dm9000_interrupt(int
      /* Received the coming packet */
      if (int_status & ISR_PRS)
          dm9000_rx(dev);
-
+
      /* Trnasmit Interrupt check */
      if (int_status & ISR_PTS)
          dm9000_tx_done(dev, db);
@@ -1116,8 +1180,12 @@ static irqreturn_t dm9000_interrupt(int
      iow(db, DM9000_IMR, db->imr_all);

      /* Restore previous register address */
+#ifdef CONFIG_DM9000_32BIT_SW_SWAP
+    writel(reg_save, db->io_addr);
+#else
      writeb(reg_save, db->io_addr);
-
+#endif
+
      spin_unlock_irqrestore(&db->lock, flags);

      return IRQ_HANDLED;
@@ -1233,11 +1301,15 @@ dm9000_phy_read(struct net_device *dev,
      int ret;

      mutex_lock(&db->addr_lock);
-
+
      spin_lock_irqsave(&db->lock,flags);

      /* Save previous register address */
-    reg_save = readb(db->io_addr);
+#ifdef CONFIG_DM9000_32BIT_SW_SWAP
+   reg_save = (u8)readl(db->io_addr);
+#else
+   reg_save = readb(db->io_addr);
+#endif

      /* Fill the phyxcer register into REG_0C */
      iow(db, DM9000_EPAR, DM9000_PHY | reg);
@@ -1250,7 +1322,11 @@ dm9000_phy_read(struct net_device *dev,
      dm9000_msleep(db, 1);        /* Wait read complete */

      spin_lock_irqsave(&db->lock,flags);
-    reg_save = readb(db->io_addr);
+#ifdef CONFIG_DM9000_32BIT_SW_SWAP
+   reg_save = (u8)readl(db->io_addr);
+#else
+   reg_save = readb(db->io_addr);
+#endif

      iow(db, DM9000_EPCR, 0x0);    /* Clear phyxcer read command */

@@ -1258,9 +1334,14 @@ dm9000_phy_read(struct net_device *dev,
      ret = (ior(db, DM9000_EPDRH) << 8) | ior(db, DM9000_EPDRL);

      /* restore the previous address */
+#ifdef CONFIG_DM9000_32BIT_SW_SWAP
+    writel(reg_save, db->io_addr);
+#else
      writeb(reg_save, db->io_addr);
-    spin_unlock_irqrestore(&db->lock,flags);
+#endif

+    spin_unlock_irqrestore(&db->lock,flags);
+
      mutex_unlock(&db->addr_lock);

      dm9000_dbg(db, 5, "phy_read[%02x] -> %04x\n", reg, ret);
@@ -1284,7 +1365,11 @@ dm9000_phy_write(struct net_device *dev,
      spin_lock_irqsave(&db->lock,flags);

      /* Save previous register address */
-    reg_save = readb(db->io_addr);
+#ifdef CONFIG_DM9000_32BIT_SW_SWAP
+   reg_save = (u8)readl(db->io_addr);
+#else
+   reg_save = readb(db->io_addr);
+#endif

      /* Fill the phyxcer register into REG_0C */
      iow(db, DM9000_EPAR, DM9000_PHY | reg);
@@ -1295,18 +1380,31 @@ dm9000_phy_write(struct net_device *dev,

      iow(db, DM9000_EPCR, EPCR_EPOS | EPCR_ERPRW);    /* Issue phyxcer 
write command */

+#ifdef CONFIG_DM9000_32BIT_SW_SWAP
+    writel(reg_save, db->io_addr);
+#else
      writeb(reg_save, db->io_addr);
+#endif
+
      spin_unlock_irqrestore(&db->lock, flags);

      dm9000_msleep(db, 1);        /* Wait write complete */

      spin_lock_irqsave(&db->lock,flags);
-    reg_save = readb(db->io_addr);
+#ifdef CONFIG_DM9000_32BIT_SW_SWAP
+   reg_save = (u8)readl(db->io_addr);
+#else
+   reg_save = readb(db->io_addr);
+#endif

      iow(db, DM9000_EPCR, 0x0);    /* Clear phyxcer write command */

      /* restore the previous address */
+#ifdef CONFIG_DM9000_32BIT_SW_SWAP
+    writel(reg_save, db->io_addr);
+#else
      writeb(reg_save, db->io_addr);
+#endif

      spin_unlock_irqrestore(&db->lock, flags);
      mutex_unlock(&db->addr_lock);
@@ -1713,4 +1811,3 @@ MODULE_AUTHOR("Sascha Hauer, Ben Dooks")
  MODULE_DESCRIPTION("Davicom DM9000 network driver");
  MODULE_LICENSE("GPL");
  MODULE_ALIAS("platform:dm9000");
-

--- arch/m68k/include/asm/io_no.h.orig    2011-01-05 16:53:55.904905038 
+0100
+++ arch/m68k/include/asm/io_no.h    2011-01-04 23:45:08.893049554 +0100
@@ -47,6 +47,91 @@ static inline unsigned int _swapl(volati
  #define writew(b,addr) (void)((*(volatile unsigned short *) (addr)) = (b))
  #define writel(b,addr) (void)((*(volatile unsigned int *) (addr)) = (b))

+static inline void writesb (void __iomem *reg, void *data, int count)
+{
+    unsigned char *p = (unsigned char*) data;
+
+    while (count--) writeb(*p++, reg);
+}
+
+static inline void writesbsw (void __iomem *reg, void *data, int count)
+{
+    unsigned char *p = (unsigned char *) data;
+
+    while (count--) writel((int)(*p++), reg);
+}
+
+static inline void writesw (void __iomem *reg, void *data, int count)
+{
+   unsigned short *p = (unsigned short*) data;
+
+   while (count--) writew(*p++, reg);
+}
+
+static inline void writeswsw (void __iomem *reg, void *data, int count)
+{
+   unsigned short *p = (unsigned short *) data;
+
+   while (count--) writel((int)(_swapw(*p++)), reg);
+}
+
+static inline void writesl (void __iomem *reg, void *data, int count)
+{
+   unsigned long *p = (unsigned long*) data;
+
+   while (count--) writel(*p++, reg);
+}
+
+static inline void writeslsw (void __iomem *reg, void *data, int count)
+{
+   unsigned long *p = (unsigned long *) data;
+
+   while (count--) writel((int)(_swapl(*p++)), reg);
+}
+
+static inline void readsb (void __iomem *reg, void *data, int count)
+{
+   unsigned char *p = (unsigned char *) data;
+
+   while (count--) *p++ = readb(reg);
+}
+
+static inline void readsbsw (void __iomem *reg, void *data, int count)
+{
+   unsigned char *p = (unsigned char *) data;
+
+   while (count--) *p++ = (unsigned char)readl(reg);
+}
+
+static inline void readsw (void __iomem *reg, void *data, int count)
+{
+   unsigned short *p = (unsigned short *) data;
+
+   while (count--) *p++ = readb(reg);
+}
+
+static inline void readswsw (void __iomem *reg, void *data, int count)
+{
+   unsigned short *p = (unsigned short *) data;
+
+   while (count--) *p++ = _swapw((unsigned short)readw(reg));
+}
+
+static inline void readsl (void __iomem *reg, void *data, int count)
+{
+   unsigned long *p = (unsigned long *) data;
+
+   while (count--) *p++ = readb(reg);
+}
+
+static inline void readslsw (void __iomem *reg, void *data, int count)
+{
+   unsigned long *p = (unsigned long *) data;
+
+   while (count--) *p++ = _swapl(readl(reg));
+}
+
+
  #define __raw_readb readb
  #define __raw_readw readw
  #define __raw_readl readl
@@ -180,4 +265,3 @@ extern void iounmap(void *addr);
  #endif /* __KERNEL__ */

  #endif /* _M68KNOMMU_IO_H */
-


             reply	other threads:[~2011-01-05 16:48 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-01-05 16:48 Angelo Dureghello [this message]
2011-01-05 16:59 ` [RFC PATCH] m68knommu: added dm9000 support Randy Dunlap

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4D24A0E4.1070805@gmail.com \
    --to=angelo70@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=netdev@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.