* Define your architecture specific bus configuration parameters here.
*/
-#if defined(CONFIG_SA1100_GRAPHICSCLIENT) || \
- defined(CONFIG_SA1100_PFS168) || \
- defined(CONFIG_SA1100_FLEXANET) || \
- defined(CONFIG_SA1100_GRAPHICSMASTER) || \
- defined(CONFIG_ARCH_LUBBOCK)
+#if defined(CONFIG_ARCH_LUBBOCK)
/* We can only do 16-bit reads and writes in the static memory space. */
#define SMC_CAN_USE_8BIT 0
__l--; \
} \
} while (0)
-#define set_irq_type(irq, type)
+#define SMC_IRQ_FLAGS (0)
+
+#elif defined(CONFIG_SA1100_PLEB)
+/* We can only do 16-bit reads and writes in the static memory space. */
+#define SMC_CAN_USE_8BIT 1
+#define SMC_CAN_USE_16BIT 1
+#define SMC_CAN_USE_32BIT 0
+#define SMC_IO_SHIFT 0
+#define SMC_NOWAIT 1
+
+#define SMC_inb(a, r) readb((a) + (r))
+#define SMC_insb(a, r, p, l) readsb((a) + (r), p, (l))
+#define SMC_inw(a, r) readw((a) + (r))
+#define SMC_insw(a, r, p, l) readsw((a) + (r), p, l)
+#define SMC_outb(v, a, r) writeb(v, (a) + (r))
+#define SMC_outsb(a, r, p, l) writesb((a) + (r), p, (l))
+#define SMC_outw(v, a, r) writew(v, (a) + (r))
+#define SMC_outsw(a, r, p, l) writesw((a) + (r), p, l)
+
+#define SMC_IRQ_FLAGS (0)
#elif defined(CONFIG_SA1100_ASSABET)
/* We actually can't write halfwords properly if not word aligned */
static inline void
-SMC_outw(u16 val, unsigned long ioaddr, int reg)
+SMC_outw(u16 val, void __iomem *ioaddr, int reg)
{
if (reg & 2) {
unsigned int v = val << 16;
}
}
+#elif defined(CONFIG_ARCH_OMAP)
+
+/* We can only do 16-bit reads and writes in the static memory space. */
+#define SMC_CAN_USE_8BIT 0
+#define SMC_CAN_USE_16BIT 1
+#define SMC_CAN_USE_32BIT 0
+#define SMC_IO_SHIFT 0
+#define SMC_NOWAIT 1
+
+#define SMC_inb(a, r) readb((a) + (r))
+#define SMC_outb(v, a, r) writeb(v, (a) + (r))
+#define SMC_inw(a, r) readw((a) + (r))
+#define SMC_outw(v, a, r) writew(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)
+#define SMC_inl(a, r) readl((a) + (r))
+#define SMC_outl(v, a, r) writel(v, (a) + (r))
+#define SMC_insl(a, r, p, l) readsl((a) + (r), p, l)
+#define SMC_outsl(a, r, p, l) writesl((a) + (r), p, l)
+
+#include <asm/mach-types.h>
+#include <asm/arch/cpu.h>
+
+#define SMC_IRQ_FLAGS (( \
+ machine_is_omap_h2() \
+ || machine_is_omap_h3() \
+ || (machine_is_omap_innovator() && !cpu_is_omap1510()) \
+ ) ? SA_TRIGGER_FALLING : SA_TRIGGER_RISING)
+
+
+#elif defined(CONFIG_SH_SH4202_MICRODEV)
+
+#define SMC_CAN_USE_8BIT 0
+#define SMC_CAN_USE_16BIT 1
+#define SMC_CAN_USE_32BIT 0
+
+#define SMC_inb(a, r) inb((a) + (r) - 0xa0000000)
+#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_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)
+#define SMC_insw(a, r, p, l) insw((a) + (r) - 0xa0000000, p, l)
+#define SMC_outsw(a, r, p, l) outsw((a) + (r) - 0xa0000000, p, l)
+
+#define SMC_IRQ_FLAGS (0)
+
#elif defined(CONFIG_ISA)
#define SMC_CAN_USE_8BIT 1
#define SMC_insw(a, r, p, l) insw((a) + (r), p, l)
#define SMC_outsw(a, r, p, l) outsw((a) + (r), p, l)
+#elif defined(CONFIG_M32R)
+
+#define SMC_CAN_USE_8BIT 0
+#define SMC_CAN_USE_16BIT 1
+#define SMC_CAN_USE_32BIT 0
+
+#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_insw(a, r, p, l) insw(((u32)a) + (r), p, l)
+#define SMC_outsw(a, r, p, l) outsw(((u32)a) + (r), p, l)
+
+#define SMC_IRQ_FLAGS (0)
+
+#define RPC_LSA_DEFAULT RPC_LED_TX_RX
+#define RPC_LSB_DEFAULT RPC_LED_100_10
+
+#elif defined(CONFIG_MACH_LPD7A400) || defined(CONFIG_MACH_LPD7A404)
+
+/* The LPD7A40X_IOBARRIER is necessary to overcome a mismatch between
+ * the way that the CPU handles chip selects and the way that the SMC
+ * chip expects the chip select to operate. Refer to
+ * Documentation/arm/Sharp-LH/IOBarrier for details. The read from
+ * IOBARRIER is a byte as a least-common denominator of possible
+ * regions to use as the barrier. It would be wasteful to read 32
+ * bits from a byte oriented region.
+ *
+ * There is no explicit protection against interrupts intervening
+ * between the writew and the IOBARRIER. In SMC ISR there is a
+ * preamble that performs an IOBARRIER in the extremely unlikely event
+ * that the driver interrupts itself between a writew to the chip an
+ * the IOBARRIER that follows *and* the cache is large enough that the
+ * first off-chip access while handing the interrupt is to the SMC
+ * chip. Other devices in the same address space as the SMC chip must
+ * be aware of the potential for trouble and perform a similar
+ * IOBARRIER on entry to their ISR.
+ */
+
+#include <asm/arch/constants.h> /* IOBARRIER_VIRT */
+
+#define SMC_CAN_USE_8BIT 0
+#define SMC_CAN_USE_16BIT 1
+#define SMC_CAN_USE_32BIT 0
+#define SMC_NOWAIT 0
+#define LPD7A40X_IOBARRIER readb (IOBARRIER_VIRT)
+
+#define SMC_inw(a,r) readw ((void*) ((a) + (r)))
+#define SMC_insw(a,r,p,l) readsw ((void*) ((a) + (r)), p, l)
+#define SMC_outw(v,a,r) ({ writew ((v), (a) + (r)); LPD7A40X_IOBARRIER; })
+
+static inline void SMC_outsw (unsigned long a, int r, unsigned char* p, int l)
+{
+ unsigned short* ps = (unsigned short*) p;
+ while (l-- > 0) {
+ writew (*ps++, a + r);
+ LPD7A40X_IOBARRIER;
+ }
+}
+
+#define SMC_INTERRUPT_PREAMBLE LPD7A40X_IOBARRIER
+
+#define RPC_LSA_DEFAULT RPC_LED_TX_RX
+#define RPC_LSB_DEFAULT RPC_LED_100_10
+
+#elif defined(CONFIG_SOC_AU1X00)
+
+#include <au1xxx.h>
+
+/* We can only do 16-bit reads and writes in the static memory space. */
+#define SMC_CAN_USE_8BIT 0
+#define SMC_CAN_USE_16BIT 1
+#define SMC_CAN_USE_32BIT 0
+#define SMC_IO_SHIFT 0
+#define SMC_NOWAIT 1
+
+#define SMC_inw(a, r) au_readw((unsigned long)((a) + (r)))
+#define SMC_insw(a, r, p, l) \
+ do { \
+ unsigned long _a = (unsigned long)((a) + (r)); \
+ int _l = (l); \
+ u16 *_p = (u16 *)(p); \
+ while (_l-- > 0) \
+ *_p++ = au_readw(_a); \
+ } while(0)
+#define SMC_outw(v, a, r) au_writew(v, (unsigned long)((a) + (r)))
+#define SMC_outsw(a, r, p, l) \
+ do { \
+ unsigned long _a = (unsigned long)((a) + (r)); \
+ int _l = (l); \
+ const u16 *_p = (const u16 *)(p); \
+ while (_l-- > 0) \
+ au_writew(*_p++ , _a); \
+ } while(0)
+
+#define SMC_IRQ_FLAGS (0)
+
#else
#define SMC_CAN_USE_8BIT 1
#endif
+#ifndef SMC_IRQ_FLAGS
+#define SMC_IRQ_FLAGS SA_TRIGGER_RISING
+#endif
#ifdef SMC_USE_PXA_DMA
/*
* different and probably not worth it for that reason, and not as critical
* as RX which can overrun memory and lose packets.
*/
-#include <linux/pci.h>
+#include <linux/dma-mapping.h>
#include <asm/dma.h>
+#include <asm/arch/pxa-regs.h>
#ifdef SMC_insl
#undef SMC_insl
#define SMC_insl(a, r, p, l) \
smc_pxa_dma_insl(a, lp->physaddr, r, dev->dma, p, l)
static inline void
-smc_pxa_dma_insl(u_long ioaddr, u_long physaddr, int reg, int dma,
+smc_pxa_dma_insl(void __iomem *ioaddr, u_long physaddr, int reg, int dma,
u_char *buf, int len)
{
dma_addr_t dmabuf;
/* 64 bit alignment is required for memory to memory DMA */
if ((long)buf & 4) {
- *((u32 *)buf)++ = SMC_inl(ioaddr, reg);
+ *((u32 *)buf) = SMC_inl(ioaddr, reg);
+ buf += 4;
len--;
}
len *= 4;
- dmabuf = dma_map_single(NULL, buf, len, PCI_DMA_FROMDEVICE);
+ dmabuf = dma_map_single(NULL, buf, len, DMA_FROM_DEVICE);
DCSR(dma) = DCSR_NODESC;
DTADR(dma) = dmabuf;
DSADR(dma) = physaddr + reg;
DCMD(dma) = (DCMD_INCTRGADDR | DCMD_BURST32 |
DCMD_WIDTH4 | (DCMD_LENGTH & len));
DCSR(dma) = DCSR_NODESC | DCSR_RUN;
- while (!(DCSR(dma) & DCSR_STOPSTATE));
+ while (!(DCSR(dma) & DCSR_STOPSTATE))
+ cpu_relax();
DCSR(dma) = 0;
- dma_unmap_single(NULL, dmabuf, len, PCI_DMA_FROMDEVICE);
+ dma_unmap_single(NULL, dmabuf, len, DMA_FROM_DEVICE);
}
#endif
#define SMC_insw(a, r, p, l) \
smc_pxa_dma_insw(a, lp->physaddr, r, dev->dma, p, l)
static inline void
-smc_pxa_dma_insw(u_long ioaddr, u_long physaddr, int reg, int dma,
+smc_pxa_dma_insw(void __iomem *ioaddr, u_long physaddr, int reg, int dma,
u_char *buf, int len)
{
dma_addr_t dmabuf;
/* 64 bit alignment is required for memory to memory DMA */
while ((long)buf & 6) {
- *((u16 *)buf)++ = SMC_inw(ioaddr, reg);
+ *((u16 *)buf) = SMC_inw(ioaddr, reg);
+ buf += 2;
len--;
}
len *= 2;
- dmabuf = dma_map_single(NULL, buf, len, PCI_DMA_FROMDEVICE);
+ dmabuf = dma_map_single(NULL, buf, len, DMA_FROM_DEVICE);
DCSR(dma) = DCSR_NODESC;
DTADR(dma) = dmabuf;
DSADR(dma) = physaddr + reg;
DCMD(dma) = (DCMD_INCTRGADDR | DCMD_BURST32 |
DCMD_WIDTH2 | (DCMD_LENGTH & len));
DCSR(dma) = DCSR_NODESC | DCSR_RUN;
- while (!(DCSR(dma) & DCSR_STOPSTATE));
+ while (!(DCSR(dma) & DCSR_STOPSTATE))
+ cpu_relax();
DCSR(dma) = 0;
- dma_unmap_single(NULL, dmabuf, len, PCI_DMA_FROMDEVICE);
+ dma_unmap_single(NULL, dmabuf, len, DMA_FROM_DEVICE);
}
#endif
#define SMC_IO_SHIFT 0
#endif
#define SMC_IO_EXTENT (16 << SMC_IO_SHIFT)
-
+#define SMC_DATA_EXTENT (4)
/*
. Bank Select Register:
NULL, NULL, NULL};
-/*
- . Transmit status bits
-*/
-#define TS_SUCCESS 0x0001
-#define TS_LOSTCAR 0x0400
-#define TS_LATCOL 0x0200
-#define TS_16COL 0x0010
-
/*
. Receive status bits
*/
#define SMC_GET_FIFO() SMC_inw( ioaddr, FIFO_REG )
#define SMC_GET_PTR() SMC_inw( ioaddr, PTR_REG )
#define SMC_SET_PTR(x) SMC_outw( x, ioaddr, PTR_REG )
+#define SMC_GET_EPH_STATUS() SMC_inw( ioaddr, EPH_STATUS_REG )
#define SMC_GET_RCR() SMC_inw( ioaddr, RCR_REG )
#define SMC_SET_RCR(x) SMC_outw( x, ioaddr, RCR_REG )
#define SMC_GET_REV() SMC_inw( ioaddr, REV_REG )
SMC_outw( addr[4]|(addr[5] << 8), ioaddr, ADDR2_REG ); \
} while (0)
-#define SMC_CLEAR_MCAST() \
- do { \
- SMC_outw( 0, ioaddr, MCAST_REG1 ); \
- SMC_outw( 0, ioaddr, MCAST_REG2 ); \
- SMC_outw( 0, ioaddr, MCAST_REG3 ); \
- SMC_outw( 0, ioaddr, MCAST_REG4 ); \
- } while (0)
#define SMC_SET_MCAST(x) \
do { \
- unsigned char *mt = (x); \
+ const unsigned char *mt = (x); \
SMC_outw( mt[0] | (mt[1] << 8), ioaddr, MCAST_REG1 ); \
SMC_outw( mt[2] | (mt[3] << 8), ioaddr, MCAST_REG2 ); \
SMC_outw( mt[4] | (mt[5] << 8), ioaddr, MCAST_REG3 ); \
#endif
#if SMC_CAN_USE_32BIT
-#define SMC_PUSH_DATA(p, l) \
+#define _SMC_PUSH_DATA(p, l) \
do { \
char *__ptr = (p); \
int __len = (l); \
- if (__len >= 2 && (long)__ptr & 2) { \
+ if (__len >= 2 && (unsigned long)__ptr & 2) { \
__len -= 2; \
- SMC_outw( *((u16 *)__ptr)++, ioaddr, DATA_REG );\
+ SMC_outw( *(u16 *)__ptr, ioaddr, DATA_REG ); \
+ __ptr += 2; \
} \
SMC_outsl( ioaddr, DATA_REG, __ptr, __len >> 2); \
if (__len & 2) { \
SMC_outw( *((u16 *)__ptr), ioaddr, DATA_REG ); \
} \
} while (0)
-#define SMC_PULL_DATA(p, l) \
+#define _SMC_PULL_DATA(p, l) \
do { \
char *__ptr = (p); \
int __len = (l); \
- if ((long)__ptr & 2) { \
+ if ((unsigned long)__ptr & 2) { \
/* \
* We want 32bit alignment here. \
* Since some buses perform a full 32bit \
* SMC_inw() here. Back both source (on chip \
* and destination) pointers of 2 bytes. \
*/ \
- (long)__ptr &= ~2; \
+ __ptr -= 2; \
__len += 2; \
SMC_SET_PTR( 2|PTR_READ|PTR_RCV|PTR_AUTOINC ); \
} \
SMC_insl( ioaddr, DATA_REG, __ptr, __len >> 2); \
} while (0)
#elif SMC_CAN_USE_16BIT
-#define SMC_PUSH_DATA(p, l) SMC_outsw( ioaddr, DATA_REG, p, (l) >> 1 )
-#define SMC_PULL_DATA(p, l) SMC_insw ( ioaddr, DATA_REG, p, (l) >> 1 )
+#define _SMC_PUSH_DATA(p, l) SMC_outsw( ioaddr, DATA_REG, p, (l) >> 1 )
+#define _SMC_PULL_DATA(p, l) SMC_insw ( ioaddr, DATA_REG, p, (l) >> 1 )
#elif SMC_CAN_USE_8BIT
-#define SMC_PUSH_DATA(p, l) SMC_outsb( ioaddr, DATA_REG, p, l )
-#define SMC_PULL_DATA(p, l) SMC_insb ( ioaddr, DATA_REG, p, l )
+#define _SMC_PUSH_DATA(p, l) SMC_outsb( ioaddr, DATA_REG, p, l )
+#define _SMC_PULL_DATA(p, l) SMC_insb ( ioaddr, DATA_REG, p, l )
#endif
#if ! SMC_CAN_USE_16BIT
})
#endif
+#ifdef SMC_CAN_USE_DATACS
+#define SMC_PUSH_DATA(p, l) \
+ if ( lp->datacs ) { \
+ unsigned char *__ptr = (p); \
+ int __len = (l); \
+ if (__len >= 2 && (unsigned long)__ptr & 2) { \
+ __len -= 2; \
+ SMC_outw( *((u16 *)__ptr), ioaddr, DATA_REG ); \
+ __ptr += 2; \
+ } \
+ outsl(lp->datacs, __ptr, __len >> 2); \
+ if (__len & 2) { \
+ __ptr += (__len & ~3); \
+ SMC_outw( *((u16 *)__ptr), ioaddr, DATA_REG ); \
+ } \
+ } else { \
+ _SMC_PUSH_DATA(p, l); \
+ }
+
+#define SMC_PULL_DATA(p, l) \
+ if ( lp->datacs ) { \
+ unsigned char *__ptr = (p); \
+ int __len = (l); \
+ if ((unsigned long)__ptr & 2) { \
+ /* \
+ * We want 32bit alignment here. \
+ * Since some buses perform a full 32bit \
+ * fetch even for 16bit data we can't use \
+ * SMC_inw() here. Back both source (on chip \
+ * and destination) pointers of 2 bytes. \
+ */ \
+ __ptr -= 2; \
+ __len += 2; \
+ SMC_SET_PTR( 2|PTR_READ|PTR_RCV|PTR_AUTOINC ); \
+ } \
+ __len += 2; \
+ insl( lp->datacs, __ptr, __len >> 2); \
+ } else { \
+ _SMC_PULL_DATA(p, l); \
+ }
+#else
+#define SMC_PUSH_DATA(p, l) _SMC_PUSH_DATA(p, l)
+#define SMC_PULL_DATA(p, l) _SMC_PULL_DATA(p, l)
+#endif
+
+#if !defined (SMC_INTERRUPT_PREAMBLE)
+# define SMC_INTERRUPT_PREAMBLE
+#endif
#endif /* _SMC91X_H_ */