|
From: NIIBE Y. <gn...@ch...> - 2000-05-03 02:19:38
|
Here is new I/O support. I'm about to connect IDE disk to
SolutionEngine on my desk. I'll commit this soon.
2000-05-03 NIIBE Yutaka <gn...@m1...>
* arch/sh/config.in (CONFIG_IOPORT_START): New CONFIG variable.
(CONFIG_CF_ENABLER): Conditionalize it (Not for SolutionEngine).
* include/asm-sh/ide.h (ide_default_irq, ide_default_io_base):
Use PORT, instead of ADDR.
* include/asm-sh/io.h (inb_local, outb_local): Removed.
(inb,inw,inl,insb,insw,insl,outb,outw,outl,outsb,outsw,outsl):
Make them real function.
(sh_isa_slot,isa_readb,isa_readw,isa_readl,isa_writeb,
isa_writew,isa_writel,isa_memset_io,isa_memcpy_fromio): Added.
SolutionEngine support.
* include/asm-sh/smc37c93x.h: New file by Kazumoto Kojima.
* arch/sh/kernel/setup_se.c: New file by Kazumoto Kojima.
* include/asm-sh/hitachi_se.h: Ditto.
* arch/sh/kernel/Makefile (O_OBJS): Added irq_ipr.o, removing
irq_onchip.c. Added setup_se.c.
Index: arch/sh/config.in
===================================================================
RCS file: /cvsroot/linuxsh/kernel/arch/sh/config.in,v
retrieving revision 1.3
diff -u -r1.3 config.in
--- arch/sh/config.in 2000/04/14 17:56:34 1.3
+++ arch/sh/config.in 2000/05/03 02:01:51
@@ -15,6 +15,10 @@
mainmenu_option next_comment
comment 'Processor type and features'
+choice 'SuperH system type' \
+ "Generic CONFIG_SH_GENERIC \
+ SolutionEngine CONFIG_SH_SOLUTION_ENGINE" Generic
+
choice 'Processor type' \
"SH7708 CONFIG_CPU_SUBTYPE_SH7708 \
SH7709 CONFIG_CPU_SUBTYPE_SH7709 \
@@ -32,7 +36,12 @@
define_bool CONFIG_CPU_SH4 y
fi
bool 'Little Endian' CONFIG_LITTLE_ENDIAN
-hex 'Physical memory start address' CONFIG_MEMORY_START 08000000
+if [ "$CONFIG_SH_SOLUTION_ENGINE" = "y" ]; then
+ define_hex CONFIG_MEMORY_START 0c000000
+else
+ hex 'Physical memory start address' CONFIG_MEMORY_START 08000000
+ hex 'I/O port offset address' CONFIG_IOPORT_START ba000000
+fi
endmenu
mainmenu_option next_comment
@@ -52,7 +61,9 @@
bool 'Networking support' CONFIG_NET
-bool 'Directy Connected Compact Flash support' CONFIG_CF_ENABLER
+if [ "$CONFIG_SH_SOLUTION_ENGINE" != "y" ]; then
+ bool 'Directy Connected Compact Flash support' CONFIG_CF_ENABLER
+fi
bool 'PCI support' CONFIG_PCI
if [ "$CONFIG_PCI" = "y" ]; then
Index: arch/sh/kernel/Makefile
===================================================================
RCS file: /cvsroot/linuxsh/kernel/arch/sh/kernel/Makefile,v
retrieving revision 1.2
diff -u -r1.2 Makefile
--- arch/sh/kernel/Makefile 2000/04/14 19:14:01 1.2
+++ arch/sh/kernel/Makefile 2000/05/03 02:01:51
@@ -10,7 +10,7 @@
$(CC) $(AFLAGS) -traditional -c $< -o $*.o
O_TARGET := kernel.o
-O_OBJS := process.o signal.o entry.o traps.o irq.o irq_onchip.o \
+O_OBJS := process.o signal.o entry.o traps.o irq.o irq_ipr.o \
ptrace.o setup.o time.o sys_sh.o semaphore.o pci-sh.o \
irq_imask.o
OX_OBJS := sh_ksyms.o
@@ -18,6 +18,14 @@
ifdef CONFIG_CF_ENABLER
O_OBJS += cf-enabler.o
+endif
+
+ifdef CONFIG_SH_GENERIC
+O_OBJS += io_generic.o
+endif
+
+ifdef CONFIG_SH_SOLUTION_ENGINE
+O_OBJS += setup_se.o io_se.o
endif
ifdef CONFIG_CPU_SH4
Index: arch/sh/kernel/io_generic.c
===================================================================
RCS file: io_generic.c
diff -N io_generic.c
--- /dev/null Tue May 5 13:32:27 1998
+++ io_generic.c Tue May 2 19:01:51 2000
@@ -0,0 +1,77 @@
+/* $Id$
+ *
+ * linux/arch/sh/kernel/io_generic.c
+ *
+ * Copyright (C) 2000 Niibe Yutaka
+ *
+ * Generic I/O routine.
+ *
+ */
+
+#define PORT2ADDR(x) (CONFIG_IOPORT_START+(x))
+
+unsigned long inb(unsigned long port)
+{
+ return *(volatile unsigned char*)PORT2ADDR(port);
+}
+
+unsigned long inw(unsigned long port)
+{
+ return *(volatile unsigned short*)PORT2ADDR(port);
+}
+
+unsigned long inl(unsigned long port)
+{
+ return *(volatile unsigned long*)PORT2ADDR(port);
+}
+
+void insb(unsigned long port, void *buffer, int count)
+{
+ unsigned char *buf=buffer;
+ while(count--) *buf++=inb(port);
+}
+
+void insw(unsigned long port, void *buffer, int count)
+{
+ unsigned short *buf=buffer;
+ while(count--) *buf++=inw(port);
+}
+
+void insl(unsigned long port, void *buffer, int count)
+{
+ unsigned long *buf=buffer;
+ while(count--) *buf++=inl(port);
+}
+
+void outb(unsigned char b, unsigned long port)
+{
+ *(volatile unsigned char*)PORT2ADDR(port) = b;
+}
+
+void outw(unsigned short b, unsigned long port)
+{
+ *(volatile unsigned short*)PORT2ADDR(port) = b;
+}
+
+void outl(unsigned int b, unsigned long port)
+{
+ *(volatile unsigned long*)PORT2ADDR(port) = b;
+}
+
+void outsb(unsigned long port, const void *buffer, int count)
+{
+ const unsigned char *buf=buffer;
+ while(count--) outb(*buf++, port);
+}
+
+void outsw(unsigned long port, const void *buffer, int count)
+{
+ const unsigned short *buf=buffer;
+ while(count--) outw(*buf++, port);
+}
+
+void outsl(unsigned long port, const void *buffer, int count)
+{
+ const unsigned long *buf=buffer;
+ while(count--) outl(*buf++, port);
+}
Index: arch/sh/kernel/io_se.c
===================================================================
RCS file: io_se.c
diff -N io_se.c
--- /dev/null Tue May 5 13:32:27 1998
+++ io_se.c Tue May 2 19:01:51 2000
@@ -0,0 +1,194 @@
+/* $Id$
+ *
+ * linux/arch/sh/kernel/io_se.c
+ *
+ * Copyright (C) 2000 Kazumoto Kojima
+ *
+ * I/O routine for Hitachi SolutionEngine.
+ *
+ */
+#include <linux/config.h>
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <asm/hitachi_se.h>
+
+/* SH pcmcia io window base, start and end. */
+int sh_pcic_io_wbase = 0xb8400000;
+int sh_pcic_io_start;
+int sh_pcic_io_stop;
+int sh_pcic_io_type;
+int sh_pcic_io_dummy;
+
+/* MS7750 requires special versions of __in*, __out* routines, since
+ PC-like io ports are located at upper half byte of 16-bit word which
+ can be accessed only with 16-bit wide. */
+
+static inline volatile __u16 *
+port2adr(unsigned int port)
+{
+ if (port >= 0x2000)
+ return (volatile __u16 *) (PA_MRSHPC + (port - 0x2000));
+ else if (port >= 0x1000)
+ return (volatile __u16 *) (PA_83902 + (port << 1));
+ else if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)
+ return (volatile __u16 *) (sh_pcic_io_wbase + (port &~ 1));
+ else
+ return (volatile __u16 *) (PA_SUPERIO + (port << 1));
+}
+
+static inline int
+shifted_port(unsigned int port)
+{
+ if (0x1f0 <= port && port < 0x1f8)
+ return 0;
+ else if (port == 0x3f6)
+ return 0;
+ else
+ return 1;
+}
+
+#define maybebadio(name,port) \
+ printk("bad PC-like io %s for port 0x%x at 0x%08x\n", \
+ #name, (port), (__u32) __builtin_return_address(0))
+
+unsigned long inb(unsigned int port)
+{
+ if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)
+ return *(__u8 *) (sh_pcic_io_wbase + 0x40000 + port);
+ else if (shifted_port(port))
+ return (*port2adr(port) >> 8);
+ else
+ return (*port2adr(port))&0xff;
+}
+
+unsigned long inw(unsigned int port)
+{
+ if (port >= 0x2000 ||
+ (sh_pcic_io_start <= port && port <= sh_pcic_io_stop))
+ return *port2adr(port);
+ else
+ maybebadio(inw, port);
+ return 0;
+}
+
+unsigned long inl(unsigned int port)
+{
+ maybebadio(inl, port);
+ return 0;
+}
+
+void outb(unsigned int value, unsigned int port)
+{
+ if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)
+ *(__u8 *)(sh_pcic_io_wbase + port) = value;
+ else if (shifted_port(port))
+ *(port2adr(port)) = value << 8;
+ else
+ *(port2adr(port)) = value;
+}
+
+void outw(unsigned int value, unsigned int port)
+{
+ if (port >= 0x2000 ||
+ (sh_pcic_io_start <= port && port <= sh_pcic_io_stop))
+ *port2adr(port) = value;
+ else
+ maybebadio(outw, port);
+}
+
+void outl(unsigned int value, unsigned int port)
+{
+ maybebadio(outl, port);
+}
+
+void insb(unsigned int port, void *addr, unsigned long count)
+{
+ volatile __u16 *p = port2adr(port);
+
+ if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop) {
+ volatile __u8 *bp = (__u8 *) (sh_pcic_io_wbase + 0x40000 + port);
+ while (count--)
+ *((__u8 *) addr)++ = *bp;
+ }
+ else if (shifted_port(port)) {
+ while (count--)
+ *((__u8 *) addr)++ = *p >> 8;
+ } else {
+ while (count--)
+ *((__u8 *) addr)++ = *p;
+ }
+}
+
+void insw(unsigned int port, void *addr, unsigned long count)
+{
+ volatile __u16 *p = port2adr(port);
+ while (count--)
+ *((__u16 *) addr)++ = *p;
+}
+
+void insl(unsigned int port, void *addr, unsigned long count)
+{
+ maybebadio(insl, port);
+}
+
+void outsb(unsigned int port, const void *addr, unsigned long count)
+{
+ volatile __u16 *p = port2adr(port);
+
+ if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop) {
+ volatile __u8 *bp = (__u8 *) (sh_pcic_io_wbase + port);
+ while (count--)
+ *bp = *((__u8 *) addr)++;
+ } else if (shifted_port(port)) {
+ while (count--)
+ *p = *((__u8 *) addr)++ << 8;
+ } else {
+ while (count--)
+ *p = *((__u8 *) addr)++;
+ }
+}
+
+void outsw(unsigned int port, const void *addr, unsigned long count)
+{
+ volatile __u16 *p = port2adr(port);
+ while (count--)
+ *p = *((__u16 *) addr)++;
+}
+
+void outsl(unsigned int port, const void *addr, unsigned long count)
+{
+ maybebadio(outsw, port);
+}
+
+/* Map ISA bus address to the real address. Only for PCMCIA. */
+
+/* ISA page descriptor. */
+static __u32 sh_isa_memmap[256];
+
+int
+sh_isa_mmap(__u32 start, __u32 length, __u32 offset)
+{
+ int idx;
+
+ if (start >= 0x100000 || (start & 0xfff) || (length != 0x1000))
+ return -1;
+
+ idx = start >> 12;
+ sh_isa_memmap[idx] = 0xb8000000 + (offset &~ 0xfff);
+#if 0
+ printk("sh_isa_mmap: start %x len %x offset %x (idx %x paddr %x)\n",
+ start, length, offset, idx, sh_isa_memmap[idx]);
+#endif
+ return 0;
+}
+
+unsigned long
+sh_isa_slot(unsigned long offset)
+{
+ int idx;
+
+ idx = (offset >> 12) & 0xff;
+ offset &= 0xfff;
+ return sh_isa_memmap[idx] + offset;
+}
Index: arch/sh/kernel/setup_se.c
===================================================================
RCS file: setup_se.c
diff -N setup_se.c
--- /dev/null Tue May 5 13:32:27 1998
+++ setup_se.c Tue May 2 19:01:51 2000
@@ -0,0 +1,120 @@
+/* $Id$
+ *
+ * linux/arch/sh/kernel/setup_se.c
+ *
+ * Copyright (C) 2000 Kazumoto Kojima
+ *
+ * Hitachi SolutionEngine Support.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+
+#include <linux/hdreg.h>
+#include <linux/ide.h>
+#include <asm/io.h>
+#include <asm/hitachi_se.h>
+#include <asm/smc37c93x.h>
+
+/*
+ * Configure the Super I/O chip
+ */
+static void __init smsc_config(int index, int data)
+{
+ outb(index, INDEX_PORT);
+ outb(data, DATA_PORT);
+}
+
+static void __init init_smsc(void)
+{
+ outb(CONFIG_ENTER, CONFIG_PORT);
+ outb(CONFIG_ENTER, CONFIG_PORT);
+
+ /* FDC */
+ smsc_config(CURRENT_LDN_INDEX, LDN_FDC);
+ smsc_config(ACTIVATE_INDEX, 0x01);
+ smsc_config(IRQ_SELECT_INDEX, 0x06); /* IRQ6 */
+
+ /* IDE1 */
+ smsc_config(CURRENT_LDN_INDEX, LDN_IDE1);
+ smsc_config(ACTIVATE_INDEX, 0x01);
+ smsc_config(IRQ_SELECT_INDEX, 0x0E); /* IRQ14 */
+
+#if 0
+ smsc_config(0x24, 0x04); /* XXX: What's that? */
+#endif
+
+ /* COM1 */
+ smsc_config(CURRENT_LDN_INDEX, LDN_COM1);
+ smsc_config(ACTIVATE_INDEX, 0x01);
+ smsc_config(IO_BASE_HI_INDEX, 0x03);
+ smsc_config(IO_BASE_LO_INDEX, 0xf8);
+ smsc_config(IRQ_SELECT_INDEX, 0x03); /* IRQ3 */
+
+ /* RTC */
+ smsc_config(CURRENT_LDN_INDEX, LDN_RTC);
+ smsc_config(ACTIVATE_INDEX, 0x01);
+ smsc_config(IRQ_SELECT_INDEX, 0x08); /* XXX: needed? IRQ8 */
+
+ /* XXX: COM2, PARPORT, KBD, and MOUSE come here... */
+ outb(CONFIG_EXIT, CONFIG_PORT);
+}
+
+/*
+ * Initialize IRQ setting
+ */
+static void __init init_se_IRQ(void)
+{
+ int i;
+
+ /*
+ * Super I/O (Just mimic PC):
+ * 1: keyboard
+ * 3: serial 0
+ * 4: serial 1
+ * 5: printer
+ * 6: floppy
+ * 8: rtc
+ * 12: mouse
+ * 14: ide0
+ */
+ set_ipr_data(14, BCR_ILCRA, 2, 14);
+ set_ipr_data(12, BCR_ILCRA, 1, 12);
+ set_ipr_data( 8, BCR_ILCRB, 1, 8);
+ set_ipr_data( 6, BCR_ILCRC, 3, 6);
+ set_ipr_data( 5, BCR_ILCRC, 2, 5);
+ set_ipr_data( 4, BCR_ILCRC, 1, 4);
+ set_ipr_data( 3, BCR_ILCRC, 0, 3);
+ set_ipr_data( 1, BCR_ILCRD, 3, 1);
+
+ set_ipr_data(10, BCR_ILCRD, 1, 10); /* LAN */
+
+ set_ipr_data(15, BCR_ILCRE, 3, 13); /* PCIRQ3 */
+ set_ipr_data(11, BCR_ILCRE, 2, 11); /* PCIRQ2 */
+ set_ipr_data( 9, BCR_ILCRE, 1, 9); /* PCIRQ1 */
+ set_ipr_data( 7, BCR_ILCRE, 0, 7); /* PCIRQ0 */
+
+ /* #2, #13 are allocated for SLOT IRQ #1 and #2 (for now) */
+ /* NOTE: #2 and #13 are not used on PC */
+ set_ipr_data(13, BCR_ILCRG, 1, 13); /* SLOTIRQ2 */
+ set_ipr_data( 2, BCR_ILCRG, 0, 2); /* SLOTIRQ1 */
+
+ for (i = 1; i < 16; i++) {
+ make_ipr_irq(i);
+ }
+}
+
+/*
+ * Initialize the board
+ */
+int __init setup_se(void)
+{
+ init_se_IRQ();
+ init_smsc();
+ /* XXX: RTC setting comes here */
+ return 0;
+}
+
+module_init(setup_se);
Index: include/asm-sh/ide.h
===================================================================
RCS file: /cvsroot/linuxsh/kernel/include/asm-sh/ide.h,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 ide.h
--- include/asm-sh/ide.h 2000/04/14 16:48:21 1.1.1.1
+++ include/asm-sh/ide.h 2000/05/03 02:01:52
@@ -25,8 +25,8 @@
static __inline__ int ide_default_irq(ide_ioreg_t base)
{
switch (base) {
- case 0xba0001f0: return 14;
- case 0xba000170: return 14;
+ case 0x01f0: return 14;
+ case 0x0170: return 14;
default:
return 0;
}
@@ -36,9 +36,9 @@
{
switch (index) {
case 0:
- return 0xba0001f0;
+ return 0x01f0;
case 1:
- return 0xba000170;
+ return 0x0170;
default:
return 0;
}
Index: include/asm-sh/io.h
===================================================================
RCS file: /cvsroot/linuxsh/kernel/include/asm-sh/io.h,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 io.h
--- include/asm-sh/io.h 2000/04/14 16:48:21 1.1.1.1
+++ include/asm-sh/io.h 2000/05/03 02:01:52
@@ -53,103 +53,60 @@
*(volatile unsigned long*)addr = b;
}
-extern __inline__ unsigned long inb_local(unsigned long addr)
-{
- return readb(addr);
-}
-
-extern __inline__ void outb_local(unsigned char b, unsigned long addr)
-{
- return writeb(b,addr);
-}
-
-extern __inline__ unsigned long inb(unsigned long addr)
-{
- return readb(addr);
-}
-
-extern __inline__ unsigned long inw(unsigned long addr)
-{
- return readw(addr);
-}
-
-extern __inline__ unsigned long inl(unsigned long addr)
-{
- return readl(addr);
-}
-
-extern __inline__ void insb(unsigned long addr, void *buffer, int count)
-{
- unsigned char *buf=buffer;
- while(count--) *buf++=inb(addr);
-}
-
-extern __inline__ void insw(unsigned long addr, void *buffer, int count)
-{
- unsigned short *buf=buffer;
- while(count--) *buf++=inw(addr);
-}
-
-extern __inline__ void insl(unsigned long addr, void *buffer, int count)
-{
- unsigned long *buf=buffer;
- while(count--) *buf++=inl(addr);
-}
-
-extern __inline__ void outb(unsigned char b, unsigned long addr)
-{
- return writeb(b,addr);
-}
-
-extern __inline__ void outw(unsigned short b, unsigned long addr)
-{
- return writew(b,addr);
-}
-
-extern __inline__ void outl(unsigned int b, unsigned long addr)
-{
- return writel(b,addr);
-}
-
-extern __inline__ void outsb(unsigned long addr, const void *buffer, int count)
-{
- const unsigned char *buf=buffer;
- while(count--) outb(*buf++, addr);
-}
-
-extern __inline__ void outsw(unsigned long addr, const void *buffer, int count)
-{
- const unsigned short *buf=buffer;
- while(count--) outw(*buf++, addr);
-}
-
-extern __inline__ void outsl(unsigned long addr, const void *buffer, int count)
-{
- const unsigned long *buf=buffer;
- while(count--) outl(*buf++, addr);
-}
+extern unsigned char inb(unsigned int port);
+extern unsigned short inw(unsigned int port);
+extern unsigned int inl(unsigned int port);
+extern void insb(unsigned int port, void *addr, unsigned long count);
+extern void insw(unsigned int port, void *addr, unsigned long count);
+extern void insl(unsigned int port, void *addr, unsigned long count);
+
+extern void outb(unsigned int value, unsigned int port);
+extern void outw(unsigned int value, unsigned int port);
+extern void outl(unsigned int value, unsigned int port);
+extern void outsb(unsigned int port, const void *addr, unsigned long count);
+extern void outsw(unsigned int port, const void *addr, unsigned long count);
+extern void outsl(unsigned int port, const void *addr, unsigned long count);
+
+/*
+ * If the platform has PC-like I/O, this function gives us the address
+ * from the offset.
+ */
+extern unsigned long sh_isa_slot(unsigned long offset);
+
+#define isa_readb(a) readb(sh_isa_slot(a))
+#define isa_readw(a) readw(sh_isa_slot(a))
+#define isa_readl(a) readl(sh_isa_slot(a))
+#define isa_writeb(b,a) writeb(b,sh_isa_slot(a))
+#define isa_writew(w,a) writew(w,sh_isa_slot(a))
+#define isa_writel(l,a) writel(l,sh_isa_slot(a))
+#define isa_memset_io(a,b,c) \
+ memset((void *)(sh_isa_slot((unsigned long)a)),(b),(c))
+#define isa_memcpy_fromio(a,b,c) \
+ memcpy((a),(void *)(sh_isa_slot((unsigned long)(b))),(c))
+#define isa_memcpy_toio(a,b,c) \
+ memcpy((void *)(sh_isa_slot((unsigned long)(a))),(b),(c))
#define ctrl_in(addr) *(addr)
#define ctrl_out(data,addr) *(addr) = (data)
extern __inline__ unsigned long ctrl_inb(unsigned long addr)
{
- return *(volatile unsigned char*)addr;
+ return *(volatile unsigned char*)addr;
}
extern __inline__ unsigned long ctrl_inw(unsigned long addr)
{
- return *(volatile unsigned short*)addr;
+ return *(volatile unsigned short*)addr;
}
extern __inline__ unsigned long ctrl_inl(unsigned long addr)
{
- return *(volatile unsigned long*)addr;
+ return *(volatile unsigned long*)addr;
}
extern __inline__ void ctrl_outb(unsigned char b, unsigned long addr)
{
- *(volatile unsigned char*)addr = b;
+ *(volatile unsigned char*)addr = b;
}
extern __inline__ void ctrl_outw(unsigned short b, unsigned long addr)
|