diff options
Diffstat (limited to 'arch/m32r/kernel')
| -rw-r--r-- | arch/m32r/kernel/Makefile | 1 | ||||
| -rw-r--r-- | arch/m32r/kernel/entry.S | 17 | ||||
| -rw-r--r-- | arch/m32r/kernel/io_m32104ut.c | 298 | ||||
| -rw-r--r-- | arch/m32r/kernel/setup.c | 7 | ||||
| -rw-r--r-- | arch/m32r/kernel/setup_m32104ut.c | 162 | ||||
| -rw-r--r-- | arch/m32r/kernel/time.c | 4 | 
6 files changed, 484 insertions, 5 deletions
diff --git a/arch/m32r/kernel/Makefile b/arch/m32r/kernel/Makefile index 6c6b6c37663..5a2fa886906 100644 --- a/arch/m32r/kernel/Makefile +++ b/arch/m32r/kernel/Makefile @@ -16,5 +16,6 @@ obj-$(CONFIG_PLAT_M32700UT)	+= setup_m32700ut.o io_m32700ut.o  obj-$(CONFIG_PLAT_OPSPUT)	+= setup_opsput.o io_opsput.o  obj-$(CONFIG_MODULES)		+= module.o  obj-$(CONFIG_PLAT_OAKS32R)	+= setup_oaks32r.o io_oaks32r.o +obj-$(CONFIG_PLAT_M32104UT)	+= setup_m32104ut.o io_m32104ut.o  EXTRA_AFLAGS	:= -traditional diff --git a/arch/m32r/kernel/entry.S b/arch/m32r/kernel/entry.S index f6d4a5821a2..3871b65f0c8 100644 --- a/arch/m32r/kernel/entry.S +++ b/arch/m32r/kernel/entry.S @@ -315,7 +315,7 @@ ENTRY(ei_handler)  	mv	r1, sp			; arg1(regs)  #if defined(CONFIG_CHIP_VDEC2) || defined(CONFIG_CHIP_XNUX2) \  	|| defined(CONFIG_CHIP_M32700) || defined(CONFIG_CHIP_M32102) \ -	|| defined(CONFIG_CHIP_OPSP) +	|| defined(CONFIG_CHIP_OPSP) || defined(CONFIG_CHIP_M32104)  ;    GET_ICU_STATUS;  	seth	r0, #shigh(M32R_ICU_ISTS_ADDR) @@ -541,7 +541,20 @@ check_int2:  	bra	check_end  	.fillinsn  check_end: -#endif  /* CONFIG_PLAT_OPSPUT */ +#elif defined(CONFIG_PLAT_M32104UT) +	add3	r2, r0, #-(M32R_IRQ_INT1)       ; INT1# interrupt +	bnez	r2, check_end +	; read ICU status register of PLD +	seth	r0, #high(PLD_ICUISTS) +	or3	r0, r0, #low(PLD_ICUISTS) +	lduh	r0, @r0 +	slli	r0, #21 +	srli	r0, #27                         ; ISN +	addi	r0, #(M32104UT_PLD_IRQ_BASE) +	bra	check_end +	.fillinsn +check_end: +#endif  /* CONFIG_PLAT_M32104UT */  	bl	do_IRQ  #endif  /* CONFIG_SMP */  	ld	r14, @sp+ diff --git a/arch/m32r/kernel/io_m32104ut.c b/arch/m32r/kernel/io_m32104ut.c new file mode 100644 index 00000000000..3df4215f164 --- /dev/null +++ b/arch/m32r/kernel/io_m32104ut.c @@ -0,0 +1,298 @@ +/* + *  linux/arch/m32r/kernel/io_m32104ut.c + * + *  Typical I/O routines for M32104UT board. + * + *  Copyright (c) 2001-2005  Hiroyuki Kondo, Hirokazu Takata, + *                           Hitoshi Yamamoto, Mamoru Sakugawa, + *                           Naoto Sugai, Hayato Fujiwara + */ + +#include <linux/config.h> +#include <asm/m32r.h> +#include <asm/page.h> +#include <asm/io.h> +#include <asm/byteorder.h> + +#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC) +#include <linux/types.h> + +#define M32R_PCC_IOMAP_SIZE 0x1000 + +#define M32R_PCC_IOSTART0 0x1000 +#define M32R_PCC_IOEND0   (M32R_PCC_IOSTART0 + M32R_PCC_IOMAP_SIZE - 1) + +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); +#endif /* CONFIG_PCMCIA && CONFIG_M32R_CFC */ + +#define PORT2ADDR(port)  _port2addr(port) + +static inline void *_port2addr(unsigned long port) +{ +	return (void *)(port + NONCACHE_OFFSET); +} + +#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC) +static inline void *__port2addr_ata(unsigned long port) +{ +	static int	dummy_reg; + +	switch (port) { +	case 0x1f0:	return (void *)0xac002000; +	case 0x1f1:	return (void *)0xac012800; +	case 0x1f2:	return (void *)0xac012002; +	case 0x1f3:	return (void *)0xac012802; +	case 0x1f4:	return (void *)0xac012004; +	case 0x1f5:	return (void *)0xac012804; +	case 0x1f6:	return (void *)0xac012006; +	case 0x1f7:	return (void *)0xac012806; +	case 0x3f6:	return (void *)0xac01200e; +	default: 	return (void *)&dummy_reg; +	} +} +#endif + +/* + * M32104T-LAN is located in the extended bus space + * from 0x01000000 to 0x01ffffff on physical address. + * The base address of LAN controller(LAN91C111) is 0x300. + */ +#define LAN_IOSTART	0x300 +#define LAN_IOEND	0x320 +static inline void *_port2addr_ne(unsigned long port) +{ +	return (void *)(port + NONCACHE_OFFSET + 0x01000000); +} + +static inline void delay(void) +{ +	__asm__ __volatile__ ("push r0; \n\t pop r0;" : : :"memory"); +} + +/* + * NIC I/O function + */ + +#define PORT2ADDR_NE(port)  _port2addr_ne(port) + +static inline unsigned char _ne_inb(void *portp) +{ +	return *(volatile unsigned char *)portp; +} + +static inline unsigned short _ne_inw(void *portp) +{ +	return (unsigned short)le16_to_cpu(*(volatile unsigned short *)portp); +} + +static inline void _ne_insb(void *portp, void *addr, unsigned long count) +{ +	unsigned char *buf = (unsigned char *)addr; + +	while (count--) +		*buf++ = _ne_inb(portp); +} + +static inline void _ne_outb(unsigned char b, void *portp) +{ +	*(volatile unsigned char *)portp = b; +} + +static inline void _ne_outw(unsigned short w, void *portp) +{ +	*(volatile unsigned short *)portp = cpu_to_le16(w); +} + +unsigned char _inb(unsigned long port) +{ +	if (port >= LAN_IOSTART && port < LAN_IOEND) +		return _ne_inb(PORT2ADDR_NE(port)); + +	return *(volatile unsigned char *)PORT2ADDR(port); +} + +unsigned short _inw(unsigned long port) +{ +	if (port >= LAN_IOSTART && port < LAN_IOEND) +		return _ne_inw(PORT2ADDR_NE(port)); + +	return *(volatile unsigned short *)PORT2ADDR(port); +} + +unsigned long _inl(unsigned long port) +{ +	return *(volatile unsigned long *)PORT2ADDR(port); +} + +unsigned char _inb_p(unsigned long port) +{ +	unsigned char v = _inb(port); +	delay(); +	return (v); +} + +unsigned short _inw_p(unsigned long port) +{ +	unsigned short v = _inw(port); +	delay(); +	return (v); +} + +unsigned long _inl_p(unsigned long port) +{ +	unsigned long v = _inl(port); +	delay(); +	return (v); +} + +void _outb(unsigned char b, unsigned long port) +{ +	if (port >= LAN_IOSTART && port < LAN_IOEND) +		_ne_outb(b, PORT2ADDR_NE(port)); +	else +		*(volatile unsigned char *)PORT2ADDR(port) = b; +} + +void _outw(unsigned short w, unsigned long port) +{ +	if (port >= LAN_IOSTART && port < LAN_IOEND) +		_ne_outw(w, PORT2ADDR_NE(port)); +	else +		*(volatile unsigned short *)PORT2ADDR(port) = w; +} + +void _outl(unsigned long l, unsigned long port) +{ +	*(volatile unsigned long *)PORT2ADDR(port) = l; +} + +void _outb_p(unsigned char b, unsigned long port) +{ +	_outb(b, port); +	delay(); +} + +void _outw_p(unsigned short w, unsigned long port) +{ +	_outw(w, port); +	delay(); +} + +void _outl_p(unsigned long l, unsigned long port) +{ +	_outl(l, port); +	delay(); +} + +void _insb(unsigned int port, void *addr, unsigned long count) +{ +	if (port >= LAN_IOSTART && port < LAN_IOEND) +		_ne_insb(PORT2ADDR_NE(port), addr, count); +	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 >= LAN_IOSTART && port < LAN_IOEND) { +		/* +		 * This portion is only used by smc91111.c to read data +		 * from the DATA_REG. Do not swap the data. +		 */ +		portp = PORT2ADDR_NE(port); +		while (count--) +			*buf++ = *(volatile unsigned short *)portp; +#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC) +	} else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { +		pcc_ioread_word(9, port, (void *)addr, sizeof(unsigned short), +				count, 1); +#endif +#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC) +	} else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) { +		portp = __port2addr_ata(port); +		while (count--) +			*buf++ = *(volatile unsigned short *)portp; +#endif +	} 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 >= LAN_IOSTART && port < LAN_IOEND) { +		portp = PORT2ADDR_NE(port); +		while (count--) +			_ne_outb(*buf++, portp); +	} 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 >= LAN_IOSTART && port < LAN_IOEND) { +		/* +		 * This portion is only used by smc91111.c to write data +		 * into the DATA_REG. Do not swap the data. +		 */ +		portp = PORT2ADDR_NE(port); +		while (count--) +			*(volatile unsigned short *)portp = *buf++; +#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC) +	} else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) { +		portp = __port2addr_ata(port); +		while (count--) +			*(volatile unsigned short *)portp = *buf++; +#endif +#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC) +	} else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { +		pcc_iowrite_word(9, port, (void *)addr, sizeof(unsigned short), +				 count, 1); +#endif +	} 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++; +} diff --git a/arch/m32r/kernel/setup.c b/arch/m32r/kernel/setup.c index f722ec8eb02..c2e4dccf011 100644 --- a/arch/m32r/kernel/setup.c +++ b/arch/m32r/kernel/setup.c @@ -320,6 +320,9 @@ static int show_cpuinfo(struct seq_file *m, void *v)  #elif defined(CONFIG_CHIP_MP)  	seq_printf(m, "cpu family\t: M32R-MP\n"  		"cache size\t: I-xxKB/D-xxKB\n"); +#elif  defined(CONFIG_CHIP_M32104) +	seq_printf(m,"cpu family\t: M32104\n" +		"cache size\t: I-8KB/D-8KB\n");  #else  	seq_printf(m, "cpu family\t: Unknown\n");  #endif @@ -340,6 +343,8 @@ static int show_cpuinfo(struct seq_file *m, void *v)  	seq_printf(m, "Machine\t\t: uServer\n");  #elif defined(CONFIG_PLAT_OAKS32R)  	seq_printf(m, "Machine\t\t: OAKS32R\n"); +#elif  defined(CONFIG_PLAT_M32104UT) +	seq_printf(m, "Machine\t\t: M3T-M32104UT uT Engine board\n");  #else  	seq_printf(m, "Machine\t\t: Unknown\n");  #endif @@ -389,7 +394,7 @@ unsigned long cpu_initialized __initdata = 0;   */  #if defined(CONFIG_CHIP_VDEC2) || defined(CONFIG_CHIP_XNUX2)	\  	|| defined(CONFIG_CHIP_M32700) || defined(CONFIG_CHIP_M32102) \ -	|| defined(CONFIG_CHIP_OPSP) +	|| defined(CONFIG_CHIP_OPSP) || defined(CONFIG_CHIP_M32104)  void __init cpu_init (void)  {  	int cpu_id = smp_processor_id(); diff --git a/arch/m32r/kernel/setup_m32104ut.c b/arch/m32r/kernel/setup_m32104ut.c new file mode 100644 index 00000000000..ab16c664609 --- /dev/null +++ b/arch/m32r/kernel/setup_m32104ut.c @@ -0,0 +1,162 @@ +/* + *  linux/arch/m32r/kernel/setup_m32104ut.c + * + *  Setup routines for M32104UT Board + * + *  Copyright (c) 2002-2005  Hiroyuki Kondo, Hirokazu Takata, + *                           Hitoshi Yamamoto, Mamoru Sakugawa, + *                           Naoto Sugai, Hayato Fujiwara + */ + +#include <linux/config.h> +#include <linux/irq.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/device.h> + +#include <asm/system.h> +#include <asm/m32r.h> +#include <asm/io.h> + +#define irq2port(x) (M32R_ICU_CR1_PORTL + ((x - 1) * sizeof(unsigned long))) + +#ifndef CONFIG_SMP +typedef struct { +	unsigned long icucr;  /* ICU Control Register */ +} icu_data_t; +#endif /* CONFIG_SMP */ + +icu_data_t icu_data[NR_IRQS]; + +static void disable_m32104ut_irq(unsigned int irq) +{ +	unsigned long port, data; + +	port = irq2port(irq); +	data = icu_data[irq].icucr|M32R_ICUCR_ILEVEL7; +	outl(data, port); +} + +static void enable_m32104ut_irq(unsigned int irq) +{ +	unsigned long port, data; + +	port = irq2port(irq); +	data = icu_data[irq].icucr|M32R_ICUCR_IEN|M32R_ICUCR_ILEVEL6; +	outl(data, port); +} + +static void mask_and_ack_m32104ut(unsigned int irq) +{ +	disable_m32104ut_irq(irq); +} + +static void end_m32104ut_irq(unsigned int irq) +{ +	enable_m32104ut_irq(irq); +} + +static unsigned int startup_m32104ut_irq(unsigned int irq) +{ +	enable_m32104ut_irq(irq); +	return (0); +} + +static void shutdown_m32104ut_irq(unsigned int irq) +{ +	unsigned long port; + +	port = irq2port(irq); +	outl(M32R_ICUCR_ILEVEL7, port); +} + +static struct hw_interrupt_type m32104ut_irq_type = +{ +	.typename = "M32104UT-IRQ", +	.startup = startup_m32104ut_irq, +	.shutdown = shutdown_m32104ut_irq, +	.enable = enable_m32104ut_irq, +	.disable = disable_m32104ut_irq, +	.ack = mask_and_ack_m32104ut, +	.end = end_m32104ut_irq +}; + +void __init init_IRQ(void) +{ +	static int once = 0; + +	if (once) +		return; +	else +		once++; + +#if defined(CONFIG_SMC91X) +	/* INT#0: LAN controller on M32104UT-LAN (SMC91C111)*/ +	irq_desc[M32R_IRQ_INT0].status = IRQ_DISABLED; +	irq_desc[M32R_IRQ_INT0].handler = &m32104ut_irq_type; +	irq_desc[M32R_IRQ_INT0].action = 0; +	irq_desc[M32R_IRQ_INT0].depth = 1; +	icu_data[M32R_IRQ_INT0].icucr = M32R_ICUCR_IEN | M32R_ICUCR_ISMOD11; /* "H" level sense */ +	disable_m32104ut_irq(M32R_IRQ_INT0); +#endif  /* CONFIG_SMC91X */ + +	/* MFT2 : system timer */ +	irq_desc[M32R_IRQ_MFT2].status = IRQ_DISABLED; +	irq_desc[M32R_IRQ_MFT2].handler = &m32104ut_irq_type; +	irq_desc[M32R_IRQ_MFT2].action = 0; +	irq_desc[M32R_IRQ_MFT2].depth = 1; +	icu_data[M32R_IRQ_MFT2].icucr = M32R_ICUCR_IEN; +	disable_m32104ut_irq(M32R_IRQ_MFT2); + +#ifdef CONFIG_SERIAL_M32R_SIO +	/* SIO0_R : uart receive data */ +	irq_desc[M32R_IRQ_SIO0_R].status = IRQ_DISABLED; +	irq_desc[M32R_IRQ_SIO0_R].handler = &m32104ut_irq_type; +	irq_desc[M32R_IRQ_SIO0_R].action = 0; +	irq_desc[M32R_IRQ_SIO0_R].depth = 1; +	icu_data[M32R_IRQ_SIO0_R].icucr = M32R_ICUCR_IEN; +	disable_m32104ut_irq(M32R_IRQ_SIO0_R); + +	/* SIO0_S : uart send data */ +	irq_desc[M32R_IRQ_SIO0_S].status = IRQ_DISABLED; +	irq_desc[M32R_IRQ_SIO0_S].handler = &m32104ut_irq_type; +	irq_desc[M32R_IRQ_SIO0_S].action = 0; +	irq_desc[M32R_IRQ_SIO0_S].depth = 1; +	icu_data[M32R_IRQ_SIO0_S].icucr = M32R_ICUCR_IEN; +	disable_m32104ut_irq(M32R_IRQ_SIO0_S); +#endif /* CONFIG_SERIAL_M32R_SIO */ +} + +#if defined(CONFIG_SMC91X) + +#define LAN_IOSTART     0x300 +#define LAN_IOEND       0x320 +static struct resource smc91x_resources[] = { +	[0] = { +		.start  = (LAN_IOSTART), +		.end    = (LAN_IOEND), +		.flags  = IORESOURCE_MEM, +	}, +	[1] = { +		.start  = M32R_IRQ_INT0, +		.end    = M32R_IRQ_INT0, +		.flags  = IORESOURCE_IRQ, +	} +}; + +static struct platform_device smc91x_device = { +	.name		= "smc91x", +	.id		= 0, +	.num_resources  = ARRAY_SIZE(smc91x_resources), +	.resource       = smc91x_resources, +}; +#endif + +static int __init platform_init(void) +{ +#if defined(CONFIG_SMC91X) +	platform_device_register(&smc91x_device); +#endif +	return 0; +} +arch_initcall(platform_init); diff --git a/arch/m32r/kernel/time.c b/arch/m32r/kernel/time.c index 2ebce2063fe..b8e68b54230 100644 --- a/arch/m32r/kernel/time.c +++ b/arch/m32r/kernel/time.c @@ -57,7 +57,7 @@ static unsigned long do_gettimeoffset(void)  #if defined(CONFIG_CHIP_M32102) || defined(CONFIG_CHIP_XNUX2) \  	|| defined(CONFIG_CHIP_VDEC2) || defined(CONFIG_CHIP_M32700) \ -	|| defined(CONFIG_CHIP_OPSP) +	|| defined(CONFIG_CHIP_OPSP) || defined(CONFIG_CHIP_M32104)  #ifndef CONFIG_SMP  	unsigned long count; @@ -268,7 +268,7 @@ void __init time_init(void)  #if defined(CONFIG_CHIP_M32102) || defined(CONFIG_CHIP_XNUX2) \  	|| defined(CONFIG_CHIP_VDEC2) || defined(CONFIG_CHIP_M32700) \ -	|| defined(CONFIG_CHIP_OPSP) +	|| defined(CONFIG_CHIP_OPSP) || defined(CONFIG_CHIP_M32104)  	/* M32102 MFT setup */  	setup_irq(M32R_IRQ_MFT2, &irq0);  |