diff options
Diffstat (limited to 'arch/m32r/kernel/io_usrv.c')
| -rw-r--r-- | arch/m32r/kernel/io_usrv.c | 249 | 
1 files changed, 249 insertions, 0 deletions
diff --git a/arch/m32r/kernel/io_usrv.c b/arch/m32r/kernel/io_usrv.c new file mode 100644 index 00000000000..27928a0b99e --- /dev/null +++ b/arch/m32r/kernel/io_usrv.c @@ -0,0 +1,249 @@ +/* + *  linux/arch/m32r/kernel/io_usrv.c + * + *  Typical I/O routines for uServer board. + * + *  Copyright (c) 2001 - 2003  Hiroyuki Kondo, Hirokazu Takata, + *                             Hitoshi Yamamoto, Takeo Takahashi + * + *  This file is subject to the terms and conditions of the GNU General + *  Public License.  See the file "COPYING" in the main directory of this + *  archive for more details. + * + */ + +#include <linux/config.h> +#include <asm/m32r.h> +#include <asm/page.h> +#include <asm/io.h> + +#include <linux/types.h> +#include "../drivers/m32r_cfc.h" + +extern void pcc_ioread_byte(int, unsigned long, void *, size_t, size_t, int); +extern void pcc_ioread_word(int, unsigned long, void *, size_t, size_t, int); +extern void pcc_iowrite_byte(int, unsigned long, void *, size_t, size_t, int); +extern void pcc_iowrite_word(int, unsigned long, void *, size_t, size_t, int); +#define CFC_IOSTART	CFC_IOPORT_BASE +#define CFC_IOEND	(CFC_IOSTART + (M32R_PCC_MAPSIZE * M32R_MAX_PCC) - 1) + +#if defined(CONFIG_SERIAL_8250) || defined(CONFIG_SERIAL_8250_MODULE) +#define UART0_REGSTART		0x04c20000 +#define UART1_REGSTART		0x04c20100 +#define UART_IOMAP_SIZE		8 +#define UART0_IOSTART		0x3f8 +#define UART0_IOEND		(UART0_IOSTART + UART_IOMAP_SIZE - 1) +#define UART1_IOSTART		0x2f8 +#define UART1_IOEND		(UART1_IOSTART + UART_IOMAP_SIZE - 1) +#endif	/* CONFIG_SERIAL_8250 || CONFIG_SERIAL_8250_MODULE */ + +#define PORT2ADDR(port)	_port2addr(port) + +static __inline__ void *_port2addr(unsigned long port) +{ +#if defined(CONFIG_SERIAL_8250) || defined(CONFIG_SERIAL_8250_MODULE) +	if (port >= UART0_IOSTART && port <= UART0_IOEND) +		port = ((port - UART0_IOSTART) << 1) + UART0_REGSTART; +	else if (port >= UART1_IOSTART && port <= UART1_IOEND) +		port = ((port - UART1_IOSTART) << 1) + UART1_REGSTART; +#endif	/* CONFIG_SERIAL_8250 || CONFIG_SERIAL_8250_MODULE */ +	return (void *)(port + NONCACHE_OFFSET); +} + +static __inline__ void delay(void) +{ +	__asm__ __volatile__ ("push r0; \n\t pop r0;" : : :"memory"); +} + +unsigned char _inb(unsigned long port) +{ +	if (port >= CFC_IOSTART && port <= CFC_IOEND) { +		unsigned char b; +		pcc_ioread_byte(0, port, &b, sizeof(b), 1, 0); +		return b; +	} else +		return *(volatile unsigned char *)PORT2ADDR(port); +} + +unsigned short _inw(unsigned long port) +{ +	if (port >= CFC_IOSTART && port <= CFC_IOEND) { +		unsigned short w; +		pcc_ioread_word(0, port, &w, sizeof(w), 1, 0); +		return w; +	} else +		return *(volatile unsigned short *)PORT2ADDR(port); +} + +unsigned long _inl(unsigned long port) +{ +	if (port >= CFC_IOSTART && port <= CFC_IOEND) { +		unsigned long l; +		pcc_ioread_word(0, port, &l, sizeof(l), 1, 0); +		return l; +	} else +		return *(volatile unsigned long *)PORT2ADDR(port); +} + +unsigned char _inb_p(unsigned long port) +{ +	unsigned char b; + +	if (port >= CFC_IOSTART && port <= CFC_IOEND) { +		pcc_ioread_byte(0, port, &b, sizeof(b), 1, 0); +		return b; +	} else { +		b = *(volatile unsigned char *)PORT2ADDR(port); +		delay(); +		return b; +	} +} + +unsigned short _inw_p(unsigned long port) +{ +	unsigned short w; + +	if (port >= CFC_IOSTART && port <= CFC_IOEND) { +		pcc_ioread_word(0, port, &w, sizeof(w), 1, 0); +		return w; +	} else { +		w = *(volatile unsigned short *)PORT2ADDR(port); +		delay(); +		return w; +	} +} + +unsigned long _inl_p(unsigned long port) +{ +	unsigned long v; + +	v = *(volatile unsigned long *)PORT2ADDR(port); +	delay(); + +	return v; +} + +void _outb(unsigned char b, unsigned long port) +{ +	if (port >= CFC_IOSTART && port <= CFC_IOEND) +		pcc_iowrite_byte(0, port, &b, sizeof(b), 1, 0); +	else +		*(volatile unsigned char *)PORT2ADDR(port) = b; +} + +void _outw(unsigned short w, unsigned long port) +{ +	if (port >= CFC_IOSTART && port <= CFC_IOEND) +		pcc_iowrite_word(0, port, &w, sizeof(w), 1, 0); +	else +		*(volatile unsigned short *)PORT2ADDR(port) = w; +} + +void _outl(unsigned long l, unsigned long port) +{ +	if (port >= CFC_IOSTART && port <= CFC_IOEND) +		pcc_iowrite_word(0, port, &l, sizeof(l), 1, 0); +	else +		*(volatile unsigned long *)PORT2ADDR(port) = l; +} + +void _outb_p(unsigned char b, unsigned long port) +{ +	if (port >= CFC_IOSTART && port <= CFC_IOEND) +		pcc_iowrite_byte(0, port, &b, sizeof(b), 1, 0); +	else +		*(volatile unsigned char *)PORT2ADDR(port) = b; +	delay(); +} + +void _outw_p(unsigned short w, unsigned long port) +{ +	if (port >= CFC_IOSTART && port <= CFC_IOEND) +		pcc_iowrite_word(0, port, &w, sizeof(w), 1, 0); +	else +		*(volatile unsigned short *)PORT2ADDR(port) = w; +	delay(); +} + +void _outl_p(unsigned long l, unsigned long port) +{ +	*(volatile unsigned long *)PORT2ADDR(port) = l; +	delay(); +} + +void _insb(unsigned int port, void * addr, unsigned long count) +{ +	if (port >= CFC_IOSTART && port <= CFC_IOEND) +		pcc_ioread_byte(0, port, addr, sizeof(unsigned char), count, 1); +	else { +		unsigned char *buf = addr; +		unsigned char *portp = PORT2ADDR(port); +		while (count--) +			*buf++ = *(volatile unsigned char *)portp; +	} +} + +void _insw(unsigned int port, void * addr, unsigned long count) +{ +	unsigned short *buf = addr; +	unsigned short *portp; + +	if (port >= CFC_IOSTART && port <= CFC_IOEND) +		pcc_ioread_word(0, port, addr, sizeof(unsigned short), count, +			1); +	else { +		portp = PORT2ADDR(port); +		while (count--) +			*buf++ = *(volatile unsigned short *)portp; +	} +} + +void _insl(unsigned int port, void * addr, unsigned long count) +{ +	unsigned long *buf = addr; +	unsigned long *portp; + +	portp = PORT2ADDR(port); +	while (count--) +		*buf++ = *(volatile unsigned long *)portp; +} + +void _outsb(unsigned int port, const void * addr, unsigned long count) +{ +	const unsigned char *buf = addr; +	unsigned char *portp; + +	if (port >= CFC_IOSTART && port <= CFC_IOEND) +		pcc_iowrite_byte(0, port, (void *)addr, sizeof(unsigned char), +			count, 1); +	else { +		portp = PORT2ADDR(port); +		while (count--) +			*(volatile unsigned char *)portp = *buf++; +	} +} + +void _outsw(unsigned int port, const void * addr, unsigned long count) +{ +	const unsigned short *buf = addr; +	unsigned short *portp; + +	if (port >= CFC_IOSTART && port <= CFC_IOEND) +		pcc_iowrite_word(0, port, (void *)addr, sizeof(unsigned short), +			count, 1); +	else { +		portp = PORT2ADDR(port); +		while (count--) +			*(volatile unsigned short *)portp = *buf++; +	} +} + +void _outsl(unsigned int port, const void * addr, unsigned long count) +{ +	const unsigned long *buf = addr; +	unsigned char *portp; + +	portp = PORT2ADDR(port); +	while (count--) +		*(volatile unsigned long *)portp = *buf++; +}  |