1/****************************************************************************/
2
3/*
4 *	mcfsmc.h -- SMC ethernet support for ColdFire environments.
5 *
6 *	(C) Copyright 1999-2002, Greg Ungerer (gerg@snapgear.com)
7 *	(C) Copyright 2000, Lineo Inc. (www.lineo.com)
8 */
9
10/****************************************************************************/
11#ifndef	mcfsmc_h
12#define	mcfsmc_h
13/****************************************************************************/
14
15/*
16 *	None of the current ColdFire targets that use the SMC91x111
17 *	allow 8 bit accesses. So this code is 16bit access only.
18 */
19
20
21#undef	outb
22#undef	inb
23#undef	outw
24#undef	outwd
25#undef	inw
26#undef	outl
27#undef	inl
28
29#undef	outsb
30#undef	outsw
31#undef	outsl
32#undef	insb
33#undef	insw
34#undef	insl
35
36/*
37 *	Re-defines for ColdFire environment... The SMC part is
38 *	mapped into memory space, so remap the PC-style in/out
39 *	routines to handle that.
40 */
41#define	outb	smc_outb
42#define	inb	smc_inb
43#define	outw	smc_outw
44#define	outwd	smc_outwd
45#define	inw	smc_inw
46#define	outl	smc_outl
47#define	inl	smc_inl
48
49#define	outsb	smc_outsb
50#define	outsw	smc_outsw
51#define	outsl	smc_outsl
52#define	insb	smc_insb
53#define	insw	smc_insw
54#define	insl	smc_insl
55
56
57static inline int smc_inb(unsigned int addr)
58{
59	register unsigned short	w;
60	w = *((volatile unsigned short *) (addr & ~0x1));
61	return(((addr & 0x1) ? w : (w >> 8)) & 0xff);
62}
63
64static inline void smc_outw(unsigned int val, unsigned int addr)
65{
66	*((volatile unsigned short *) addr) = (val << 8) | (val >> 8);
67}
68
69static inline int smc_inw(unsigned int addr)
70{
71	register unsigned short	w;
72	w = *((volatile unsigned short *) addr);
73	return(((w << 8) | (w >> 8)) & 0xffff);
74}
75
76static inline void smc_outl(unsigned long val, unsigned int addr)
77{
78	*((volatile unsigned long *) addr) =
79		((val << 8) & 0xff000000) | ((val >> 8) & 0x00ff0000) |
80		((val << 8) & 0x0000ff00) | ((val >> 8) & 0x000000ff);
81}
82
83static inline void smc_outwd(unsigned int val, unsigned int addr)
84{
85	*((volatile unsigned short *) addr) = val;
86}
87
88
89/*
90 *	The rep* functions are used to feed the data port with
91 *	raw data. So we do not byte swap them when copying.
92 */
93
94static inline void smc_insb(unsigned int addr, void *vbuf, int unsigned long len)
95{
96	volatile unsigned short	*rp;
97	unsigned short		*buf, *ebuf;
98
99	buf = (unsigned short *) vbuf;
100	rp = (volatile unsigned short *) addr;
101
102	/* Copy as words for as long as possible */
103	for (ebuf = buf + (len >> 1); (buf < ebuf); )
104		*buf++ = *rp;
105
106	/* Lastly, handle left over byte */
107	if (len & 0x1)
108		*((unsigned char *) buf) = (*rp >> 8) & 0xff;
109}
110
111static inline void smc_insw(unsigned int addr, void *vbuf, unsigned long len)
112{
113	volatile unsigned short	*rp;
114	unsigned short		*buf, *ebuf;
115
116	buf = (unsigned short *) vbuf;
117	rp = (volatile unsigned short *) addr;
118	for (ebuf = buf + len; (buf < ebuf); )
119		*buf++ = *rp;
120}
121
122static inline void smc_insl(unsigned int addr, void *vbuf, unsigned long len)
123{
124	volatile unsigned long	*rp;
125	unsigned long		*buf, *ebuf;
126
127	buf = (unsigned long *) vbuf;
128	rp = (volatile unsigned long *) addr;
129	for (ebuf = buf + len; (buf < ebuf); )
130		*buf++ = *rp;
131}
132
133static inline void smc_outsw(unsigned int addr, const void *vbuf, unsigned long len)
134{
135	volatile unsigned short	*rp;
136	unsigned short		*buf, *ebuf;
137
138	buf = (unsigned short *) vbuf;
139	rp = (volatile unsigned short *) addr;
140	for (ebuf = buf + len; (buf < ebuf); )
141		*rp = *buf++;
142}
143
144static inline void smc_outsl(unsigned int addr, void *vbuf, unsigned long len)
145{
146	volatile unsigned long	*rp;
147	unsigned long		*buf, *ebuf;
148
149	buf = (unsigned long *) vbuf;
150	rp = (volatile unsigned long *) addr;
151	for (ebuf = buf + len; (buf < ebuf); )
152		*rp = *buf++;
153}
154
155
156#ifdef CONFIG_NETtel
157/*
158 *	Re-map the address space of at least one of the SMC ethernet
159 *	parts. Both parts power up decoding the same address, so we
160 *	need to move one of them first, before doing enything else.
161 *
162 *	We also increase the number of wait states for this part by one.
163 */
164
165void smc_remap(unsigned int ioaddr)
166{
167	static int		once = 0;
168	extern unsigned short	ppdata;
169	if (once++ == 0) {
170		*((volatile unsigned short *)(MCF_MBAR+MCFSIM_PADDR)) = 0x00ec;
171		ppdata |= 0x0080;
172		*((volatile unsigned short *)(MCF_MBAR+MCFSIM_PADAT)) = ppdata;
173		outw(0x0001, ioaddr + BANK_SELECT);
174		outw(0x0001, ioaddr + BANK_SELECT);
175		outw(0x0067, ioaddr + BASE);
176
177		ppdata &= ~0x0080;
178		*((volatile unsigned short *)(MCF_MBAR+MCFSIM_PADAT)) = ppdata;
179	}
180
181	*((volatile unsigned short *)(MCF_MBAR+MCFSIM_CSCR3)) = 0x1180;
182}
183
184#endif
185
186/****************************************************************************/
187#endif	/* mcfsmc_h */
188