Commit 7cafb0ba authored by David S. Miller's avatar David S. Miller

Merge branch 'smc91x-dt'

Robert Jarzmik says:

====================
support smc91x on mainstone and devicetree

This series aims at bringing support to mainstone board on a
device-tree based build, as what is already in place for legacy
mainstone.

The bulk of the mainstone "specific" behavior is that a u16 write
doesn't work on a address of the form 4*n + 2, while it works on 4*n.

The legacy workaround was in SMC_outw(), with calls to
machine_is_mainstone(). These calls don't work with a pxa27x-dt
machine type, which is used when a generic device-tree pxa27x machine
is used to boot the mainstone board.

Therefore, this series enables the smc91c111 adapter of the mainstone
board to work on a device-tree build, exaclty as it's been working for
years with the legacy arch/arm/mach-pxa/mainstone.c definition.

As a sum up, this extends an existing mechanism to device-tree based
pxa platforms.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents cd94e519 c4055a8c
......@@ -13,3 +13,5 @@ Optional properties:
16-bit access only.
- power-gpios: GPIO to control the PWRDWN pin
- reset-gpios: GPIO to control the RESET pin
- pxa-u16-align4 : Boolean, put in place the workaround the force all
u16 writes to be 32 bits aligned
......@@ -85,6 +85,7 @@ static struct resource smc91x_resources[] = {
static struct smc91x_platdata smc91x_platdata = {
.flags = SMC91X_USE_8BIT | SMC91X_USE_16BIT | SMC91X_USE_32BIT |
SMC91X_USE_DMA | SMC91X_NOWAIT,
.pxa_u16_align4 = true,
};
static struct platform_device smc91x_device = {
......
......@@ -140,6 +140,7 @@ static struct resource smc91x_resources[] = {
static struct smc91x_platdata mainstone_smc91x_info = {
.flags = SMC91X_USE_8BIT | SMC91X_USE_16BIT | SMC91X_USE_32BIT |
SMC91X_NOWAIT | SMC91X_USE_DMA,
.pxa_u16_align4 = true,
};
static struct platform_device smc91x_device = {
......
......@@ -673,6 +673,7 @@ static struct resource smc91x_resources[] = {
static struct smc91x_platdata stargate2_smc91x_info = {
.flags = SMC91X_USE_8BIT | SMC91X_USE_16BIT | SMC91X_USE_32BIT
| SMC91X_NOWAIT | SMC91X_USE_DMA,
.pxa_u16_align4 = true,
};
static struct platform_device smc91x_device = {
......
......@@ -30,7 +30,7 @@
#if SMC_CAN_USE_16BIT
#define SMC_inw(a, r) inw((unsigned long) ((a) + (r)))
#define SMC_outw(v, a, r) outw(v, (unsigned long) ((a) + (r)))
#define SMC_outw(lp, v, a, r) outw(v, (unsigned long) ((a) + (r)))
#define SMC_insw(a, r, p, l) insw((unsigned long) ((a) + (r)), (p), (l))
#define SMC_outsw(a, r, p, l) outsw((unsigned long) ((a) + (r)), (p), (l))
#endif
......
......@@ -602,7 +602,8 @@ static void smc_hardware_send_pkt(unsigned long data)
SMC_PUSH_DATA(lp, buf, len & ~1);
/* Send final ctl word with the last byte if there is one */
SMC_outw(((len & 1) ? (0x2000 | buf[len-1]) : 0), ioaddr, DATA_REG(lp));
SMC_outw(lp, ((len & 1) ? (0x2000 | buf[len - 1]) : 0), ioaddr,
DATA_REG(lp));
/*
* If THROTTLE_TX_PKTS is set, we stop the queue here. This will
......@@ -2325,6 +2326,8 @@ static int smc_drv_probe(struct platform_device *pdev)
if (!device_property_read_u32(&pdev->dev, "reg-shift",
&val))
lp->io_shift = val;
lp->cfg.pxa_u16_align4 =
device_property_read_bool(&pdev->dev, "pxa-u16-align4");
}
#endif
......
......@@ -63,8 +63,6 @@
#if defined(CONFIG_ARM)
#include <asm/mach-types.h>
/* Now the bus width is specified in the platform data
* pretend here to support all I/O access types
*/
......@@ -86,11 +84,11 @@
#define SMC_inl(a, r) readl((a) + (r))
#define SMC_outb(v, a, r) writeb(v, (a) + (r))
#define SMC_outw(v, a, r) \
#define SMC_outw(lp, v, a, r) \
do { \
unsigned int __v = v, __smc_r = r; \
if (SMC_16BIT(lp)) \
__SMC_outw(__v, a, __smc_r); \
__SMC_outw(lp, __v, a, __smc_r); \
else if (SMC_8BIT(lp)) \
SMC_outw_b(__v, a, __smc_r); \
else \
......@@ -107,10 +105,10 @@
#define SMC_IRQ_FLAGS (-1) /* from resource */
/* We actually can't write halfwords properly if not word aligned */
static inline void __SMC_outw(u16 val, void __iomem *ioaddr, int reg)
static inline void _SMC_outw_align4(u16 val, void __iomem *ioaddr, int reg,
bool use_align4_workaround)
{
if ((machine_is_mainstone() || machine_is_stargate2() ||
machine_is_pxa_idp()) && reg & 2) {
if (use_align4_workaround) {
unsigned int v = val << 16;
v |= readl(ioaddr + (reg & ~2)) & 0xffff;
writel(v, ioaddr + (reg & ~2));
......@@ -119,6 +117,12 @@ static inline void __SMC_outw(u16 val, void __iomem *ioaddr, int reg)
}
}
#define __SMC_outw(lp, v, a, r) \
_SMC_outw_align4((v), (a), (r), \
IS_BUILTIN(CONFIG_ARCH_PXA) && ((r) & 2) && \
(lp)->cfg.pxa_u16_align4)
#elif defined(CONFIG_SH_SH4202_MICRODEV)
#define SMC_CAN_USE_8BIT 0
......@@ -129,7 +133,7 @@ static inline void __SMC_outw(u16 val, void __iomem *ioaddr, int reg)
#define SMC_inw(a, r) inw((a) + (r) - 0xa0000000)
#define SMC_inl(a, r) inl((a) + (r) - 0xa0000000)
#define SMC_outb(v, a, r) outb(v, (a) + (r) - 0xa0000000)
#define SMC_outw(v, a, r) outw(v, (a) + (r) - 0xa0000000)
#define SMC_outw(lp, v, a, r) outw(v, (a) + (r) - 0xa0000000)
#define SMC_outl(v, a, r) outl(v, (a) + (r) - 0xa0000000)
#define SMC_insl(a, r, p, l) insl((a) + (r) - 0xa0000000, p, l)
#define SMC_outsl(a, r, p, l) outsl((a) + (r) - 0xa0000000, p, l)
......@@ -147,7 +151,7 @@ static inline void __SMC_outw(u16 val, void __iomem *ioaddr, int reg)
#define SMC_inb(a, r) inb(((u32)a) + (r))
#define SMC_inw(a, r) inw(((u32)a) + (r))
#define SMC_outb(v, a, r) outb(v, ((u32)a) + (r))
#define SMC_outw(v, a, r) outw(v, ((u32)a) + (r))
#define SMC_outw(lp, v, a, r) outw(v, ((u32)a) + (r))
#define SMC_insw(a, r, p, l) insw(((u32)a) + (r), p, l)
#define SMC_outsw(a, r, p, l) outsw(((u32)a) + (r), p, l)
......@@ -175,7 +179,7 @@ static inline void __SMC_outw(u16 val, void __iomem *ioaddr, int reg)
#define SMC_inw(a, r) readw((a) + (r))
#define SMC_inl(a, r) readl((a) + (r))
#define SMC_outb(v, a, r) writeb(v, (a) + (r))
#define SMC_outw(v, a, r) writew(v, (a) + (r))
#define SMC_outw(lp, v, a, r) writew(v, (a) + (r))
#define SMC_outl(v, a, r) writel(v, (a) + (r))
#define SMC_insw(a, r, p, l) readsw((a) + (r), p, l)
#define SMC_outsw(a, r, p, l) writesw((a) + (r), p, l)
......@@ -207,7 +211,7 @@ static inline void mcf_outsw(void *a, unsigned char *p, int l)
}
#define SMC_inw(a, r) _swapw(readw((a) + (r)))
#define SMC_outw(v, a, r) writew(_swapw(v), (a) + (r))
#define SMC_outw(lp, v, a, r) writew(_swapw(v), (a) + (r))
#define SMC_insw(a, r, p, l) mcf_insw(a + r, p, l)
#define SMC_outsw(a, r, p, l) mcf_outsw(a + r, p, l)
......@@ -241,7 +245,7 @@ static inline void mcf_outsw(void *a, unsigned char *p, int l)
#define SMC_inw(a, r) ioread16((a) + (r))
#define SMC_inl(a, r) ioread32((a) + (r))
#define SMC_outb(v, a, r) iowrite8(v, (a) + (r))
#define SMC_outw(v, a, r) iowrite16(v, (a) + (r))
#define SMC_outw(lp, v, a, r) iowrite16(v, (a) + (r))
#define SMC_outl(v, a, r) iowrite32(v, (a) + (r))
#define SMC_insw(a, r, p, l) ioread16_rep((a) + (r), p, l)
#define SMC_outsw(a, r, p, l) iowrite16_rep((a) + (r), p, l)
......@@ -303,6 +307,8 @@ struct smc_local {
/* the low address lines on some platforms aren't connected... */
int io_shift;
/* on some platforms a u16 write must be 4-bytes aligned */
bool half_word_align4;
struct smc91x_platdata cfg;
};
......@@ -457,7 +463,7 @@ smc_pxa_dma_insw(void __iomem *ioaddr, struct smc_local *lp, int reg, int dma,
#if ! SMC_CAN_USE_16BIT
#define SMC_outw(x, ioaddr, reg) SMC_outw_b(x, ioaddr, reg)
#define SMC_outw(lp, x, ioaddr, reg) SMC_outw_b(x, ioaddr, reg)
#define SMC_inw(ioaddr, reg) SMC_inw_b(ioaddr, reg)
#define SMC_insw(a, r, p, l) BUG()
#define SMC_outsw(a, r, p, l) BUG()
......@@ -909,7 +915,7 @@ static const char * chip_ids[ 16 ] = {
else if (SMC_8BIT(lp)) \
SMC_outb(x, ioaddr, PN_REG(lp)); \
else \
SMC_outw(x, ioaddr, PN_REG(lp)); \
SMC_outw(lp, x, ioaddr, PN_REG(lp)); \
} while (0)
#define SMC_GET_AR(lp) \
......@@ -937,7 +943,7 @@ static const char * chip_ids[ 16 ] = {
int __mask; \
local_irq_save(__flags); \
__mask = SMC_inw(ioaddr, INT_REG(lp)) & ~0xff; \
SMC_outw(__mask | (x), ioaddr, INT_REG(lp)); \
SMC_outw(lp, __mask | (x), ioaddr, INT_REG(lp)); \
local_irq_restore(__flags); \
} \
} while (0)
......@@ -951,7 +957,7 @@ static const char * chip_ids[ 16 ] = {
if (SMC_8BIT(lp)) \
SMC_outb(x, ioaddr, IM_REG(lp)); \
else \
SMC_outw((x) << 8, ioaddr, INT_REG(lp)); \
SMC_outw(lp, (x) << 8, ioaddr, INT_REG(lp)); \
} while (0)
#define SMC_CURRENT_BANK(lp) SMC_inw(ioaddr, BANK_SELECT)
......@@ -961,22 +967,22 @@ static const char * chip_ids[ 16 ] = {
if (SMC_MUST_ALIGN_WRITE(lp)) \
SMC_outl((x)<<16, ioaddr, 12<<SMC_IO_SHIFT); \
else \
SMC_outw(x, ioaddr, BANK_SELECT); \
SMC_outw(lp, x, ioaddr, BANK_SELECT); \
} while (0)
#define SMC_GET_BASE(lp) SMC_inw(ioaddr, BASE_REG(lp))
#define SMC_SET_BASE(lp, x) SMC_outw(x, ioaddr, BASE_REG(lp))
#define SMC_SET_BASE(lp, x) SMC_outw(lp, x, ioaddr, BASE_REG(lp))
#define SMC_GET_CONFIG(lp) SMC_inw(ioaddr, CONFIG_REG(lp))
#define SMC_SET_CONFIG(lp, x) SMC_outw(x, ioaddr, CONFIG_REG(lp))
#define SMC_SET_CONFIG(lp, x) SMC_outw(lp, x, ioaddr, CONFIG_REG(lp))
#define SMC_GET_COUNTER(lp) SMC_inw(ioaddr, COUNTER_REG(lp))
#define SMC_GET_CTL(lp) SMC_inw(ioaddr, CTL_REG(lp))
#define SMC_SET_CTL(lp, x) SMC_outw(x, ioaddr, CTL_REG(lp))
#define SMC_SET_CTL(lp, x) SMC_outw(lp, x, ioaddr, CTL_REG(lp))
#define SMC_GET_MII(lp) SMC_inw(ioaddr, MII_REG(lp))
......@@ -987,20 +993,20 @@ static const char * chip_ids[ 16 ] = {
if (SMC_MUST_ALIGN_WRITE(lp)) \
SMC_outl((x)<<16, ioaddr, SMC_REG(lp, 8, 1)); \
else \
SMC_outw(x, ioaddr, GP_REG(lp)); \
SMC_outw(lp, x, ioaddr, GP_REG(lp)); \
} while (0)
#define SMC_SET_MII(lp, x) SMC_outw(x, ioaddr, MII_REG(lp))
#define SMC_SET_MII(lp, x) SMC_outw(lp, x, ioaddr, MII_REG(lp))
#define SMC_GET_MIR(lp) SMC_inw(ioaddr, MIR_REG(lp))
#define SMC_SET_MIR(lp, x) SMC_outw(x, ioaddr, MIR_REG(lp))
#define SMC_SET_MIR(lp, x) SMC_outw(lp, x, ioaddr, MIR_REG(lp))
#define SMC_GET_MMU_CMD(lp) SMC_inw(ioaddr, MMU_CMD_REG(lp))
#define SMC_SET_MMU_CMD(lp, x) SMC_outw(x, ioaddr, MMU_CMD_REG(lp))
#define SMC_SET_MMU_CMD(lp, x) SMC_outw(lp, x, ioaddr, MMU_CMD_REG(lp))
#define SMC_GET_FIFO(lp) SMC_inw(ioaddr, FIFO_REG(lp))
#define SMC_GET_FIFO(lp) SMC_inw(ioaddr, FIFO_REG(lp))
#define SMC_GET_PTR(lp) SMC_inw(ioaddr, PTR_REG(lp))
......@@ -1009,14 +1015,14 @@ static const char * chip_ids[ 16 ] = {
if (SMC_MUST_ALIGN_WRITE(lp)) \
SMC_outl((x)<<16, ioaddr, SMC_REG(lp, 4, 2)); \
else \
SMC_outw(x, ioaddr, PTR_REG(lp)); \
SMC_outw(lp, x, ioaddr, PTR_REG(lp)); \
} while (0)
#define SMC_GET_EPH_STATUS(lp) SMC_inw(ioaddr, EPH_STATUS_REG(lp))
#define SMC_GET_RCR(lp) SMC_inw(ioaddr, RCR_REG(lp))
#define SMC_SET_RCR(lp, x) SMC_outw(x, ioaddr, RCR_REG(lp))
#define SMC_SET_RCR(lp, x) SMC_outw(lp, x, ioaddr, RCR_REG(lp))
#define SMC_GET_REV(lp) SMC_inw(ioaddr, REV_REG(lp))
......@@ -1027,12 +1033,12 @@ static const char * chip_ids[ 16 ] = {
if (SMC_MUST_ALIGN_WRITE(lp)) \
SMC_outl((x)<<16, ioaddr, SMC_REG(lp, 8, 0)); \
else \
SMC_outw(x, ioaddr, RPC_REG(lp)); \
SMC_outw(lp, x, ioaddr, RPC_REG(lp)); \
} while (0)
#define SMC_GET_TCR(lp) SMC_inw(ioaddr, TCR_REG(lp))
#define SMC_SET_TCR(lp, x) SMC_outw(x, ioaddr, TCR_REG(lp))
#define SMC_SET_TCR(lp, x) SMC_outw(lp, x, ioaddr, TCR_REG(lp))
#ifndef SMC_GET_MAC_ADDR
#define SMC_GET_MAC_ADDR(lp, addr) \
......@@ -1049,18 +1055,18 @@ static const char * chip_ids[ 16 ] = {
#define SMC_SET_MAC_ADDR(lp, addr) \
do { \
SMC_outw(addr[0]|(addr[1] << 8), ioaddr, ADDR0_REG(lp)); \
SMC_outw(addr[2]|(addr[3] << 8), ioaddr, ADDR1_REG(lp)); \
SMC_outw(addr[4]|(addr[5] << 8), ioaddr, ADDR2_REG(lp)); \
SMC_outw(lp, addr[0] | (addr[1] << 8), ioaddr, ADDR0_REG(lp)); \
SMC_outw(lp, addr[2] | (addr[3] << 8), ioaddr, ADDR1_REG(lp)); \
SMC_outw(lp, addr[4] | (addr[5] << 8), ioaddr, ADDR2_REG(lp)); \
} while (0)
#define SMC_SET_MCAST(lp, x) \
do { \
const unsigned char *mt = (x); \
SMC_outw(mt[0] | (mt[1] << 8), ioaddr, MCAST_REG1(lp)); \
SMC_outw(mt[2] | (mt[3] << 8), ioaddr, MCAST_REG2(lp)); \
SMC_outw(mt[4] | (mt[5] << 8), ioaddr, MCAST_REG3(lp)); \
SMC_outw(mt[6] | (mt[7] << 8), ioaddr, MCAST_REG4(lp)); \
SMC_outw(lp, mt[0] | (mt[1] << 8), ioaddr, MCAST_REG1(lp)); \
SMC_outw(lp, mt[2] | (mt[3] << 8), ioaddr, MCAST_REG2(lp)); \
SMC_outw(lp, mt[4] | (mt[5] << 8), ioaddr, MCAST_REG3(lp)); \
SMC_outw(lp, mt[6] | (mt[7] << 8), ioaddr, MCAST_REG4(lp)); \
} while (0)
#define SMC_PUT_PKT_HDR(lp, status, length) \
......@@ -1069,8 +1075,8 @@ static const char * chip_ids[ 16 ] = {
SMC_outl((status) | (length)<<16, ioaddr, \
DATA_REG(lp)); \
else { \
SMC_outw(status, ioaddr, DATA_REG(lp)); \
SMC_outw(length, ioaddr, DATA_REG(lp)); \
SMC_outw(lp, status, ioaddr, DATA_REG(lp)); \
SMC_outw(lp, length, ioaddr, DATA_REG(lp)); \
} \
} while (0)
......
......@@ -39,6 +39,7 @@ struct smc91x_platdata {
unsigned long flags;
unsigned char leda;
unsigned char ledb;
bool pxa_u16_align4; /* PXA buggy u16 writes on 4*n+2 addresses */
};
#endif /* __SMC91X_H__ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment