* [RFC v2 PATCH] m68knommu: added dm9000 support
@ 2011-01-05 18:03 Angelo Dureghello
2011-01-05 23:51 ` Arnaud Lacombe
0 siblings, 1 reply; 3+ messages in thread
From: Angelo Dureghello @ 2011-01-05 18:03 UTC (permalink / raw)
To: linux-kernel, netdev; +Cc: Randy Dunlap
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>
---
--- linux/drivers/net/Kconfig.orig 2011-01-05 17:11:37.992376124 +0100
+++ linux/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
-
--- linux/drivers/net/dm9000.c.orig 2010-12-30 23:19:39.747836070 +0100
+++ linux/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");
-
--- linux/arch/m68k/include/asm/io_no.h.orig 2011-01-05 16:53:55.904905038 +0100
+++ linux/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 */
-
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [RFC v2 PATCH] m68knommu: added dm9000 support
2011-01-05 18:03 [RFC v2 PATCH] m68knommu: added dm9000 support Angelo Dureghello
@ 2011-01-05 23:51 ` Arnaud Lacombe
2011-01-06 12:39 ` Angelo Dureghello
0 siblings, 1 reply; 3+ messages in thread
From: Arnaud Lacombe @ 2011-01-05 23:51 UTC (permalink / raw)
To: Angelo Dureghello; +Cc: linux-kernel, netdev, Randy Dunlap
Hi,
[disclamer: I have no power whatsoever on the dm9k driver, and the
only dm9000 chip I've access to belongs to hardware whose parent
company is now defunct.]
Btw, Linux 68k folks is missing from the CC list.
On Wed, Jan 5, 2011 at 1:03 PM, Angelo Dureghello <angelo70@gmail.com> wrote:
> This patch allows to use the dm9000 network chip with a m68knommu
> big-endian cpu. From the HW point of view,
what hardware ?
> 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>
> ---
>
> --- linux/drivers/net/Kconfig.orig 2011-01-05 17:11:37.992376124 +0100
> +++ linux/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.
> +
I'm not sure COLDFIRE is the best dependency. AFAICS, it should
depends on endianness, and potentially board specific settings.
> config ENC28J60
> tristate "ENC28J60 support"
> depends on EXPERIMENTAL && SPI && NET_ETHERNET
> @@ -3347,4 +3355,3 @@ config VMXNET3
> module will be called vmxnet3.
>
> endif # NETDEVICES
> -
>
useless whitespace change ...
> --- linux/drivers/net/dm9000.c.orig 2010-12-30 23:19:39.747836070 +0100
> +++ linux/drivers/net/dm9000.c 2011-01-05 16:30:48.636116500 +0100
> [...]
> @@ -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
> +
All these #ifdef make the driver quite horrible to read.
> (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__);
>
C++ comment ... Why do you comment this ?
> /* 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);
> -
> +
whitespace ...
> @@ -1233,11 +1301,15 @@ dm9000_phy_read(struct net_device *dev,
> int ret;
>
> mutex_lock(&db->addr_lock);
> -
> +
whitespace ...
> @@ -1713,4 +1811,3 @@ MODULE_AUTHOR("Sascha Hauer, Ben Dooks")
> MODULE_DESCRIPTION("Davicom DM9000 network driver");
> MODULE_LICENSE("GPL");
> MODULE_ALIAS("platform:dm9000");
> -
whitespace ...
> --- linux/arch/m68k/include/asm/io_no.h.orig 2011-01-05 16:53:55.904905038 +0100
> +++ linux/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 */
Could not this be moved to a separate patch ? That way arch specific
changes are separated from the network arch-indep changes.
- Arnaud
> -
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/
>
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [RFC v2 PATCH] m68knommu: added dm9000 support
2011-01-05 23:51 ` Arnaud Lacombe
@ 2011-01-06 12:39 ` Angelo Dureghello
0 siblings, 0 replies; 3+ messages in thread
From: Angelo Dureghello @ 2011-01-06 12:39 UTC (permalink / raw)
To: Arnaud Lacombe; +Cc: linux-kernel, netdev, m68k
thanks for the review,
- sure, i agree the sw byte swap could be related to a BIG_ENDIAN config option only.
- about HW, can be replaced with something like "dm9000 to cpu bus wiring", i will be more clear in my next patch version.
- i will remove blank lines
- readsX and writesX was completely missing for m68knommu, i have seen that the most appropriate file where to create them was probably "linux/arch/m68k/include/asm/io_no.h" but any comment is appreciated.
- i am adding m68k guys list from now.
thanks
angelo
On 06/01/2011 00:51, Arnaud Lacombe wrote:
> Hi,
>
> [disclamer: I have no power whatsoever on the dm9k driver, and the
> only dm9000 chip I've access to belongs to hardware whose parent
> company is now defunct.]
>
> Btw, Linux 68k folks is missing from the CC list.
>
> On Wed, Jan 5, 2011 at 1:03 PM, Angelo Dureghello <angelo70@gmail.com> wrote:
>> This patch allows to use the dm9000 network chip with a m68knommu
>> big-endian cpu. From the HW point of view,
> what hardware ?
>
>> 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>
>> ---
>>
>> --- linux/drivers/net/Kconfig.orig 2011-01-05 17:11:37.992376124 +0100
>> +++ linux/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.
>> +
> I'm not sure COLDFIRE is the best dependency. AFAICS, it should
> depends on endianness, and potentially board specific settings.
>
>> config ENC28J60
>> tristate "ENC28J60 support"
>> depends on EXPERIMENTAL && SPI && NET_ETHERNET
>> @@ -3347,4 +3355,3 @@ config VMXNET3
>> module will be called vmxnet3.
>>
>> endif # NETDEVICES
>> -
>>
> useless whitespace change ...
>
>> --- linux/drivers/net/dm9000.c.orig 2010-12-30 23:19:39.747836070 +0100
>> +++ linux/drivers/net/dm9000.c 2011-01-05 16:30:48.636116500 +0100
>> [...]
>> @@ -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
>> +
> All these #ifdef make the driver quite horrible to read.
>
>> (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__);
>>
> C++ comment ... Why do you comment this ?
>
>> /* 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);
>> -
>> +
> whitespace ...
>
>> @@ -1233,11 +1301,15 @@ dm9000_phy_read(struct net_device *dev,
>> int ret;
>>
>> mutex_lock(&db->addr_lock);
>> -
>> +
> whitespace ...
>
>> @@ -1713,4 +1811,3 @@ MODULE_AUTHOR("Sascha Hauer, Ben Dooks")
>> MODULE_DESCRIPTION("Davicom DM9000 network driver");
>> MODULE_LICENSE("GPL");
>> MODULE_ALIAS("platform:dm9000");
>> -
> whitespace ...
>
>> --- linux/arch/m68k/include/asm/io_no.h.orig 2011-01-05 16:53:55.904905038 +0100
>> +++ linux/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 */
> Could not this be moved to a separate patch ? That way arch specific
> changes are separated from the network arch-indep changes.
>
> - Arnaud
>
>> -
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at http://vger.kernel.org/majordomo-info.html
>> Please read the FAQ at http://www.tux.org/lkml/
>>
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2011-01-06 12:39 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-01-05 18:03 [RFC v2 PATCH] m68knommu: added dm9000 support Angelo Dureghello
2011-01-05 23:51 ` Arnaud Lacombe
2011-01-06 12:39 ` Angelo Dureghello
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).