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