1*da2014a2SPaul Mundt /* 2*da2014a2SPaul Mundt * linux/arch/sh/boards/superh/microdev/io.c 3*da2014a2SPaul Mundt * 4*da2014a2SPaul Mundt * Copyright (C) 2003 Sean McGoogan (Sean.McGoogan@superh.com) 5*da2014a2SPaul Mundt * Copyright (C) 2003, 2004 SuperH, Inc. 6*da2014a2SPaul Mundt * Copyright (C) 2004 Paul Mundt 7*da2014a2SPaul Mundt * 8*da2014a2SPaul Mundt * SuperH SH4-202 MicroDev board support. 9*da2014a2SPaul Mundt * 10*da2014a2SPaul Mundt * May be copied or modified under the terms of the GNU General Public 11*da2014a2SPaul Mundt * License. See linux/COPYING for more information. 12*da2014a2SPaul Mundt */ 13*da2014a2SPaul Mundt 14*da2014a2SPaul Mundt #include <linux/init.h> 15*da2014a2SPaul Mundt #include <linux/pci.h> 16*da2014a2SPaul Mundt #include <linux/wait.h> 17*da2014a2SPaul Mundt #include <asm/io.h> 18*da2014a2SPaul Mundt #include <asm/microdev.h> 19*da2014a2SPaul Mundt 20*da2014a2SPaul Mundt /* 21*da2014a2SPaul Mundt * we need to have a 'safe' address to re-direct all I/O requests 22*da2014a2SPaul Mundt * that we do not explicitly wish to handle. This safe address 23*da2014a2SPaul Mundt * must have the following properies: 24*da2014a2SPaul Mundt * 25*da2014a2SPaul Mundt * * writes are ignored (no exception) 26*da2014a2SPaul Mundt * * reads are benign (no side-effects) 27*da2014a2SPaul Mundt * * accesses of width 1, 2 and 4-bytes are all valid. 28*da2014a2SPaul Mundt * 29*da2014a2SPaul Mundt * The Processor Version Register (PVR) has these properties. 30*da2014a2SPaul Mundt */ 31*da2014a2SPaul Mundt #define PVR 0xff000030 /* Processor Version Register */ 32*da2014a2SPaul Mundt 33*da2014a2SPaul Mundt 34*da2014a2SPaul Mundt #define IO_IDE2_BASE 0x170ul /* I/O base for SMSC FDC37C93xAPM IDE #2 */ 35*da2014a2SPaul Mundt #define IO_IDE1_BASE 0x1f0ul /* I/O base for SMSC FDC37C93xAPM IDE #1 */ 36*da2014a2SPaul Mundt #define IO_ISP1161_BASE 0x290ul /* I/O port for Philips ISP1161x USB chip */ 37*da2014a2SPaul Mundt #define IO_SERIAL2_BASE 0x2f8ul /* I/O base for SMSC FDC37C93xAPM Serial #2 */ 38*da2014a2SPaul Mundt #define IO_LAN91C111_BASE 0x300ul /* I/O base for SMSC LAN91C111 Ethernet chip */ 39*da2014a2SPaul Mundt #define IO_IDE2_MISC 0x376ul /* I/O misc for SMSC FDC37C93xAPM IDE #2 */ 40*da2014a2SPaul Mundt #define IO_SUPERIO_BASE 0x3f0ul /* I/O base for SMSC FDC37C93xAPM SuperIO chip */ 41*da2014a2SPaul Mundt #define IO_IDE1_MISC 0x3f6ul /* I/O misc for SMSC FDC37C93xAPM IDE #1 */ 42*da2014a2SPaul Mundt #define IO_SERIAL1_BASE 0x3f8ul /* I/O base for SMSC FDC37C93xAPM Serial #1 */ 43*da2014a2SPaul Mundt 44*da2014a2SPaul Mundt #define IO_ISP1161_EXTENT 0x04ul /* I/O extent for Philips ISP1161x USB chip */ 45*da2014a2SPaul Mundt #define IO_LAN91C111_EXTENT 0x10ul /* I/O extent for SMSC LAN91C111 Ethernet chip */ 46*da2014a2SPaul Mundt #define IO_SUPERIO_EXTENT 0x02ul /* I/O extent for SMSC FDC37C93xAPM SuperIO chip */ 47*da2014a2SPaul Mundt #define IO_IDE_EXTENT 0x08ul /* I/O extent for IDE Task Register set */ 48*da2014a2SPaul Mundt #define IO_SERIAL_EXTENT 0x10ul 49*da2014a2SPaul Mundt 50*da2014a2SPaul Mundt #define IO_LAN91C111_PHYS 0xa7500000ul /* Physical address of SMSC LAN91C111 Ethernet chip */ 51*da2014a2SPaul Mundt #define IO_ISP1161_PHYS 0xa7700000ul /* Physical address of Philips ISP1161x USB chip */ 52*da2014a2SPaul Mundt #define IO_SUPERIO_PHYS 0xa7800000ul /* Physical address of SMSC FDC37C93xAPM SuperIO chip */ 53*da2014a2SPaul Mundt 54*da2014a2SPaul Mundt /* 55*da2014a2SPaul Mundt * map I/O ports to memory-mapped addresses 56*da2014a2SPaul Mundt */ 57*da2014a2SPaul Mundt static unsigned long microdev_isa_port2addr(unsigned long offset) 58*da2014a2SPaul Mundt { 59*da2014a2SPaul Mundt unsigned long result; 60*da2014a2SPaul Mundt 61*da2014a2SPaul Mundt if ((offset >= IO_LAN91C111_BASE) && 62*da2014a2SPaul Mundt (offset < IO_LAN91C111_BASE + IO_LAN91C111_EXTENT)) { 63*da2014a2SPaul Mundt /* 64*da2014a2SPaul Mundt * SMSC LAN91C111 Ethernet chip 65*da2014a2SPaul Mundt */ 66*da2014a2SPaul Mundt result = IO_LAN91C111_PHYS + offset - IO_LAN91C111_BASE; 67*da2014a2SPaul Mundt } else if ((offset >= IO_SUPERIO_BASE) && 68*da2014a2SPaul Mundt (offset < IO_SUPERIO_BASE + IO_SUPERIO_EXTENT)) { 69*da2014a2SPaul Mundt /* 70*da2014a2SPaul Mundt * SMSC FDC37C93xAPM SuperIO chip 71*da2014a2SPaul Mundt * 72*da2014a2SPaul Mundt * Configuration Registers 73*da2014a2SPaul Mundt */ 74*da2014a2SPaul Mundt result = IO_SUPERIO_PHYS + (offset << 1); 75*da2014a2SPaul Mundt #if 0 76*da2014a2SPaul Mundt } else if (offset == KBD_DATA_REG || offset == KBD_CNTL_REG || 77*da2014a2SPaul Mundt offset == KBD_STATUS_REG) { 78*da2014a2SPaul Mundt /* 79*da2014a2SPaul Mundt * SMSC FDC37C93xAPM SuperIO chip 80*da2014a2SPaul Mundt * 81*da2014a2SPaul Mundt * PS/2 Keyboard + Mouse (ports 0x60 and 0x64). 82*da2014a2SPaul Mundt */ 83*da2014a2SPaul Mundt result = IO_SUPERIO_PHYS + (offset << 1); 84*da2014a2SPaul Mundt #endif 85*da2014a2SPaul Mundt } else if (((offset >= IO_IDE1_BASE) && 86*da2014a2SPaul Mundt (offset < IO_IDE1_BASE + IO_IDE_EXTENT)) || 87*da2014a2SPaul Mundt (offset == IO_IDE1_MISC)) { 88*da2014a2SPaul Mundt /* 89*da2014a2SPaul Mundt * SMSC FDC37C93xAPM SuperIO chip 90*da2014a2SPaul Mundt * 91*da2014a2SPaul Mundt * IDE #1 92*da2014a2SPaul Mundt */ 93*da2014a2SPaul Mundt result = IO_SUPERIO_PHYS + (offset << 1); 94*da2014a2SPaul Mundt } else if (((offset >= IO_IDE2_BASE) && 95*da2014a2SPaul Mundt (offset < IO_IDE2_BASE + IO_IDE_EXTENT)) || 96*da2014a2SPaul Mundt (offset == IO_IDE2_MISC)) { 97*da2014a2SPaul Mundt /* 98*da2014a2SPaul Mundt * SMSC FDC37C93xAPM SuperIO chip 99*da2014a2SPaul Mundt * 100*da2014a2SPaul Mundt * IDE #2 101*da2014a2SPaul Mundt */ 102*da2014a2SPaul Mundt result = IO_SUPERIO_PHYS + (offset << 1); 103*da2014a2SPaul Mundt } else if ((offset >= IO_SERIAL1_BASE) && 104*da2014a2SPaul Mundt (offset < IO_SERIAL1_BASE + IO_SERIAL_EXTENT)) { 105*da2014a2SPaul Mundt /* 106*da2014a2SPaul Mundt * SMSC FDC37C93xAPM SuperIO chip 107*da2014a2SPaul Mundt * 108*da2014a2SPaul Mundt * Serial #1 109*da2014a2SPaul Mundt */ 110*da2014a2SPaul Mundt result = IO_SUPERIO_PHYS + (offset << 1); 111*da2014a2SPaul Mundt } else if ((offset >= IO_SERIAL2_BASE) && 112*da2014a2SPaul Mundt (offset < IO_SERIAL2_BASE + IO_SERIAL_EXTENT)) { 113*da2014a2SPaul Mundt /* 114*da2014a2SPaul Mundt * SMSC FDC37C93xAPM SuperIO chip 115*da2014a2SPaul Mundt * 116*da2014a2SPaul Mundt * Serial #2 117*da2014a2SPaul Mundt */ 118*da2014a2SPaul Mundt result = IO_SUPERIO_PHYS + (offset << 1); 119*da2014a2SPaul Mundt } else if ((offset >= IO_ISP1161_BASE) && 120*da2014a2SPaul Mundt (offset < IO_ISP1161_BASE + IO_ISP1161_EXTENT)) { 121*da2014a2SPaul Mundt /* 122*da2014a2SPaul Mundt * Philips USB ISP1161x chip 123*da2014a2SPaul Mundt */ 124*da2014a2SPaul Mundt result = IO_ISP1161_PHYS + offset - IO_ISP1161_BASE; 125*da2014a2SPaul Mundt } else { 126*da2014a2SPaul Mundt /* 127*da2014a2SPaul Mundt * safe default. 128*da2014a2SPaul Mundt */ 129*da2014a2SPaul Mundt printk("Warning: unexpected port in %s( offset = 0x%lx )\n", 130*da2014a2SPaul Mundt __func__, offset); 131*da2014a2SPaul Mundt result = PVR; 132*da2014a2SPaul Mundt } 133*da2014a2SPaul Mundt 134*da2014a2SPaul Mundt return result; 135*da2014a2SPaul Mundt } 136*da2014a2SPaul Mundt 137*da2014a2SPaul Mundt #define PORT2ADDR(x) (microdev_isa_port2addr(x)) 138*da2014a2SPaul Mundt 139*da2014a2SPaul Mundt static inline void delay(void) 140*da2014a2SPaul Mundt { 141*da2014a2SPaul Mundt #if defined(CONFIG_PCI) 142*da2014a2SPaul Mundt /* System board present, just make a dummy SRAM access. (CS0 will be 143*da2014a2SPaul Mundt mapped to PCI memory, probably good to avoid it.) */ 144*da2014a2SPaul Mundt ctrl_inw(0xa6800000); 145*da2014a2SPaul Mundt #else 146*da2014a2SPaul Mundt /* CS0 will be mapped to flash, ROM etc so safe to access it. */ 147*da2014a2SPaul Mundt ctrl_inw(0xa0000000); 148*da2014a2SPaul Mundt #endif 149*da2014a2SPaul Mundt } 150*da2014a2SPaul Mundt 151*da2014a2SPaul Mundt unsigned char microdev_inb(unsigned long port) 152*da2014a2SPaul Mundt { 153*da2014a2SPaul Mundt #ifdef CONFIG_PCI 154*da2014a2SPaul Mundt if (port >= PCIBIOS_MIN_IO) 155*da2014a2SPaul Mundt return microdev_pci_inb(port); 156*da2014a2SPaul Mundt #endif 157*da2014a2SPaul Mundt return *(volatile unsigned char*)PORT2ADDR(port); 158*da2014a2SPaul Mundt } 159*da2014a2SPaul Mundt 160*da2014a2SPaul Mundt unsigned short microdev_inw(unsigned long port) 161*da2014a2SPaul Mundt { 162*da2014a2SPaul Mundt #ifdef CONFIG_PCI 163*da2014a2SPaul Mundt if (port >= PCIBIOS_MIN_IO) 164*da2014a2SPaul Mundt return microdev_pci_inw(port); 165*da2014a2SPaul Mundt #endif 166*da2014a2SPaul Mundt return *(volatile unsigned short*)PORT2ADDR(port); 167*da2014a2SPaul Mundt } 168*da2014a2SPaul Mundt 169*da2014a2SPaul Mundt unsigned int microdev_inl(unsigned long port) 170*da2014a2SPaul Mundt { 171*da2014a2SPaul Mundt #ifdef CONFIG_PCI 172*da2014a2SPaul Mundt if (port >= PCIBIOS_MIN_IO) 173*da2014a2SPaul Mundt return microdev_pci_inl(port); 174*da2014a2SPaul Mundt #endif 175*da2014a2SPaul Mundt return *(volatile unsigned int*)PORT2ADDR(port); 176*da2014a2SPaul Mundt } 177*da2014a2SPaul Mundt 178*da2014a2SPaul Mundt void microdev_outw(unsigned short b, unsigned long port) 179*da2014a2SPaul Mundt { 180*da2014a2SPaul Mundt #ifdef CONFIG_PCI 181*da2014a2SPaul Mundt if (port >= PCIBIOS_MIN_IO) { 182*da2014a2SPaul Mundt microdev_pci_outw(b, port); 183*da2014a2SPaul Mundt return; 184*da2014a2SPaul Mundt } 185*da2014a2SPaul Mundt #endif 186*da2014a2SPaul Mundt *(volatile unsigned short*)PORT2ADDR(port) = b; 187*da2014a2SPaul Mundt } 188*da2014a2SPaul Mundt 189*da2014a2SPaul Mundt void microdev_outb(unsigned char b, unsigned long port) 190*da2014a2SPaul Mundt { 191*da2014a2SPaul Mundt #ifdef CONFIG_PCI 192*da2014a2SPaul Mundt if (port >= PCIBIOS_MIN_IO) { 193*da2014a2SPaul Mundt microdev_pci_outb(b, port); 194*da2014a2SPaul Mundt return; 195*da2014a2SPaul Mundt } 196*da2014a2SPaul Mundt #endif 197*da2014a2SPaul Mundt 198*da2014a2SPaul Mundt /* 199*da2014a2SPaul Mundt * There is a board feature with the current SH4-202 MicroDev in 200*da2014a2SPaul Mundt * that the 2 byte enables (nBE0 and nBE1) are tied together (and 201*da2014a2SPaul Mundt * to the Chip Select Line (Ethernet_CS)). Due to this connectivity, 202*da2014a2SPaul Mundt * it is not possible to safely perform 8-bit writes to the 203*da2014a2SPaul Mundt * Ethernet registers, as 16-bits will be consumed from the Data 204*da2014a2SPaul Mundt * lines (corrupting the other byte). Hence, this function is 205*da2014a2SPaul Mundt * written to implement 16-bit read/modify/write for all byte-wide 206*da2014a2SPaul Mundt * accesses. 207*da2014a2SPaul Mundt * 208*da2014a2SPaul Mundt * Note: there is no problem with byte READS (even or odd). 209*da2014a2SPaul Mundt * 210*da2014a2SPaul Mundt * Sean McGoogan - 16th June 2003. 211*da2014a2SPaul Mundt */ 212*da2014a2SPaul Mundt if ((port >= IO_LAN91C111_BASE) && 213*da2014a2SPaul Mundt (port < IO_LAN91C111_BASE + IO_LAN91C111_EXTENT)) { 214*da2014a2SPaul Mundt /* 215*da2014a2SPaul Mundt * Then are trying to perform a byte-write to the 216*da2014a2SPaul Mundt * LAN91C111. This needs special care. 217*da2014a2SPaul Mundt */ 218*da2014a2SPaul Mundt if (port % 2 == 1) { /* is the port odd ? */ 219*da2014a2SPaul Mundt /* unset bit-0, i.e. make even */ 220*da2014a2SPaul Mundt const unsigned long evenPort = port-1; 221*da2014a2SPaul Mundt unsigned short word; 222*da2014a2SPaul Mundt 223*da2014a2SPaul Mundt /* 224*da2014a2SPaul Mundt * do a 16-bit read/write to write to 'port', 225*da2014a2SPaul Mundt * preserving even byte. 226*da2014a2SPaul Mundt * 227*da2014a2SPaul Mundt * Even addresses are bits 0-7 228*da2014a2SPaul Mundt * Odd addresses are bits 8-15 229*da2014a2SPaul Mundt */ 230*da2014a2SPaul Mundt word = microdev_inw(evenPort); 231*da2014a2SPaul Mundt word = (word & 0xffu) | (b << 8); 232*da2014a2SPaul Mundt microdev_outw(word, evenPort); 233*da2014a2SPaul Mundt } else { 234*da2014a2SPaul Mundt /* else, we are trying to do an even byte write */ 235*da2014a2SPaul Mundt unsigned short word; 236*da2014a2SPaul Mundt 237*da2014a2SPaul Mundt /* 238*da2014a2SPaul Mundt * do a 16-bit read/write to write to 'port', 239*da2014a2SPaul Mundt * preserving odd byte. 240*da2014a2SPaul Mundt * 241*da2014a2SPaul Mundt * Even addresses are bits 0-7 242*da2014a2SPaul Mundt * Odd addresses are bits 8-15 243*da2014a2SPaul Mundt */ 244*da2014a2SPaul Mundt word = microdev_inw(port); 245*da2014a2SPaul Mundt word = (word & 0xff00u) | (b); 246*da2014a2SPaul Mundt microdev_outw(word, port); 247*da2014a2SPaul Mundt } 248*da2014a2SPaul Mundt } else { 249*da2014a2SPaul Mundt *(volatile unsigned char*)PORT2ADDR(port) = b; 250*da2014a2SPaul Mundt } 251*da2014a2SPaul Mundt } 252*da2014a2SPaul Mundt 253*da2014a2SPaul Mundt void microdev_outl(unsigned int b, unsigned long port) 254*da2014a2SPaul Mundt { 255*da2014a2SPaul Mundt #ifdef CONFIG_PCI 256*da2014a2SPaul Mundt if (port >= PCIBIOS_MIN_IO) { 257*da2014a2SPaul Mundt microdev_pci_outl(b, port); 258*da2014a2SPaul Mundt return; 259*da2014a2SPaul Mundt } 260*da2014a2SPaul Mundt #endif 261*da2014a2SPaul Mundt *(volatile unsigned int*)PORT2ADDR(port) = b; 262*da2014a2SPaul Mundt } 263*da2014a2SPaul Mundt 264*da2014a2SPaul Mundt unsigned char microdev_inb_p(unsigned long port) 265*da2014a2SPaul Mundt { 266*da2014a2SPaul Mundt unsigned char v = microdev_inb(port); 267*da2014a2SPaul Mundt delay(); 268*da2014a2SPaul Mundt return v; 269*da2014a2SPaul Mundt } 270*da2014a2SPaul Mundt 271*da2014a2SPaul Mundt unsigned short microdev_inw_p(unsigned long port) 272*da2014a2SPaul Mundt { 273*da2014a2SPaul Mundt unsigned short v = microdev_inw(port); 274*da2014a2SPaul Mundt delay(); 275*da2014a2SPaul Mundt return v; 276*da2014a2SPaul Mundt } 277*da2014a2SPaul Mundt 278*da2014a2SPaul Mundt unsigned int microdev_inl_p(unsigned long port) 279*da2014a2SPaul Mundt { 280*da2014a2SPaul Mundt unsigned int v = microdev_inl(port); 281*da2014a2SPaul Mundt delay(); 282*da2014a2SPaul Mundt return v; 283*da2014a2SPaul Mundt } 284*da2014a2SPaul Mundt 285*da2014a2SPaul Mundt void microdev_outb_p(unsigned char b, unsigned long port) 286*da2014a2SPaul Mundt { 287*da2014a2SPaul Mundt microdev_outb(b, port); 288*da2014a2SPaul Mundt delay(); 289*da2014a2SPaul Mundt } 290*da2014a2SPaul Mundt 291*da2014a2SPaul Mundt void microdev_outw_p(unsigned short b, unsigned long port) 292*da2014a2SPaul Mundt { 293*da2014a2SPaul Mundt microdev_outw(b, port); 294*da2014a2SPaul Mundt delay(); 295*da2014a2SPaul Mundt } 296*da2014a2SPaul Mundt 297*da2014a2SPaul Mundt void microdev_outl_p(unsigned int b, unsigned long port) 298*da2014a2SPaul Mundt { 299*da2014a2SPaul Mundt microdev_outl(b, port); 300*da2014a2SPaul Mundt delay(); 301*da2014a2SPaul Mundt } 302*da2014a2SPaul Mundt 303*da2014a2SPaul Mundt void microdev_insb(unsigned long port, void *buffer, unsigned long count) 304*da2014a2SPaul Mundt { 305*da2014a2SPaul Mundt volatile unsigned char *port_addr; 306*da2014a2SPaul Mundt unsigned char *buf = buffer; 307*da2014a2SPaul Mundt 308*da2014a2SPaul Mundt port_addr = (volatile unsigned char *)PORT2ADDR(port); 309*da2014a2SPaul Mundt 310*da2014a2SPaul Mundt while (count--) 311*da2014a2SPaul Mundt *buf++ = *port_addr; 312*da2014a2SPaul Mundt } 313*da2014a2SPaul Mundt 314*da2014a2SPaul Mundt void microdev_insw(unsigned long port, void *buffer, unsigned long count) 315*da2014a2SPaul Mundt { 316*da2014a2SPaul Mundt volatile unsigned short *port_addr; 317*da2014a2SPaul Mundt unsigned short *buf = buffer; 318*da2014a2SPaul Mundt 319*da2014a2SPaul Mundt port_addr = (volatile unsigned short *)PORT2ADDR(port); 320*da2014a2SPaul Mundt 321*da2014a2SPaul Mundt while (count--) 322*da2014a2SPaul Mundt *buf++ = *port_addr; 323*da2014a2SPaul Mundt } 324*da2014a2SPaul Mundt 325*da2014a2SPaul Mundt void microdev_insl(unsigned long port, void *buffer, unsigned long count) 326*da2014a2SPaul Mundt { 327*da2014a2SPaul Mundt volatile unsigned long *port_addr; 328*da2014a2SPaul Mundt unsigned int *buf = buffer; 329*da2014a2SPaul Mundt 330*da2014a2SPaul Mundt port_addr = (volatile unsigned long *)PORT2ADDR(port); 331*da2014a2SPaul Mundt 332*da2014a2SPaul Mundt while (count--) 333*da2014a2SPaul Mundt *buf++ = *port_addr; 334*da2014a2SPaul Mundt } 335*da2014a2SPaul Mundt 336*da2014a2SPaul Mundt void microdev_outsb(unsigned long port, const void *buffer, unsigned long count) 337*da2014a2SPaul Mundt { 338*da2014a2SPaul Mundt volatile unsigned char *port_addr; 339*da2014a2SPaul Mundt const unsigned char *buf = buffer; 340*da2014a2SPaul Mundt 341*da2014a2SPaul Mundt port_addr = (volatile unsigned char *)PORT2ADDR(port); 342*da2014a2SPaul Mundt 343*da2014a2SPaul Mundt while (count--) 344*da2014a2SPaul Mundt *port_addr = *buf++; 345*da2014a2SPaul Mundt } 346*da2014a2SPaul Mundt 347*da2014a2SPaul Mundt void microdev_outsw(unsigned long port, const void *buffer, unsigned long count) 348*da2014a2SPaul Mundt { 349*da2014a2SPaul Mundt volatile unsigned short *port_addr; 350*da2014a2SPaul Mundt const unsigned short *buf = buffer; 351*da2014a2SPaul Mundt 352*da2014a2SPaul Mundt port_addr = (volatile unsigned short *)PORT2ADDR(port); 353*da2014a2SPaul Mundt 354*da2014a2SPaul Mundt while (count--) 355*da2014a2SPaul Mundt *port_addr = *buf++; 356*da2014a2SPaul Mundt } 357*da2014a2SPaul Mundt 358*da2014a2SPaul Mundt void microdev_outsl(unsigned long port, const void *buffer, unsigned long count) 359*da2014a2SPaul Mundt { 360*da2014a2SPaul Mundt volatile unsigned long *port_addr; 361*da2014a2SPaul Mundt const unsigned int *buf = buffer; 362*da2014a2SPaul Mundt 363*da2014a2SPaul Mundt port_addr = (volatile unsigned long *)PORT2ADDR(port); 364*da2014a2SPaul Mundt 365*da2014a2SPaul Mundt while (count--) 366*da2014a2SPaul Mundt *port_addr = *buf++; 367*da2014a2SPaul Mundt } 368