Messages in this thread Patches in this message | | | Date | Wed, 05 Jan 2011 17:48:36 +0100 | From | Angelo Dureghello <> | Subject | [RFC PATCH] m68knommu: added dm9000 support |
| |
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 */ -
| |