mcfsmc.h 4.5 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
/****************************************************************************/

/*
 *	mcfsmc.h -- SMC ethernet support for ColdFire environments.
 *
 *	(C) Copyright 1999-2002, Greg Ungerer (gerg@snapgear.com)
 *	(C) Copyright 2000, Lineo Inc. (www.lineo.com) 
 */

/****************************************************************************/
#ifndef	mcfsmc_h
#define	mcfsmc_h
/****************************************************************************/

/*
 *	None of the current ColdFire targets that use the SMC91x111
 *	allow 8 bit accesses. So this code is 16bit access only.
 */


#undef	outb
#undef	inb
#undef	outw
#undef	outwd
#undef	inw	
#undef	outl
#undef	inl

#undef	outsb
#undef	outsw
#undef	outsl
#undef	insb
#undef	insw
#undef	insl

/*
 *	Re-defines for ColdFire environment... The SMC part is
 *	mapped into memory space, so remap the PC-style in/out
 *	routines to handle that.
 */
#define	outb	smc_outb
#define	inb	smc_inb
#define	outw	smc_outw
#define	outwd	smc_outwd
#define	inw	smc_inw
#define	outl	smc_outl
#define	inl	smc_inl

#define	outsb	smc_outsb
#define	outsw	smc_outsw
#define	outsl	smc_outsl
#define	insb	smc_insb
#define	insw	smc_insw
#define	insl	smc_insl


static inline int smc_inb(unsigned int addr)
{
	register unsigned short	w;
	w = *((volatile unsigned short *) (addr & ~0x1));
	return(((addr & 0x1) ? w : (w >> 8)) & 0xff);
}

static inline void smc_outw(unsigned int val, unsigned int addr)
{
	*((volatile unsigned short *) addr) = (val << 8) | (val >> 8);
}

static inline int smc_inw(unsigned int addr)
{
	register unsigned short	w;
	w = *((volatile unsigned short *) addr);
	return(((w << 8) | (w >> 8)) & 0xffff);
}

static inline void smc_outl(unsigned long val, unsigned int addr)
{
	*((volatile unsigned long *) addr) = 
		((val << 8) & 0xff000000) | ((val >> 8) & 0x00ff0000) |
		((val << 8) & 0x0000ff00) | ((val >> 8) & 0x000000ff);
}

static inline void smc_outwd(unsigned int val, unsigned int addr)
{
	*((volatile unsigned short *) addr) = val;
}


/*
 *	The rep* functions are used to feed the data port with
 *	raw data. So we do not byte swap them when copying.
 */

static inline void smc_insb(unsigned int addr, void *vbuf, int unsigned long len)
{
	volatile unsigned short	*rp;
	unsigned short		*buf, *ebuf;

	buf = (unsigned short *) vbuf;
	rp = (volatile unsigned short *) addr;

	/* Copy as words for as long as possible */
	for (ebuf = buf + (len >> 1); (buf < ebuf); )
		*buf++ = *rp;

	/* Lastly, handle left over byte */
	if (len & 0x1)
		*((unsigned char *) buf) = (*rp >> 8) & 0xff;
}

static inline void smc_insw(unsigned int addr, void *vbuf, unsigned long len)
{
	volatile unsigned short	*rp;
	unsigned short		*buf, *ebuf;

	buf = (unsigned short *) vbuf;
	rp = (volatile unsigned short *) addr;
	for (ebuf = buf + len; (buf < ebuf); )
		*buf++ = *rp;
}

static inline void smc_insl(unsigned int addr, void *vbuf, unsigned long len)
{
	volatile unsigned long	*rp;
	unsigned long		*buf, *ebuf;

	buf = (unsigned long *) vbuf;
	rp = (volatile unsigned long *) addr;
	for (ebuf = buf + len; (buf < ebuf); )
		*buf++ = *rp;
}

static inline void smc_outsw(unsigned int addr, const void *vbuf, unsigned long len)
{
	volatile unsigned short	*rp;
	unsigned short		*buf, *ebuf;

	buf = (unsigned short *) vbuf;
	rp = (volatile unsigned short *) addr;
	for (ebuf = buf + len; (buf < ebuf); )
		*rp = *buf++;
}

static inline void smc_outsl(unsigned int addr, void *vbuf, unsigned long len)
{
	volatile unsigned long	*rp;
	unsigned long		*buf, *ebuf;

	buf = (unsigned long *) vbuf;
	rp = (volatile unsigned long *) addr;
	for (ebuf = buf + len; (buf < ebuf); )
		*rp = *buf++;
}


#ifdef CONFIG_NETtel
/*
 *	Re-map the address space of at least one of the SMC ethernet
 *	parts. Both parts power up decoding the same address, so we
 *	need to move one of them first, before doing enything else.
 *
 *	We also increase the number of wait states for this part by one.
 */

void smc_remap(unsigned int ioaddr)
{
	static int		once = 0;
	extern unsigned short	ppdata;
	if (once++ == 0) {
		*((volatile unsigned short *)(MCF_MBAR+MCFSIM_PADDR)) = 0x00ec;
		ppdata |= 0x0080;
		*((volatile unsigned short *)(MCF_MBAR+MCFSIM_PADAT)) = ppdata;
		outw(0x0001, ioaddr + BANK_SELECT);
		outw(0x0001, ioaddr + BANK_SELECT);
		outw(0x0067, ioaddr + BASE);

		ppdata &= ~0x0080;
		*((volatile unsigned short *)(MCF_MBAR+MCFSIM_PADAT)) = ppdata;
	}
	
	*((volatile unsigned short *)(MCF_MBAR+MCFSIM_CSCR3)) = 0x1180;
}

#endif

/****************************************************************************/
#endif	/* mcfsmc_h */