aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh/boards
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/sh/boards
Linux-2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'arch/sh/boards')
-rw-r--r--arch/sh/boards/adx/Makefile6
-rw-r--r--arch/sh/boards/adx/irq.c31
-rw-r--r--arch/sh/boards/adx/irq_maskreg.c107
-rw-r--r--arch/sh/boards/adx/setup.c56
-rw-r--r--arch/sh/boards/bigsur/Makefile6
-rw-r--r--arch/sh/boards/bigsur/io.c125
-rw-r--r--arch/sh/boards/bigsur/irq.c348
-rw-r--r--arch/sh/boards/bigsur/led.c55
-rw-r--r--arch/sh/boards/bigsur/setup.c96
-rw-r--r--arch/sh/boards/cat68701/Makefile6
-rw-r--r--arch/sh/boards/cat68701/irq.c28
-rw-r--r--arch/sh/boards/cat68701/setup.c86
-rw-r--r--arch/sh/boards/cqreek/Makefile6
-rw-r--r--arch/sh/boards/cqreek/irq.c128
-rw-r--r--arch/sh/boards/cqreek/setup.c101
-rw-r--r--arch/sh/boards/dmida/Makefile7
-rw-r--r--arch/sh/boards/dmida/mach.c59
-rw-r--r--arch/sh/boards/dreamcast/Makefile6
-rw-r--r--arch/sh/boards/dreamcast/irq.c160
-rw-r--r--arch/sh/boards/dreamcast/rtc.c81
-rw-r--r--arch/sh/boards/dreamcast/setup.c83
-rw-r--r--arch/sh/boards/ec3104/Makefile6
-rw-r--r--arch/sh/boards/ec3104/io.c81
-rw-r--r--arch/sh/boards/ec3104/irq.c196
-rw-r--r--arch/sh/boards/ec3104/setup.c78
-rw-r--r--arch/sh/boards/harp/Makefile8
-rw-r--r--arch/sh/boards/harp/irq.c148
-rw-r--r--arch/sh/boards/harp/led.c52
-rw-r--r--arch/sh/boards/harp/mach.c62
-rw-r--r--arch/sh/boards/harp/pcidma.c42
-rw-r--r--arch/sh/boards/harp/setup.c91
-rw-r--r--arch/sh/boards/hp6xx/hp620/Makefile6
-rw-r--r--arch/sh/boards/hp6xx/hp620/mach.c52
-rw-r--r--arch/sh/boards/hp6xx/hp620/setup.c45
-rw-r--r--arch/sh/boards/hp6xx/hp680/Makefile6
-rw-r--r--arch/sh/boards/hp6xx/hp680/mach.c53
-rw-r--r--arch/sh/boards/hp6xx/hp680/setup.c41
-rw-r--r--arch/sh/boards/hp6xx/hp690/Makefile6
-rw-r--r--arch/sh/boards/hp6xx/hp690/mach.c48
-rw-r--r--arch/sh/boards/mpc1211/Makefile8
-rw-r--r--arch/sh/boards/mpc1211/led.c64
-rw-r--r--arch/sh/boards/mpc1211/pci.c296
-rw-r--r--arch/sh/boards/mpc1211/rtc.c152
-rw-r--r--arch/sh/boards/mpc1211/setup.c360
-rw-r--r--arch/sh/boards/overdrive/Makefile8
-rw-r--r--arch/sh/boards/overdrive/fpga.c134
-rw-r--r--arch/sh/boards/overdrive/galileo.c588
-rw-r--r--arch/sh/boards/overdrive/io.c173
-rw-r--r--arch/sh/boards/overdrive/irq.c192
-rw-r--r--arch/sh/boards/overdrive/led.c59
-rw-r--r--arch/sh/boards/overdrive/mach.c62
-rw-r--r--arch/sh/boards/overdrive/pcidma.c46
-rw-r--r--arch/sh/boards/overdrive/setup.c41
-rw-r--r--arch/sh/boards/overdrive/time.c119
-rw-r--r--arch/sh/boards/renesas/edosk7705/Makefile10
-rw-r--r--arch/sh/boards/renesas/edosk7705/io.c94
-rw-r--r--arch/sh/boards/renesas/edosk7705/setup.c60
-rw-r--r--arch/sh/boards/renesas/hs7751rvoip/Makefile12
-rw-r--r--arch/sh/boards/renesas/hs7751rvoip/io.c310
-rw-r--r--arch/sh/boards/renesas/hs7751rvoip/irq.c122
-rw-r--r--arch/sh/boards/renesas/hs7751rvoip/led.c27
-rw-r--r--arch/sh/boards/renesas/hs7751rvoip/mach.c55
-rw-r--r--arch/sh/boards/renesas/hs7751rvoip/pci.c150
-rw-r--r--arch/sh/boards/renesas/hs7751rvoip/setup.c89
-rw-r--r--arch/sh/boards/renesas/rts7751r2d/Makefile10
-rw-r--r--arch/sh/boards/renesas/rts7751r2d/io.c319
-rw-r--r--arch/sh/boards/renesas/rts7751r2d/irq.c135
-rw-r--r--arch/sh/boards/renesas/rts7751r2d/led.c67
-rw-r--r--arch/sh/boards/renesas/rts7751r2d/mach.c70
-rw-r--r--arch/sh/boards/renesas/rts7751r2d/setup.c31
-rw-r--r--arch/sh/boards/renesas/systemh/Makefile13
-rw-r--r--arch/sh/boards/renesas/systemh/io.c283
-rw-r--r--arch/sh/boards/renesas/systemh/irq.c111
-rw-r--r--arch/sh/boards/renesas/systemh/setup.c80
-rw-r--r--arch/sh/boards/saturn/Makefile8
-rw-r--r--arch/sh/boards/saturn/io.c26
-rw-r--r--arch/sh/boards/saturn/irq.c118
-rw-r--r--arch/sh/boards/saturn/setup.c43
-rw-r--r--arch/sh/boards/saturn/smp.c68
-rw-r--r--arch/sh/boards/se/7300/Makefile7
-rw-r--r--arch/sh/boards/se/7300/io.c265
-rw-r--r--arch/sh/boards/se/7300/irq.c37
-rw-r--r--arch/sh/boards/se/7300/led.c69
-rw-r--r--arch/sh/boards/se/7300/setup.c66
-rw-r--r--arch/sh/boards/se/73180/Makefile7
-rw-r--r--arch/sh/boards/se/73180/io.c265
-rw-r--r--arch/sh/boards/se/73180/irq.c137
-rw-r--r--arch/sh/boards/se/73180/led.c67
-rw-r--r--arch/sh/boards/se/73180/setup.c68
-rw-r--r--arch/sh/boards/se/770x/Makefile6
-rw-r--r--arch/sh/boards/se/770x/io.c226
-rw-r--r--arch/sh/boards/se/770x/irq.c80
-rw-r--r--arch/sh/boards/se/770x/led.c68
-rw-r--r--arch/sh/boards/se/770x/mach.c68
-rw-r--r--arch/sh/boards/se/770x/setup.c85
-rw-r--r--arch/sh/boards/se/7751/Makefile8
-rw-r--r--arch/sh/boards/se/7751/io.c244
-rw-r--r--arch/sh/boards/se/7751/irq.c67
-rw-r--r--arch/sh/boards/se/7751/led.c68
-rw-r--r--arch/sh/boards/se/7751/mach.c55
-rw-r--r--arch/sh/boards/se/7751/pci.c148
-rw-r--r--arch/sh/boards/se/7751/setup.c228
-rw-r--r--arch/sh/boards/sh03/Makefile6
-rw-r--r--arch/sh/boards/sh03/led.c49
-rw-r--r--arch/sh/boards/sh03/rtc.c144
-rw-r--r--arch/sh/boards/sh03/setup.c72
-rw-r--r--arch/sh/boards/sh2000/Makefile6
-rw-r--r--arch/sh/boards/sh2000/setup.c71
-rw-r--r--arch/sh/boards/snapgear/Makefile6
-rw-r--r--arch/sh/boards/snapgear/io.c226
-rw-r--r--arch/sh/boards/snapgear/rtc.c333
-rw-r--r--arch/sh/boards/snapgear/setup.c216
-rw-r--r--arch/sh/boards/superh/microdev/Makefile8
-rw-r--r--arch/sh/boards/superh/microdev/io.c370
-rw-r--r--arch/sh/boards/superh/microdev/irq.c200
-rw-r--r--arch/sh/boards/superh/microdev/led.c102
-rw-r--r--arch/sh/boards/superh/microdev/setup.c278
-rw-r--r--arch/sh/boards/unknown/Makefile6
-rw-r--r--arch/sh/boards/unknown/io.c46
-rw-r--r--arch/sh/boards/unknown/mach.c67
-rw-r--r--arch/sh/boards/unknown/setup.c23
121 files changed, 11783 insertions, 0 deletions
diff --git a/arch/sh/boards/adx/Makefile b/arch/sh/boards/adx/Makefile
new file mode 100644
index 00000000000..5b1c531b399
--- /dev/null
+++ b/arch/sh/boards/adx/Makefile
@@ -0,0 +1,6 @@
1#
2# Makefile for ADX boards
3#
4
5obj-y := setup.o irq.o irq_maskreq.o
6
diff --git a/arch/sh/boards/adx/irq.c b/arch/sh/boards/adx/irq.c
new file mode 100644
index 00000000000..c6ca409dff9
--- /dev/null
+++ b/arch/sh/boards/adx/irq.c
@@ -0,0 +1,31 @@
1/*
2 * linux/arch/sh/boards/adx/irq.c
3 *
4 * Copyright (C) 2001 A&D Co., Ltd.
5 *
6 * I/O routine and setup routines for A&D ADX Board
7 *
8 * This file is subject to the terms and conditions of the GNU General Public
9 * License. See the file "COPYING" in the main directory of this archive
10 * for more details.
11 *
12 */
13
14#include <asm/irq.h>
15
16void init_adx_IRQ(void)
17{
18 int i;
19
20/* printk("init_adx_IRQ()\n");*/
21 /* setup irq_mask_register */
22 irq_mask_register = (unsigned short *)0xa6000008;
23
24 /* cover all external interrupt area by maskreg_irq_type
25 * (Actually, irq15 doesn't exist)
26 */
27 for (i = 0; i < 16; i++) {
28 make_maskreg_irq(i);
29 disable_irq(i);
30 }
31}
diff --git a/arch/sh/boards/adx/irq_maskreg.c b/arch/sh/boards/adx/irq_maskreg.c
new file mode 100644
index 00000000000..ca91bb0f1f5
--- /dev/null
+++ b/arch/sh/boards/adx/irq_maskreg.c
@@ -0,0 +1,107 @@
1/*
2 * linux/arch/sh/kernel/irq_maskreg.c
3 *
4 * Copyright (C) 2001 A&D Co., Ltd. <http://www.aandd.co.jp>
5 *
6 * This file may be copied or modified under the terms of the GNU
7 * General Public License. See linux/COPYING for more information.
8 *
9 * Interrupt handling for Simple external interrupt mask register
10 *
11 * This is for the machine which have single 16 bit register
12 * for masking external IRQ individually.
13 * Each bit of the register is for masking each interrupt.
14 */
15
16#include <linux/config.h>
17#include <linux/kernel.h>
18#include <linux/init.h>
19#include <linux/irq.h>
20
21#include <asm/system.h>
22#include <asm/io.h>
23#include <asm/machvec.h>
24
25/* address of external interrupt mask register
26 * address must be set prior to use these (maybe in init_XXX_irq())
27 * XXX : is it better to use .config than specifying it in code? */
28unsigned short *irq_mask_register = 0;
29
30/* forward declaration */
31static unsigned int startup_maskreg_irq(unsigned int irq);
32static void shutdown_maskreg_irq(unsigned int irq);
33static void enable_maskreg_irq(unsigned int irq);
34static void disable_maskreg_irq(unsigned int irq);
35static void mask_and_ack_maskreg(unsigned int);
36static void end_maskreg_irq(unsigned int irq);
37
38/* hw_interrupt_type */
39static struct hw_interrupt_type maskreg_irq_type = {
40 " Mask Register",
41 startup_maskreg_irq,
42 shutdown_maskreg_irq,
43 enable_maskreg_irq,
44 disable_maskreg_irq,
45 mask_and_ack_maskreg,
46 end_maskreg_irq
47};
48
49/* actual implementatin */
50static unsigned int startup_maskreg_irq(unsigned int irq)
51{
52 enable_maskreg_irq(irq);
53 return 0; /* never anything pending */
54}
55
56static void shutdown_maskreg_irq(unsigned int irq)
57{
58 disable_maskreg_irq(irq);
59}
60
61static void disable_maskreg_irq(unsigned int irq)
62{
63 if (irq_mask_register) {
64 unsigned long flags;
65 unsigned short val, mask = 0x01 << irq;
66
67 /* Set "irq"th bit */
68 local_irq_save(flags);
69 val = ctrl_inw((unsigned long)irq_mask_register);
70 val |= mask;
71 ctrl_outw(val, (unsigned long)irq_mask_register);
72 local_irq_restore(flags);
73 }
74}
75
76static void enable_maskreg_irq(unsigned int irq)
77{
78 if (irq_mask_register) {
79 unsigned long flags;
80 unsigned short val, mask = ~(0x01 << irq);
81
82 /* Clear "irq"th bit */
83 local_irq_save(flags);
84 val = ctrl_inw((unsigned long)irq_mask_register);
85 val &= mask;
86 ctrl_outw(val, (unsigned long)irq_mask_register);
87 local_irq_restore(flags);
88 }
89}
90
91static void mask_and_ack_maskreg(unsigned int irq)
92{
93 disable_maskreg_irq(irq);
94}
95
96static void end_maskreg_irq(unsigned int irq)
97{
98 if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
99 enable_maskreg_irq(irq);
100}
101
102void make_maskreg_irq(unsigned int irq)
103{
104 disable_irq_nosync(irq);
105 irq_desc[irq].handler = &maskreg_irq_type;
106 disable_maskreg_irq(irq);
107}
diff --git a/arch/sh/boards/adx/setup.c b/arch/sh/boards/adx/setup.c
new file mode 100644
index 00000000000..4938d959234
--- /dev/null
+++ b/arch/sh/boards/adx/setup.c
@@ -0,0 +1,56 @@
1/*
2 * linux/arch/sh/board/adx/setup.c
3 *
4 * Copyright (C) 2001 A&D Co., Ltd.
5 *
6 * I/O routine and setup routines for A&D ADX Board
7 *
8 * This file is subject to the terms and conditions of the GNU General Public
9 * License. See the file "COPYING" in the main directory of this archive
10 * for more details.
11 *
12 */
13
14#include <asm/machvec.h>
15#include <linux/module.h>
16
17extern void init_adx_IRQ(void);
18extern void *cf_io_base;
19
20const char *get_system_type(void)
21{
22 return "A&D ADX";
23}
24
25unsigned long adx_isa_port2addr(unsigned long offset)
26{
27 /* CompactFlash (IDE) */
28 if (((offset >= 0x1f0) && (offset <= 0x1f7)) || (offset == 0x3f6)) {
29 return (unsigned long)cf_io_base + offset;
30 }
31
32 /* eth0 */
33 if ((offset >= 0x300) && (offset <= 0x30f)) {
34 return 0xa5000000 + offset; /* COMM BOARD (AREA1) */
35 }
36
37 return offset + 0xb0000000; /* IOBUS (AREA 4)*/
38}
39
40/*
41 * The Machine Vector
42 */
43
44struct sh_machine_vector mv_adx __initmv = {
45 .mv_nr_irqs = 48,
46 .mv_isa_port2addr = adx_isa_port2addr,
47 .mv_init_irq = init_adx_IRQ,
48};
49ALIAS_MV(adx)
50
51int __init platform_setup(void)
52{
53 /* Nothing to see here .. */
54 return 0;
55}
56
diff --git a/arch/sh/boards/bigsur/Makefile b/arch/sh/boards/bigsur/Makefile
new file mode 100644
index 00000000000..0ff9497ac58
--- /dev/null
+++ b/arch/sh/boards/bigsur/Makefile
@@ -0,0 +1,6 @@
1#
2# Makefile for the BigSur specific parts of the kernel
3#
4
5obj-y := setup.o io.o irq.o led.o
6
diff --git a/arch/sh/boards/bigsur/io.c b/arch/sh/boards/bigsur/io.c
new file mode 100644
index 00000000000..697144de741
--- /dev/null
+++ b/arch/sh/boards/bigsur/io.c
@@ -0,0 +1,125 @@
1/*
2 * include/asm-sh/io_bigsur.c
3 *
4 * By Dustin McIntire (dustin@sensoria.com) (c)2001
5 * Derived from io_hd64465.h, which bore the message:
6 * By Greg Banks <gbanks@pocketpenguins.com>
7 * (c) 2000 PocketPenguins Inc.
8 * and from io_hd64461.h, which bore the message:
9 * Copyright 2000 Stuart Menefy (stuart.menefy@st.com)
10 *
11 * May be copied or modified under the terms of the GNU General Public
12 * License. See linux/COPYING for more information.
13 *
14 * IO functions for a Hitachi Big Sur Evaluation Board.
15 */
16
17#include <linux/config.h>
18#include <linux/kernel.h>
19#include <linux/module.h>
20#include <asm/machvec.h>
21#include <asm/io.h>
22#include <asm/bigsur/bigsur.h>
23
24/* Low iomap maps port 0-1K to addresses in 8byte chunks */
25#define BIGSUR_IOMAP_LO_THRESH 0x400
26#define BIGSUR_IOMAP_LO_SHIFT 3
27#define BIGSUR_IOMAP_LO_MASK ((1<<BIGSUR_IOMAP_LO_SHIFT)-1)
28#define BIGSUR_IOMAP_LO_NMAP (BIGSUR_IOMAP_LO_THRESH>>BIGSUR_IOMAP_LO_SHIFT)
29static u32 bigsur_iomap_lo[BIGSUR_IOMAP_LO_NMAP];
30static u8 bigsur_iomap_lo_shift[BIGSUR_IOMAP_LO_NMAP];
31
32/* High iomap maps port 1K-64K to addresses in 1K chunks */
33#define BIGSUR_IOMAP_HI_THRESH 0x10000
34#define BIGSUR_IOMAP_HI_SHIFT 10
35#define BIGSUR_IOMAP_HI_MASK ((1<<BIGSUR_IOMAP_HI_SHIFT)-1)
36#define BIGSUR_IOMAP_HI_NMAP (BIGSUR_IOMAP_HI_THRESH>>BIGSUR_IOMAP_HI_SHIFT)
37static u32 bigsur_iomap_hi[BIGSUR_IOMAP_HI_NMAP];
38static u8 bigsur_iomap_hi_shift[BIGSUR_IOMAP_HI_NMAP];
39
40#ifndef MAX
41#define MAX(a,b) ((a)>(b)?(a):(b))
42#endif
43
44void bigsur_port_map(u32 baseport, u32 nports, u32 addr, u8 shift)
45{
46 u32 port, endport = baseport + nports;
47
48 pr_debug("bigsur_port_map(base=0x%0x, n=0x%0x, addr=0x%08x)\n",
49 baseport, nports, addr);
50
51 for (port = baseport ;
52 port < endport && port < BIGSUR_IOMAP_LO_THRESH ;
53 port += (1<<BIGSUR_IOMAP_LO_SHIFT)) {
54 pr_debug(" maplo[0x%x] = 0x%08x\n", port, addr);
55 bigsur_iomap_lo[port>>BIGSUR_IOMAP_LO_SHIFT] = addr;
56 bigsur_iomap_lo_shift[port>>BIGSUR_IOMAP_LO_SHIFT] = shift;
57 addr += (1<<(BIGSUR_IOMAP_LO_SHIFT));
58 }
59
60 for (port = MAX(baseport, BIGSUR_IOMAP_LO_THRESH) ;
61 port < endport && port < BIGSUR_IOMAP_HI_THRESH ;
62 port += (1<<BIGSUR_IOMAP_HI_SHIFT)) {
63 pr_debug(" maphi[0x%x] = 0x%08x\n", port, addr);
64 bigsur_iomap_hi[port>>BIGSUR_IOMAP_HI_SHIFT] = addr;
65 bigsur_iomap_hi_shift[port>>BIGSUR_IOMAP_HI_SHIFT] = shift;
66 addr += (1<<(BIGSUR_IOMAP_HI_SHIFT));
67 }
68}
69EXPORT_SYMBOL(bigsur_port_map);
70
71void bigsur_port_unmap(u32 baseport, u32 nports)
72{
73 u32 port, endport = baseport + nports;
74
75 pr_debug("bigsur_port_unmap(base=0x%0x, n=0x%0x)\n", baseport, nports);
76
77 for (port = baseport ;
78 port < endport && port < BIGSUR_IOMAP_LO_THRESH ;
79 port += (1<<BIGSUR_IOMAP_LO_SHIFT)) {
80 bigsur_iomap_lo[port>>BIGSUR_IOMAP_LO_SHIFT] = 0;
81 }
82
83 for (port = MAX(baseport, BIGSUR_IOMAP_LO_THRESH) ;
84 port < endport && port < BIGSUR_IOMAP_HI_THRESH ;
85 port += (1<<BIGSUR_IOMAP_HI_SHIFT)) {
86 bigsur_iomap_hi[port>>BIGSUR_IOMAP_HI_SHIFT] = 0;
87 }
88}
89EXPORT_SYMBOL(bigsur_port_unmap);
90
91unsigned long bigsur_isa_port2addr(unsigned long port)
92{
93 unsigned long addr = 0;
94 unsigned char shift;
95
96 /* Physical address not in P0, do nothing */
97 if (PXSEG(port)) {
98 addr = port;
99 /* physical address in P0, map to P2 */
100 } else if (port >= 0x30000) {
101 addr = P2SEGADDR(port);
102 /* Big Sur I/O + HD64465 registers 0x10000-0x30000 */
103 } else if (port >= BIGSUR_IOMAP_HI_THRESH) {
104 addr = BIGSUR_INTERNAL_BASE + (port - BIGSUR_IOMAP_HI_THRESH);
105 /* Handle remapping of high IO/PCI IO ports */
106 } else if (port >= BIGSUR_IOMAP_LO_THRESH) {
107 addr = bigsur_iomap_hi[port >> BIGSUR_IOMAP_HI_SHIFT];
108 shift = bigsur_iomap_hi_shift[port >> BIGSUR_IOMAP_HI_SHIFT];
109
110 if (addr != 0)
111 addr += (port & BIGSUR_IOMAP_HI_MASK) << shift;
112 } else {
113 /* Handle remapping of low IO ports */
114 addr = bigsur_iomap_lo[port >> BIGSUR_IOMAP_LO_SHIFT];
115 shift = bigsur_iomap_lo_shift[port >> BIGSUR_IOMAP_LO_SHIFT];
116
117 if (addr != 0)
118 addr += (port & BIGSUR_IOMAP_LO_MASK) << shift;
119 }
120
121 pr_debug("%s(0x%08lx) = 0x%08lx\n", __FUNCTION__, port, addr);
122
123 return addr;
124}
125
diff --git a/arch/sh/boards/bigsur/irq.c b/arch/sh/boards/bigsur/irq.c
new file mode 100644
index 00000000000..c188fc32dc9
--- /dev/null
+++ b/arch/sh/boards/bigsur/irq.c
@@ -0,0 +1,348 @@
1/*
2 *
3 * By Dustin McIntire (dustin@sensoria.com) (c)2001
4 *
5 * Setup and IRQ handling code for the HD64465 companion chip.
6 * by Greg Banks <gbanks@pocketpenguins.com>
7 * Copyright (c) 2000 PocketPenguins Inc
8 *
9 * Derived from setup_hd64465.c which bore the message:
10 * Greg Banks <gbanks@pocketpenguins.com>
11 * Copyright (c) 2000 PocketPenguins Inc and
12 * Copyright (C) 2000 YAEGASHI Takeshi
13 * and setup_cqreek.c which bore message:
14 * Copyright (C) 2000 Niibe Yutaka
15 *
16 * May be copied or modified under the terms of the GNU General Public
17 * License. See linux/COPYING for more information.
18 *
19 * IRQ functions for a Hitachi Big Sur Evaluation Board.
20 *
21 */
22
23#include <linux/config.h>
24#include <linux/sched.h>
25#include <linux/module.h>
26#include <linux/kernel.h>
27#include <linux/param.h>
28#include <linux/ioport.h>
29#include <linux/interrupt.h>
30#include <linux/init.h>
31#include <linux/irq.h>
32#include <linux/bitops.h>
33
34#include <asm/io.h>
35#include <asm/irq.h>
36
37#include <asm/bigsur/io.h>
38#include <asm/hd64465/hd64465.h>
39#include <asm/bigsur/bigsur.h>
40
41//#define BIGSUR_DEBUG 3
42#undef BIGSUR_DEBUG
43
44#ifdef BIGSUR_DEBUG
45#define DPRINTK(args...) printk(args)
46#define DIPRINTK(n, args...) if (BIGSUR_DEBUG>(n)) printk(args)
47#else
48#define DPRINTK(args...)
49#define DIPRINTK(n, args...)
50#endif /* BIGSUR_DEBUG */
51
52#ifdef CONFIG_HD64465
53extern int hd64465_irq_demux(int irq);
54#endif /* CONFIG_HD64465 */
55
56
57/*===========================================================*/
58// Big Sur CPLD IRQ Routines
59/*===========================================================*/
60
61/* Level 1 IRQ routines */
62static void disable_bigsur_l1irq(unsigned int irq)
63{
64 unsigned long flags;
65 unsigned char mask;
66 unsigned int mask_port = ((irq - BIGSUR_IRQ_LOW)/8) ? BIGSUR_IRLMR1 : BIGSUR_IRLMR0;
67 unsigned char bit = (1 << ((irq - MGATE_IRQ_LOW)%8) );
68
69 if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH) {
70 DPRINTK("Disable L1 IRQ %d\n", irq);
71 DIPRINTK(2,"disable_bigsur_l1irq: IMR=0x%08x mask=0x%x\n",
72 mask_port, bit);
73 local_irq_save(flags);
74
75 /* Disable IRQ - set mask bit */
76 mask = inb(mask_port) | bit;
77 outb(mask, mask_port);
78 local_irq_restore(flags);
79 return;
80 }
81 DPRINTK("disable_bigsur_l1irq: Invalid IRQ %d\n", irq);
82}
83
84static void enable_bigsur_l1irq(unsigned int irq)
85{
86 unsigned long flags;
87 unsigned char mask;
88 unsigned int mask_port = ((irq - BIGSUR_IRQ_LOW)/8) ? BIGSUR_IRLMR1 : BIGSUR_IRLMR0;
89 unsigned char bit = (1 << ((irq - MGATE_IRQ_LOW)%8) );
90
91 if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH) {
92 DPRINTK("Enable L1 IRQ %d\n", irq);
93 DIPRINTK(2,"enable_bigsur_l1irq: IMR=0x%08x mask=0x%x\n",
94 mask_port, bit);
95 local_irq_save(flags);
96 /* Enable L1 IRQ - clear mask bit */
97 mask = inb(mask_port) & ~bit;
98 outb(mask, mask_port);
99 local_irq_restore(flags);
100 return;
101 }
102 DPRINTK("enable_bigsur_l1irq: Invalid IRQ %d\n", irq);
103}
104
105
106/* Level 2 irq masks and registers for L2 decoding */
107/* Level2 bitmasks for each level 1 IRQ */
108const u32 bigsur_l2irq_mask[] =
109 {0x40,0x80,0x08,0x01,0x01,0x3C,0x3E,0xFF,0x40,0x80,0x06,0x03};
110/* Level2 to ISR[n] map for each level 1 IRQ */
111const u32 bigsur_l2irq_reg[] =
112 { 2, 2, 3, 3, 1, 2, 1, 0, 1, 1, 3, 2};
113/* Level2 to Level 1 IRQ map */
114const u32 bigsur_l2_l1_map[] =
115 {7,7,7,7,7,7,7,7, 4,6,6,6,6,6,8,9, 11,11,5,5,5,5,0,1, 3,10,10,2,-1,-1,-1,-1};
116/* IRQ inactive level (high or low) */
117const u32 bigsur_l2_inactv_state[] = {0x00, 0xBE, 0xFC, 0xF7};
118
119/* CPLD external status and mask registers base and offsets */
120static const u32 isr_base = BIGSUR_IRQ0;
121static const u32 isr_offset = BIGSUR_IRQ0 - BIGSUR_IRQ1;
122static const u32 imr_base = BIGSUR_IMR0;
123static const u32 imr_offset = BIGSUR_IMR0 - BIGSUR_IMR1;
124
125#define REG_NUM(irq) ((irq-BIGSUR_2NDLVL_IRQ_LOW)/8 )
126
127/* Level 2 IRQ routines */
128static void disable_bigsur_l2irq(unsigned int irq)
129{
130 unsigned long flags;
131 unsigned char mask;
132 unsigned char bit = 1 << ((irq-BIGSUR_2NDLVL_IRQ_LOW)%8);
133 unsigned int mask_port = imr_base - REG_NUM(irq)*imr_offset;
134
135 if(irq >= BIGSUR_2NDLVL_IRQ_LOW && irq < BIGSUR_2NDLVL_IRQ_HIGH) {
136 DPRINTK("Disable L2 IRQ %d\n", irq);
137 DIPRINTK(2,"disable_bigsur_l2irq: IMR=0x%08x mask=0x%x\n",
138 mask_port, bit);
139 local_irq_save(flags);
140
141 /* Disable L2 IRQ - set mask bit */
142 mask = inb(mask_port) | bit;
143 outb(mask, mask_port);
144 local_irq_restore(flags);
145 return;
146 }
147 DPRINTK("disable_bigsur_l2irq: Invalid IRQ %d\n", irq);
148}
149
150static void enable_bigsur_l2irq(unsigned int irq)
151{
152 unsigned long flags;
153 unsigned char mask;
154 unsigned char bit = 1 << ((irq-BIGSUR_2NDLVL_IRQ_LOW)%8);
155 unsigned int mask_port = imr_base - REG_NUM(irq)*imr_offset;
156
157 if(irq >= BIGSUR_2NDLVL_IRQ_LOW && irq < BIGSUR_2NDLVL_IRQ_HIGH) {
158 DPRINTK("Enable L2 IRQ %d\n", irq);
159 DIPRINTK(2,"enable_bigsur_l2irq: IMR=0x%08x mask=0x%x\n",
160 mask_port, bit);
161 local_irq_save(flags);
162
163 /* Enable L2 IRQ - clear mask bit */
164 mask = inb(mask_port) & ~bit;
165 outb(mask, mask_port);
166 local_irq_restore(flags);
167 return;
168 }
169 DPRINTK("enable_bigsur_l2irq: Invalid IRQ %d\n", irq);
170}
171
172static void mask_and_ack_bigsur(unsigned int irq)
173{
174 DPRINTK("mask_and_ack_bigsur IRQ %d\n", irq);
175 if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH)
176 disable_bigsur_l1irq(irq);
177 else
178 disable_bigsur_l2irq(irq);
179}
180
181static void end_bigsur_irq(unsigned int irq)
182{
183 DPRINTK("end_bigsur_irq IRQ %d\n", irq);
184 if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) {
185 if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH)
186 enable_bigsur_l1irq(irq);
187 else
188 enable_bigsur_l2irq(irq);
189 }
190}
191
192static unsigned int startup_bigsur_irq(unsigned int irq)
193{
194 u8 mask;
195 u32 reg;
196
197 DPRINTK("startup_bigsur_irq IRQ %d\n", irq);
198
199 if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH) {
200 /* Enable the L1 IRQ */
201 enable_bigsur_l1irq(irq);
202 /* Enable all L2 IRQs in this L1 IRQ */
203 mask = ~(bigsur_l2irq_mask[irq-BIGSUR_IRQ_LOW]);
204 reg = imr_base - bigsur_l2irq_reg[irq-BIGSUR_IRQ_LOW] * imr_offset;
205 mask &= inb(reg);
206 outb(mask,reg);
207 DIPRINTK(2,"startup_bigsur_irq: IMR=0x%08x mask=0x%x\n",reg,inb(reg));
208 }
209 else {
210 /* Enable the L2 IRQ - clear mask bit */
211 enable_bigsur_l2irq(irq);
212 /* Enable the L1 bit masking this L2 IRQ */
213 enable_bigsur_l1irq(bigsur_l2_l1_map[irq-BIGSUR_2NDLVL_IRQ_LOW]);
214 DIPRINTK(2,"startup_bigsur_irq: L1=%d L2=%d\n",
215 bigsur_l2_l1_map[irq-BIGSUR_2NDLVL_IRQ_LOW],irq);
216 }
217 return 0;
218}
219
220static void shutdown_bigsur_irq(unsigned int irq)
221{
222 DPRINTK("shutdown_bigsur_irq IRQ %d\n", irq);
223 if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH)
224 disable_bigsur_l1irq(irq);
225 else
226 disable_bigsur_l2irq(irq);
227}
228
229/* Define the IRQ structures for the L1 and L2 IRQ types */
230static struct hw_interrupt_type bigsur_l1irq_type = {
231 "BigSur-CPLD-Level1-IRQ",
232 startup_bigsur_irq,
233 shutdown_bigsur_irq,
234 enable_bigsur_l1irq,
235 disable_bigsur_l1irq,
236 mask_and_ack_bigsur,
237 end_bigsur_irq
238};
239
240static struct hw_interrupt_type bigsur_l2irq_type = {
241 "BigSur-CPLD-Level2-IRQ",
242 startup_bigsur_irq,
243 shutdown_bigsur_irq,
244 enable_bigsur_l2irq,
245 disable_bigsur_l2irq,
246 mask_and_ack_bigsur,
247 end_bigsur_irq
248};
249
250
251static void make_bigsur_l1isr(unsigned int irq) {
252
253 /* sanity check first */
254 if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH) {
255 /* save the handler in the main description table */
256 irq_desc[irq].handler = &bigsur_l1irq_type;
257 irq_desc[irq].status = IRQ_DISABLED;
258 irq_desc[irq].action = 0;
259 irq_desc[irq].depth = 1;
260
261 disable_bigsur_l1irq(irq);
262 return;
263 }
264 DPRINTK("make_bigsur_l1isr: bad irq, %d\n", irq);
265 return;
266}
267
268static void make_bigsur_l2isr(unsigned int irq) {
269
270 /* sanity check first */
271 if(irq >= BIGSUR_2NDLVL_IRQ_LOW && irq < BIGSUR_2NDLVL_IRQ_HIGH) {
272 /* save the handler in the main description table */
273 irq_desc[irq].handler = &bigsur_l2irq_type;
274 irq_desc[irq].status = IRQ_DISABLED;
275 irq_desc[irq].action = 0;
276 irq_desc[irq].depth = 1;
277
278 disable_bigsur_l2irq(irq);
279 return;
280 }
281 DPRINTK("make_bigsur_l2isr: bad irq, %d\n", irq);
282 return;
283}
284
285/* The IRQ's will be decoded as follows:
286 * If a level 2 handler exists and there is an unmasked active
287 * IRQ, the 2nd level handler will be called.
288 * If a level 2 handler does not exist for the active IRQ
289 * the 1st level handler will be called.
290 */
291
292int bigsur_irq_demux(int irq)
293{
294 int dmux_irq = irq;
295 u8 mask, actv_irqs;
296 u32 reg_num;
297
298 DIPRINTK(3,"bigsur_irq_demux, irq=%d\n", irq);
299 /* decode the 1st level IRQ */
300 if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH) {
301 /* Get corresponding L2 ISR bitmask and ISR number */
302 mask = bigsur_l2irq_mask[irq-BIGSUR_IRQ_LOW];
303 reg_num = bigsur_l2irq_reg[irq-BIGSUR_IRQ_LOW];
304 /* find the active IRQ's (XOR with inactive level)*/
305 actv_irqs = inb(isr_base-reg_num*isr_offset) ^
306 bigsur_l2_inactv_state[reg_num];
307 /* decode active IRQ's */
308 actv_irqs = actv_irqs & mask & ~(inb(imr_base-reg_num*imr_offset));
309 /* if NEZ then we have an active L2 IRQ */
310 if(actv_irqs) dmux_irq = ffz(~actv_irqs) + reg_num*8+BIGSUR_2NDLVL_IRQ_LOW;
311 /* if no 2nd level IRQ action, but has 1st level, use 1st level handler */
312 if(!irq_desc[dmux_irq].action && irq_desc[irq].action)
313 dmux_irq = irq;
314 DIPRINTK(1,"bigsur_irq_demux: irq=%d dmux_irq=%d mask=0x%04x reg=%d\n",
315 irq, dmux_irq, mask, reg_num);
316 }
317#ifdef CONFIG_HD64465
318 dmux_irq = hd64465_irq_demux(dmux_irq);
319#endif /* CONFIG_HD64465 */
320 DIPRINTK(3,"bigsur_irq_demux, demux_irq=%d\n", dmux_irq);
321
322 return dmux_irq;
323}
324
325/*===========================================================*/
326// Big Sur Init Routines
327/*===========================================================*/
328void __init init_bigsur_IRQ(void)
329{
330 int i;
331
332 if (!MACH_BIGSUR) return;
333
334 /* Create ISR's for Big Sur CPLD IRQ's */
335 /*==============================================================*/
336 for(i=BIGSUR_IRQ_LOW;i<BIGSUR_IRQ_HIGH;i++)
337 make_bigsur_l1isr(i);
338
339 printk(KERN_INFO "Big Sur CPLD L1 interrupts %d to %d.\n",
340 BIGSUR_IRQ_LOW,BIGSUR_IRQ_HIGH);
341
342 for(i=BIGSUR_2NDLVL_IRQ_LOW;i<BIGSUR_2NDLVL_IRQ_HIGH;i++)
343 make_bigsur_l2isr(i);
344
345 printk(KERN_INFO "Big Sur CPLD L2 interrupts %d to %d.\n",
346 BIGSUR_2NDLVL_IRQ_LOW,BIGSUR_2NDLVL_IRQ_HIGH);
347
348}
diff --git a/arch/sh/boards/bigsur/led.c b/arch/sh/boards/bigsur/led.c
new file mode 100644
index 00000000000..0a2339c6944
--- /dev/null
+++ b/arch/sh/boards/bigsur/led.c
@@ -0,0 +1,55 @@
1/*
2 * linux/arch/sh/kernel/led_bigsur.c
3 *
4 * By Dustin McIntire (dustin@sensoria.com) (c)2001
5 * Derived from led_se.c and led.c, which bore the message:
6 * Copyright (C) 2000 Stuart Menefy <stuart.menefy@st.com>
7 *
8 * May be copied or modified under the terms of the GNU General Public
9 * License. See linux/COPYING for more information.
10 *
11 * This file contains Big Sur specific LED code.
12 */
13
14#include <linux/config.h>
15#include <asm/io.h>
16#include <asm/bigsur/bigsur.h>
17
18static void mach_led(int position, int value)
19{
20 int word;
21
22 word = bigsur_inl(BIGSUR_CSLR);
23 if (value) {
24 bigsur_outl(word & ~BIGSUR_LED, BIGSUR_CSLR);
25 } else {
26 bigsur_outl(word | BIGSUR_LED, BIGSUR_CSLR);
27 }
28}
29
30#ifdef CONFIG_HEARTBEAT
31
32#include <linux/sched.h>
33
34/* Cycle the LED on/off */
35void heartbeat_bigsur(void)
36{
37 static unsigned cnt = 0, period = 0, dist = 0;
38
39 if (cnt == 0 || cnt == dist)
40 mach_led( -1, 1);
41 else if (cnt == 7 || cnt == dist+7)
42 mach_led( -1, 0);
43
44 if (++cnt > period) {
45 cnt = 0;
46 /* The hyperbolic function below modifies the heartbeat period
47 * length in dependency of the current (5min) load. It goes
48 * through the points f(0)=126, f(1)=86, f(5)=51,
49 * f(inf)->30. */
50 period = ((672<<FSHIFT)/(5*avenrun[0]+(7<<FSHIFT))) + 30;
51 dist = period / 4;
52 }
53}
54#endif /* CONFIG_HEARTBEAT */
55
diff --git a/arch/sh/boards/bigsur/setup.c b/arch/sh/boards/bigsur/setup.c
new file mode 100644
index 00000000000..e69be05195f
--- /dev/null
+++ b/arch/sh/boards/bigsur/setup.c
@@ -0,0 +1,96 @@
1/*
2 *
3 * By Dustin McIntire (dustin@sensoria.com) (c)2001
4 *
5 * Setup and IRQ handling code for the HD64465 companion chip.
6 * by Greg Banks <gbanks@pocketpenguins.com>
7 * Copyright (c) 2000 PocketPenguins Inc
8 *
9 * Derived from setup_hd64465.c which bore the message:
10 * Greg Banks <gbanks@pocketpenguins.com>
11 * Copyright (c) 2000 PocketPenguins Inc and
12 * Copyright (C) 2000 YAEGASHI Takeshi
13 * and setup_cqreek.c which bore message:
14 * Copyright (C) 2000 Niibe Yutaka
15 *
16 * May be copied or modified under the terms of the GNU General Public
17 * License. See linux/COPYING for more information.
18 *
19 * Setup functions for a Hitachi Big Sur Evaluation Board.
20 *
21 */
22
23#include <linux/config.h>
24#include <linux/sched.h>
25#include <linux/module.h>
26#include <linux/kernel.h>
27#include <linux/param.h>
28#include <linux/ioport.h>
29#include <linux/interrupt.h>
30#include <linux/init.h>
31#include <linux/irq.h>
32#include <linux/bitops.h>
33
34#include <asm/io.h>
35#include <asm/irq.h>
36#include <asm/machvec.h>
37#include <asm/bigsur/io.h>
38#include <asm/hd64465/hd64465.h>
39#include <asm/bigsur/bigsur.h>
40
41/*===========================================================*/
42// Big Sur Init Routines
43/*===========================================================*/
44
45const char *get_system_type(void)
46{
47 return "Big Sur";
48}
49
50/*
51 * The Machine Vector
52 */
53extern void heartbeat_bigsur(void);
54extern void init_bigsur_IRQ(void);
55
56struct sh_machine_vector mv_bigsur __initmv = {
57 .mv_nr_irqs = NR_IRQS, // Defined in <asm/irq.h>
58
59 .mv_isa_port2addr = bigsur_isa_port2addr,
60 .mv_irq_demux = bigsur_irq_demux,
61
62 .mv_init_irq = init_bigsur_IRQ,
63#ifdef CONFIG_HEARTBEAT
64 .mv_heartbeat = heartbeat_bigsur,
65#endif
66};
67ALIAS_MV(bigsur)
68
69int __init platform_setup(void)
70{
71 /* Mask all 2nd level IRQ's */
72 outb(-1,BIGSUR_IMR0);
73 outb(-1,BIGSUR_IMR1);
74 outb(-1,BIGSUR_IMR2);
75 outb(-1,BIGSUR_IMR3);
76
77 /* Mask 1st level interrupts */
78 outb(-1,BIGSUR_IRLMR0);
79 outb(-1,BIGSUR_IRLMR1);
80
81#if defined (CONFIG_HD64465) && defined (CONFIG_SERIAL)
82 /* remap IO ports for first ISA serial port to HD64465 UART */
83 bigsur_port_map(0x3f8, 8, CONFIG_HD64465_IOBASE + 0x8000, 1);
84#endif /* CONFIG_HD64465 && CONFIG_SERIAL */
85 /* TODO: setup IDE registers */
86 bigsur_port_map(BIGSUR_IDECTL_IOPORT, 2, BIGSUR_ICTL, 8);
87 /* Setup the Ethernet port to BIGSUR_ETHER_IOPORT */
88 bigsur_port_map(BIGSUR_ETHER_IOPORT, 16, BIGSUR_ETHR+BIGSUR_ETHER_IOPORT, 0);
89 /* set page to 1 */
90 outw(1, BIGSUR_ETHR+0xe);
91 /* set the IO port to BIGSUR_ETHER_IOPORT */
92 outw(BIGSUR_ETHER_IOPORT<<3, BIGSUR_ETHR+0x2);
93
94 return 0;
95}
96
diff --git a/arch/sh/boards/cat68701/Makefile b/arch/sh/boards/cat68701/Makefile
new file mode 100644
index 00000000000..52c1de0a6df
--- /dev/null
+++ b/arch/sh/boards/cat68701/Makefile
@@ -0,0 +1,6 @@
1#
2# Makefile for the CAT-68701 specific parts of the kernel
3#
4
5obj-y := setup.o irq.o
6
diff --git a/arch/sh/boards/cat68701/irq.c b/arch/sh/boards/cat68701/irq.c
new file mode 100644
index 00000000000..f9a6d185fb8
--- /dev/null
+++ b/arch/sh/boards/cat68701/irq.c
@@ -0,0 +1,28 @@
1/*
2 * linux/arch/sh/boards/cat68701/irq.c
3 *
4 * Copyright (C) 2000 Niibe Yutaka
5 * 2001 Yutaro Ebihara
6 *
7 * Setup routines for A-ONE Corp CAT-68701 SH7708 Board
8 *
9 * This file is subject to the terms and conditions of the GNU General Public
10 * License. See the file "COPYING" in the main directory of this archive
11 * for more details.
12 *
13 */
14
15#include <asm/irq.h>
16
17int cat68701_irq_demux(int irq)
18{
19 if(irq==13) return 14;
20 if(irq==7) return 10;
21 return irq;
22}
23
24void init_cat68701_IRQ()
25{
26 make_imask_irq(10);
27 make_imask_irq(14);
28}
diff --git a/arch/sh/boards/cat68701/setup.c b/arch/sh/boards/cat68701/setup.c
new file mode 100644
index 00000000000..ae8a350ade5
--- /dev/null
+++ b/arch/sh/boards/cat68701/setup.c
@@ -0,0 +1,86 @@
1/*
2 * linux/arch/sh/boards/cat68701/setup.c
3 *
4 * Copyright (C) 2000 Niibe Yutaka
5 * 2001 Yutaro Ebihara
6 *
7 * Setup routines for A-ONE Corp CAT-68701 SH7708 Board
8 *
9 * This file is subject to the terms and conditions of the GNU General Public
10 * License. See the file "COPYING" in the main directory of this archive
11 * for more details.
12 *
13 */
14
15#include <asm/io.h>
16#include <asm/machvec.h>
17#include <asm/mach/io.h>
18#include <linux/config.h>
19#include <linux/module.h>
20#include <linux/init.h>
21#include <linux/sched.h>
22
23const char *get_system_type(void)
24{
25 return "CAT-68701";
26}
27
28#ifdef CONFIG_HEARTBEAT
29void heartbeat_cat68701()
30{
31 static unsigned int cnt = 0, period = 0 , bit = 0;
32 cnt += 1;
33 if (cnt < period) {
34 return;
35 }
36 cnt = 0;
37
38 /* Go through the points (roughly!):
39 * f(0)=10, f(1)=16, f(2)=20, f(5)=35,f(inf)->110
40 */
41 period = 110 - ( (300<<FSHIFT)/
42 ((avenrun[0]/5) + (3<<FSHIFT)) );
43
44 if(bit){ bit=0; }else{ bit=1; }
45 outw(bit<<15,0x3fe);
46}
47#endif /* CONFIG_HEARTBEAT */
48
49unsigned long cat68701_isa_port2addr(unsigned long offset)
50{
51 /* CompactFlash (IDE) */
52 if (((offset >= 0x1f0) && (offset <= 0x1f7)) || (offset==0x3f6))
53 return 0xba000000 + offset;
54
55 /* INPUT PORT */
56 if ((offset >= 0x3fc) && (offset <= 0x3fd))
57 return 0xb4007000 + offset;
58
59 /* OUTPUT PORT */
60 if ((offset >= 0x3fe) && (offset <= 0x3ff))
61 return 0xb4007400 + offset;
62
63 return offset + 0xb4000000; /* other I/O (EREA 5)*/
64}
65
66/*
67 * The Machine Vector
68 */
69
70struct sh_machine_vector mv_cat68701 __initmv = {
71 .mv_nr_irqs = 32,
72 .mv_isa_port2addr = cat68701_isa_port2addr,
73 .mv_irq_demux = cat68701_irq_demux,
74
75 .mv_init_irq = init_cat68701_IRQ,
76#ifdef CONFIG_HEARTBEAT
77 .mv_heartbeat = heartbeat_cat68701,
78#endif
79};
80ALIAS_MV(cat68701)
81
82int __init platform_setup(void)
83{
84 /* dummy read erea5 (CS8900A) */
85}
86
diff --git a/arch/sh/boards/cqreek/Makefile b/arch/sh/boards/cqreek/Makefile
new file mode 100644
index 00000000000..1a788a85eba
--- /dev/null
+++ b/arch/sh/boards/cqreek/Makefile
@@ -0,0 +1,6 @@
1#
2# Makefile for the CqREEK specific parts of the kernel
3#
4
5obj-y := setup.o irq.o
6
diff --git a/arch/sh/boards/cqreek/irq.c b/arch/sh/boards/cqreek/irq.c
new file mode 100644
index 00000000000..fa6cfe5a20a
--- /dev/null
+++ b/arch/sh/boards/cqreek/irq.c
@@ -0,0 +1,128 @@
1/* $Id: irq.c,v 1.1.2.4 2002/11/04 20:33:56 lethal Exp $
2 *
3 * arch/sh/boards/cqreek/irq.c
4 *
5 * Copyright (C) 2000 Niibe Yutaka
6 *
7 * CqREEK IDE/ISA Bridge Support.
8 *
9 */
10
11#include <linux/irq.h>
12#include <linux/init.h>
13
14#include <asm/cqreek/cqreek.h>
15#include <asm/io.h>
16#include <asm/io_generic.h>
17#include <asm/irq.h>
18#include <asm/machvec.h>
19#include <asm/machvec_init.h>
20#include <asm/rtc.h>
21
22struct cqreek_irq_data {
23 unsigned short mask_port; /* Port of Interrupt Mask Register */
24 unsigned short stat_port; /* Port of Interrupt Status Register */
25 unsigned short bit; /* Value of the bit */
26};
27static struct cqreek_irq_data cqreek_irq_data[NR_IRQS];
28
29static void disable_cqreek_irq(unsigned int irq)
30{
31 unsigned long flags;
32 unsigned short mask;
33 unsigned short mask_port = cqreek_irq_data[irq].mask_port;
34 unsigned short bit = cqreek_irq_data[irq].bit;
35
36 local_irq_save(flags);
37 /* Disable IRQ */
38 mask = inw(mask_port) & ~bit;
39 outw_p(mask, mask_port);
40 local_irq_restore(flags);
41}
42
43static void enable_cqreek_irq(unsigned int irq)
44{
45 unsigned long flags;
46 unsigned short mask;
47 unsigned short mask_port = cqreek_irq_data[irq].mask_port;
48 unsigned short bit = cqreek_irq_data[irq].bit;
49
50 local_irq_save(flags);
51 /* Enable IRQ */
52 mask = inw(mask_port) | bit;
53 outw_p(mask, mask_port);
54 local_irq_restore(flags);
55}
56
57static void mask_and_ack_cqreek(unsigned int irq)
58{
59 unsigned short stat_port = cqreek_irq_data[irq].stat_port;
60 unsigned short bit = cqreek_irq_data[irq].bit;
61
62 disable_cqreek_irq(irq);
63 /* Clear IRQ (it might be edge IRQ) */
64 inw(stat_port);
65 outw_p(bit, stat_port);
66}
67
68static void end_cqreek_irq(unsigned int irq)
69{
70 if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
71 enable_cqreek_irq(irq);
72}
73
74static unsigned int startup_cqreek_irq(unsigned int irq)
75{
76 enable_cqreek_irq(irq);
77 return 0;
78}
79
80static void shutdown_cqreek_irq(unsigned int irq)
81{
82 disable_cqreek_irq(irq);
83}
84
85static struct hw_interrupt_type cqreek_irq_type = {
86 "CqREEK-IRQ",
87 startup_cqreek_irq,
88 shutdown_cqreek_irq,
89 enable_cqreek_irq,
90 disable_cqreek_irq,
91 mask_and_ack_cqreek,
92 end_cqreek_irq
93};
94
95int cqreek_has_ide, cqreek_has_isa;
96
97/* XXX: This is just for test for my NE2000 ISA board
98 What we really need is virtualized IRQ and demultiplexer like HP600 port */
99void __init init_cqreek_IRQ(void)
100{
101 if (cqreek_has_ide) {
102 cqreek_irq_data[14].mask_port = BRIDGE_IDE_INTR_MASK;
103 cqreek_irq_data[14].stat_port = BRIDGE_IDE_INTR_STAT;
104 cqreek_irq_data[14].bit = 1;
105
106 irq_desc[14].handler = &cqreek_irq_type;
107 irq_desc[14].status = IRQ_DISABLED;
108 irq_desc[14].action = 0;
109 irq_desc[14].depth = 1;
110
111 disable_cqreek_irq(14);
112 }
113
114 if (cqreek_has_isa) {
115 cqreek_irq_data[10].mask_port = BRIDGE_ISA_INTR_MASK;
116 cqreek_irq_data[10].stat_port = BRIDGE_ISA_INTR_STAT;
117 cqreek_irq_data[10].bit = (1 << 10);
118
119 /* XXX: Err... we may need demultiplexer for ISA irq... */
120 irq_desc[10].handler = &cqreek_irq_type;
121 irq_desc[10].status = IRQ_DISABLED;
122 irq_desc[10].action = 0;
123 irq_desc[10].depth = 1;
124
125 disable_cqreek_irq(10);
126 }
127}
128
diff --git a/arch/sh/boards/cqreek/setup.c b/arch/sh/boards/cqreek/setup.c
new file mode 100644
index 00000000000..29b537cd654
--- /dev/null
+++ b/arch/sh/boards/cqreek/setup.c
@@ -0,0 +1,101 @@
1/* $Id: setup.c,v 1.5 2003/08/04 01:51:58 lethal Exp $
2 *
3 * arch/sh/kernel/setup_cqreek.c
4 *
5 * Copyright (C) 2000 Niibe Yutaka
6 *
7 * CqREEK IDE/ISA Bridge Support.
8 *
9 */
10
11#include <linux/config.h>
12#include <linux/kernel.h>
13#include <linux/init.h>
14#include <linux/irq.h>
15
16#include <asm/mach/cqreek.h>
17#include <asm/machvec.h>
18#include <asm/io.h>
19#include <asm/io_generic.h>
20#include <asm/irq.h>
21#include <asm/rtc.h>
22
23#define IDE_OFFSET 0xA4000000UL
24#define ISA_OFFSET 0xA4A00000UL
25
26const char *get_system_type(void)
27{
28 return "CqREEK";
29}
30
31static unsigned long cqreek_port2addr(unsigned long port)
32{
33 if (0x0000<=port && port<=0x0040)
34 return IDE_OFFSET + port;
35 if ((0x01f0<=port && port<=0x01f7) || port == 0x03f6)
36 return IDE_OFFSET + port;
37
38 return ISA_OFFSET + port;
39}
40
41/*
42 * The Machine Vector
43 */
44struct sh_machine_vector mv_cqreek __initmv = {
45#if defined(CONFIG_CPU_SH4)
46 .mv_nr_irqs = 48,
47#elif defined(CONFIG_CPU_SUBTYPE_SH7708)
48 .mv_nr_irqs = 32,
49#elif defined(CONFIG_CPU_SUBTYPE_SH7709)
50 .mv_nr_irqs = 61,
51#endif
52
53 .mv_init_irq = init_cqreek_IRQ,
54
55 .mv_isa_port2addr = cqreek_port2addr,
56};
57ALIAS_MV(cqreek)
58
59/*
60 * Initialize the board
61 */
62void __init platform_setup(void)
63{
64 int i;
65/* udelay is not available at setup time yet... */
66#define DELAY() do {for (i=0; i<10000; i++) ctrl_inw(0xa0000000);} while(0)
67
68 if ((inw (BRIDGE_FEATURE) & 1)) { /* We have IDE interface */
69 outw_p(0, BRIDGE_IDE_INTR_LVL);
70 outw_p(0, BRIDGE_IDE_INTR_MASK);
71
72 outw_p(0, BRIDGE_IDE_CTRL);
73 DELAY();
74
75 outw_p(0x8000, BRIDGE_IDE_CTRL);
76 DELAY();
77
78 outw_p(0xffff, BRIDGE_IDE_INTR_STAT); /* Clear interrupt status */
79 outw_p(0x0f-14, BRIDGE_IDE_INTR_LVL); /* Use 14 IPR */
80 outw_p(1, BRIDGE_IDE_INTR_MASK); /* Enable interrupt */
81 cqreek_has_ide=1;
82 }
83
84 if ((inw (BRIDGE_FEATURE) & 2)) { /* We have ISA interface */
85 outw_p(0, BRIDGE_ISA_INTR_LVL);
86 outw_p(0, BRIDGE_ISA_INTR_MASK);
87
88 outw_p(0, BRIDGE_ISA_CTRL);
89 DELAY();
90 outw_p(0x8000, BRIDGE_ISA_CTRL);
91 DELAY();
92
93 outw_p(0xffff, BRIDGE_ISA_INTR_STAT); /* Clear interrupt status */
94 outw_p(0x0f-10, BRIDGE_ISA_INTR_LVL); /* Use 10 IPR */
95 outw_p(0xfff8, BRIDGE_ISA_INTR_MASK); /* Enable interrupt */
96 cqreek_has_isa=1;
97 }
98
99 printk(KERN_INFO "CqREEK Setup (IDE=%d, ISA=%d)...done\n", cqreek_has_ide, cqreek_has_isa);
100}
101
diff --git a/arch/sh/boards/dmida/Makefile b/arch/sh/boards/dmida/Makefile
new file mode 100644
index 00000000000..75999aa0a2d
--- /dev/null
+++ b/arch/sh/boards/dmida/Makefile
@@ -0,0 +1,7 @@
1#
2# Makefile for the DataMyte Industrial Digital Assistant(tm) specific parts
3# of the kernel
4#
5
6obj-y := mach.o
7
diff --git a/arch/sh/boards/dmida/mach.c b/arch/sh/boards/dmida/mach.c
new file mode 100644
index 00000000000..d03a25f989c
--- /dev/null
+++ b/arch/sh/boards/dmida/mach.c
@@ -0,0 +1,59 @@
1/*
2 * linux/arch/sh/boards/dmida/mach.c
3 *
4 * by Greg Banks <gbanks@pocketpenguins.com>
5 * (c) 2000 PocketPenguins Inc
6 *
7 * Derived from mach_hp600.c, which bore the message:
8 * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com)
9 *
10 * May be copied or modified under the terms of the GNU General Public
11 * License. See linux/COPYING for more information.
12 *
13 * Machine vector for the DataMyte Industrial Digital Assistant(tm).
14 * See http://www.dmida.com
15 *
16 */
17
18#include <linux/init.h>
19
20#include <asm/machvec.h>
21#include <asm/rtc.h>
22#include <asm/machvec_init.h>
23
24#include <asm/io.h>
25#include <asm/hd64465/hd64465.h>
26#include <asm/irq.h>
27
28/*
29 * The Machine Vector
30 */
31
32struct sh_machine_vector mv_dmida __initmv = {
33 .mv_nr_irqs = HD64465_IRQ_BASE+HD64465_IRQ_NUM,
34
35 .mv_inb = hd64465_inb,
36 .mv_inw = hd64465_inw,
37 .mv_inl = hd64465_inl,
38 .mv_outb = hd64465_outb,
39 .mv_outw = hd64465_outw,
40 .mv_outl = hd64465_outl,
41
42 .mv_inb_p = hd64465_inb_p,
43 .mv_inw_p = hd64465_inw,
44 .mv_inl_p = hd64465_inl,
45 .mv_outb_p = hd64465_outb_p,
46 .mv_outw_p = hd64465_outw,
47 .mv_outl_p = hd64465_outl,
48
49 .mv_insb = hd64465_insb,
50 .mv_insw = hd64465_insw,
51 .mv_insl = hd64465_insl,
52 .mv_outsb = hd64465_outsb,
53 .mv_outsw = hd64465_outsw,
54 .mv_outsl = hd64465_outsl,
55
56 .mv_irq_demux = hd64465_irq_demux,
57};
58ALIAS_MV(dmida)
59
diff --git a/arch/sh/boards/dreamcast/Makefile b/arch/sh/boards/dreamcast/Makefile
new file mode 100644
index 00000000000..7b97546c7e5
--- /dev/null
+++ b/arch/sh/boards/dreamcast/Makefile
@@ -0,0 +1,6 @@
1#
2# Makefile for the Sega Dreamcast specific parts of the kernel
3#
4
5obj-y := setup.o irq.o rtc.o
6
diff --git a/arch/sh/boards/dreamcast/irq.c b/arch/sh/boards/dreamcast/irq.c
new file mode 100644
index 00000000000..b10a6b11c03
--- /dev/null
+++ b/arch/sh/boards/dreamcast/irq.c
@@ -0,0 +1,160 @@
1/*
2 * arch/sh/boards/dreamcast/irq.c
3 *
4 * Holly IRQ support for the Sega Dreamcast.
5 *
6 * Copyright (c) 2001, 2002 M. R. Brown <mrbrown@0xd6.org>
7 *
8 * This file is part of the LinuxDC project (www.linuxdc.org)
9 * Released under the terms of the GNU GPL v2.0
10 */
11
12#include <linux/irq.h>
13
14#include <asm/io.h>
15#include <asm/irq.h>
16#include <asm/dreamcast/sysasic.h>
17
18/* Dreamcast System ASIC Hardware Events -
19
20 The Dreamcast's System ASIC (a.k.a. Holly) is responsible for receiving
21 hardware events from system peripherals and triggering an SH7750 IRQ.
22 Hardware events can trigger IRQs 13, 11, or 9 depending on which bits are
23 set in the Event Mask Registers (EMRs). When a hardware event is
24 triggered, it's corresponding bit in the Event Status Registers (ESRs)
25 is set, and that bit should be rewritten to the ESR to acknowledge that
26 event.
27
28 There are three 32-bit ESRs located at 0xa05f8900 - 0xa05f6908. Event
29 types can be found in include/asm-sh/dc_sysasic.h. There are three groups
30 of EMRs that parallel the ESRs. Each EMR group corresponds to an IRQ, so
31 0xa05f6910 - 0xa05f6918 triggers IRQ 13, 0xa05f6920 - 0xa05f6928 triggers
32 IRQ 11, and 0xa05f6930 - 0xa05f6938 triggers IRQ 9.
33
34 In the kernel, these events are mapped to virtual IRQs so that drivers can
35 respond to them as they would a normal interrupt. In order to keep this
36 mapping simple, the events are mapped as:
37
38 6900/6910 - Events 0-31, IRQ 13
39 6904/6924 - Events 32-63, IRQ 11
40 6908/6938 - Events 64-95, IRQ 9
41
42*/
43
44#define ESR_BASE 0x005f6900 /* Base event status register */
45#define EMR_BASE 0x005f6910 /* Base event mask register */
46
47/* Helps us determine the EMR group that this event belongs to: 0 = 0x6910,
48 1 = 0x6920, 2 = 0x6930; also determine the event offset */
49#define LEVEL(event) (((event) - HW_EVENT_IRQ_BASE) / 32)
50
51/* Return the hardware event's bit positon within the EMR/ESR */
52#define EVENT_BIT(event) (((event) - HW_EVENT_IRQ_BASE) & 31)
53
54/* For each of these *_irq routines, the IRQ passed in is the virtual IRQ
55 (logically mapped to the corresponding bit for the hardware event). */
56
57/* Disable the hardware event by masking its bit in its EMR */
58static inline void disable_systemasic_irq(unsigned int irq)
59{
60 unsigned long flags;
61 __u32 emr = EMR_BASE + (LEVEL(irq) << 4) + (LEVEL(irq) << 2);
62 __u32 mask;
63
64 local_irq_save(flags);
65 mask = inl(emr);
66 mask &= ~(1 << EVENT_BIT(irq));
67 outl(mask, emr);
68 local_irq_restore(flags);
69}
70
71/* Enable the hardware event by setting its bit in its EMR */
72static inline void enable_systemasic_irq(unsigned int irq)
73{
74 unsigned long flags;
75 __u32 emr = EMR_BASE + (LEVEL(irq) << 4) + (LEVEL(irq) << 2);
76 __u32 mask;
77
78 local_irq_save(flags);
79 mask = inl(emr);
80 mask |= (1 << EVENT_BIT(irq));
81 outl(mask, emr);
82 local_irq_restore(flags);
83}
84
85/* Acknowledge a hardware event by writing its bit back to its ESR */
86static void ack_systemasic_irq(unsigned int irq)
87{
88 __u32 esr = ESR_BASE + (LEVEL(irq) << 2);
89 disable_systemasic_irq(irq);
90 outl((1 << EVENT_BIT(irq)), esr);
91}
92
93/* After a IRQ has been ack'd and responded to, it needs to be renabled */
94static void end_systemasic_irq(unsigned int irq)
95{
96 if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
97 enable_systemasic_irq(irq);
98}
99
100static unsigned int startup_systemasic_irq(unsigned int irq)
101{
102 enable_systemasic_irq(irq);
103
104 return 0;
105}
106
107static void shutdown_systemasic_irq(unsigned int irq)
108{
109 disable_systemasic_irq(irq);
110}
111
112struct hw_interrupt_type systemasic_int = {
113 .typename = "System ASIC",
114 .startup = startup_systemasic_irq,
115 .shutdown = shutdown_systemasic_irq,
116 .enable = enable_systemasic_irq,
117 .disable = disable_systemasic_irq,
118 .ack = ack_systemasic_irq,
119 .end = end_systemasic_irq,
120};
121
122/*
123 * Map the hardware event indicated by the processor IRQ to a virtual IRQ.
124 */
125int systemasic_irq_demux(int irq)
126{
127 __u32 emr, esr, status, level;
128 __u32 j, bit;
129
130 switch (irq) {
131 case 13:
132 level = 0;
133 break;
134 case 11:
135 level = 1;
136 break;
137 case 9:
138 level = 2;
139 break;
140 default:
141 return irq;
142 }
143 emr = EMR_BASE + (level << 4) + (level << 2);
144 esr = ESR_BASE + (level << 2);
145
146 /* Mask the ESR to filter any spurious, unwanted interrtupts */
147 status = inl(esr);
148 status &= inl(emr);
149
150 /* Now scan and find the first set bit as the event to map */
151 for (bit = 1, j = 0; j < 32; bit <<= 1, j++) {
152 if (status & bit) {
153 irq = HW_EVENT_IRQ_BASE + j + (level << 5);
154 return irq;
155 }
156 }
157
158 /* Not reached */
159 return irq;
160}
diff --git a/arch/sh/boards/dreamcast/rtc.c b/arch/sh/boards/dreamcast/rtc.c
new file mode 100644
index 00000000000..379de162913
--- /dev/null
+++ b/arch/sh/boards/dreamcast/rtc.c
@@ -0,0 +1,81 @@
1/* arch/sh/kernel/rtc-aica.c
2 *
3 * Dreamcast AICA RTC routines.
4 *
5 * Copyright (c) 2001, 2002 M. R. Brown <mrbrown@0xd6.org>
6 * Copyright (c) 2002 Paul Mundt <lethal@chaoticdreams.org>
7 *
8 * Released under the terms of the GNU GPL v2.0.
9 *
10 */
11
12#include <linux/time.h>
13
14#include <asm/io.h>
15
16extern void (*rtc_get_time)(struct timespec *);
17extern int (*rtc_set_time)(const time_t);
18
19/* The AICA RTC has an Epoch of 1/1/1950, so we must subtract 20 years (in
20 seconds to get the standard Unix Epoch when getting the time, and add 20
21 years when setting the time. */
22#define TWENTY_YEARS ((20 * 365LU + 5) * 86400)
23
24/* The AICA RTC is represented by a 32-bit seconds counter stored in 2 16-bit
25 registers.*/
26#define AICA_RTC_SECS_H 0xa0710000
27#define AICA_RTC_SECS_L 0xa0710004
28
29/**
30 * aica_rtc_gettimeofday - Get the time from the AICA RTC
31 * @ts: pointer to resulting timespec
32 *
33 * Grabs the current RTC seconds counter and adjusts it to the Unix Epoch.
34 */
35void aica_rtc_gettimeofday(struct timespec *ts) {
36 unsigned long val1, val2;
37
38 do {
39 val1 = ((ctrl_inl(AICA_RTC_SECS_H) & 0xffff) << 16) |
40 (ctrl_inl(AICA_RTC_SECS_L) & 0xffff);
41
42 val2 = ((ctrl_inl(AICA_RTC_SECS_H) & 0xffff) << 16) |
43 (ctrl_inl(AICA_RTC_SECS_L) & 0xffff);
44 } while (val1 != val2);
45
46 ts->tv_sec = val1 - TWENTY_YEARS;
47
48 /* Can't get nanoseconds with just a seconds counter. */
49 ts->tv_nsec = 0;
50}
51
52/**
53 * aica_rtc_settimeofday - Set the AICA RTC to the current time
54 * @secs: contains the time_t to set
55 *
56 * Adjusts the given @tv to the AICA Epoch and sets the RTC seconds counter.
57 */
58int aica_rtc_settimeofday(const time_t secs) {
59 unsigned long val1, val2;
60 unsigned long adj = secs + TWENTY_YEARS;
61
62 do {
63 ctrl_outl((adj & 0xffff0000) >> 16, AICA_RTC_SECS_H);
64 ctrl_outl((adj & 0xffff), AICA_RTC_SECS_L);
65
66 val1 = ((ctrl_inl(AICA_RTC_SECS_H) & 0xffff) << 16) |
67 (ctrl_inl(AICA_RTC_SECS_L) & 0xffff);
68
69 val2 = ((ctrl_inl(AICA_RTC_SECS_H) & 0xffff) << 16) |
70 (ctrl_inl(AICA_RTC_SECS_L) & 0xffff);
71 } while (val1 != val2);
72
73 return 0;
74}
75
76void aica_time_init(void)
77{
78 rtc_get_time = aica_rtc_gettimeofday;
79 rtc_set_time = aica_rtc_settimeofday;
80}
81
diff --git a/arch/sh/boards/dreamcast/setup.c b/arch/sh/boards/dreamcast/setup.c
new file mode 100644
index 00000000000..55dece35cde
--- /dev/null
+++ b/arch/sh/boards/dreamcast/setup.c
@@ -0,0 +1,83 @@
1/*
2 * arch/sh/boards/dreamcast/setup.c
3 *
4 * Hardware support for the Sega Dreamcast.
5 *
6 * Copyright (c) 2001, 2002 M. R. Brown <mrbrown@linuxdc.org>
7 * Copyright (c) 2002, 2003, 2004 Paul Mundt <lethal@linux-sh.org>
8 *
9 * This file is part of the LinuxDC project (www.linuxdc.org)
10 *
11 * Released under the terms of the GNU GPL v2.0.
12 *
13 * This file originally bore the message (with enclosed-$):
14 * Id: setup_dc.c,v 1.5 2001/05/24 05:09:16 mrbrown Exp
15 * SEGA Dreamcast support
16 */
17
18#include <linux/sched.h>
19#include <linux/kernel.h>
20#include <linux/param.h>
21#include <linux/interrupt.h>
22#include <linux/init.h>
23#include <linux/irq.h>
24#include <linux/device.h>
25
26#include <asm/io.h>
27#include <asm/irq.h>
28#include <asm/machvec.h>
29#include <asm/machvec_init.h>
30#include <asm/mach/sysasic.h>
31
32extern struct hw_interrupt_type systemasic_int;
33/* XXX: Move this into it's proper header. */
34extern void (*board_time_init)(void);
35extern void aica_time_init(void);
36extern int gapspci_init(void);
37extern int systemasic_irq_demux(int);
38
39void *dreamcast_consistent_alloc(struct device *, size_t, dma_addr_t *, int);
40int dreamcast_consistent_free(struct device *, size_t, void *, dma_addr_t);
41
42const char *get_system_type(void)
43{
44 return "Sega Dreamcast";
45}
46
47struct sh_machine_vector mv_dreamcast __initmv = {
48 .mv_nr_irqs = NR_IRQS,
49
50 .mv_irq_demux = systemasic_irq_demux,
51
52#ifdef CONFIG_PCI
53 .mv_consistent_alloc = dreamcast_consistent_alloc,
54 .mv_consistent_free = dreamcast_consistent_free,
55#endif
56};
57ALIAS_MV(dreamcast)
58
59int __init platform_setup(void)
60{
61 int i;
62
63 /* Mask all hardware events */
64 /* XXX */
65
66 /* Acknowledge any previous events */
67 /* XXX */
68
69 __set_io_port_base(0xa0000000);
70
71 /* Assign all virtual IRQs to the System ASIC int. handler */
72 for (i = HW_EVENT_IRQ_BASE; i < HW_EVENT_IRQ_MAX; i++)
73 irq_desc[i].handler = &systemasic_int;
74
75 board_time_init = aica_time_init;
76
77#ifdef CONFIG_PCI
78 if (gapspci_init() < 0)
79 printk(KERN_WARNING "GAPSPCI was not detected.\n");
80#endif
81
82 return 0;
83}
diff --git a/arch/sh/boards/ec3104/Makefile b/arch/sh/boards/ec3104/Makefile
new file mode 100644
index 00000000000..178891534b6
--- /dev/null
+++ b/arch/sh/boards/ec3104/Makefile
@@ -0,0 +1,6 @@
1#
2# Makefile for the EC3104 specific parts of the kernel
3#
4
5obj-y := setup.o io.o irq.o
6
diff --git a/arch/sh/boards/ec3104/io.c b/arch/sh/boards/ec3104/io.c
new file mode 100644
index 00000000000..a70928c4475
--- /dev/null
+++ b/arch/sh/boards/ec3104/io.c
@@ -0,0 +1,81 @@
1/*
2 * linux/arch/sh/kernel/io_ec3104.c
3 * EC3104 companion chip support
4 *
5 * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
6 *
7 */
8/* EC3104 note:
9 * This code was written without any documentation about the EC3104 chip. While
10 * I hope I got most of the basic functionality right, the register names I use
11 * are most likely completely different from those in the chip documentation.
12 *
13 * If you have any further information about the EC3104, please tell me
14 * (prumpf@tux.org).
15 */
16
17#include <linux/kernel.h>
18#include <linux/types.h>
19#include <asm/io.h>
20#include <asm/page.h>
21#include <asm/ec3104/ec3104.h>
22
23/*
24 * EC3104 has a real ISA bus which we redirect low port accesses to (the
25 * actual device on mine is a ESS 1868, and I don't want to hack the driver
26 * more than strictly necessary). I am not going to duplicate the
27 * hard coding of PC addresses (for the 16550s aso) here though; it's just
28 * too ugly.
29 */
30
31#define low_port(port) ((port) < 0x10000)
32
33static inline unsigned long port2addr(unsigned long port)
34{
35 switch(port >> 16) {
36 case 0:
37 return EC3104_ISA_BASE + port * 2;
38
39 /* XXX hack. it's unclear what to do about the serial ports */
40 case 1:
41 return EC3104_BASE + (port&0xffff) * 4;
42
43 default:
44 /* XXX PCMCIA */
45 return 0;
46 }
47}
48
49unsigned char ec3104_inb(unsigned long port)
50{
51 u8 ret;
52
53 ret = *(volatile u8 *)port2addr(port);
54
55 return ret;
56}
57
58unsigned short ec3104_inw(unsigned long port)
59{
60 BUG();
61}
62
63unsigned long ec3104_inl(unsigned long port)
64{
65 BUG();
66}
67
68void ec3104_outb(unsigned char data, unsigned long port)
69{
70 *(volatile u8 *)port2addr(port) = data;
71}
72
73void ec3104_outw(unsigned short data, unsigned long port)
74{
75 BUG();
76}
77
78void ec3104_outl(unsigned long data, unsigned long port)
79{
80 BUG();
81}
diff --git a/arch/sh/boards/ec3104/irq.c b/arch/sh/boards/ec3104/irq.c
new file mode 100644
index 00000000000..ffa4ff1f090
--- /dev/null
+++ b/arch/sh/boards/ec3104/irq.c
@@ -0,0 +1,196 @@
1/*
2 * linux/arch/sh/boards/ec3104/irq.c
3 * EC3104 companion chip support
4 *
5 * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
6 *
7 */
8
9#include <asm/io.h>
10#include <asm/irq.h>
11#include <asm/ec3104/ec3104.h>
12
13/* This is for debugging mostly; here's the table that I intend to keep
14 * in here:
15 *
16 * index function base addr power interrupt bit
17 * 0 power b0ec0000 --- 00000001 (unused)
18 * 1 irqs b0ec1000 --- 00000002 (unused)
19 * 2 ?? b0ec2000 b0ec0008 00000004
20 * 3 PS2 (1) b0ec3000 b0ec000c 00000008
21 * 4 PS2 (2) b0ec4000 b0ec0010 00000010
22 * 5 ?? b0ec5000 b0ec0014 00000020
23 * 6 I2C b0ec6000 b0ec0018 00000040
24 * 7 serial (1) b0ec7000 b0ec001c 00000080
25 * 8 serial (2) b0ec8000 b0ec0020 00000100
26 * 9 serial (3) b0ec9000 b0ec0024 00000200
27 * 10 serial (4) b0eca000 b0ec0028 00000400
28 * 12 GPIO (1) b0ecc000 b0ec0030
29 * 13 GPIO (2) b0ecc000 b0ec0030
30 * 16 pcmcia (1) b0ed0000 b0ec0040 00010000
31 * 17 pcmcia (2) b0ed1000 b0ec0044 00020000
32 */
33
34/* I used the register names from another interrupt controller I worked with,
35 * since it seems to be identical to the ec3104 except that all bits are
36 * inverted:
37 *
38 * IRR: Interrupt Request Register (pending and enabled interrupts)
39 * IMR: Interrupt Mask Register (which interrupts are enabled)
40 * IPR: Interrupt Pending Register (pending interrupts, even disabled ones)
41 *
42 * 0 bits mean pending or enabled, 1 bits mean not pending or disabled. all
43 * IRQs seem to be level-triggered.
44 */
45
46#define EC3104_IRR (EC3104_BASE + 0x1000)
47#define EC3104_IMR (EC3104_BASE + 0x1004)
48#define EC3104_IPR (EC3104_BASE + 0x1008)
49
50#define ctrl_readl(addr) (*(volatile u32 *)(addr))
51#define ctrl_writel(data,addr) (*(volatile u32 *)(addr) = (data))
52#define ctrl_readb(addr) (*(volatile u8 *)(addr))
53
54static char *ec3104_name(unsigned index)
55{
56 switch(index) {
57 case 0:
58 return "power management";
59 case 1:
60 return "interrupts";
61 case 3:
62 return "PS2 (1)";
63 case 4:
64 return "PS2 (2)";
65 case 5:
66 return "I2C (1)";
67 case 6:
68 return "I2C (2)";
69 case 7:
70 return "serial (1)";
71 case 8:
72 return "serial (2)";
73 case 9:
74 return "serial (3)";
75 case 10:
76 return "serial (4)";
77 case 16:
78 return "pcmcia (1)";
79 case 17:
80 return "pcmcia (2)";
81 default: {
82 static char buf[32];
83
84 sprintf(buf, "unknown (%d)", index);
85
86 return buf;
87 }
88 }
89}
90
91int get_pending_interrupts(char *buf)
92{
93 u32 ipr;
94 u32 bit;
95 char *p = buf;
96
97 p += sprintf(p, "pending: (");
98
99 ipr = ctrl_inl(EC3104_IPR);
100
101 for (bit = 1; bit < 32; bit++)
102 if (!(ipr & (1<<bit)))
103 p += sprintf(p, "%s ", ec3104_name(bit));
104
105 p += sprintf(p, ")\n");
106
107 return p - buf;
108}
109
110static inline u32 ec3104_irq2mask(unsigned int irq)
111{
112 return (1 << (irq - EC3104_IRQBASE));
113}
114
115static inline void mask_ec3104_irq(unsigned int irq)
116{
117 u32 mask;
118
119 mask = ctrl_readl(EC3104_IMR);
120
121 mask |= ec3104_irq2mask(irq);
122
123 ctrl_writel(mask, EC3104_IMR);
124}
125
126static inline void unmask_ec3104_irq(unsigned int irq)
127{
128 u32 mask;
129
130 mask = ctrl_readl(EC3104_IMR);
131
132 mask &= ~ec3104_irq2mask(irq);
133
134 ctrl_writel(mask, EC3104_IMR);
135}
136
137static void disable_ec3104_irq(unsigned int irq)
138{
139 mask_ec3104_irq(irq);
140}
141
142static void enable_ec3104_irq(unsigned int irq)
143{
144 unmask_ec3104_irq(irq);
145}
146
147static void mask_and_ack_ec3104_irq(unsigned int irq)
148{
149 mask_ec3104_irq(irq);
150}
151
152static void end_ec3104_irq(unsigned int irq)
153{
154 if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
155 unmask_ec3104_irq(irq);
156}
157
158static unsigned int startup_ec3104_irq(unsigned int irq)
159{
160 unmask_ec3104_irq(irq);
161
162 return 0;
163}
164
165static void shutdown_ec3104_irq(unsigned int irq)
166{
167 mask_ec3104_irq(irq);
168
169}
170
171static struct hw_interrupt_type ec3104_int = {
172 .typename = "EC3104",
173 .enable = enable_ec3104_irq,
174 .disable = disable_ec3104_irq,
175 .ack = mask_and_ack_ec3104_irq,
176 .end = end_ec3104_irq,
177 .startup = startup_ec3104_irq,
178 .shutdown = shutdown_ec3104_irq,
179};
180
181/* Yuck. the _demux API is ugly */
182int ec3104_irq_demux(int irq)
183{
184 if (irq == EC3104_IRQ) {
185 unsigned int mask;
186
187 mask = ctrl_readl(EC3104_IRR);
188
189 if (mask == 0xffffffff)
190 return EC3104_IRQ;
191 else
192 return EC3104_IRQBASE + ffz(mask);
193 }
194
195 return irq;
196}
diff --git a/arch/sh/boards/ec3104/setup.c b/arch/sh/boards/ec3104/setup.c
new file mode 100644
index 00000000000..5130ba2b6ff
--- /dev/null
+++ b/arch/sh/boards/ec3104/setup.c
@@ -0,0 +1,78 @@
1/*
2 * linux/arch/sh/boards/ec3104/setup.c
3 * EC3104 companion chip support
4 *
5 * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
6 *
7 */
8/* EC3104 note:
9 * This code was written without any documentation about the EC3104 chip. While
10 * I hope I got most of the basic functionality right, the register names I use
11 * are most likely completely different from those in the chip documentation.
12 *
13 * If you have any further information about the EC3104, please tell me
14 * (prumpf@tux.org).
15 */
16
17#include <linux/sched.h>
18#include <linux/kernel.h>
19#include <linux/param.h>
20#include <linux/interrupt.h>
21#include <linux/init.h>
22#include <linux/irq.h>
23#include <linux/types.h>
24
25#include <asm/io.h>
26#include <asm/irq.h>
27#include <asm/machvec.h>
28#include <asm/mach/ec3104.h>
29
30const char *get_system_type(void)
31{
32 return "EC3104";
33}
34
35/*
36 * The Machine Vector
37 */
38
39struct sh_machine_vector mv_ec3104 __initmv = {
40 .mv_nr_irqs = 96,
41
42 .mv_inb = ec3104_inb,
43 .mv_inw = ec3104_inw,
44 .mv_inl = ec3104_inl,
45 .mv_outb = ec3104_outb,
46 .mv_outw = ec3104_outw,
47 .mv_outl = ec3104_outl,
48
49 .mv_irq_demux = ec3104_irq_demux,
50};
51
52ALIAS_MV(ec3104)
53
54int __init platform_setup(void)
55{
56 char str[8];
57 int i;
58
59 if (0)
60 return 0;
61
62 for (i=0; i<8; i++)
63 str[i] = ctrl_readb(EC3104_BASE + i);
64
65 for (i = EC3104_IRQBASE; i < EC3104_IRQBASE + 32; i++)
66 irq_desc[i].handler = &ec3104_int;
67
68 printk("initializing EC3104 \"%.8s\" at %08x, IRQ %d, IRQ base %d\n",
69 str, EC3104_BASE, EC3104_IRQ, EC3104_IRQBASE);
70
71
72 /* mask all interrupts. this should have been done by the boot
73 * loader for us but we want to be sure ... */
74 ctrl_writel(0xffffffff, EC3104_IMR);
75
76 return 0;
77}
78
diff --git a/arch/sh/boards/harp/Makefile b/arch/sh/boards/harp/Makefile
new file mode 100644
index 00000000000..eb753d31812
--- /dev/null
+++ b/arch/sh/boards/harp/Makefile
@@ -0,0 +1,8 @@
1#
2# Makefile for STMicroelectronics board specific parts of the kernel
3#
4
5obj-y := irq.o setup.o mach.o led.o
6
7obj-$(CONFIG_PCI) += pcidma.o
8
diff --git a/arch/sh/boards/harp/irq.c b/arch/sh/boards/harp/irq.c
new file mode 100644
index 00000000000..acd58489970
--- /dev/null
+++ b/arch/sh/boards/harp/irq.c
@@ -0,0 +1,148 @@
1/*
2 * Copyright (C) 2000 David J. Mckay (david.mckay@st.com)
3 *
4 * May be copied or modified under the terms of the GNU General Public
5 * License. See linux/COPYING for more information.
6 *
7 * Looks after interrupts on the HARP board.
8 *
9 * Bases on the IPR irq system
10 */
11
12#include <linux/config.h>
13#include <linux/init.h>
14#include <linux/irq.h>
15
16#include <asm/system.h>
17#include <asm/io.h>
18#include <asm/harp/harp.h>
19
20
21#define NUM_EXTERNAL_IRQS 16
22
23// Early versions of the STB1 Overdrive required this nasty frig
24//#define INVERT_INTMASK_WRITES
25
26static void enable_harp_irq(unsigned int irq);
27static void disable_harp_irq(unsigned int irq);
28
29/* shutdown is same as "disable" */
30#define shutdown_harp_irq disable_harp_irq
31
32static void mask_and_ack_harp(unsigned int);
33static void end_harp_irq(unsigned int irq);
34
35static unsigned int startup_harp_irq(unsigned int irq)
36{
37 enable_harp_irq(irq);
38 return 0; /* never anything pending */
39}
40
41static struct hw_interrupt_type harp_irq_type = {
42 "Harp-IRQ",
43 startup_harp_irq,
44 shutdown_harp_irq,
45 enable_harp_irq,
46 disable_harp_irq,
47 mask_and_ack_harp,
48 end_harp_irq
49};
50
51static void disable_harp_irq(unsigned int irq)
52{
53 unsigned val, flags;
54 unsigned maskReg;
55 unsigned mask;
56 int pri;
57
58 if (irq < 0 || irq >= NUM_EXTERNAL_IRQS)
59 return;
60
61 pri = 15 - irq;
62
63 if (pri < 8) {
64 maskReg = EPLD_INTMASK0;
65 } else {
66 maskReg = EPLD_INTMASK1;
67 pri -= 8;
68 }
69
70 local_irq_save(flags);
71 mask = ctrl_inl(maskReg);
72 mask &= (~(1 << pri));
73#if defined(INVERT_INTMASK_WRITES)
74 mask ^= 0xff;
75#endif
76 ctrl_outl(mask, maskReg);
77 local_irq_restore(flags);
78}
79
80static void enable_harp_irq(unsigned int irq)
81{
82 unsigned flags;
83 unsigned maskReg;
84 unsigned mask;
85 int pri;
86
87 if (irq < 0 || irq >= NUM_EXTERNAL_IRQS)
88 return;
89
90 pri = 15 - irq;
91
92 if (pri < 8) {
93 maskReg = EPLD_INTMASK0;
94 } else {
95 maskReg = EPLD_INTMASK1;
96 pri -= 8;
97 }
98
99 local_irq_save(flags);
100 mask = ctrl_inl(maskReg);
101
102
103 mask |= (1 << pri);
104
105#if defined(INVERT_INTMASK_WRITES)
106 mask ^= 0xff;
107#endif
108 ctrl_outl(mask, maskReg);
109
110 local_irq_restore(flags);
111}
112
113/* This functions sets the desired irq handler to be an overdrive type */
114static void __init make_harp_irq(unsigned int irq)
115{
116 disable_irq_nosync(irq);
117 irq_desc[irq].handler = &harp_irq_type;
118 disable_harp_irq(irq);
119}
120
121static void mask_and_ack_harp(unsigned int irq)
122{
123 disable_harp_irq(irq);
124}
125
126static void end_harp_irq(unsigned int irq)
127{
128 enable_harp_irq(irq);
129}
130
131void __init init_harp_irq(void)
132{
133 int i;
134
135#if !defined(INVERT_INTMASK_WRITES)
136 // On the harp these are set to enable an interrupt
137 ctrl_outl(0x00, EPLD_INTMASK0);
138 ctrl_outl(0x00, EPLD_INTMASK1);
139#else
140 // On the Overdrive the data is inverted before being stored in the reg
141 ctrl_outl(0xff, EPLD_INTMASK0);
142 ctrl_outl(0xff, EPLD_INTMASK1);
143#endif
144
145 for (i = 0; i < NUM_EXTERNAL_IRQS; i++) {
146 make_harp_irq(i);
147 }
148}
diff --git a/arch/sh/boards/harp/led.c b/arch/sh/boards/harp/led.c
new file mode 100644
index 00000000000..76ca4ccac70
--- /dev/null
+++ b/arch/sh/boards/harp/led.c
@@ -0,0 +1,52 @@
1/*
2 * linux/arch/sh/stboards/led.c
3 *
4 * Copyright (C) 2000 Stuart Menefy <stuart.menefy@st.com>
5 *
6 * May be copied or modified under the terms of the GNU General Public
7 * License. See linux/COPYING for more information.
8 *
9 * This file contains ST40STB1 HARP and compatible code.
10 */
11
12#include <linux/config.h>
13#include <asm/io.h>
14#include <asm/harp/harp.h>
15
16/* Harp: Flash LD10 (front pannel) connected to EPLD (IC8) */
17/* Overdrive: Flash LD1 (front panel) connected to EPLD (IC4) */
18/* Works for HARP and overdrive */
19static void mach_led(int position, int value)
20{
21 if (value) {
22 ctrl_outl(EPLD_LED_ON, EPLD_LED);
23 } else {
24 ctrl_outl(EPLD_LED_OFF, EPLD_LED);
25 }
26}
27
28#ifdef CONFIG_HEARTBEAT
29
30#include <linux/sched.h>
31
32/* acts like an actual heart beat -- ie thump-thump-pause... */
33void heartbeat_harp(void)
34{
35 static unsigned cnt = 0, period = 0, dist = 0;
36
37 if (cnt == 0 || cnt == dist)
38 mach_led( -1, 1);
39 else if (cnt == 7 || cnt == dist+7)
40 mach_led( -1, 0);
41
42 if (++cnt > period) {
43 cnt = 0;
44 /* The hyperbolic function below modifies the heartbeat period
45 * length in dependency of the current (5min) load. It goes
46 * through the points f(0)=126, f(1)=86, f(5)=51,
47 * f(inf)->30. */
48 period = ((672<<FSHIFT)/(5*avenrun[0]+(7<<FSHIFT))) + 30;
49 dist = period / 4;
50 }
51}
52#endif
diff --git a/arch/sh/boards/harp/mach.c b/arch/sh/boards/harp/mach.c
new file mode 100644
index 00000000000..a946dd1674c
--- /dev/null
+++ b/arch/sh/boards/harp/mach.c
@@ -0,0 +1,62 @@
1/*
2 * linux/arch/sh/boards/harp/mach.c
3 *
4 * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com)
5 *
6 * May be copied or modified under the terms of the GNU General Public
7 * License. See linux/COPYING for more information.
8 *
9 * Machine vector for the STMicroelectronics STB1 HARP and compatible boards
10 */
11
12#include <linux/init.h>
13
14#include <asm/machvec.h>
15#include <asm/rtc.h>
16#include <asm/machvec_init.h>
17#include <asm/hd64465/io.h>
18#include <asm/hd64465/hd64465.h>
19
20void setup_harp(void);
21void init_harp_irq(void);
22void heartbeat_harp(void);
23
24/*
25 * The Machine Vector
26 */
27
28struct sh_machine_vector mv_harp __initmv = {
29 .mv_nr_irqs = 89 + HD64465_IRQ_NUM,
30
31 .mv_inb = hd64465_inb,
32 .mv_inw = hd64465_inw,
33 .mv_inl = hd64465_inl,
34 .mv_outb = hd64465_outb,
35 .mv_outw = hd64465_outw,
36 .mv_outl = hd64465_outl,
37
38 .mv_inb_p = hd64465_inb_p,
39 .mv_inw_p = hd64465_inw,
40 .mv_inl_p = hd64465_inl,
41 .mv_outb_p = hd64465_outb_p,
42 .mv_outw_p = hd64465_outw,
43 .mv_outl_p = hd64465_outl,
44
45 .mv_insb = hd64465_insb,
46 .mv_insw = hd64465_insw,
47 .mv_insl = hd64465_insl,
48 .mv_outsb = hd64465_outsb,
49 .mv_outsw = hd64465_outsw,
50 .mv_outsl = hd64465_outsl,
51
52 .mv_isa_port2addr = hd64465_isa_port2addr,
53
54#ifdef CONFIG_PCI
55 .mv_init_irq = init_harp_irq,
56#endif
57#ifdef CONFIG_HEARTBEAT
58 .mv_heartbeat = heartbeat_harp,
59#endif
60};
61
62ALIAS_MV(harp)
diff --git a/arch/sh/boards/harp/pcidma.c b/arch/sh/boards/harp/pcidma.c
new file mode 100644
index 00000000000..475311390fd
--- /dev/null
+++ b/arch/sh/boards/harp/pcidma.c
@@ -0,0 +1,42 @@
1/*
2 * Copyright (C) 2001 David J. Mckay (david.mckay@st.com)
3 *
4 * May be copied or modified under the terms of the GNU General Public
5 * License. See linux/COPYING for more information.
6 *
7 * Dynamic DMA mapping support.
8 */
9
10#include <linux/types.h>
11#include <linux/mm.h>
12#include <linux/string.h>
13#include <linux/pci.h>
14#include <asm/io.h>
15#include <asm/addrspace.h>
16
17
18void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
19 dma_addr_t * dma_handle)
20{
21 void *ret;
22 int gfp = GFP_ATOMIC;
23
24 ret = (void *) __get_free_pages(gfp, get_order(size));
25
26 if (ret != NULL) {
27 /* Is it neccessary to do the memset? */
28 memset(ret, 0, size);
29 *dma_handle = virt_to_bus(ret);
30 }
31 /* We must flush the cache before we pass it on to the device */
32 flush_cache_all();
33 return P2SEGADDR(ret);
34}
35
36void pci_free_consistent(struct pci_dev *hwdev, size_t size,
37 void *vaddr, dma_addr_t dma_handle)
38{
39 unsigned long p1addr=P1SEGADDR((unsigned long)vaddr);
40
41 free_pages(p1addr, get_order(size));
42}
diff --git a/arch/sh/boards/harp/setup.c b/arch/sh/boards/harp/setup.c
new file mode 100644
index 00000000000..05b01b8f40a
--- /dev/null
+++ b/arch/sh/boards/harp/setup.c
@@ -0,0 +1,91 @@
1/*
2 * arch/sh/stboard/setup.c
3 *
4 * Copyright (C) 2001 Stuart Menefy (stuart.menefy@st.com)
5 *
6 * May be copied or modified under the terms of the GNU General Public
7 * License. See linux/COPYING for more information.
8 *
9 * STMicroelectronics ST40STB1 HARP and compatible support.
10 */
11
12#include <linux/config.h>
13#include <linux/kernel.h>
14#include <linux/init.h>
15#include <asm/io.h>
16#include <asm/harp/harp.h>
17
18const char *get_system_type(void)
19{
20 return "STB1 Harp";
21}
22
23/*
24 * Initialize the board
25 */
26int __init platform_setup(void)
27{
28#ifdef CONFIG_SH_STB1_HARP
29 unsigned long ic8_version, ic36_version;
30
31 ic8_version = ctrl_inl(EPLD_REVID2);
32 ic36_version = ctrl_inl(EPLD_REVID1);
33
34 printk("STMicroelectronics STB1 HARP initialisaton\n");
35 printk("EPLD versions: IC8: %d.%02d, IC36: %d.%02d\n",
36 (ic8_version >> 4) & 0xf, ic8_version & 0xf,
37 (ic36_version >> 4) & 0xf, ic36_version & 0xf);
38#elif defined(CONFIG_SH_STB1_OVERDRIVE)
39 unsigned long version;
40
41 version = ctrl_inl(EPLD_REVID);
42
43 printk("STMicroelectronics STB1 Overdrive initialisaton\n");
44 printk("EPLD version: %d.%02d\n",
45 (version >> 4) & 0xf, version & 0xf);
46#else
47#error Undefined machine
48#endif
49
50 /* Currently all STB1 chips have problems with the sleep instruction,
51 * so disable it here.
52 */
53 disable_hlt();
54
55 return 0;
56}
57
58/*
59 * pcibios_map_platform_irq
60 *
61 * This is board specific and returns the IRQ for a given PCI device.
62 * It is used by the PCI code (arch/sh/kernel/st40_pci*)
63 *
64 */
65
66#define HARP_PCI_IRQ 1
67#define HARP_BRIDGE_IRQ 2
68#define OVERDRIVE_SLOT0_IRQ 0
69
70
71int __init pcibios_map_platform_irq(struct pci_dev *dev, u8 slot, u8 pin)
72{
73 switch (slot) {
74#ifdef CONFIG_SH_STB1_HARP
75 case 2: /*This is the PCI slot on the */
76 return HARP_PCI_IRQ;
77 case 1: /* this is the bridge */
78 return HARP_BRIDGE_IRQ;
79#elif defined(CONFIG_SH_STB1_OVERDRIVE)
80 case 1:
81 case 2:
82 case 3:
83 return slot - 1;
84#else
85#error Unknown board
86#endif
87 default:
88 return -1;
89 }
90}
91
diff --git a/arch/sh/boards/hp6xx/hp620/Makefile b/arch/sh/boards/hp6xx/hp620/Makefile
new file mode 100644
index 00000000000..20691dbce34
--- /dev/null
+++ b/arch/sh/boards/hp6xx/hp620/Makefile
@@ -0,0 +1,6 @@
1#
2# Makefile for the HP620 specific parts of the kernel
3#
4
5obj-y := mach.o setup.o
6
diff --git a/arch/sh/boards/hp6xx/hp620/mach.c b/arch/sh/boards/hp6xx/hp620/mach.c
new file mode 100644
index 00000000000..0392d82b4a7
--- /dev/null
+++ b/arch/sh/boards/hp6xx/hp620/mach.c
@@ -0,0 +1,52 @@
1/*
2 * linux/arch/sh/boards/hp6xx/hp620/mach.c
3 *
4 * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com)
5 *
6 * May be copied or modified under the terms of the GNU General Public
7 * License. See linux/COPYING for more information.
8 *
9 * Machine vector for the HP620
10 */
11
12#include <linux/init.h>
13
14#include <asm/machvec.h>
15#include <asm/rtc.h>
16#include <asm/machvec_init.h>
17
18#include <asm/io.h>
19#include <asm/hd64461/hd64461.h>
20#include <asm/irq.h>
21
22/*
23 * The Machine Vector
24 */
25
26struct sh_machine_vector mv_hp620 __initmv = {
27 .mv_nr_irqs = HD64461_IRQBASE+HD64461_IRQ_NUM,
28
29 .mv_inb = hd64461_inb,
30 .mv_inw = hd64461_inw,
31 .mv_inl = hd64461_inl,
32 .mv_outb = hd64461_outb,
33 .mv_outw = hd64461_outw,
34 .mv_outl = hd64461_outl,
35
36 .mv_inb_p = hd64461_inb_p,
37 .mv_inw_p = hd64461_inw,
38 .mv_inl_p = hd64461_inl,
39 .mv_outb_p = hd64461_outb_p,
40 .mv_outw_p = hd64461_outw,
41 .mv_outl_p = hd64461_outl,
42
43 .mv_insb = hd64461_insb,
44 .mv_insw = hd64461_insw,
45 .mv_insl = hd64461_insl,
46 .mv_outsb = hd64461_outsb,
47 .mv_outsw = hd64461_outsw,
48 .mv_outsl = hd64461_outsl,
49
50 .mv_irq_demux = hd64461_irq_demux,
51};
52ALIAS_MV(hp620)
diff --git a/arch/sh/boards/hp6xx/hp620/setup.c b/arch/sh/boards/hp6xx/hp620/setup.c
new file mode 100644
index 00000000000..045fc5da727
--- /dev/null
+++ b/arch/sh/boards/hp6xx/hp620/setup.c
@@ -0,0 +1,45 @@
1/*
2 * linux/arch/sh/boards/hp6xx/hp620/setup.c
3 *
4 * Copyright (C) 2002 Andriy Skulysh, 2005 Kristoffer Ericson
5 *
6 * May be copied or modified under the terms of the GNU General Public
7 * License. See Linux/COPYING for more information.
8 *
9 * Setup code for an HP620.
10 * Due to similiarity with hp680/hp690 same inits are done (for now)
11 */
12
13#include <linux/config.h>
14#include <linux/init.h>
15#include <asm/hd64461/hd64461.h>
16#include <asm/io.h>
17#include <asm/hp6xx/hp6xx.h>
18#include <asm/cpu/dac.h>
19
20const char *get_system_type(void)
21{
22 return "HP620";
23}
24
25int __init platform_setup(void)
26{
27 u16 v;
28
29 v = inw(HD64461_STBCR);
30 v |= HD64461_STBCR_SURTST | HD64461_STBCR_SIRST |
31 HD64461_STBCR_STM1ST | HD64461_STBCR_STM0ST |
32 HD64461_STBCR_SAFEST | HD64461_STBCR_SPC0ST |
33 HD64461_STBCR_SMIAST | HD64461_STBCR_SAFECKE_OST |
34 HD64461_STBCR_SAFECKE_IST;
35 outw(v, HD64461_STBCR);
36
37 v = inw(HD64461_GPADR);
38 v |= HD64461_GPADR_SPEAKER | HD64461_GPADR_PCMCIA0;
39 outw(v, HD64461_GPADR);
40
41 sh_dac_disable(DAC_SPEAKER_VOLUME);
42
43 return 0;
44}
45
diff --git a/arch/sh/boards/hp6xx/hp680/Makefile b/arch/sh/boards/hp6xx/hp680/Makefile
new file mode 100644
index 00000000000..0beef11d9b1
--- /dev/null
+++ b/arch/sh/boards/hp6xx/hp680/Makefile
@@ -0,0 +1,6 @@
1#
2# Makefile for the HP680 specific parts of the kernel
3#
4
5obj-y := mach.o setup.o
6
diff --git a/arch/sh/boards/hp6xx/hp680/mach.c b/arch/sh/boards/hp6xx/hp680/mach.c
new file mode 100644
index 00000000000..d7348613604
--- /dev/null
+++ b/arch/sh/boards/hp6xx/hp680/mach.c
@@ -0,0 +1,53 @@
1/*
2 * linux/arch/sh/boards/hp6xx/hp680/mach.c
3 *
4 * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com)
5 *
6 * May be copied or modified under the terms of the GNU General Public
7 * License. See linux/COPYING for more information.
8 *
9 * Machine vector for the HP680
10 */
11
12#include <linux/init.h>
13
14#include <asm/machvec.h>
15#include <asm/rtc.h>
16#include <asm/machvec_init.h>
17
18#include <asm/io.h>
19#include <asm/hd64461/hd64461.h>
20#include <asm/hp6xx/io.h>
21#include <asm/irq.h>
22
23struct sh_machine_vector mv_hp680 __initmv = {
24 .mv_nr_irqs = HD64461_IRQBASE + HD64461_IRQ_NUM,
25
26 .mv_inb = hd64461_inb,
27 .mv_inw = hd64461_inw,
28 .mv_inl = hd64461_inl,
29 .mv_outb = hd64461_outb,
30 .mv_outw = hd64461_outw,
31 .mv_outl = hd64461_outl,
32
33 .mv_inb_p = hd64461_inb_p,
34 .mv_inw_p = hd64461_inw,
35 .mv_inl_p = hd64461_inl,
36 .mv_outb_p = hd64461_outb_p,
37 .mv_outw_p = hd64461_outw,
38 .mv_outl_p = hd64461_outl,
39
40 .mv_insb = hd64461_insb,
41 .mv_insw = hd64461_insw,
42 .mv_insl = hd64461_insl,
43 .mv_outsb = hd64461_outsb,
44 .mv_outsw = hd64461_outsw,
45 .mv_outsl = hd64461_outsl,
46
47 .mv_readw = hd64461_readw,
48 .mv_writew = hd64461_writew,
49
50 .mv_irq_demux = hd64461_irq_demux,
51};
52
53ALIAS_MV(hp680)
diff --git a/arch/sh/boards/hp6xx/hp680/setup.c b/arch/sh/boards/hp6xx/hp680/setup.c
new file mode 100644
index 00000000000..4170190f264
--- /dev/null
+++ b/arch/sh/boards/hp6xx/hp680/setup.c
@@ -0,0 +1,41 @@
1/*
2 * linux/arch/sh/boards/hp6xx/hp680/setup.c
3 *
4 * Copyright (C) 2002 Andriy Skulysh
5 *
6 * May be copied or modified under the terms of the GNU General Public
7 * License. See linux/COPYING for more information.
8 *
9 * Setup code for an HP680 (internal peripherials only)
10 */
11
12#include <linux/config.h>
13#include <linux/init.h>
14#include <asm/hd64461/hd64461.h>
15#include <asm/io.h>
16#include <asm/hp6xx/hp6xx.h>
17#include <asm/cpu/dac.h>
18
19const char *get_system_type(void)
20{
21 return "HP680";
22}
23
24int __init platform_setup(void)
25{
26 u16 v;
27 v = inw(HD64461_STBCR);
28 v |= HD64461_STBCR_SURTST | HD64461_STBCR_SIRST |
29 HD64461_STBCR_STM1ST | HD64461_STBCR_STM0ST |
30 HD64461_STBCR_SAFEST | HD64461_STBCR_SPC0ST |
31 HD64461_STBCR_SMIAST | HD64461_STBCR_SAFECKE_OST |
32 HD64461_STBCR_SAFECKE_IST;
33 outw(v, HD64461_STBCR);
34 v = inw(HD64461_GPADR);
35 v |= HD64461_GPADR_SPEAKER | HD64461_GPADR_PCMCIA0;
36 outw(v, HD64461_GPADR);
37
38 sh_dac_disable(DAC_SPEAKER_VOLUME);
39
40 return 0;
41}
diff --git a/arch/sh/boards/hp6xx/hp690/Makefile b/arch/sh/boards/hp6xx/hp690/Makefile
new file mode 100644
index 00000000000..fbbe95e75f8
--- /dev/null
+++ b/arch/sh/boards/hp6xx/hp690/Makefile
@@ -0,0 +1,6 @@
1#
2# Makefile for the HP690 specific parts of the kernel
3#
4
5obj-y := mach.o
6
diff --git a/arch/sh/boards/hp6xx/hp690/mach.c b/arch/sh/boards/hp6xx/hp690/mach.c
new file mode 100644
index 00000000000..2a4c68783cd
--- /dev/null
+++ b/arch/sh/boards/hp6xx/hp690/mach.c
@@ -0,0 +1,48 @@
1/*
2 * linux/arch/sh/boards/hp6xx/hp690/mach.c
3 *
4 * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com)
5 *
6 * May be copied or modified under the terms of the GNU General Public
7 * License. See linux/COPYING for more information.
8 *
9 * Machine vector for the HP690
10 */
11
12#include <linux/init.h>
13
14#include <asm/machvec.h>
15#include <asm/rtc.h>
16#include <asm/machvec_init.h>
17
18#include <asm/io.h>
19#include <asm/hd64461/hd64461.h>
20#include <asm/irq.h>
21
22struct sh_machine_vector mv_hp690 __initmv = {
23 .mv_nr_irqs = HD64461_IRQBASE+HD64461_IRQ_NUM,
24
25 .mv_inb = hd64461_inb,
26 .mv_inw = hd64461_inw,
27 .mv_inl = hd64461_inl,
28 .mv_outb = hd64461_outb,
29 .mv_outw = hd64461_outw,
30 .mv_outl = hd64461_outl,
31
32 .mv_inb_p = hd64461_inb_p,
33 .mv_inw_p = hd64461_inw,
34 .mv_inl_p = hd64461_inl,
35 .mv_outb_p = hd64461_outb_p,
36 .mv_outw_p = hd64461_outw,
37 .mv_outl_p = hd64461_outl,
38
39 .mv_insb = hd64461_insb,
40 .mv_insw = hd64461_insw,
41 .mv_insl = hd64461_insl,
42 .mv_outsb = hd64461_outsb,
43 .mv_outsw = hd64461_outsw,
44 .mv_outsl = hd64461_outsl,
45
46 .mv_irq_demux = hd64461_irq_demux,
47};
48ALIAS_MV(hp690)
diff --git a/arch/sh/boards/mpc1211/Makefile b/arch/sh/boards/mpc1211/Makefile
new file mode 100644
index 00000000000..1644ebed78c
--- /dev/null
+++ b/arch/sh/boards/mpc1211/Makefile
@@ -0,0 +1,8 @@
1#
2# Makefile for the Interface (CTP/PCI/MPC-SH02) specific parts of the kernel
3#
4
5obj-y := setup.o rtc.o led.o
6
7obj-$(CONFIG_PCI) += pci.o
8
diff --git a/arch/sh/boards/mpc1211/led.c b/arch/sh/boards/mpc1211/led.c
new file mode 100644
index 00000000000..0a31beec346
--- /dev/null
+++ b/arch/sh/boards/mpc1211/led.c
@@ -0,0 +1,64 @@
1/*
2 * linux/arch/sh/kernel/led_mpc1211.c
3 *
4 * Copyright (C) 2001 Saito.K & Jeanne
5 *
6 * This file contains Interface MPC-1211 specific LED code.
7 */
8
9#include <linux/config.h>
10
11static void mach_led(int position, int value)
12{
13 volatile unsigned char* p = (volatile unsigned char*)0xa2000000;
14
15 if (value) {
16 *p |= 1;
17 } else {
18 *p &= ~1;
19 }
20}
21
22#ifdef CONFIG_HEARTBEAT
23
24#include <linux/sched.h>
25
26/* Cycle the LED's in the clasic Knightrider/Sun pattern */
27void heartbeat_mpc1211(void)
28{
29 static unsigned int cnt = 0, period = 0;
30 volatile unsigned char* p = (volatile unsigned char*)0xa2000000;
31 static unsigned bit = 0, up = 1;
32
33 cnt += 1;
34 if (cnt < period) {
35 return;
36 }
37
38 cnt = 0;
39
40 /* Go through the points (roughly!):
41 * f(0)=10, f(1)=16, f(2)=20, f(5)=35,f(inf)->110
42 */
43 period = 110 - ( (300<<FSHIFT)/
44 ((avenrun[0]/5) + (3<<FSHIFT)) );
45
46 if (up) {
47 if (bit == 7) {
48 bit--;
49 up=0;
50 } else {
51 bit ++;
52 }
53 } else {
54 if (bit == 0) {
55 bit++;
56 up=1;
57 } else {
58 bit--;
59 }
60 }
61 *p = 1<<bit;
62
63}
64#endif /* CONFIG_HEARTBEAT */
diff --git a/arch/sh/boards/mpc1211/pci.c b/arch/sh/boards/mpc1211/pci.c
new file mode 100644
index 00000000000..ba3a6543975
--- /dev/null
+++ b/arch/sh/boards/mpc1211/pci.c
@@ -0,0 +1,296 @@
1/*
2 * Low-Level PCI Support for the MPC-1211(CTP/PCI/MPC-SH02)
3 *
4 * (c) 2002-2003 Saito.K & Jeanne
5 *
6 * Dustin McIntire (dustin@sensoria.com)
7 * Derived from arch/i386/kernel/pci-*.c which bore the message:
8 * (c) 1999--2000 Martin Mares <mj@ucw.cz>
9 *
10 * May be copied or modified under the terms of the GNU General Public
11 * License. See linux/COPYING for more information.
12 *
13 */
14#include <linux/config.h>
15#include <linux/types.h>
16#include <linux/kernel.h>
17#include <linux/init.h>
18#include <linux/delay.h>
19#include <linux/pci.h>
20#include <linux/sched.h>
21#include <linux/ioport.h>
22#include <linux/errno.h>
23#include <linux/irq.h>
24#include <linux/interrupt.h>
25
26#include <asm/machvec.h>
27#include <asm/io.h>
28#include <asm/mpc1211/pci.h>
29
30static struct resource mpcpci_io_resource = {
31 "MPCPCI IO",
32 0x00000000,
33 0xffffffff,
34 IORESOURCE_IO
35};
36
37static struct resource mpcpci_mem_resource = {
38 "MPCPCI mem",
39 0x00000000,
40 0xffffffff,
41 IORESOURCE_MEM
42};
43
44static struct pci_ops pci_direct_conf1;
45struct pci_channel board_pci_channels[] = {
46 {&pci_direct_conf1, &mpcpci_io_resource, &mpcpci_mem_resource, 0, 256},
47 {NULL, NULL, NULL, 0, 0},
48};
49
50/*
51 * Direct access to PCI hardware...
52 */
53
54
55#define CONFIG_CMD(bus, devfn, where) (0x80000000 | (bus->number << 16) | (devfn << 8) | (where & ~3))
56
57/*
58 * Functions for accessing PCI configuration space with type 1 accesses
59 */
60static int pci_conf1_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value)
61{
62 u32 word;
63 unsigned long flags;
64
65 /*
66 * PCIPDR may only be accessed as 32 bit words,
67 * so we must do byte alignment by hand
68 */
69 local_irq_save(flags);
70 writel(CONFIG_CMD(bus,devfn,where), PCIPAR);
71 word = readl(PCIPDR);
72 local_irq_restore(flags);
73
74 switch (size) {
75 case 1:
76 switch (where & 0x3) {
77 case 3:
78 *value = (u8)(word >> 24);
79 break;
80 case 2:
81 *value = (u8)(word >> 16);
82 break;
83 case 1:
84 *value = (u8)(word >> 8);
85 break;
86 default:
87 *value = (u8)word;
88 break;
89 }
90 break;
91 case 2:
92 switch (where & 0x3) {
93 case 3:
94 *value = (u16)(word >> 24);
95 local_irq_save(flags);
96 writel(CONFIG_CMD(bus,devfn,(where+1)), PCIPAR);
97 word = readl(PCIPDR);
98 local_irq_restore(flags);
99 *value |= ((word & 0xff) << 8);
100 break;
101 case 2:
102 *value = (u16)(word >> 16);
103 break;
104 case 1:
105 *value = (u16)(word >> 8);
106 break;
107 default:
108 *value = (u16)word;
109 break;
110 }
111 break;
112 case 4:
113 *value = word;
114 break;
115 }
116 PCIDBG(4,"pci_conf1_read@0x%08x=0x%x\n", CONFIG_CMD(bus,devfn,where),*value);
117 return PCIBIOS_SUCCESSFUL;
118}
119
120/*
121 * Since MPC-1211 only does 32bit access we'll have to do a read,mask,write operation.
122 * We'll allow an odd byte offset, though it should be illegal.
123 */
124static int pci_conf1_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value)
125{
126 u32 word,mask = 0;
127 unsigned long flags;
128 u32 shift = (where & 3) * 8;
129
130 if(size == 1) {
131 mask = ((1 << 8) - 1) << shift; // create the byte mask
132 } else if(size == 2){
133 if(shift == 24)
134 return PCIBIOS_BAD_REGISTER_NUMBER;
135 mask = ((1 << 16) - 1) << shift; // create the word mask
136 }
137 local_irq_save(flags);
138 writel(CONFIG_CMD(bus,devfn,where), PCIPAR);
139 if(size == 4){
140 writel(value, PCIPDR);
141 local_irq_restore(flags);
142 PCIDBG(4,"pci_conf1_write@0x%08x=0x%x\n", CONFIG_CMD(bus,devfn,where),value);
143 return PCIBIOS_SUCCESSFUL;
144 }
145 word = readl(PCIPDR);
146 word &= ~mask;
147 word |= ((value << shift) & mask);
148 writel(word, PCIPDR);
149 local_irq_restore(flags);
150 PCIDBG(4,"pci_conf1_write@0x%08x=0x%x\n", CONFIG_CMD(bus,devfn,where),word);
151 return PCIBIOS_SUCCESSFUL;
152}
153
154#undef CONFIG_CMD
155
156static struct pci_ops pci_direct_conf1 = {
157 .read = pci_conf1_read,
158 .write = pci_conf1_write,
159};
160
161static void __devinit quirk_ali_ide_ports(struct pci_dev *dev)
162{
163 dev->resource[0].start = 0x1f0;
164 dev->resource[0].end = 0x1f7;
165 dev->resource[0].flags = IORESOURCE_IO;
166 dev->resource[1].start = 0x3f6;
167 dev->resource[1].end = 0x3f6;
168 dev->resource[1].flags = IORESOURCE_IO;
169 dev->resource[2].start = 0x170;
170 dev->resource[2].end = 0x177;
171 dev->resource[2].flags = IORESOURCE_IO;
172 dev->resource[3].start = 0x376;
173 dev->resource[3].end = 0x376;
174 dev->resource[3].flags = IORESOURCE_IO;
175 dev->resource[4].start = 0xf000;
176 dev->resource[4].end = 0xf00f;
177 dev->resource[4].flags = IORESOURCE_IO;
178}
179DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M5229, quirk_ali_ide_ports);
180
181char * __devinit pcibios_setup(char *str)
182{
183 return str;
184}
185
186/*
187 * Called after each bus is probed, but before its children
188 * are examined.
189 */
190
191void __init pcibios_fixup_bus(struct pci_bus *b)
192{
193 pci_read_bridge_bases(b);
194}
195
196/*
197 * IRQ functions
198 */
199static inline u8 bridge_swizzle(u8 pin, u8 slot)
200{
201 return (((pin-1) + slot) % 4) + 1;
202}
203
204static inline u8 bridge_swizzle_pci_1(u8 pin, u8 slot)
205{
206 return (((pin-1) - slot) & 3) + 1;
207}
208
209static u8 __init mpc1211_swizzle(struct pci_dev *dev, u8 *pinp)
210{
211 unsigned long flags;
212 u8 pin = *pinp;
213 u32 word;
214
215 for ( ; dev->bus->self; dev = dev->bus->self) {
216 if (!pin)
217 continue;
218
219 if (dev->bus->number == 1) {
220 local_irq_save(flags);
221 writel(0x80000000 | 0x2c, PCIPAR);
222 word = readl(PCIPDR);
223 local_irq_restore(flags);
224 word >>= 16;
225
226 if (word == 0x0001)
227 pin = bridge_swizzle_pci_1(pin, PCI_SLOT(dev->devfn));
228 else
229 pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn));
230 } else
231 pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn));
232 }
233
234 *pinp = pin;
235
236 return PCI_SLOT(dev->devfn);
237}
238
239static int __init map_mpc1211_irq(struct pci_dev *dev, u8 slot, u8 pin)
240{
241 int irq = -1;
242
243 /* now lookup the actual IRQ on a platform specific basis (pci-'platform'.c) */
244 if (dev->bus->number == 0) {
245 switch (slot) {
246 case 13: irq = 9; break; /* USB */
247 case 22: irq = 10; break; /* LAN */
248 default: irq = 0; break;
249 }
250 } else {
251 switch (pin) {
252 case 0: irq = 0; break;
253 case 1: irq = 7; break;
254 case 2: irq = 9; break;
255 case 3: irq = 10; break;
256 case 4: irq = 11; break;
257 }
258 }
259
260 if( irq < 0 ) {
261 PCIDBG(3, "PCI: Error mapping IRQ on device %s\n", pci_name(dev));
262 return irq;
263 }
264
265 PCIDBG(2, "Setting IRQ for slot %s to %d\n", pci_name(dev), irq);
266
267 return irq;
268}
269
270void __init pcibios_fixup_irqs(void)
271{
272 pci_fixup_irqs(mpc1211_swizzle, map_mpc1211_irq);
273}
274
275void pcibios_align_resource(void *data, struct resource *res,
276 unsigned long size, unsigned long align)
277{
278 unsigned long start = res->start;
279
280 if (res->flags & IORESOURCE_IO) {
281 if (start >= 0x10000UL) {
282 if ((start & 0xffffUL) < 0x4000UL) {
283 start = (start & 0xffff0000UL) + 0x4000UL;
284 } else if ((start & 0xffffUL) >= 0xf000UL) {
285 start = (start & 0xffff0000UL) + 0x10000UL;
286 }
287 res->start = start;
288 } else {
289 if (start & 0x300) {
290 start = (start + 0x3ff) & ~0x3ff;
291 res->start = start;
292 }
293 }
294 }
295}
296
diff --git a/arch/sh/boards/mpc1211/rtc.c b/arch/sh/boards/mpc1211/rtc.c
new file mode 100644
index 00000000000..4d100f04807
--- /dev/null
+++ b/arch/sh/boards/mpc1211/rtc.c
@@ -0,0 +1,152 @@
1/*
2 * linux/arch/sh/kernel/rtc-mpc1211.c -- MPC-1211 on-chip RTC support
3 *
4 * Copyright (C) 2002 Saito.K & Jeanne
5 *
6 */
7
8#include <linux/init.h>
9#include <linux/kernel.h>
10#include <linux/sched.h>
11#include <linux/time.h>
12#include <linux/mc146818rtc.h>
13
14#ifndef BCD_TO_BIN
15#define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10)
16#endif
17
18#ifndef BIN_TO_BCD
19#define BIN_TO_BCD(val) ((val)=(((val)/10)<<4) + (val)%10)
20#endif
21
22/* arc/i386/kernel/time.c */
23unsigned long get_cmos_time(void)
24{
25 unsigned int year, mon, day, hour, min, sec;
26 int i;
27
28 spin_lock(&rtc_lock);
29 /* The Linux interpretation of the CMOS clock register contents:
30 * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
31 * RTC registers show the second which has precisely just started.
32 * Let's hope other operating systems interpret the RTC the same way.
33 */
34 /* read RTC exactly on falling edge of update flag */
35 for (i = 0 ; i < 1000000 ; i++) /* may take up to 1 second... */
36 if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)
37 break;
38 for (i = 0 ; i < 1000000 ; i++) /* must try at least 2.228 ms */
39 if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP))
40 break;
41 do { /* Isn't this overkill ? UIP above should guarantee consistency */
42 sec = CMOS_READ(RTC_SECONDS);
43 min = CMOS_READ(RTC_MINUTES);
44 hour = CMOS_READ(RTC_HOURS);
45 day = CMOS_READ(RTC_DAY_OF_MONTH);
46 mon = CMOS_READ(RTC_MONTH);
47 year = CMOS_READ(RTC_YEAR);
48 } while (sec != CMOS_READ(RTC_SECONDS));
49 if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
50 {
51 BCD_TO_BIN(sec);
52 BCD_TO_BIN(min);
53 BCD_TO_BIN(hour);
54 BCD_TO_BIN(day);
55 BCD_TO_BIN(mon);
56 BCD_TO_BIN(year);
57 }
58 spin_unlock(&rtc_lock);
59 if ((year += 1900) < 1970)
60 year += 100;
61 return mktime(year, mon, day, hour, min, sec);
62}
63
64void mpc1211_rtc_gettimeofday(struct timeval *tv)
65{
66
67 tv->tv_sec = get_cmos_time();
68 tv->tv_usec = 0;
69}
70
71/* arc/i386/kernel/time.c */
72/*
73 * In order to set the CMOS clock precisely, set_rtc_mmss has to be
74 * called 500 ms after the second nowtime has started, because when
75 * nowtime is written into the registers of the CMOS clock, it will
76 * jump to the next second precisely 500 ms later. Check the Motorola
77 * MC146818A or Dallas DS12887 data sheet for details.
78 *
79 * BUG: This routine does not handle hour overflow properly; it just
80 * sets the minutes. Usually you'll only notice that after reboot!
81 */
82static int set_rtc_mmss(unsigned long nowtime)
83{
84 int retval = 0;
85 int real_seconds, real_minutes, cmos_minutes;
86 unsigned char save_control, save_freq_select;
87
88 /* gets recalled with irq locally disabled */
89 spin_lock(&rtc_lock);
90 save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */
91 CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
92
93 save_freq_select = CMOS_READ(RTC_FREQ_SELECT); /* stop and reset prescaler */
94 CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
95
96 cmos_minutes = CMOS_READ(RTC_MINUTES);
97 if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
98 BCD_TO_BIN(cmos_minutes);
99
100 /*
101 * since we're only adjusting minutes and seconds,
102 * don't interfere with hour overflow. This avoids
103 * messing with unknown time zones but requires your
104 * RTC not to be off by more than 15 minutes
105 */
106 real_seconds = nowtime % 60;
107 real_minutes = nowtime / 60;
108 if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1)
109 real_minutes += 30; /* correct for half hour time zone */
110 real_minutes %= 60;
111
112 if (abs(real_minutes - cmos_minutes) < 30) {
113 if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
114 BIN_TO_BCD(real_seconds);
115 BIN_TO_BCD(real_minutes);
116 }
117 CMOS_WRITE(real_seconds,RTC_SECONDS);
118 CMOS_WRITE(real_minutes,RTC_MINUTES);
119 } else {
120 printk(KERN_WARNING
121 "set_rtc_mmss: can't update from %d to %d\n",
122 cmos_minutes, real_minutes);
123 retval = -1;
124 }
125
126 /* The following flags have to be released exactly in this order,
127 * otherwise the DS12887 (popular MC146818A clone with integrated
128 * battery and quartz) will not reset the oscillator and will not
129 * update precisely 500 ms later. You won't find this mentioned in
130 * the Dallas Semiconductor data sheets, but who believes data
131 * sheets anyway ... -- Markus Kuhn
132 */
133 CMOS_WRITE(save_control, RTC_CONTROL);
134 CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
135 spin_unlock(&rtc_lock);
136
137 return retval;
138}
139
140int mpc1211_rtc_settimeofday(const struct timeval *tv)
141{
142 unsigned long nowtime = tv->tv_sec;
143
144 return set_rtc_mmss(nowtime);
145}
146
147void mpc1211_time_init(void)
148{
149 rtc_get_time = mpc1211_rtc_gettimeofday;
150 rtc_set_time = mpc1211_rtc_settimeofday;
151}
152
diff --git a/arch/sh/boards/mpc1211/setup.c b/arch/sh/boards/mpc1211/setup.c
new file mode 100644
index 00000000000..2bb581b9168
--- /dev/null
+++ b/arch/sh/boards/mpc1211/setup.c
@@ -0,0 +1,360 @@
1/*
2 * linux/arch/sh/board/mpc1211/setup.c
3 *
4 * Copyright (C) 2002 Saito.K & Jeanne, Fujii.Y
5 *
6 */
7
8#include <linux/config.h>
9#include <linux/init.h>
10#include <linux/irq.h>
11#include <linux/hdreg.h>
12#include <linux/ide.h>
13#include <linux/interrupt.h>
14
15#include <asm/io.h>
16#include <asm/machvec.h>
17#include <asm/mpc1211/mpc1211.h>
18#include <asm/mpc1211/pci.h>
19#include <asm/mpc1211/m1543c.h>
20
21
22/* ALI15X3 SMBus address offsets */
23#define SMBHSTSTS (0 + 0x3100)
24#define SMBHSTCNT (1 + 0x3100)
25#define SMBHSTSTART (2 + 0x3100)
26#define SMBHSTCMD (7 + 0x3100)
27#define SMBHSTADD (3 + 0x3100)
28#define SMBHSTDAT0 (4 + 0x3100)
29#define SMBHSTDAT1 (5 + 0x3100)
30#define SMBBLKDAT (6 + 0x3100)
31
32/* Other settings */
33#define MAX_TIMEOUT 500 /* times 1/100 sec */
34
35/* ALI15X3 command constants */
36#define ALI15X3_ABORT 0x04
37#define ALI15X3_T_OUT 0x08
38#define ALI15X3_QUICK 0x00
39#define ALI15X3_BYTE 0x10
40#define ALI15X3_BYTE_DATA 0x20
41#define ALI15X3_WORD_DATA 0x30
42#define ALI15X3_BLOCK_DATA 0x40
43#define ALI15X3_BLOCK_CLR 0x80
44
45/* ALI15X3 status register bits */
46#define ALI15X3_STS_IDLE 0x04
47#define ALI15X3_STS_BUSY 0x08
48#define ALI15X3_STS_DONE 0x10
49#define ALI15X3_STS_DEV 0x20 /* device error */
50#define ALI15X3_STS_COLL 0x40 /* collision or no response */
51#define ALI15X3_STS_TERM 0x80 /* terminated by abort */
52#define ALI15X3_STS_ERR 0xE0 /* all the bad error bits */
53
54const char *get_system_type(void)
55{
56 return "Interface MPC-1211(CTP/PCI/MPC-SH02)";
57}
58
59static void __init pci_write_config(unsigned long busNo,
60 unsigned long devNo,
61 unsigned long fncNo,
62 unsigned long cnfAdd,
63 unsigned long cnfData)
64{
65 ctrl_outl((0x80000000
66 + ((busNo & 0xff) << 16)
67 + ((devNo & 0x1f) << 11)
68 + ((fncNo & 0x07) << 8)
69 + (cnfAdd & 0xfc)), PCIPAR);
70
71 ctrl_outl(cnfData, PCIPDR);
72}
73
74/*
75 Initialize IRQ setting
76*/
77
78static unsigned char m_irq_mask = 0xfb;
79static unsigned char s_irq_mask = 0xff;
80volatile unsigned long irq_err_count;
81
82static void disable_mpc1211_irq(unsigned int irq)
83{
84 unsigned long flags;
85
86 save_and_cli(flags);
87 if( irq < 8) {
88 m_irq_mask |= (1 << irq);
89 outb(m_irq_mask,I8259_M_MR);
90 } else {
91 s_irq_mask |= (1 << (irq - 8));
92 outb(s_irq_mask,I8259_S_MR);
93 }
94 restore_flags(flags);
95
96}
97
98static void enable_mpc1211_irq(unsigned int irq)
99{
100 unsigned long flags;
101
102 save_and_cli(flags);
103
104 if( irq < 8) {
105 m_irq_mask &= ~(1 << irq);
106 outb(m_irq_mask,I8259_M_MR);
107 } else {
108 s_irq_mask &= ~(1 << (irq - 8));
109 outb(s_irq_mask,I8259_S_MR);
110 }
111 restore_flags(flags);
112}
113
114static inline int mpc1211_irq_real(unsigned int irq)
115{
116 int value;
117 int irqmask;
118
119 if ( irq < 8) {
120 irqmask = 1<<irq;
121 outb(0x0b,I8259_M_CR); /* ISR register */
122 value = inb(I8259_M_CR) & irqmask;
123 outb(0x0a,I8259_M_CR); /* back ro the IPR reg */
124 return value;
125 }
126 irqmask = 1<<(irq - 8);
127 outb(0x0b,I8259_S_CR); /* ISR register */
128 value = inb(I8259_S_CR) & irqmask;
129 outb(0x0a,I8259_S_CR); /* back ro the IPR reg */
130 return value;
131}
132
133static void mask_and_ack_mpc1211(unsigned int irq)
134{
135 unsigned long flags;
136
137 save_and_cli(flags);
138
139 if(irq < 8) {
140 if(m_irq_mask & (1<<irq)){
141 if(!mpc1211_irq_real(irq)){
142 irq_err_count++;
143 printk("spurious 8259A interrupt: IRQ %x\n",irq);
144 }
145 } else {
146 m_irq_mask |= (1<<irq);
147 }
148 inb(I8259_M_MR); /* DUMMY */
149 outb(m_irq_mask,I8259_M_MR); /* disable */
150 outb(0x60+irq,I8259_M_CR); /* EOI */
151
152 } else {
153 if(s_irq_mask & (1<<(irq - 8))){
154 if(!mpc1211_irq_real(irq)){
155 irq_err_count++;
156 printk("spurious 8259A interrupt: IRQ %x\n",irq);
157 }
158 } else {
159 s_irq_mask |= (1<<(irq - 8));
160 }
161 inb(I8259_S_MR); /* DUMMY */
162 outb(s_irq_mask,I8259_S_MR); /* disable */
163 outb(0x60+(irq-8),I8259_S_CR); /* EOI */
164 outb(0x60+2,I8259_M_CR);
165 }
166 restore_flags(flags);
167}
168
169static void end_mpc1211_irq(unsigned int irq)
170{
171 enable_mpc1211_irq(irq);
172}
173
174static unsigned int startup_mpc1211_irq(unsigned int irq)
175{
176 enable_mpc1211_irq(irq);
177 return 0;
178}
179
180static void shutdown_mpc1211_irq(unsigned int irq)
181{
182 disable_mpc1211_irq(irq);
183}
184
185static struct hw_interrupt_type mpc1211_irq_type = {
186 .typename = "MPC1211-IRQ",
187 .startup = startup_mpc1211_irq,
188 .shutdown = shutdown_mpc1211_irq,
189 .enable = enable_mpc1211_irq,
190 .disable = disable_mpc1211_irq,
191 .ack = mask_and_ack_mpc1211,
192 .end = end_mpc1211_irq
193};
194
195static void make_mpc1211_irq(unsigned int irq)
196{
197 irq_desc[irq].handler = &mpc1211_irq_type;
198 irq_desc[irq].status = IRQ_DISABLED;
199 irq_desc[irq].action = 0;
200 irq_desc[irq].depth = 1;
201 disable_mpc1211_irq(irq);
202}
203
204int mpc1211_irq_demux(int irq)
205{
206 unsigned int poll;
207
208 if( irq == 2 ) {
209 outb(0x0c,I8259_M_CR);
210 poll = inb(I8259_M_CR);
211 if(poll & 0x80) {
212 irq = (poll & 0x07);
213 }
214 if( irq == 2) {
215 outb(0x0c,I8259_S_CR);
216 poll = inb(I8259_S_CR);
217 irq = (poll & 0x07) + 8;
218 }
219 }
220 return irq;
221}
222
223void __init init_mpc1211_IRQ(void)
224{
225 int i;
226 /*
227 * Super I/O (Just mimic PC):
228 * 1: keyboard
229 * 3: serial 1
230 * 4: serial 0
231 * 5: printer
232 * 6: floppy
233 * 8: rtc
234 * 10: lan
235 * 12: mouse
236 * 14: ide0
237 * 15: ide1
238 */
239
240 pci_write_config(0,0,0,0x54, 0xb0b0002d);
241 outb(0x11, I8259_M_CR); /* mater icw1 edge trigger */
242 outb(0x11, I8259_S_CR); /* slave icw1 edge trigger */
243 outb(0x20, I8259_M_MR); /* m icw2 base vec 0x08 */
244 outb(0x28, I8259_S_MR); /* s icw2 base vec 0x70 */
245 outb(0x04, I8259_M_MR); /* m icw3 slave irq2 */
246 outb(0x02, I8259_S_MR); /* s icw3 slave id */
247 outb(0x01, I8259_M_MR); /* m icw4 non buf normal eoi*/
248 outb(0x01, I8259_S_MR); /* s icw4 non buf normal eo1*/
249 outb(0xfb, I8259_M_MR); /* disable irq0--irq7 */
250 outb(0xff, I8259_S_MR); /* disable irq8--irq15 */
251
252 for ( i=0; i < 16; i++) {
253 if(i != 2) {
254 make_mpc1211_irq(i);
255 }
256 }
257}
258
259/*
260 Initialize the board
261*/
262
263
264static void delay (void)
265{
266 volatile unsigned short tmp;
267 tmp = *(volatile unsigned short *) 0xa0000000;
268}
269
270static void delay1000 (void)
271{
272 int i;
273
274 for (i=0; i<1000; i++)
275 delay ();
276}
277
278static int put_smb_blk(unsigned char *p, int address, int command, int no)
279{
280 int temp;
281 int timeout;
282 int i;
283
284 outb(0xff, SMBHSTSTS);
285 temp = inb(SMBHSTSTS);
286 for (timeout = 0; (timeout < MAX_TIMEOUT) && !(temp & ALI15X3_STS_IDLE); timeout++) {
287 delay1000();
288 temp = inb(SMBHSTSTS);
289 }
290 if (timeout >= MAX_TIMEOUT){
291 return -1;
292 }
293
294 outb(((address & 0x7f) << 1), SMBHSTADD);
295 outb(0xc0, SMBHSTCNT);
296 outb(command & 0xff, SMBHSTCMD);
297 outb(no & 0x1f, SMBHSTDAT0);
298
299 for(i = 1; i <= no; i++) {
300 outb(*p++, SMBBLKDAT);
301 }
302 outb(0xff, SMBHSTSTART);
303
304 temp = inb(SMBHSTSTS);
305 for (timeout = 0; (timeout < MAX_TIMEOUT) && !(temp & (ALI15X3_STS_ERR | ALI15X3_STS_DONE)); timeout++) {
306 delay1000();
307 temp = inb(SMBHSTSTS);
308 }
309 if (timeout >= MAX_TIMEOUT) {
310 return -2;
311 }
312 if ( temp & ALI15X3_STS_ERR ){
313 return -3;
314 }
315 return 0;
316}
317
318/*
319 * The Machine Vector
320 */
321
322struct sh_machine_vector mv_mpc1211 __initmv = {
323 .mv_nr_irqs = 48,
324 .mv_irq_demux = mpc1211_irq_demux,
325 .mv_init_irq = init_mpc1211_IRQ,
326
327#ifdef CONFIG_HEARTBEAT
328 .mv_heartbeat = heartbeat_mpc1211,
329#endif
330};
331
332ALIAS_MV(mpc1211)
333
334/* arch/sh/boards/mpc1211/rtc.c */
335void mpc1211_time_init(void);
336
337int __init platform_setup(void)
338{
339 unsigned char spd_buf[128];
340
341 __set_io_port_base(PA_PCI_IO);
342
343 pci_write_config(0,0,0,0x54, 0xb0b00000);
344
345 do {
346 outb(ALI15X3_ABORT, SMBHSTCNT);
347 spd_buf[0] = 0x0c;
348 spd_buf[1] = 0x43;
349 spd_buf[2] = 0x7f;
350 spd_buf[3] = 0x03;
351 spd_buf[4] = 0x00;
352 spd_buf[5] = 0x03;
353 spd_buf[6] = 0x00;
354 } while (put_smb_blk(spd_buf, 0x69, 0, 7) < 0);
355
356 board_time_init = mpc1211_time_init;
357
358 return 0;
359}
360
diff --git a/arch/sh/boards/overdrive/Makefile b/arch/sh/boards/overdrive/Makefile
new file mode 100644
index 00000000000..1762b59e927
--- /dev/null
+++ b/arch/sh/boards/overdrive/Makefile
@@ -0,0 +1,8 @@
1#
2# Makefile for the STMicroelectronics Overdrive specific parts of the kernel
3#
4
5obj-y := mach.o setup.o io.o irq.o led.o time.o
6
7obj-$(CONFIG_PCI) += fpga.o galileo.o pcidma.o
8
diff --git a/arch/sh/boards/overdrive/fpga.c b/arch/sh/boards/overdrive/fpga.c
new file mode 100644
index 00000000000..3a1ec940344
--- /dev/null
+++ b/arch/sh/boards/overdrive/fpga.c
@@ -0,0 +1,134 @@
1/*
2 * Copyright (C) 2000 David J. Mckay (david.mckay@st.com)
3 *
4 * May be copied or modified under the terms of the GNU General Public
5 * License. See linux/COPYING for more information.
6 *
7 * This file handles programming up the Altera Flex10K that interfaces to
8 * the Galileo, and does the PS/2 keyboard and mouse
9 *
10 */
11
12
13#include <linux/config.h>
14#include <linux/kernel.h>
15#include <linux/smp.h>
16#include <linux/smp_lock.h>
17#include <linux/init.h>
18#include <linux/errno.h>
19#include <linux/pci.h>
20#include <linux/delay.h>
21
22
23#include <asm/overdriver/gt64111.h>
24#include <asm/overdrive/overdrive.h>
25#include <asm/overdrive/fpga.h>
26
27#define FPGA_NotConfigHigh() (*FPGA_ControlReg) = (*FPGA_ControlReg) | ENABLE_FPGA_BIT
28#define FPGA_NotConfigLow() (*FPGA_ControlReg) = (*FPGA_ControlReg) & RESET_FPGA_MASK
29
30/* I need to find out what (if any) the real delay factor here is */
31/* The delay is definately not critical */
32#define long_delay() {int i;for(i=0;i<10000;i++);}
33#define short_delay() {int i;for(i=0;i<100;i++);}
34
35static void __init program_overdrive_fpga(const unsigned char *fpgacode,
36 int size)
37{
38 int timeout = 0;
39 int i, j;
40 unsigned char b;
41 static volatile unsigned char *FPGA_ControlReg =
42 (volatile unsigned char *) (OVERDRIVE_CTRL);
43 static volatile unsigned char *FPGA_ProgramReg =
44 (volatile unsigned char *) (FPGA_DCLK_ADDRESS);
45
46 printk("FPGA: Commencing FPGA Programming\n");
47
48 /* The PCI reset but MUST be low when programming the FPGA !!! */
49 b = (*FPGA_ControlReg) & RESET_PCI_MASK;
50
51 (*FPGA_ControlReg) = b;
52
53 /* Prepare FPGA to program */
54
55 FPGA_NotConfigHigh();
56 long_delay();
57
58 FPGA_NotConfigLow();
59 short_delay();
60
61 while ((*FPGA_ProgramReg & FPGA_NOT_STATUS) != 0) {
62 printk("FPGA: Waiting for NotStatus to go Low ... \n");
63 }
64
65 FPGA_NotConfigHigh();
66
67 /* Wait for FPGA "ready to be programmed" signal */
68 printk("FPGA: Waiting for NotStatus to go high (FPGA ready)... \n");
69
70 for (timeout = 0;
71 (((*FPGA_ProgramReg & FPGA_NOT_STATUS) == 0)
72 && (timeout < FPGA_TIMEOUT)); timeout++);
73
74 /* Check if timeout condition occured - i.e. an error */
75
76 if (timeout == FPGA_TIMEOUT) {
77 printk
78 ("FPGA: Failed to program - Timeout waiting for notSTATUS to go high\n");
79 return;
80 }
81
82 printk("FPGA: Copying data to FPGA ... %d bytes\n", size);
83
84 /* Copy array to FPGA - bit at a time */
85
86 for (i = 0; i < size; i++) {
87 volatile unsigned w = 0;
88
89 for (j = 0; j < 8; j++) {
90 *FPGA_ProgramReg = (fpgacode[i] >> j) & 0x01;
91 short_delay();
92 }
93 if ((i & 0x3ff) == 0) {
94 printk(".");
95 }
96 }
97
98 /* Waiting for CONFDONE to go high - means the program is complete */
99
100 for (timeout = 0;
101 (((*FPGA_ProgramReg & FPGA_CONFDONE) == 0)
102 && (timeout < FPGA_TIMEOUT)); timeout++) {
103
104 *FPGA_ProgramReg = 0x0;
105 long_delay();
106 }
107
108 if (timeout == FPGA_TIMEOUT) {
109 printk
110 ("FPGA: Failed to program - Timeout waiting for CONFDONE to go high\n");
111 return;
112 } else { /* Clock another 10 times - gets the device into a working state */
113 for (i = 0; i < 10; i++) {
114 *FPGA_ProgramReg = 0x0;
115 short_delay();
116 }
117 }
118
119 printk("FPGA: Programming complete\n");
120}
121
122
123static const unsigned char __init fpgacode[] = {
124#include "./overdrive.ttf" /* Code from maxplus2 compiler */
125 , 0, 0
126};
127
128
129int __init init_overdrive_fpga(void)
130{
131 program_overdrive_fpga(fpgacode, sizeof(fpgacode));
132
133 return 0;
134}
diff --git a/arch/sh/boards/overdrive/galileo.c b/arch/sh/boards/overdrive/galileo.c
new file mode 100644
index 00000000000..276fa11ee4c
--- /dev/null
+++ b/arch/sh/boards/overdrive/galileo.c
@@ -0,0 +1,588 @@
1/*
2 * Copyright (C) 2000 David J. Mckay (david.mckay@st.com)
3 *
4 * May be copied or modified under the terms of the GNU General Public
5 * License. See linux/COPYING for more information.
6 *
7 * This file contains the PCI routines required for the Galileo GT6411
8 * PCI bridge as used on the Orion and Overdrive boards.
9 *
10 */
11
12#include <linux/config.h>
13#include <linux/kernel.h>
14#include <linux/smp.h>
15#include <linux/smp_lock.h>
16#include <linux/init.h>
17#include <linux/errno.h>
18#include <linux/pci.h>
19#include <linux/delay.h>
20#include <linux/types.h>
21#include <linux/ioport.h>
22
23#include <asm/overdrive/overdrive.h>
24#include <asm/overdrive/gt64111.h>
25
26
27/* After boot, we shift the Galileo registers so that they appear
28 * in BANK6, along with IO space. This means we can have one contingous
29 * lump of PCI address space without these registers appearing in the
30 * middle of them
31 */
32
33#define GT64111_BASE_ADDRESS 0xbb000000
34#define GT64111_IO_BASE_ADDRESS 0x1000
35/* The GT64111 registers appear at this address to the SH4 after reset */
36#define RESET_GT64111_BASE_ADDRESS 0xb4000000
37
38/* Macros used to access the Galileo registers */
39#define RESET_GT64111_REG(x) (RESET_GT64111_BASE_ADDRESS+x)
40#define GT64111_REG(x) (GT64111_BASE_ADDRESS+x)
41
42#define RESET_GT_WRITE(x,v) writel((v),RESET_GT64111_REG(x))
43
44#define RESET_GT_READ(x) readl(RESET_GT64111_REG(x))
45
46#define GT_WRITE(x,v) writel((v),GT64111_REG(x))
47#define GT_WRITE_BYTE(x,v) writeb((v),GT64111_REG(x))
48#define GT_WRITE_SHORT(x,v) writew((v),GT64111_REG(x))
49
50#define GT_READ(x) readl(GT64111_REG(x))
51#define GT_READ_BYTE(x) readb(GT64111_REG(x))
52#define GT_READ_SHORT(x) readw(GT64111_REG(x))
53
54
55/* Where the various SH banks start at */
56#define SH_BANK4_ADR 0xb0000000
57#define SH_BANK5_ADR 0xb4000000
58#define SH_BANK6_ADR 0xb8000000
59
60/* Masks out everything but lines 28,27,26 */
61#define BANK_SELECT_MASK 0x1c000000
62
63#define SH4_TO_BANK(x) ( (x) & BANK_SELECT_MASK)
64
65/*
66 * Masks used for address conversaion. Bank 6 is used for IO and
67 * has all the address bits zeroed by the FPGA. Special case this
68 */
69#define MEMORY_BANK_MASK 0x1fffffff
70#define IO_BANK_MASK 0x03ffffff
71
72/* Mark bank 6 as the bank used for IO. You can change this in the FPGA code
73 * if you want
74 */
75#define IO_BANK_ADR PCI_GTIO_BASE
76
77/* Will select the correct mask to apply depending on the SH$ address */
78#define SELECT_BANK_MASK(x) \
79 ( (SH4_TO_BANK(x)==SH4_TO_BANK(IO_BANK_ADR)) ? IO_BANK_MASK : MEMORY_BANK_MASK)
80
81/* Converts between PCI space and P2 region */
82#define SH4_TO_PCI(x) ((x)&SELECT_BANK_MASK(x))
83
84/* Various macros for figuring out what to stick in the Galileo registers.
85 * You *really* don't want to figure this stuff out by hand, you always get
86 * it wrong
87 */
88#define GT_MEM_LO_ADR(x) ((((unsigned)((x)&SELECT_BANK_MASK(x)))>>21)&0x7ff)
89#define GT_MEM_HI_ADR(x) ((((unsigned)((x)&SELECT_BANK_MASK(x)))>>21)&0x7f)
90#define GT_MEM_SUB_ADR(x) ((((unsigned)((x)&SELECT_BANK_MASK(x)))>>20)&0xff)
91
92#define PROGRAM_HI_LO(block,a,s) \
93 GT_WRITE(block##_LO_DEC_ADR,GT_MEM_LO_ADR(a));\
94 GT_WRITE(block##_HI_DEC_ADR,GT_MEM_HI_ADR(a+s-1))
95
96#define PROGRAM_SUB_HI_LO(block,a,s) \
97 GT_WRITE(block##_LO_DEC_ADR,GT_MEM_SUB_ADR(a));\
98 GT_WRITE(block##_HI_DEC_ADR,GT_MEM_SUB_ADR(a+s-1))
99
100/* We need to set the size, and the offset register */
101
102#define GT_BAR_MASK(x) ((x)&~0xfff)
103
104/* Macro to set up the BAR in the Galileo. Essentially used for the DRAM */
105#define PROGRAM_GT_BAR(block,a,s) \
106 GT_WRITE(PCI_##block##_BANK_SIZE,GT_BAR_MASK((s-1)));\
107 write_config_to_galileo(PCI_CONFIG_##block##_BASE_ADR,\
108 GT_BAR_MASK(a))
109
110#define DISABLE_GT_BAR(block) \
111 GT_WRITE(PCI_##block##_BANK_SIZE,0),\
112 GT_CONFIG_WRITE(PCI_CONFIG_##block##_BASE_ADR,\
113 0x80000000)
114
115/* Macros to disable things we are not going to use */
116#define DISABLE_DECODE(x) GT_WRITE(x##_LO_DEC_ADR,0x7ff);\
117 GT_WRITE(x##_HI_DEC_ADR,0x00)
118
119#define DISABLE_SUB_DECODE(x) GT_WRITE(x##_LO_DEC_ADR,0xff);\
120 GT_WRITE(x##_HI_DEC_ADR,0x00)
121
122static void __init reset_pci(void)
123{
124 /* Set RESET_PCI bit high */
125 writeb(readb(OVERDRIVE_CTRL) | ENABLE_PCI_BIT, OVERDRIVE_CTRL);
126 udelay(250);
127
128 /* Set RESET_PCI bit low */
129 writeb(readb(OVERDRIVE_CTRL) & RESET_PCI_MASK, OVERDRIVE_CTRL);
130 udelay(250);
131
132 writeb(readb(OVERDRIVE_CTRL) | ENABLE_PCI_BIT, OVERDRIVE_CTRL);
133 udelay(250);
134}
135
136static int write_config_to_galileo(int where, u32 val);
137#define GT_CONFIG_WRITE(where,val) write_config_to_galileo(where,val)
138
139#define ENABLE_PCI_DRAM
140
141
142#ifdef TEST_DRAM
143/* Test function to check out if the PCI DRAM is working OK */
144static int /* __init */ test_dram(unsigned *base, unsigned size)
145{
146 unsigned *p = base;
147 unsigned *end = (unsigned *) (((unsigned) base) + size);
148 unsigned w;
149
150 for (p = base; p < end; p++) {
151 *p = 0xffffffff;
152 if (*p != 0xffffffff) {
153 printk("AAARGH -write failed!!! at %p is %x\n", p,
154 *p);
155 return 0;
156 }
157 *p = 0x0;
158 if (*p != 0x0) {
159 printk("AAARGH -write failed!!!\n");
160 return 0;
161 }
162 }
163
164 for (p = base; p < end; p++) {
165 *p = (unsigned) p;
166 if (*p != (unsigned) p) {
167 printk("Failed at 0x%p, actually is 0x%x\n", p,
168 *p);
169 return 0;
170 }
171 }
172
173 for (p = base; p < end; p++) {
174 w = ((unsigned) p & 0xffff0000);
175 *p = w | (w >> 16);
176 }
177
178 for (p = base; p < end; p++) {
179 w = ((unsigned) p & 0xffff0000);
180 w |= (w >> 16);
181 if (*p != w) {
182 printk
183 ("Failed at 0x%p, should be 0x%x actually is 0x%x\n",
184 p, w, *p);
185 return 0;
186 }
187 }
188
189 return 1;
190}
191#endif
192
193
194/* Function to set up and initialise the galileo. This sets up the BARS,
195 * maps the DRAM into the address space etc,etc
196 */
197int __init galileo_init(void)
198{
199 reset_pci();
200
201 /* Now shift the galileo regs into this block */
202 RESET_GT_WRITE(INTERNAL_SPACE_DEC,
203 GT_MEM_LO_ADR(GT64111_BASE_ADDRESS));
204
205 /* Should have a sanity check here, that you can read back at the new
206 * address what you just wrote
207 */
208
209 /* Disable decode for all regions */
210 DISABLE_DECODE(RAS10);
211 DISABLE_DECODE(RAS32);
212 DISABLE_DECODE(CS20);
213 DISABLE_DECODE(CS3);
214 DISABLE_DECODE(PCI_IO);
215 DISABLE_DECODE(PCI_MEM0);
216 DISABLE_DECODE(PCI_MEM1);
217
218 /* Disable all BARS */
219 GT_WRITE(BAR_ENABLE_ADR, 0x1ff);
220 DISABLE_GT_BAR(RAS10);
221 DISABLE_GT_BAR(RAS32);
222 DISABLE_GT_BAR(CS20);
223 DISABLE_GT_BAR(CS3);
224
225 /* Tell the BAR where the IO registers now are */
226 GT_CONFIG_WRITE(PCI_CONFIG_INT_REG_IO_ADR,GT_BAR_MASK(
227 (GT64111_IO_BASE_ADDRESS &
228 IO_BANK_MASK)));
229 /* set up a 112 Mb decode */
230 PROGRAM_HI_LO(PCI_MEM0, SH_BANK4_ADR, 112 * 1024 * 1024);
231
232 /* Set up a 32 MB io space decode */
233 PROGRAM_HI_LO(PCI_IO, IO_BANK_ADR, 32 * 1024 * 1024);
234
235#ifdef ENABLE_PCI_DRAM
236 /* Program up the DRAM configuration - there is DRAM only in bank 0 */
237 /* Now set up the DRAM decode */
238 PROGRAM_HI_LO(RAS10, PCI_DRAM_BASE, PCI_DRAM_SIZE);
239 /* And the sub decode */
240 PROGRAM_SUB_HI_LO(RAS0, PCI_DRAM_BASE, PCI_DRAM_SIZE);
241
242 DISABLE_SUB_DECODE(RAS1);
243
244 /* Set refresh rate */
245 GT_WRITE(DRAM_BANK0_PARMS, 0x3f);
246 GT_WRITE(DRAM_CFG, 0x100);
247
248 /* we have to lob off the top bits rememeber!! */
249 PROGRAM_GT_BAR(RAS10, SH4_TO_PCI(PCI_DRAM_BASE), PCI_DRAM_SIZE);
250
251#endif
252
253 /* We are only interested in decoding RAS10 and the Galileo's internal
254 * registers (as IO) on the PCI bus
255 */
256#ifdef ENABLE_PCI_DRAM
257 GT_WRITE(BAR_ENABLE_ADR, (~((1 << 8) | (1 << 3))) & 0x1ff);
258#else
259 GT_WRITE(BAR_ENABLE_ADR, (~(1 << 3)) & 0x1ff);
260#endif
261
262 /* Change the class code to host bridge, it actually powers up
263 * as a memory controller
264 */
265 GT_CONFIG_WRITE(8, 0x06000011);
266
267 /* Allow the galileo to master the PCI bus */
268 GT_CONFIG_WRITE(PCI_COMMAND,
269 PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |
270 PCI_COMMAND_IO);
271
272
273#if 0
274 printk("Testing PCI DRAM - ");
275 if(test_dram(PCI_DRAM_BASE,PCI_DRAM_SIZE)) {
276 printk("Passed\n");
277 }else {
278 printk("FAILED\n");
279 }
280#endif
281 return 0;
282
283}
284
285
286#define SET_CONFIG_BITS(bus,devfn,where)\
287 ((1<<31) | ((bus) << 16) | ((devfn) << 8) | ((where) & ~3))
288
289#define CONFIG_CMD(dev, where) SET_CONFIG_BITS((dev)->bus->number,(dev)->devfn,where)
290
291/* This write to the galileo config registers, unlike the functions below, can
292 * be used before the PCI subsystem has started up
293 */
294static int __init write_config_to_galileo(int where, u32 val)
295{
296 GT_WRITE(PCI_CFG_ADR, SET_CONFIG_BITS(0, 0, where));
297
298 GT_WRITE(PCI_CFG_DATA, val);
299 return 0;
300}
301
302/* We exclude the galileo and slot 31, the galileo because I don't know how to stop
303 * the setup code shagging up the setup I have done on it, and 31 because the whole
304 * thing locks up if you try to access that slot (which doesn't exist of course anyway
305 */
306
307#define EXCLUDED_DEV(dev) ((dev->bus->number==0) && ((PCI_SLOT(dev->devfn)==0) || (PCI_SLOT(dev->devfn) == 31)))
308
309static int galileo_read_config_byte(struct pci_dev *dev, int where,
310 u8 * val)
311{
312
313
314 /* I suspect this doesn't work because this drives a special cycle ? */
315 if (EXCLUDED_DEV(dev)) {
316 *val = 0xff;
317 return PCIBIOS_SUCCESSFUL;
318 }
319 /* Start the config cycle */
320 GT_WRITE(PCI_CFG_ADR, CONFIG_CMD(dev, where));
321 /* Read back the result */
322 *val = GT_READ_BYTE(PCI_CFG_DATA + (where & 3));
323
324 return PCIBIOS_SUCCESSFUL;
325}
326
327
328static int galileo_read_config_word(struct pci_dev *dev, int where,
329 u16 * val)
330{
331
332 if (EXCLUDED_DEV(dev)) {
333 *val = 0xffff;
334 return PCIBIOS_SUCCESSFUL;
335 }
336
337 GT_WRITE(PCI_CFG_ADR, CONFIG_CMD(dev, where));
338 *val = GT_READ_SHORT(PCI_CFG_DATA + (where & 2));
339
340 return PCIBIOS_SUCCESSFUL;
341}
342
343
344static int galileo_read_config_dword(struct pci_dev *dev, int where,
345 u32 * val)
346{
347 if (EXCLUDED_DEV(dev)) {
348 *val = 0xffffffff;
349 return PCIBIOS_SUCCESSFUL;
350 }
351
352 GT_WRITE(PCI_CFG_ADR, CONFIG_CMD(dev, where));
353 *val = GT_READ(PCI_CFG_DATA);
354
355 return PCIBIOS_SUCCESSFUL;
356}
357
358static int galileo_write_config_byte(struct pci_dev *dev, int where,
359 u8 val)
360{
361 GT_WRITE(PCI_CFG_ADR, CONFIG_CMD(dev, where));
362
363 GT_WRITE_BYTE(PCI_CFG_DATA + (where & 3), val);
364
365 return PCIBIOS_SUCCESSFUL;
366}
367
368
369static int galileo_write_config_word(struct pci_dev *dev, int where,
370 u16 val)
371{
372 GT_WRITE(PCI_CFG_ADR, CONFIG_CMD(dev, where));
373
374 GT_WRITE_SHORT(PCI_CFG_DATA + (where & 2), val);
375
376 return PCIBIOS_SUCCESSFUL;
377}
378
379static int galileo_write_config_dword(struct pci_dev *dev, int where,
380 u32 val)
381{
382 GT_WRITE(PCI_CFG_ADR, CONFIG_CMD(dev, where));
383
384 GT_WRITE(PCI_CFG_DATA, val);
385
386 return PCIBIOS_SUCCESSFUL;
387}
388
389static struct pci_ops pci_config_ops = {
390 galileo_read_config_byte,
391 galileo_read_config_word,
392 galileo_read_config_dword,
393 galileo_write_config_byte,
394 galileo_write_config_word,
395 galileo_write_config_dword
396};
397
398
399/* Everything hangs off this */
400static struct pci_bus *pci_root_bus;
401
402
403static u8 __init no_swizzle(struct pci_dev *dev, u8 * pin)
404{
405 return PCI_SLOT(dev->devfn);
406}
407
408static int __init map_od_irq(struct pci_dev *dev, u8 slot, u8 pin)
409{
410 /* Slot 1: Galileo
411 * Slot 2: PCI Slot 1
412 * Slot 3: PCI Slot 2
413 * Slot 4: ESS
414 */
415 switch (slot) {
416 case 2:
417 return OVERDRIVE_PCI_IRQ1;
418 case 3:
419 /* Note this assumes you have a hacked card in slot 2 */
420 return OVERDRIVE_PCI_IRQ2;
421 case 4:
422 return OVERDRIVE_ESS_IRQ;
423 default:
424 /* printk("PCI: Unexpected IRQ mapping request for slot %d\n", slot); */
425 return -1;
426 }
427}
428
429
430
431void __init
432pcibios_fixup_pbus_ranges(struct pci_bus *bus, struct pbus_set_ranges_data *ranges)
433{
434 ranges->io_start -= bus->resource[0]->start;
435 ranges->io_end -= bus->resource[0]->start;
436 ranges->mem_start -= bus->resource[1]->start;
437 ranges->mem_end -= bus->resource[1]->start;
438}
439
440static void __init pci_fixup_ide_bases(struct pci_dev *d)
441{
442 int i;
443
444 /*
445 * PCI IDE controllers use non-standard I/O port decoding, respect it.
446 */
447 if ((d->class >> 8) != PCI_CLASS_STORAGE_IDE)
448 return;
449 printk("PCI: IDE base address fixup for %s\n", pci_name(d));
450 for(i=0; i<4; i++) {
451 struct resource *r = &d->resource[i];
452 if ((r->start & ~0x80) == 0x374) {
453 r->start |= 2;
454 r->end = r->start;
455 }
456 }
457}
458DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases);
459
460void __init pcibios_init(void)
461{
462 static struct resource galio,galmem;
463
464 /* Allocate the registers used by the Galileo */
465 galio.flags = IORESOURCE_IO;
466 galio.name = "Galileo GT64011";
467 galmem.flags = IORESOURCE_MEM|IORESOURCE_PREFETCH;
468 galmem.name = "Galileo GT64011 DRAM";
469
470 allocate_resource(&ioport_resource, &galio, 256,
471 GT64111_IO_BASE_ADDRESS,GT64111_IO_BASE_ADDRESS+256, 256, NULL, NULL);
472 allocate_resource(&iomem_resource, &galmem,PCI_DRAM_SIZE,
473 PHYSADDR(PCI_DRAM_BASE), PHYSADDR(PCI_DRAM_BASE)+PCI_DRAM_SIZE,
474 PCI_DRAM_SIZE, NULL, NULL);
475
476 /* ok, do the scan man */
477 pci_root_bus = pci_scan_bus(0, &pci_config_ops, NULL);
478
479 pci_assign_unassigned_resources();
480 pci_fixup_irqs(no_swizzle, map_od_irq);
481
482#ifdef TEST_DRAM
483 printk("Testing PCI DRAM - ");
484 if(test_dram(PCI_DRAM_BASE,PCI_DRAM_SIZE)) {
485 printk("Passed\n");
486 }else {
487 printk("FAILED\n");
488 }
489#endif
490
491}
492
493char * __init pcibios_setup(char *str)
494{
495 return str;
496}
497
498
499
500int pcibios_enable_device(struct pci_dev *dev)
501{
502
503 u16 cmd, old_cmd;
504 int idx;
505 struct resource *r;
506
507 pci_read_config_word(dev, PCI_COMMAND, &cmd);
508 old_cmd = cmd;
509 for (idx = 0; idx < 6; idx++) {
510 r = dev->resource + idx;
511 if (!r->start && r->end) {
512 printk(KERN_ERR
513 "PCI: Device %s not available because"
514 " of resource collisions\n",
515 pci_name(dev));
516 return -EINVAL;
517 }
518 if (r->flags & IORESOURCE_IO)
519 cmd |= PCI_COMMAND_IO;
520 if (r->flags & IORESOURCE_MEM)
521 cmd |= PCI_COMMAND_MEMORY;
522 }
523 if (cmd != old_cmd) {
524 printk("PCI: enabling device %s (%04x -> %04x)\n",
525 pci_name(dev), old_cmd, cmd);
526 pci_write_config_word(dev, PCI_COMMAND, cmd);
527 }
528 return 0;
529
530}
531
532/* We should do some optimisation work here I think. Ok for now though */
533void __init pcibios_fixup_bus(struct pci_bus *bus)
534{
535
536}
537
538void pcibios_align_resource(void *data, struct resource *res,
539 unsigned long size)
540{
541}
542
543void __init pcibios_update_resource(struct pci_dev *dev, struct resource *root,
544 struct resource *res, int resource)
545{
546
547 unsigned long where, size;
548 u32 reg;
549
550
551 printk("PCI: Assigning %3s %08lx to %s\n",
552 res->flags & IORESOURCE_IO ? "IO" : "MEM",
553 res->start, dev->name);
554
555 where = PCI_BASE_ADDRESS_0 + resource * 4;
556 size = res->end - res->start;
557
558 pci_read_config_dword(dev, where, &reg);
559 reg = (reg & size) | (((u32) (res->start - root->start)) & ~size);
560 pci_write_config_dword(dev, where, reg);
561}
562
563
564void __init pcibios_update_irq(struct pci_dev *dev, int irq)
565{
566 printk("PCI: Assigning IRQ %02d to %s\n", irq, dev->name);
567 pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
568}
569
570/*
571 * If we set up a device for bus mastering, we need to check the latency
572 * timer as certain crappy BIOSes forget to set it properly.
573 */
574unsigned int pcibios_max_latency = 255;
575
576void pcibios_set_master(struct pci_dev *dev)
577{
578 u8 lat;
579 pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
580 if (lat < 16)
581 lat = (64 <= pcibios_max_latency) ? 64 : pcibios_max_latency;
582 else if (lat > pcibios_max_latency)
583 lat = pcibios_max_latency;
584 else
585 return;
586 printk("PCI: Setting latency timer of device %s to %d\n", pci_name(dev), lat);
587 pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat);
588}
diff --git a/arch/sh/boards/overdrive/io.c b/arch/sh/boards/overdrive/io.c
new file mode 100644
index 00000000000..65f3fd0563d
--- /dev/null
+++ b/arch/sh/boards/overdrive/io.c
@@ -0,0 +1,173 @@
1/*
2 * Copyright (C) 2000 David J. Mckay (david.mckay@st.com)
3 *
4 * May be copied or modified under the terms of the GNU General Public
5 * License. See linux/COPYING for more information.
6 *
7 * This file contains the I/O routines for use on the overdrive board
8 *
9 */
10
11#include <linux/config.h>
12#include <linux/types.h>
13#include <linux/delay.h>
14#include <asm/processor.h>
15#include <asm/io.h>
16#include <asm/addrspace.h>
17
18#include <asm/overdrive/overdrive.h>
19
20/*
21 * readX/writeX() are used to access memory mapped devices. On some
22 * architectures the memory mapped IO stuff needs to be accessed
23 * differently. On the SuperH architecture, we just read/write the
24 * memory location directly.
25 */
26
27#define dprintk(x...)
28
29/* Translates an IO address to where it is mapped in memory */
30
31#define io_addr(x) (((unsigned)(x))|PCI_GTIO_BASE)
32
33unsigned char od_inb(unsigned long port)
34{
35dprintk("od_inb(%x)\n", port);
36 return readb(io_addr(port)) & 0xff;
37}
38
39
40unsigned short od_inw(unsigned long port)
41{
42dprintk("od_inw(%x)\n", port);
43 return readw(io_addr(port)) & 0xffff;
44}
45
46unsigned int od_inl(unsigned long port)
47{
48dprintk("od_inl(%x)\n", port);
49 return readl(io_addr(port));
50}
51
52void od_outb(unsigned char value, unsigned long port)
53{
54dprintk("od_outb(%x, %x)\n", value, port);
55 writeb(value, io_addr(port));
56}
57
58void od_outw(unsigned short value, unsigned long port)
59{
60dprintk("od_outw(%x, %x)\n", value, port);
61 writew(value, io_addr(port));
62}
63
64void od_outl(unsigned int value, unsigned long port)
65{
66dprintk("od_outl(%x, %x)\n", value, port);
67 writel(value, io_addr(port));
68}
69
70/* This is horrible at the moment - needs more work to do something sensible */
71#define IO_DELAY() udelay(10)
72
73#define OUT_DELAY(x,type) \
74void od_out##x##_p(unsigned type value,unsigned long port){out##x(value,port);IO_DELAY();}
75
76#define IN_DELAY(x,type) \
77unsigned type od_in##x##_p(unsigned long port) {unsigned type tmp=in##x(port);IO_DELAY();return tmp;}
78
79
80OUT_DELAY(b,char)
81OUT_DELAY(w,short)
82OUT_DELAY(l,int)
83
84IN_DELAY(b,char)
85IN_DELAY(w,short)
86IN_DELAY(l,int)
87
88
89/* Now for the string version of these functions */
90void od_outsb(unsigned long port, const void *addr, unsigned long count)
91{
92 int i;
93 unsigned char *p = (unsigned char *) addr;
94
95 for (i = 0; i < count; i++, p++) {
96 outb(*p, port);
97 }
98}
99
100
101void od_insb(unsigned long port, void *addr, unsigned long count)
102{
103 int i;
104 unsigned char *p = (unsigned char *) addr;
105
106 for (i = 0; i < count; i++, p++) {
107 *p = inb(port);
108 }
109}
110
111/* For the 16 and 32 bit string functions, we have to worry about alignment.
112 * The SH does not do unaligned accesses, so we have to read as bytes and
113 * then write as a word or dword.
114 * This can be optimised a lot more, especially in the case where the data
115 * is aligned
116 */
117
118void od_outsw(unsigned long port, const void *addr, unsigned long count)
119{
120 int i;
121 unsigned short tmp;
122 unsigned char *p = (unsigned char *) addr;
123
124 for (i = 0; i < count; i++, p += 2) {
125 tmp = (*p) | ((*(p + 1)) << 8);
126 outw(tmp, port);
127 }
128}
129
130
131void od_insw(unsigned long port, void *addr, unsigned long count)
132{
133 int i;
134 unsigned short tmp;
135 unsigned char *p = (unsigned char *) addr;
136
137 for (i = 0; i < count; i++, p += 2) {
138 tmp = inw(port);
139 p[0] = tmp & 0xff;
140 p[1] = (tmp >> 8) & 0xff;
141 }
142}
143
144
145void od_outsl(unsigned long port, const void *addr, unsigned long count)
146{
147 int i;
148 unsigned tmp;
149 unsigned char *p = (unsigned char *) addr;
150
151 for (i = 0; i < count; i++, p += 4) {
152 tmp = (*p) | ((*(p + 1)) << 8) | ((*(p + 2)) << 16) |
153 ((*(p + 3)) << 24);
154 outl(tmp, port);
155 }
156}
157
158
159void od_insl(unsigned long port, void *addr, unsigned long count)
160{
161 int i;
162 unsigned tmp;
163 unsigned char *p = (unsigned char *) addr;
164
165 for (i = 0; i < count; i++, p += 4) {
166 tmp = inl(port);
167 p[0] = tmp & 0xff;
168 p[1] = (tmp >> 8) & 0xff;
169 p[2] = (tmp >> 16) & 0xff;
170 p[3] = (tmp >> 24) & 0xff;
171
172 }
173}
diff --git a/arch/sh/boards/overdrive/irq.c b/arch/sh/boards/overdrive/irq.c
new file mode 100644
index 00000000000..23adc6be71e
--- /dev/null
+++ b/arch/sh/boards/overdrive/irq.c
@@ -0,0 +1,192 @@
1/*
2 * Copyright (C) 2000 David J. Mckay (david.mckay@st.com)
3 *
4 * May be copied or modified under the terms of the GNU General Public
5 * License. See linux/COPYING for more information.
6 *
7 * Looks after interrupts on the overdrive board.
8 *
9 * Bases on the IPR irq system
10 */
11
12#include <linux/config.h>
13#include <linux/init.h>
14#include <linux/irq.h>
15
16#include <asm/system.h>
17#include <asm/io.h>
18
19#include <asm/overdrive/overdrive.h>
20
21struct od_data {
22 int overdrive_irq;
23 int irq_mask;
24};
25
26#define NUM_EXTERNAL_IRQS 16
27#define EXTERNAL_IRQ_NOT_IN_USE (-1)
28#define EXTERNAL_IRQ_NOT_ASSIGNED (-1)
29
30/*
31 * This table is used to determine what to program into the FPGA's CT register
32 * for the specified Linux IRQ.
33 *
34 * The irq_mask gives the interrupt number from the PCI board (PCI_Int(6:0))
35 * but is one greater than that because the because the FPGA treats 0
36 * as disabled, a value of 1 asserts PCI_Int0, and so on.
37 *
38 * The overdrive_irq specifies which of the eight interrupt sources generates
39 * that interrupt, and but is multiplied by four to give the bit offset into
40 * the CT register.
41 *
42 * The seven interrupts levels (SH4 IRL's) we have available here is hardwired
43 * by the EPLD. The assignments here of which PCI interrupt generates each
44 * level is arbitary.
45 */
46static struct od_data od_data_table[NUM_EXTERNAL_IRQS] = {
47 /* overdrive_irq , irq_mask */
48 {EXTERNAL_IRQ_NOT_ASSIGNED, EXTERNAL_IRQ_NOT_IN_USE}, /* 0 */
49 {EXTERNAL_IRQ_NOT_ASSIGNED, 7}, /* 1 */
50 {EXTERNAL_IRQ_NOT_ASSIGNED, 6}, /* 2 */
51 {EXTERNAL_IRQ_NOT_ASSIGNED, EXTERNAL_IRQ_NOT_IN_USE}, /* 3 */
52 {EXTERNAL_IRQ_NOT_ASSIGNED, 5}, /* 4 */
53 {EXTERNAL_IRQ_NOT_ASSIGNED, EXTERNAL_IRQ_NOT_IN_USE}, /* 5 */
54 {EXTERNAL_IRQ_NOT_ASSIGNED, EXTERNAL_IRQ_NOT_IN_USE}, /* 6 */
55 {EXTERNAL_IRQ_NOT_ASSIGNED, 4}, /* 7 */
56 {EXTERNAL_IRQ_NOT_ASSIGNED, EXTERNAL_IRQ_NOT_IN_USE}, /* 8 */
57 {EXTERNAL_IRQ_NOT_ASSIGNED, EXTERNAL_IRQ_NOT_IN_USE}, /* 9 */
58 {EXTERNAL_IRQ_NOT_ASSIGNED, 3}, /* 10 */
59 {EXTERNAL_IRQ_NOT_ASSIGNED, 2}, /* 11 */
60 {EXTERNAL_IRQ_NOT_ASSIGNED, EXTERNAL_IRQ_NOT_IN_USE}, /* 12 */
61 {EXTERNAL_IRQ_NOT_ASSIGNED, 1}, /* 13 */
62 {EXTERNAL_IRQ_NOT_ASSIGNED, EXTERNAL_IRQ_NOT_IN_USE}, /* 14 */
63 {EXTERNAL_IRQ_NOT_ASSIGNED, EXTERNAL_IRQ_NOT_IN_USE} /* 15 */
64};
65
66static void set_od_data(int overdrive_irq, int irq)
67{
68 if (irq >= NUM_EXTERNAL_IRQS || irq < 0)
69 return;
70 od_data_table[irq].overdrive_irq = overdrive_irq << 2;
71}
72
73static void enable_od_irq(unsigned int irq);
74void disable_od_irq(unsigned int irq);
75
76/* shutdown is same as "disable" */
77#define shutdown_od_irq disable_od_irq
78
79static void mask_and_ack_od(unsigned int);
80static void end_od_irq(unsigned int irq);
81
82static unsigned int startup_od_irq(unsigned int irq)
83{
84 enable_od_irq(irq);
85 return 0; /* never anything pending */
86}
87
88static struct hw_interrupt_type od_irq_type = {
89 "Overdrive-IRQ",
90 startup_od_irq,
91 shutdown_od_irq,
92 enable_od_irq,
93 disable_od_irq,
94 mask_and_ack_od,
95 end_od_irq
96};
97
98static void disable_od_irq(unsigned int irq)
99{
100 unsigned val, flags;
101 int overdrive_irq;
102 unsigned mask;
103
104 /* Not a valid interrupt */
105 if (irq < 0 || irq >= NUM_EXTERNAL_IRQS)
106 return;
107
108 /* Is is necessary to use a cli here? Would a spinlock not be
109 * mroe efficient?
110 */
111 local_irq_save(flags);
112 overdrive_irq = od_data_table[irq].overdrive_irq;
113 if (overdrive_irq != EXTERNAL_IRQ_NOT_ASSIGNED) {
114 mask = ~(0x7 << overdrive_irq);
115 val = ctrl_inl(OVERDRIVE_INT_CT);
116 val &= mask;
117 ctrl_outl(val, OVERDRIVE_INT_CT);
118 }
119 local_irq_restore(flags);
120}
121
122static void enable_od_irq(unsigned int irq)
123{
124 unsigned val, flags;
125 int overdrive_irq;
126 unsigned mask;
127
128 /* Not a valid interrupt */
129 if (irq < 0 || irq >= NUM_EXTERNAL_IRQS)
130 return;
131
132 /* Set priority in OD back to original value */
133 local_irq_save(flags);
134 /* This one is not in use currently */
135 overdrive_irq = od_data_table[irq].overdrive_irq;
136 if (overdrive_irq != EXTERNAL_IRQ_NOT_ASSIGNED) {
137 val = ctrl_inl(OVERDRIVE_INT_CT);
138 mask = ~(0x7 << overdrive_irq);
139 val &= mask;
140 mask = od_data_table[irq].irq_mask << overdrive_irq;
141 val |= mask;
142 ctrl_outl(val, OVERDRIVE_INT_CT);
143 }
144 local_irq_restore(flags);
145}
146
147
148
149/* this functions sets the desired irq handler to be an overdrive type */
150static void __init make_od_irq(unsigned int irq)
151{
152 disable_irq_nosync(irq);
153 irq_desc[irq].handler = &od_irq_type;
154 disable_od_irq(irq);
155}
156
157
158static void mask_and_ack_od(unsigned int irq)
159{
160 disable_od_irq(irq);
161}
162
163static void end_od_irq(unsigned int irq)
164{
165 enable_od_irq(irq);
166}
167
168void __init init_overdrive_irq(void)
169{
170 int i;
171
172 /* Disable all interrupts */
173 ctrl_outl(0, OVERDRIVE_INT_CT);
174
175 /* Update interrupt pin mode to use encoded interrupts */
176 i = ctrl_inw(INTC_ICR);
177 i &= ~INTC_ICR_IRLM;
178 ctrl_outw(i, INTC_ICR);
179
180 for (i = 0; i < NUM_EXTERNAL_IRQS; i++) {
181 if (od_data_table[i].irq_mask != EXTERNAL_IRQ_NOT_IN_USE) {
182 make_od_irq(i);
183 } else if (i != 15) { // Cannot use imask on level 15
184 make_imask_irq(i);
185 }
186 }
187
188 /* Set up the interrupts */
189 set_od_data(OVERDRIVE_PCI_INTA, OVERDRIVE_PCI_IRQ1);
190 set_od_data(OVERDRIVE_PCI_INTB, OVERDRIVE_PCI_IRQ2);
191 set_od_data(OVERDRIVE_AUDIO_INT, OVERDRIVE_ESS_IRQ);
192}
diff --git a/arch/sh/boards/overdrive/led.c b/arch/sh/boards/overdrive/led.c
new file mode 100644
index 00000000000..734742e9227
--- /dev/null
+++ b/arch/sh/boards/overdrive/led.c
@@ -0,0 +1,59 @@
1/*
2 * linux/arch/sh/overdrive/led.c
3 *
4 * Copyright (C) 1999 Stuart Menefy <stuart.menefy@st.com>
5 *
6 * May be copied or modified under the terms of the GNU General Public
7 * License. See linux/COPYING for more information.
8 *
9 * This file contains an Overdrive specific LED feature.
10 */
11
12#include <linux/config.h>
13#include <asm/system.h>
14#include <asm/io.h>
15#include <asm/overdrive/overdrive.h>
16
17static void mach_led(int position, int value)
18{
19 unsigned long flags;
20 unsigned long reg;
21
22 local_irq_save(flags);
23
24 reg = readl(OVERDRIVE_CTRL);
25 if (value) {
26 reg |= (1<<3);
27 } else {
28 reg &= ~(1<<3);
29 }
30 writel(reg, OVERDRIVE_CTRL);
31
32 local_irq_restore(flags);
33}
34
35#ifdef CONFIG_HEARTBEAT
36
37#include <linux/sched.h>
38
39/* acts like an actual heart beat -- ie thump-thump-pause... */
40void heartbeat_od(void)
41{
42 static unsigned cnt = 0, period = 0, dist = 0;
43
44 if (cnt == 0 || cnt == dist)
45 mach_led( -1, 1);
46 else if (cnt == 7 || cnt == dist+7)
47 mach_led( -1, 0);
48
49 if (++cnt > period) {
50 cnt = 0;
51 /* The hyperbolic function below modifies the heartbeat period
52 * length in dependency of the current (5min) load. It goes
53 * through the points f(0)=126, f(1)=86, f(5)=51,
54 * f(inf)->30. */
55 period = ((672<<FSHIFT)/(5*avenrun[0]+(7<<FSHIFT))) + 30;
56 dist = period / 4;
57 }
58}
59#endif /* CONFIG_HEARTBEAT */
diff --git a/arch/sh/boards/overdrive/mach.c b/arch/sh/boards/overdrive/mach.c
new file mode 100644
index 00000000000..2834a03ae47
--- /dev/null
+++ b/arch/sh/boards/overdrive/mach.c
@@ -0,0 +1,62 @@
1/*
2 * linux/arch/sh/overdrive/mach.c
3 *
4 * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com)
5 *
6 * May be copied or modified under the terms of the GNU General Public
7 * License. See linux/COPYING for more information.
8 *
9 * Machine vector for the STMicroelectronics Overdrive
10 */
11
12#include <linux/init.h>
13
14#include <asm/machvec.h>
15#include <asm/rtc.h>
16#include <asm/machvec_init.h>
17
18#include <asm/io_unknown.h>
19#include <asm/io_generic.h>
20#include <asm/overdrive/io.h>
21
22void heartbeat_od(void);
23void init_overdrive_irq(void);
24void galileo_pcibios_init(void);
25
26/*
27 * The Machine Vector
28 */
29
30struct sh_machine_vector mv_od __initmv = {
31 .mv_nr_irqs = 48,
32
33 .mv_inb = od_inb,
34 .mv_inw = od_inw,
35 .mv_inl = od_inl,
36 .mv_outb = od_outb,
37 .mv_outw = od_outw,
38 .mv_outl = od_outl,
39
40 .mv_inb_p = od_inb_p,
41 .mv_inw_p = od_inw_p,
42 .mv_inl_p = od_inl_p,
43 .mv_outb_p = od_outb_p,
44 .mv_outw_p = od_outw_p,
45 .mv_outl_p = od_outl_p,
46
47 .mv_insb = od_insb,
48 .mv_insw = od_insw,
49 .mv_insl = od_insl,
50 .mv_outsb = od_outsb,
51 .mv_outsw = od_outsw,
52 .mv_outsl = od_outsl,
53
54#ifdef CONFIG_PCI
55 .mv_init_irq = init_overdrive_irq,
56#endif
57#ifdef CONFIG_HEARTBEAT
58 .mv_heartbeat = heartbeat_od,
59#endif
60};
61
62ALIAS_MV(od)
diff --git a/arch/sh/boards/overdrive/pcidma.c b/arch/sh/boards/overdrive/pcidma.c
new file mode 100644
index 00000000000..1c9bfeda00b
--- /dev/null
+++ b/arch/sh/boards/overdrive/pcidma.c
@@ -0,0 +1,46 @@
1/*
2 * Copyright (C) 2000 David J. Mckay (david.mckay@st.com)
3 *
4 * May be copied or modified under the terms of the GNU General Public
5 * License. See linux/COPYING for more information.
6 *
7 * Dynamic DMA mapping support.
8 *
9 * On the overdrive, we can only DMA from memory behind the PCI bus!
10 * this means that all DMA'able memory must come from there.
11 * this restriction will not apply to later boards.
12 */
13
14#include <linux/types.h>
15#include <linux/mm.h>
16#include <linux/string.h>
17#include <linux/pci.h>
18#include <asm/io.h>
19
20void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
21 dma_addr_t * dma_handle)
22{
23 void *ret;
24 int gfp = GFP_ATOMIC;
25
26 printk("BUG: pci_alloc_consistent() called - not yet supported\n");
27 /* We ALWAYS need DMA memory on the overdrive hardware,
28 * due to it's extreme weirdness
29 * Need to flush the cache here as well, since the memory
30 * can still be seen through the cache!
31 */
32 gfp |= GFP_DMA;
33 ret = (void *) __get_free_pages(gfp, get_order(size));
34
35 if (ret != NULL) {
36 memset(ret, 0, size);
37 *dma_handle = virt_to_bus(ret);
38 }
39 return ret;
40}
41
42void pci_free_consistent(struct pci_dev *hwdev, size_t size,
43 void *vaddr, dma_addr_t dma_handle)
44{
45 free_pages((unsigned long) vaddr, get_order(size));
46}
diff --git a/arch/sh/boards/overdrive/setup.c b/arch/sh/boards/overdrive/setup.c
new file mode 100644
index 00000000000..a36ce0284ed
--- /dev/null
+++ b/arch/sh/boards/overdrive/setup.c
@@ -0,0 +1,41 @@
1/*
2 * arch/sh/overdrive/setup.c
3 *
4 * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com)
5 *
6 * May be copied or modified under the terms of the GNU General Public
7 * License. See linux/COPYING for more information.
8 *
9 * STMicroelectronics Overdrive Support.
10 */
11
12#include <linux/config.h>
13#include <linux/kernel.h>
14#include <linux/init.h>
15#include <asm/io.h>
16
17#include <asm/overdrive/overdrive.h>
18#include <asm/overdrive/fpga.h>
19
20extern void od_time_init(void);
21
22const char *get_system_type(void)
23{
24 return "SH7750 Overdrive";
25}
26
27/*
28 * Initialize the board
29 */
30int __init platform_setup(void)
31{
32#ifdef CONFIG_PCI
33 init_overdrive_fpga();
34 galileo_init();
35#endif
36
37 board_time_init = od_time_init;
38
39 /* Enable RS232 receive buffers */
40 writel(0x1e, OVERDRIVE_CTRL);
41}
diff --git a/arch/sh/boards/overdrive/time.c b/arch/sh/boards/overdrive/time.c
new file mode 100644
index 00000000000..68533690e09
--- /dev/null
+++ b/arch/sh/boards/overdrive/time.c
@@ -0,0 +1,119 @@
1/*
2 * arch/sh/boards/overdrive/time.c
3 *
4 * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com)
5 * Copyright (C) 2002 Paul Mundt (lethal@chaoticdreams.org)
6 *
7 * May be copied or modified under the terms of the GNU General Public
8 * License. See linux/COPYING for more information.
9 *
10 * STMicroelectronics Overdrive Support.
11 */
12
13void od_time_init(void)
14{
15 struct frqcr_data {
16 unsigned short frqcr;
17 struct {
18 unsigned char multiplier;
19 unsigned char divisor;
20 } factor[3];
21 };
22
23 static struct frqcr_data st40_frqcr_table[] = {
24 { 0x000, {{1,1}, {1,1}, {1,2}}},
25 { 0x002, {{1,1}, {1,1}, {1,4}}},
26 { 0x004, {{1,1}, {1,1}, {1,8}}},
27 { 0x008, {{1,1}, {1,2}, {1,2}}},
28 { 0x00A, {{1,1}, {1,2}, {1,4}}},
29 { 0x00C, {{1,1}, {1,2}, {1,8}}},
30 { 0x011, {{1,1}, {2,3}, {1,6}}},
31 { 0x013, {{1,1}, {2,3}, {1,3}}},
32 { 0x01A, {{1,1}, {1,2}, {1,4}}},
33 { 0x01C, {{1,1}, {1,2}, {1,8}}},
34 { 0x023, {{1,1}, {2,3}, {1,3}}},
35 { 0x02C, {{1,1}, {1,2}, {1,8}}},
36 { 0x048, {{1,2}, {1,2}, {1,4}}},
37 { 0x04A, {{1,2}, {1,2}, {1,6}}},
38 { 0x04C, {{1,2}, {1,2}, {1,8}}},
39 { 0x05A, {{1,2}, {1,3}, {1,6}}},
40 { 0x05C, {{1,2}, {1,3}, {1,6}}},
41 { 0x063, {{1,2}, {1,4}, {1,4}}},
42 { 0x06C, {{1,2}, {1,4}, {1,8}}},
43 { 0x091, {{1,3}, {1,3}, {1,6}}},
44 { 0x093, {{1,3}, {1,3}, {1,6}}},
45 { 0x0A3, {{1,3}, {1,6}, {1,6}}},
46 { 0x0DA, {{1,4}, {1,4}, {1,8}}},
47 { 0x0DC, {{1,4}, {1,4}, {1,8}}},
48 { 0x0EC, {{1,4}, {1,8}, {1,8}}},
49 { 0x123, {{1,4}, {1,4}, {1,8}}},
50 { 0x16C, {{1,4}, {1,8}, {1,8}}},
51 };
52
53 struct memclk_data {
54 unsigned char multiplier;
55 unsigned char divisor;
56 };
57 static struct memclk_data st40_memclk_table[8] = {
58 {1,1}, // 000
59 {1,2}, // 001
60 {1,3}, // 010
61 {2,3}, // 011
62 {1,4}, // 100
63 {1,6}, // 101
64 {1,8}, // 110
65 {1,8} // 111
66 };
67
68 unsigned long pvr;
69
70 /*
71 * This should probably be moved into the SH3 probing code, and then
72 * use the processor structure to determine which CPU we are running
73 * on.
74 */
75 pvr = ctrl_inl(CCN_PVR);
76 printk("PVR %08x\n", pvr);
77
78 if (((pvr >> CCN_PVR_CHIP_SHIFT) & CCN_PVR_CHIP_MASK) == CCN_PVR_CHIP_ST40STB1) {
79 /*
80 * Unfortunatly the STB1 FRQCR values are different from the
81 * 7750 ones.
82 */
83 struct frqcr_data *d;
84 int a;
85 unsigned long memclkcr;
86 struct memclk_data *e;
87
88 for (a=0; a<ARRAY_SIZE(st40_frqcr_table); a++) {
89 d = &st40_frqcr_table[a];
90 if (d->frqcr == (frqcr & 0x1ff))
91 break;
92 }
93 if (a == ARRAY_SIZE(st40_frqcr_table)) {
94 d = st40_frqcr_table;
95 printk("ERROR: Unrecognised FRQCR value, using default multipliers\n");
96 }
97
98 memclkcr = ctrl_inl(CLOCKGEN_MEMCLKCR);
99 e = &st40_memclk_table[memclkcr & MEMCLKCR_RATIO_MASK];
100
101 printk("Clock multipliers: CPU: %d/%d Bus: %d/%d Mem: %d/%d Periph: %d/%d\n",
102 d->factor[0].multiplier, d->factor[0].divisor,
103 d->factor[1].multiplier, d->factor[1].divisor,
104 e->multiplier, e->divisor,
105 d->factor[2].multiplier, d->factor[2].divisor);
106
107 current_cpu_data.master_clock = current_cpu_data.module_clock *
108 d->factor[2].divisor /
109 d->factor[2].multiplier;
110 current_cpu_data.bus_clock = current_cpu_data.master_clock *
111 d->factor[1].multiplier /
112 d->factor[1].divisor;
113 current_cpu_data.memory_clock = current_cpu_data.master_clock *
114 e->multiplier / e->divisor;
115 current_cpu_data.cpu_clock = current_cpu_data.master_clock *
116 d->factor[0].multiplier /
117 d->factor[0].divisor;
118}
119
diff --git a/arch/sh/boards/renesas/edosk7705/Makefile b/arch/sh/boards/renesas/edosk7705/Makefile
new file mode 100644
index 00000000000..7fccbf2e4a1
--- /dev/null
+++ b/arch/sh/boards/renesas/edosk7705/Makefile
@@ -0,0 +1,10 @@
1#
2# Makefile for the EDOSK7705 specific parts of the kernel
3#
4# Note! Dependencies are done automagically by 'make dep', which also
5# removes any old dependencies. DON'T put your own dependencies here
6# unless it's something special (ie not a .c file).
7#
8
9obj-y := setup.o io.o
10
diff --git a/arch/sh/boards/renesas/edosk7705/io.c b/arch/sh/boards/renesas/edosk7705/io.c
new file mode 100644
index 00000000000..541cea2a652
--- /dev/null
+++ b/arch/sh/boards/renesas/edosk7705/io.c
@@ -0,0 +1,94 @@
1/*
2 * arch/sh/boards/renesas/edosk7705/io.c
3 *
4 * Copyright (C) 2001 Ian da Silva, Jeremy Siegel
5 * Based largely on io_se.c.
6 *
7 * I/O routines for Hitachi EDOSK7705 board.
8 *
9 */
10
11#include <linux/kernel.h>
12#include <linux/types.h>
13#include <asm/io.h>
14#include <asm/edosk7705/io.h>
15#include <asm/addrspace.h>
16
17#define SMC_IOADDR 0xA2000000
18
19#define maybebadio(name,port) \
20 printk("bad PC-like io %s for port 0x%lx at 0x%08x\n", \
21 #name, (port), (__u32) __builtin_return_address(0))
22
23/* Map the Ethernet addresses as if it is at 0x300 - 0x320 */
24unsigned long sh_edosk7705_isa_port2addr(unsigned long port)
25{
26 if (port >= 0x300 && port < 0x320) {
27 /* SMC91C96 registers are 4 byte aligned rather than the
28 * usual 2 byte!
29 */
30 return SMC_IOADDR + ( (port - 0x300) * 2);
31 }
32
33 maybebadio(sh_edosk7705_isa_port2addr, port);
34 return port;
35}
36
37/* Trying to read / write bytes on odd-byte boundaries to the Ethernet
38 * registers causes problems. So we bit-shift the value and read / write
39 * in 2 byte chunks. Setting the low byte to 0 does not cause problems
40 * now as odd byte writes are only made on the bit mask / interrupt
41 * register. This may not be the case in future Mar-2003 SJD
42 */
43unsigned char sh_edosk7705_inb(unsigned long port)
44{
45 if (port >= 0x300 && port < 0x320 && port & 0x01) {
46 return (volatile unsigned char)(generic_inw(port -1) >> 8);
47 }
48 return *(volatile unsigned char *)sh_edosk7705_isa_port2addr(port);
49}
50
51unsigned int sh_edosk7705_inl(unsigned long port)
52{
53 return *(volatile unsigned long *)port;
54}
55
56void sh_edosk7705_outb(unsigned char value, unsigned long port)
57{
58 if (port >= 0x300 && port < 0x320 && port & 0x01) {
59 generic_outw(((unsigned short)value << 8), port -1);
60 return;
61 }
62 *(volatile unsigned char *)sh_edosk7705_isa_port2addr(port) = value;
63}
64
65void sh_edosk7705_outl(unsigned int value, unsigned long port)
66{
67 *(volatile unsigned long *)port = value;
68}
69
70void sh_edosk7705_insb(unsigned long port, void *addr, unsigned long count)
71{
72 unsigned char *p = addr;
73 while (count--) *p++ = sh_edosk7705_inb(port);
74}
75
76void sh_edosk7705_insl(unsigned long port, void *addr, unsigned long count)
77{
78 unsigned long *p = (unsigned long*)addr;
79 while (count--)
80 *p++ = *(volatile unsigned long *)port;
81}
82
83void sh_edosk7705_outsb(unsigned long port, const void *addr, unsigned long count)
84{
85 unsigned char *p = (unsigned char*)addr;
86 while (count--) sh_edosk7705_outb(*p++, port);
87}
88
89void sh_edosk7705_outsl(unsigned long port, const void *addr, unsigned long count)
90{
91 unsigned long *p = (unsigned long*)addr;
92 while (count--) sh_edosk7705_outl(*p++, port);
93}
94
diff --git a/arch/sh/boards/renesas/edosk7705/setup.c b/arch/sh/boards/renesas/edosk7705/setup.c
new file mode 100644
index 00000000000..8b6f0c2af09
--- /dev/null
+++ b/arch/sh/boards/renesas/edosk7705/setup.c
@@ -0,0 +1,60 @@
1/*
2 * arch/sh/boards/renesas/edosk7705/setup.c
3 *
4 * Copyright (C) 2000 Kazumoto Kojima
5 *
6 * Hitachi SolutionEngine Support.
7 *
8 * Modified for edosk7705 development
9 * board by S. Dunn, 2003.
10 */
11
12#include <linux/config.h>
13#include <linux/init.h>
14#include <asm/machvec.h>
15#include <asm/machvec_init.h>
16#include <asm/edosk7705/io.h>
17
18static void init_edosk7705(void);
19
20/*
21 * The Machine Vector
22 */
23
24struct sh_machine_vector mv_edosk7705 __initmv = {
25 .mv_nr_irqs = 80,
26
27 .mv_inb = sh_edosk7705_inb,
28 .mv_inl = sh_edosk7705_inl,
29 .mv_outb = sh_edosk7705_outb,
30 .mv_outl = sh_edosk7705_outl,
31
32 .mv_inl_p = sh_edosk7705_inl,
33 .mv_outl_p = sh_edosk7705_outl,
34
35 .mv_insb = sh_edosk7705_insb,
36 .mv_insl = sh_edosk7705_insl,
37 .mv_outsb = sh_edosk7705_outsb,
38 .mv_outsl = sh_edosk7705_outsl,
39
40 .mv_isa_port2addr = sh_edosk7705_isa_port2addr,
41 .mv_init_irq = init_edosk7705,
42};
43ALIAS_MV(edosk7705)
44
45static void __init init_edosk7705(void)
46{
47 /* This is the Ethernet interrupt */
48 make_imask_irq(0x09);
49}
50
51const char *get_system_type(void)
52{
53 return "EDOSK7705";
54}
55
56void __init platform_setup(void)
57{
58 /* Nothing .. */
59}
60
diff --git a/arch/sh/boards/renesas/hs7751rvoip/Makefile b/arch/sh/boards/renesas/hs7751rvoip/Makefile
new file mode 100644
index 00000000000..e8b4109ace1
--- /dev/null
+++ b/arch/sh/boards/renesas/hs7751rvoip/Makefile
@@ -0,0 +1,12 @@
1#
2# Makefile for the HS7751RVoIP specific parts of the kernel
3#
4# Note! Dependencies are done automagically by 'make dep', which also
5# removes any old dependencies. DON'T put your own dependencies here
6# unless it's something special (ie not a .c file).
7#
8
9obj-y := mach.o setup.o io.o irq.o led.o
10
11obj-$(CONFIG_PCI) += pci.o
12
diff --git a/arch/sh/boards/renesas/hs7751rvoip/io.c b/arch/sh/boards/renesas/hs7751rvoip/io.c
new file mode 100644
index 00000000000..456753d2649
--- /dev/null
+++ b/arch/sh/boards/renesas/hs7751rvoip/io.c
@@ -0,0 +1,310 @@
1/*
2 * linux/arch/sh/kernel/io_hs7751rvoip.c
3 *
4 * Copyright (C) 2001 Ian da Silva, Jeremy Siegel
5 * Based largely on io_se.c.
6 *
7 * I/O routine for Renesas Technology sales HS7751RVoIP
8 *
9 * Initial version only to support LAN access; some
10 * placeholder code from io_hs7751rvoip.c left in with the
11 * expectation of later SuperIO and PCMCIA access.
12 */
13
14#include <linux/config.h>
15#include <linux/kernel.h>
16#include <linux/types.h>
17#include <asm/io.h>
18#include <asm/hs7751rvoip/hs7751rvoip.h>
19#include <asm/addrspace.h>
20
21#include <linux/module.h>
22#include <linux/pci.h>
23#include "../../../drivers/pci/pci-sh7751.h"
24
25extern void *area5_io8_base; /* Area 5 8bit I/O Base address */
26extern void *area6_io8_base; /* Area 6 8bit I/O Base address */
27extern void *area5_io16_base; /* Area 5 16bit I/O Base address */
28extern void *area6_io16_base; /* Area 6 16bit I/O Base address */
29
30/*
31 * The 7751R HS7751RVoIP uses the built-in PCI controller (PCIC)
32 * of the 7751R processor, and has a SuperIO accessible via the PCI.
33 * The board also includes a PCMCIA controller on its memory bus,
34 * like the other Solution Engine boards.
35 */
36
37#define PCIIOBR (volatile long *)PCI_REG(SH7751_PCIIOBR)
38#define PCIMBR (volatile long *)PCI_REG(SH7751_PCIMBR)
39#define PCI_IO_AREA SH7751_PCI_IO_BASE
40#define PCI_MEM_AREA SH7751_PCI_CONFIG_BASE
41
42#define PCI_IOMAP(adr) (PCI_IO_AREA + (adr & ~SH7751_PCIIOBR_MASK))
43
44#if defined(CONFIG_HS7751RVOIP_CODEC)
45#define CODEC_IO_BASE 0x1000
46#endif
47
48#define maybebadio(name,port) \
49 printk("bad PC-like io %s for port 0x%lx at 0x%08x\n", \
50 #name, (port), (__u32) __builtin_return_address(0))
51
52static inline void delay(void)
53{
54 ctrl_inw(0xa0000000);
55}
56
57static inline unsigned long port2adr(unsigned int port)
58{
59 if ((0x1f0 <= port && port < 0x1f8) || port == 0x3f6)
60 if (port == 0x3f6)
61 return ((unsigned long)area5_io16_base + 0x0c);
62 else
63 return ((unsigned long)area5_io16_base + 0x800 + ((port-0x1f0) << 1));
64 else
65 maybebadio(port2adr, (unsigned long)port);
66 return port;
67}
68
69/* The 7751R HS7751RVoIP seems to have everything hooked */
70/* up pretty normally (nothing on high-bytes only...) so this */
71/* shouldn't be needed */
72static inline int shifted_port(unsigned long port)
73{
74 /* For IDE registers, value is not shifted */
75 if ((0x1f0 <= port && port < 0x1f8) || port == 0x3f6)
76 return 0;
77 else
78 return 1;
79}
80
81#if defined(CONFIG_HS7751RVOIP_CODEC)
82static inline int
83codec_port(unsigned long port)
84{
85 if (CODEC_IO_BASE <= port && port < (CODEC_IO_BASE+0x20))
86 return 1;
87 else
88 return 0;
89}
90#endif
91
92/* In case someone configures the kernel w/o PCI support: in that */
93/* scenario, don't ever bother to check for PCI-window addresses */
94
95/* NOTE: WINDOW CHECK MAY BE A BIT OFF, HIGH PCIBIOS_MIN_IO WRAPS? */
96#if defined(CONFIG_PCI)
97#define CHECK_SH7751_PCIIO(port) \
98 ((port >= PCIBIOS_MIN_IO) && (port < (PCIBIOS_MIN_IO + SH7751_PCI_IO_SIZE)))
99#else
100#define CHECK_SH7751_PCIIO(port) (0)
101#endif
102
103/*
104 * General outline: remap really low stuff [eventually] to SuperIO,
105 * stuff in PCI IO space (at or above window at pci.h:PCIBIOS_MIN_IO)
106 * is mapped through the PCI IO window. Stuff with high bits (PXSEG)
107 * should be way beyond the window, and is used w/o translation for
108 * compatibility.
109 */
110unsigned char hs7751rvoip_inb(unsigned long port)
111{
112 if (PXSEG(port))
113 return *(volatile unsigned char *)port;
114#if defined(CONFIG_HS7751RVOIP_CODEC)
115 else if (codec_port(port))
116 return *(volatile unsigned char *)((unsigned long)area6_io8_base+(port-CODEC_IO_BASE));
117#endif
118 else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
119 return *(volatile unsigned char *)PCI_IOMAP(port);
120 else
121 return (*(volatile unsigned short *)port2adr(port) & 0xff);
122}
123
124unsigned char hs7751rvoip_inb_p(unsigned long port)
125{
126 unsigned char v;
127
128 if (PXSEG(port))
129 v = *(volatile unsigned char *)port;
130#if defined(CONFIG_HS7751RVOIP_CODEC)
131 else if (codec_port(port))
132 v = *(volatile unsigned char *)((unsigned long)area6_io8_base+(port-CODEC_IO_BASE));
133#endif
134 else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
135 v = *(volatile unsigned char *)PCI_IOMAP(port);
136 else
137 v = (*(volatile unsigned short *)port2adr(port) & 0xff);
138 delay();
139 return v;
140}
141
142unsigned short hs7751rvoip_inw(unsigned long port)
143{
144 if (PXSEG(port))
145 return *(volatile unsigned short *)port;
146 else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
147 return *(volatile unsigned short *)PCI_IOMAP(port);
148 else
149 maybebadio(inw, port);
150 return 0;
151}
152
153unsigned int hs7751rvoip_inl(unsigned long port)
154{
155 if (PXSEG(port))
156 return *(volatile unsigned long *)port;
157 else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
158 return *(volatile unsigned long *)PCI_IOMAP(port);
159 else
160 maybebadio(inl, port);
161 return 0;
162}
163
164void hs7751rvoip_outb(unsigned char value, unsigned long port)
165{
166
167 if (PXSEG(port))
168 *(volatile unsigned char *)port = value;
169#if defined(CONFIG_HS7751RVOIP_CODEC)
170 else if (codec_port(port))
171 *(volatile unsigned cjar *)((unsigned long)area6_io8_base+(port-CODEC_IO_BASE)) = value;
172#endif
173 else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
174 *(unsigned char *)PCI_IOMAP(port) = value;
175 else
176 *(volatile unsigned short *)port2adr(port) = value;
177}
178
179void hs7751rvoip_outb_p(unsigned char value, unsigned long port)
180{
181 if (PXSEG(port))
182 *(volatile unsigned char *)port = value;
183#if defined(CONFIG_HS7751RVOIP_CODEC)
184 else if (codec_port(port))
185 *(volatile unsigned cjar *)((unsigned long)area6_io8_base+(port-CODEC_IO_BASE)) = value;
186#endif
187 else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
188 *(unsigned char *)PCI_IOMAP(port) = value;
189 else
190 *(volatile unsigned short *)port2adr(port) = value;
191 delay();
192}
193
194void hs7751rvoip_outw(unsigned short value, unsigned long port)
195{
196 if (PXSEG(port))
197 *(volatile unsigned short *)port = value;
198 else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
199 *(unsigned short *)PCI_IOMAP(port) = value;
200 else
201 maybebadio(outw, port);
202}
203
204void hs7751rvoip_outl(unsigned int value, unsigned long port)
205{
206 if (PXSEG(port))
207 *(volatile unsigned long *)port = value;
208 else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
209 *((unsigned long *)PCI_IOMAP(port)) = value;
210 else
211 maybebadio(outl, port);
212}
213
214void hs7751rvoip_insb(unsigned long port, void *addr, unsigned long count)
215{
216 if (PXSEG(port))
217 while (count--) *((unsigned char *) addr)++ = *(volatile unsigned char *)port;
218#if defined(CONFIG_HS7751RVOIP_CODEC)
219 else if (codec_port(port))
220 while (count--) *((unsigned char *) addr)++ = *(volatile unsigned char *)((unsigned long)area6_io8_base+(port-CODEC_IO_BASE));
221#endif
222 else if (CHECK_SH7751_PCIIO(port) || shifted_port(port)) {
223 volatile __u8 *bp = (__u8 *)PCI_IOMAP(port);
224
225 while (count--) *((volatile unsigned char *) addr)++ = *bp;
226 } else {
227 volatile __u16 *p = (volatile unsigned short *)port2adr(port);
228
229 while (count--) *((unsigned char *) addr)++ = *p & 0xff;
230 }
231}
232
233void hs7751rvoip_insw(unsigned long port, void *addr, unsigned long count)
234{
235 volatile __u16 *p;
236
237 if (PXSEG(port))
238 p = (volatile unsigned short *)port;
239 else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
240 p = (volatile unsigned short *)PCI_IOMAP(port);
241 else
242 p = (volatile unsigned short *)port2adr(port);
243 while (count--) *((__u16 *) addr)++ = *p;
244}
245
246void hs7751rvoip_insl(unsigned long port, void *addr, unsigned long count)
247{
248 if (CHECK_SH7751_PCIIO(port) || shifted_port(port)) {
249 volatile __u32 *p = (__u32 *)PCI_IOMAP(port);
250
251 while (count--) *((__u32 *) addr)++ = *p;
252 } else
253 maybebadio(insl, port);
254}
255
256void hs7751rvoip_outsb(unsigned long port, const void *addr, unsigned long count)
257{
258 if (PXSEG(port))
259 while (count--) *(volatile unsigned char *)port = *((unsigned char *) addr)++;
260#if defined(CONFIG_HS7751RVOIP_CODEC)
261 else if (codec_port(port))
262 while (count--) *(volatile unsigned char *)((unsigned long)area6_io8_base+(port-CODEC_IO_BASE)) = *((unsigned char *) addr)++;
263#endif
264 else if (CHECK_SH7751_PCIIO(port) || shifted_port(port)) {
265 volatile __u8 *bp = (__u8 *)PCI_IOMAP(port);
266
267 while (count--) *bp = *((volatile unsigned char *) addr)++;
268 } else {
269 volatile __u16 *p = (volatile unsigned short *)port2adr(port);
270
271 while (count--) *p = *((unsigned char *) addr)++;
272 }
273}
274
275void hs7751rvoip_outsw(unsigned long port, const void *addr, unsigned long count)
276{
277 volatile __u16 *p;
278
279 if (PXSEG(port))
280 p = (volatile unsigned short *)port;
281 else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
282 p = (volatile unsigned short *)PCI_IOMAP(port);
283 else
284 p = (volatile unsigned short *)port2adr(port);
285 while (count--) *p = *((__u16 *) addr)++;
286}
287
288void hs7751rvoip_outsl(unsigned long port, const void *addr, unsigned long count)
289{
290 if (CHECK_SH7751_PCIIO(port) || shifted_port(port)) {
291 volatile __u32 *p = (__u32 *)PCI_IOMAP(port);
292
293 while (count--) *p = *((__u32 *) addr)++;
294 } else
295 maybebadio(outsl, port);
296}
297
298void *hs7751rvoip_ioremap(unsigned long offset, unsigned long size)
299{
300 if (offset >= 0xfd000000)
301 return (void *)offset;
302 else
303 return (void *)P2SEGADDR(offset);
304}
305EXPORT_SYMBOL(hs7751rvoip_ioremap);
306
307unsigned long hs7751rvoip_isa_port2addr(unsigned long offset)
308{
309 return port2adr(offset);
310}
diff --git a/arch/sh/boards/renesas/hs7751rvoip/irq.c b/arch/sh/boards/renesas/hs7751rvoip/irq.c
new file mode 100644
index 00000000000..a7921f67a35
--- /dev/null
+++ b/arch/sh/boards/renesas/hs7751rvoip/irq.c
@@ -0,0 +1,122 @@
1/*
2 * linux/arch/sh/boards/renesas/hs7751rvoip/irq.c
3 *
4 * Copyright (C) 2000 Kazumoto Kojima
5 *
6 * Renesas Technology Sales HS7751RVoIP Support.
7 *
8 * Modified for HS7751RVoIP by
9 * Atom Create Engineering Co., Ltd. 2002.
10 * Lineo uSolutions, Inc. 2003.
11 */
12
13#include <linux/config.h>
14#include <linux/init.h>
15#include <linux/irq.h>
16#include <asm/io.h>
17#include <asm/irq.h>
18#include <asm/hs7751rvoip/hs7751rvoip.h>
19
20static int mask_pos[] = {8, 9, 10, 11, 12, 13, 0, 1, 2, 3, 4, 5, 6, 7};
21
22static void enable_hs7751rvoip_irq(unsigned int irq);
23static void disable_hs7751rvoip_irq(unsigned int irq);
24
25/* shutdown is same as "disable" */
26#define shutdown_hs7751rvoip_irq disable_hs7751rvoip_irq
27
28static void ack_hs7751rvoip_irq(unsigned int irq);
29static void end_hs7751rvoip_irq(unsigned int irq);
30
31static unsigned int startup_hs7751rvoip_irq(unsigned int irq)
32{
33 enable_hs7751rvoip_irq(irq);
34 return 0; /* never anything pending */
35}
36
37static void disable_hs7751rvoip_irq(unsigned int irq)
38{
39 unsigned long flags;
40 unsigned short val;
41 unsigned short mask = 0xffff ^ (0x0001 << mask_pos[irq]);
42
43 /* Set the priority in IPR to 0 */
44 local_irq_save(flags);
45 val = ctrl_inw(IRLCNTR3);
46 val &= mask;
47 ctrl_outw(val, IRLCNTR3);
48 local_irq_restore(flags);
49}
50
51static void enable_hs7751rvoip_irq(unsigned int irq)
52{
53 unsigned long flags;
54 unsigned short val;
55 unsigned short value = (0x0001 << mask_pos[irq]);
56
57 /* Set priority in IPR back to original value */
58 local_irq_save(flags);
59 val = ctrl_inw(IRLCNTR3);
60 val |= value;
61 ctrl_outw(val, IRLCNTR3);
62 local_irq_restore(flags);
63}
64
65static void ack_hs7751rvoip_irq(unsigned int irq)
66{
67 disable_hs7751rvoip_irq(irq);
68}
69
70static void end_hs7751rvoip_irq(unsigned int irq)
71{
72 if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
73 enable_hs7751rvoip_irq(irq);
74}
75
76static struct hw_interrupt_type hs7751rvoip_irq_type = {
77 "HS7751RVoIP IRQ",
78 startup_hs7751rvoip_irq,
79 shutdown_hs7751rvoip_irq,
80 enable_hs7751rvoip_irq,
81 disable_hs7751rvoip_irq,
82 ack_hs7751rvoip_irq,
83 end_hs7751rvoip_irq,
84};
85
86static void make_hs7751rvoip_irq(unsigned int irq)
87{
88 disable_irq_nosync(irq);
89 irq_desc[irq].handler = &hs7751rvoip_irq_type;
90 disable_hs7751rvoip_irq(irq);
91}
92
93/*
94 * Initialize IRQ setting
95 */
96void __init init_hs7751rvoip_IRQ(void)
97{
98 int i;
99
100 /* IRL0=ON HOOK1
101 * IRL1=OFF HOOK1
102 * IRL2=ON HOOK2
103 * IRL3=OFF HOOK2
104 * IRL4=Ringing Detection
105 * IRL5=CODEC
106 * IRL6=Ethernet
107 * IRL7=Ethernet Hub
108 * IRL8=USB Communication
109 * IRL9=USB Connection
110 * IRL10=USB DMA
111 * IRL11=CF Card
112 * IRL12=PCMCIA
113 * IRL13=PCI Slot
114 */
115 ctrl_outw(0x9876, IRLCNTR1);
116 ctrl_outw(0xdcba, IRLCNTR2);
117 ctrl_outw(0x0050, IRLCNTR4);
118 ctrl_outw(0x4321, IRLCNTR5);
119
120 for (i=0; i<14; i++)
121 make_hs7751rvoip_irq(i);
122}
diff --git a/arch/sh/boards/renesas/hs7751rvoip/led.c b/arch/sh/boards/renesas/hs7751rvoip/led.c
new file mode 100644
index 00000000000..18a13c8da8a
--- /dev/null
+++ b/arch/sh/boards/renesas/hs7751rvoip/led.c
@@ -0,0 +1,27 @@
1/*
2 * linux/arch/sh/kernel/setup_hs7751rvoip.c
3 *
4 * Copyright (C) 2000 Kazumoto Kojima
5 *
6 * Renesas Technology Sales HS7751RVoIP Support.
7 *
8 * Modified for HS7751RVoIP by
9 * Atom Create Engineering Co., Ltd. 2002.
10 * Lineo uSolutions, Inc. 2003.
11 */
12
13#include <linux/config.h>
14#include <asm/io.h>
15#include <asm/hs7751rvoip/hs7751rvoip.h>
16
17extern unsigned int debug_counter;
18
19void debug_led_disp(void)
20{
21 unsigned short value;
22
23 value = (unsigned char)debug_counter++;
24 ctrl_outb((0xf0|value), PA_OUTPORTR);
25 if (value == 0x0f)
26 debug_counter = 0;
27}
diff --git a/arch/sh/boards/renesas/hs7751rvoip/mach.c b/arch/sh/boards/renesas/hs7751rvoip/mach.c
new file mode 100644
index 00000000000..8bbed60220c
--- /dev/null
+++ b/arch/sh/boards/renesas/hs7751rvoip/mach.c
@@ -0,0 +1,55 @@
1/*
2 * linux/arch/sh/kernel/mach_hs7751rvoip.c
3 *
4 * Minor tweak of mach_se.c file to reference hs7751rvoip-specific items.
5 *
6 * May be copied or modified under the terms of the GNU General Public
7 * License. See linux/COPYING for more information.
8 *
9 * Machine vector for the Renesas Technology sales HS7751RVoIP
10 */
11
12#include <linux/config.h>
13#include <linux/init.h>
14
15#include <asm/machvec.h>
16#include <asm/rtc.h>
17#include <asm/irq.h>
18#include <asm/hs7751rvoip/io.h>
19
20extern void init_hs7751rvoip_IRQ(void);
21extern void *hs7751rvoip_ioremap(unsigned long, unsigned long);
22
23/*
24 * The Machine Vector
25 */
26
27struct sh_machine_vector mv_hs7751rvoip __initmv = {
28 .mv_nr_irqs = 72,
29
30 .mv_inb = hs7751rvoip_inb,
31 .mv_inw = hs7751rvoip_inw,
32 .mv_inl = hs7751rvoip_inl,
33 .mv_outb = hs7751rvoip_outb,
34 .mv_outw = hs7751rvoip_outw,
35 .mv_outl = hs7751rvoip_outl,
36
37 .mv_inb_p = hs7751rvoip_inb_p,
38 .mv_inw_p = hs7751rvoip_inw,
39 .mv_inl_p = hs7751rvoip_inl,
40 .mv_outb_p = hs7751rvoip_outb_p,
41 .mv_outw_p = hs7751rvoip_outw,
42 .mv_outl_p = hs7751rvoip_outl,
43
44 .mv_insb = hs7751rvoip_insb,
45 .mv_insw = hs7751rvoip_insw,
46 .mv_insl = hs7751rvoip_insl,
47 .mv_outsb = hs7751rvoip_outsb,
48 .mv_outsw = hs7751rvoip_outsw,
49 .mv_outsl = hs7751rvoip_outsl,
50
51 .mv_ioremap = hs7751rvoip_ioremap,
52 .mv_isa_port2addr = hs7751rvoip_isa_port2addr,
53 .mv_init_irq = init_hs7751rvoip_IRQ,
54};
55ALIAS_MV(hs7751rvoip)
diff --git a/arch/sh/boards/renesas/hs7751rvoip/pci.c b/arch/sh/boards/renesas/hs7751rvoip/pci.c
new file mode 100644
index 00000000000..7a442d1eca4
--- /dev/null
+++ b/arch/sh/boards/renesas/hs7751rvoip/pci.c
@@ -0,0 +1,150 @@
1/*
2 * linux/arch/sh/kernel/pci-hs7751rvoip.c
3 *
4 * Author: Ian DaSilva (idasilva@mvista.com)
5 *
6 * Highly leveraged from pci-bigsur.c, written by Dustin McIntire.
7 *
8 * May be copied or modified under the terms of the GNU General Public
9 * License. See linux/COPYING for more information.
10 *
11 * PCI initialization for the Renesas SH7751R HS7751RVoIP board
12 */
13
14#include <linux/config.h>
15#include <linux/kernel.h>
16#include <linux/types.h>
17#include <linux/init.h>
18#include <linux/delay.h>
19#include <linux/pci.h>
20#include <linux/module.h>
21
22#include <asm/io.h>
23#include "../../../drivers/pci/pci-sh7751.h"
24#include <asm/hs7751rvoip/hs7751rvoip.h>
25
26#define PCIMCR_MRSET_OFF 0xBFFFFFFF
27#define PCIMCR_RFSH_OFF 0xFFFFFFFB
28
29/*
30 * Only long word accesses of the PCIC's internal local registers and the
31 * configuration registers from the CPU is supported.
32 */
33#define PCIC_WRITE(x,v) writel((v), PCI_REG(x))
34#define PCIC_READ(x) readl(PCI_REG(x))
35
36/*
37 * Description: This function sets up and initializes the pcic, sets
38 * up the BARS, maps the DRAM into the address space etc, etc.
39 */
40int __init pcibios_init_platform(void)
41{
42 unsigned long bcr1, wcr1, wcr2, wcr3, mcr;
43 unsigned short bcr2, bcr3;
44
45 /*
46 * Initialize the slave bus controller on the pcic. The values used
47 * here should not be hardcoded, but they should be taken from the bsc
48 * on the processor, to make this function as generic as possible.
49 * (i.e. Another sbc may usr different SDRAM timing settings -- in order
50 * for the pcic to work, its settings need to be exactly the same.)
51 */
52 bcr1 = (*(volatile unsigned long *)(SH7751_BCR1));
53 bcr2 = (*(volatile unsigned short *)(SH7751_BCR2));
54 bcr3 = (*(volatile unsigned short *)(SH7751_BCR3));
55 wcr1 = (*(volatile unsigned long *)(SH7751_WCR1));
56 wcr2 = (*(volatile unsigned long *)(SH7751_WCR2));
57 wcr3 = (*(volatile unsigned long *)(SH7751_WCR3));
58 mcr = (*(volatile unsigned long *)(SH7751_MCR));
59
60 bcr1 = bcr1 | 0x00080000; /* Enable Bit 19, BREQEN */
61 (*(volatile unsigned long *)(SH7751_BCR1)) = bcr1;
62
63 bcr1 = bcr1 | 0x40080000; /* Enable Bit 19 BREQEN, set PCIC to slave */
64 PCIC_WRITE(SH7751_PCIBCR1, bcr1); /* PCIC BCR1 */
65 PCIC_WRITE(SH7751_PCIBCR2, bcr2); /* PCIC BCR2 */
66 PCIC_WRITE(SH7751_PCIBCR3, bcr3); /* PCIC BCR3 */
67 PCIC_WRITE(SH7751_PCIWCR1, wcr1); /* PCIC WCR1 */
68 PCIC_WRITE(SH7751_PCIWCR2, wcr2); /* PCIC WCR2 */
69 PCIC_WRITE(SH7751_PCIWCR3, wcr3); /* PCIC WCR3 */
70 mcr = (mcr & PCIMCR_MRSET_OFF) & PCIMCR_RFSH_OFF;
71 PCIC_WRITE(SH7751_PCIMCR, mcr); /* PCIC MCR */
72
73 /* Enable all interrupts, so we know what to fix */
74 PCIC_WRITE(SH7751_PCIINTM, 0x0000c3ff);
75 PCIC_WRITE(SH7751_PCIAINTM, 0x0000380f);
76
77 /* Set up standard PCI config registers */
78 PCIC_WRITE(SH7751_PCICONF1, 0xFB900047); /* Bus Master, Mem & I/O access */
79 PCIC_WRITE(SH7751_PCICONF2, 0x00000000); /* PCI Class code & Revision ID */
80 PCIC_WRITE(SH7751_PCICONF4, 0xab000001); /* PCI I/O address (local regs) */
81 PCIC_WRITE(SH7751_PCICONF5, 0x0c000000); /* PCI MEM address (local RAM) */
82 PCIC_WRITE(SH7751_PCICONF6, 0xd0000000); /* PCI MEM address (unused) */
83 PCIC_WRITE(SH7751_PCICONF11, 0x35051054); /* PCI Subsystem ID & Vendor ID */
84 PCIC_WRITE(SH7751_PCILSR0, 0x03f00000); /* MEM (full 64M exposed) */
85 PCIC_WRITE(SH7751_PCILSR1, 0x00000000); /* MEM (unused) */
86 PCIC_WRITE(SH7751_PCILAR0, 0x0c000000); /* MEM (direct map from PCI) */
87 PCIC_WRITE(SH7751_PCILAR1, 0x00000000); /* MEM (unused) */
88
89 /* Now turn it on... */
90 PCIC_WRITE(SH7751_PCICR, 0xa5000001);
91
92 /*
93 * Set PCIMBR and PCIIOBR here, assuming a single window
94 * (16M MEM, 256K IO) is enough. If a larger space is
95 * needed, the readx/writex and inx/outx functions will
96 * have to do more (e.g. setting registers for each call).
97 */
98
99 /*
100 * Set the MBR so PCI address is one-to-one with window,
101 * meaning all calls go straight through... use ifdef to
102 * catch erroneous assumption.
103 */
104 BUG_ON(PCIBIOS_MIN_MEM != SH7751_PCI_MEMORY_BASE);
105
106 PCIC_WRITE(SH7751_PCIMBR, PCIBIOS_MIN_MEM);
107
108 /* Set IOBR for window containing area specified in pci.h */
109 PCIC_WRITE(SH7751_PCIIOBR, (PCIBIOS_MIN_IO & SH7751_PCIIOBR_MASK));
110
111 /* All done, may as well say so... */
112 printk("SH7751R PCI: Finished initialization of the PCI controller\n");
113
114 return 1;
115}
116
117int __init pcibios_map_platform_irq(u8 slot, u8 pin)
118{
119 switch (slot) {
120 case 0: return IRQ_PCISLOT; /* PCI Extend slot */
121 case 1: return IRQ_PCMCIA; /* PCI Cardbus Bridge */
122 case 2: return IRQ_PCIETH; /* Realtek Ethernet controller */
123 case 3: return IRQ_PCIHUB; /* Realtek Ethernet Hub controller */
124 default:
125 printk("PCI: Bad IRQ mapping request for slot %d\n", slot);
126 return -1;
127 }
128}
129
130static struct resource sh7751_io_resource = {
131 .name = "SH7751_IO",
132 .start = 0x4000,
133 .end = 0x4000 + SH7751_PCI_IO_SIZE - 1,
134 .flags = IORESOURCE_IO
135};
136
137static struct resource sh7751_mem_resource = {
138 .name = "SH7751_mem",
139 .start = SH7751_PCI_MEMORY_BASE,
140 .end = SH7751_PCI_MEMORY_BASE + SH7751_PCI_MEM_SIZE - 1,
141 .flags = IORESOURCE_MEM
142};
143
144extern struct pci_ops sh7751_pci_ops;
145
146struct pci_channel board_pci_channels[] = {
147 { &sh7751_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0xff },
148 { NULL, NULL, NULL, 0, 0 },
149};
150EXPORT_SYMBOL(board_pci_channels);
diff --git a/arch/sh/boards/renesas/hs7751rvoip/setup.c b/arch/sh/boards/renesas/hs7751rvoip/setup.c
new file mode 100644
index 00000000000..f1a78b6c714
--- /dev/null
+++ b/arch/sh/boards/renesas/hs7751rvoip/setup.c
@@ -0,0 +1,89 @@
1/*
2 * linux/arch/sh/kernel/setup_hs7751rvoip.c
3 *
4 * Copyright (C) 2000 Kazumoto Kojima
5 *
6 * Renesas Technology Sales HS7751RVoIP Support.
7 *
8 * Modified for HS7751RVoIP by
9 * Atom Create Engineering Co., Ltd. 2002.
10 * Lineo uSolutions, Inc. 2003.
11 */
12
13#include <linux/config.h>
14#include <linux/init.h>
15#include <linux/irq.h>
16
17#include <linux/hdreg.h>
18#include <linux/ide.h>
19#include <asm/io.h>
20#include <asm/hs7751rvoip/hs7751rvoip.h>
21
22#include <linux/mm.h>
23#include <linux/vmalloc.h>
24
25/* defined in mm/ioremap.c */
26extern void * p3_ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags);
27
28unsigned int debug_counter;
29
30const char *get_system_type(void)
31{
32 return "HS7751RVoIP";
33}
34
35/*
36 * Initialize the board
37 */
38void __init platform_setup(void)
39{
40 printk(KERN_INFO "Renesas Technology Sales HS7751RVoIP-2 support.\n");
41 ctrl_outb(0xf0, PA_OUTPORTR);
42 debug_counter = 0;
43}
44
45void *area5_io8_base;
46void *area6_io8_base;
47void *area5_io16_base;
48void *area6_io16_base;
49
50int __init cf_init(void)
51{
52 pgprot_t prot;
53 unsigned long paddrbase, psize;
54
55 /* open I/O area window */
56 paddrbase = virt_to_phys((void *)(PA_AREA5_IO+0x00000800));
57 psize = PAGE_SIZE;
58 prot = PAGE_KERNEL_PCC(1, _PAGE_PCC_COM16);
59 area5_io16_base = p3_ioremap(paddrbase, psize, prot.pgprot);
60 if (!area5_io16_base) {
61 printk("allocate_cf_area : can't open CF I/O window!\n");
62 return -ENOMEM;
63 }
64
65 /* XXX : do we need attribute and common-memory area also? */
66
67 paddrbase = virt_to_phys((void *)PA_AREA6_IO);
68 psize = PAGE_SIZE;
69#if defined(CONFIG_HS7751RVOIP_CODEC)
70 prot = PAGE_KERNEL_PCC(0, _PAGE_PCC_COM8);
71#else
72 prot = PAGE_KERNEL_PCC(0, _PAGE_PCC_IO8);
73#endif
74 area6_io8_base = p3_ioremap(paddrbase, psize, prot.pgprot);
75 if (!area6_io8_base) {
76 printk("allocate_cf_area : can't open CODEC I/O 8bit window!\n");
77 return -ENOMEM;
78 }
79 prot = PAGE_KERNEL_PCC(0, _PAGE_PCC_IO16);
80 area6_io16_base = p3_ioremap(paddrbase, psize, prot.pgprot);
81 if (!area6_io16_base) {
82 printk("allocate_cf_area : can't open CODEC I/O 16bit window!\n");
83 return -ENOMEM;
84 }
85
86 return 0;
87}
88
89__initcall (cf_init);
diff --git a/arch/sh/boards/renesas/rts7751r2d/Makefile b/arch/sh/boards/renesas/rts7751r2d/Makefile
new file mode 100644
index 00000000000..daa53334bdc
--- /dev/null
+++ b/arch/sh/boards/renesas/rts7751r2d/Makefile
@@ -0,0 +1,10 @@
1#
2# Makefile for the RTS7751R2D specific parts of the kernel
3#
4# Note! Dependencies are done automagically by 'make dep', which also
5# removes any old dependencies. DON'T put your own dependencies here
6# unless it's something special (ie not a .c file).
7#
8
9obj-y := mach.o setup.o io.o irq.o led.o
10
diff --git a/arch/sh/boards/renesas/rts7751r2d/io.c b/arch/sh/boards/renesas/rts7751r2d/io.c
new file mode 100644
index 00000000000..c46f9154cfd
--- /dev/null
+++ b/arch/sh/boards/renesas/rts7751r2d/io.c
@@ -0,0 +1,319 @@
1/*
2 * linux/arch/sh/kernel/io_rts7751r2d.c
3 *
4 * Copyright (C) 2001 Ian da Silva, Jeremy Siegel
5 * Based largely on io_se.c.
6 *
7 * I/O routine for Renesas Technology sales RTS7751R2D.
8 *
9 * Initial version only to support LAN access; some
10 * placeholder code from io_rts7751r2d.c left in with the
11 * expectation of later SuperIO and PCMCIA access.
12 */
13
14#include <linux/kernel.h>
15#include <linux/types.h>
16#include <asm/io.h>
17#include <asm/rts7751r2d/rts7751r2d.h>
18#include <asm/addrspace.h>
19
20#include <linux/module.h>
21#include <linux/pci.h>
22#include "../../../drivers/pci/pci-sh7751.h"
23
24/*
25 * The 7751R RTS7751R2D uses the built-in PCI controller (PCIC)
26 * of the 7751R processor, and has a SuperIO accessible via the PCI.
27 * The board also includes a PCMCIA controller on its memory bus,
28 * like the other Solution Engine boards.
29 */
30
31#define PCIIOBR (volatile long *)PCI_REG(SH7751_PCIIOBR)
32#define PCIMBR (volatile long *)PCI_REG(SH7751_PCIMBR)
33#define PCI_IO_AREA SH7751_PCI_IO_BASE
34#define PCI_MEM_AREA SH7751_PCI_CONFIG_BASE
35
36#define PCI_IOMAP(adr) (PCI_IO_AREA + (adr & ~SH7751_PCIIOBR_MASK))
37
38#define maybebadio(name,port) \
39 printk("bad PC-like io %s for port 0x%lx at 0x%08x\n", \
40 #name, (port), (__u32) __builtin_return_address(0))
41
42static inline void delay(void)
43{
44 ctrl_inw(0xa0000000);
45}
46
47static inline unsigned long port2adr(unsigned int port)
48{
49 if ((0x1f0 <= port && port < 0x1f8) || port == 0x3f6)
50 if (port == 0x3f6)
51 return (PA_AREA5_IO + 0x80c);
52 else
53 return (PA_AREA5_IO + 0x1000 + ((port-0x1f0) << 1));
54 else
55 maybebadio(port2adr, (unsigned long)port);
56
57 return port;
58}
59
60static inline unsigned long port88796l(unsigned int port, int flag)
61{
62 unsigned long addr;
63
64 if (flag)
65 addr = PA_AX88796L + ((port - AX88796L_IO_BASE) << 1);
66 else
67 addr = PA_AX88796L + ((port - AX88796L_IO_BASE) << 1) + 0x1000;
68
69 return addr;
70}
71
72/* The 7751R RTS7751R2D seems to have everything hooked */
73/* up pretty normally (nothing on high-bytes only...) so this */
74/* shouldn't be needed */
75static inline int shifted_port(unsigned long port)
76{
77 /* For IDE registers, value is not shifted */
78 if ((0x1f0 <= port && port < 0x1f8) || port == 0x3f6)
79 return 0;
80 else
81 return 1;
82}
83
84/* In case someone configures the kernel w/o PCI support: in that */
85/* scenario, don't ever bother to check for PCI-window addresses */
86
87/* NOTE: WINDOW CHECK MAY BE A BIT OFF, HIGH PCIBIOS_MIN_IO WRAPS? */
88#if defined(CONFIG_PCI)
89#define CHECK_SH7751_PCIIO(port) \
90 ((port >= PCIBIOS_MIN_IO) && (port < (PCIBIOS_MIN_IO + SH7751_PCI_IO_SIZE)))
91#else
92#define CHECK_SH7751_PCIIO(port) (0)
93#endif
94
95#if defined(CONFIG_NE2000) || defined(CONFIG_NE2000_MODULE)
96#define CHECK_AX88796L_PORT(port) \
97 ((port >= AX88796L_IO_BASE) && (port < (AX88796L_IO_BASE+0x20)))
98#else
99#define CHECK_AX88796L_PORT(port) (0)
100#endif
101
102/*
103 * General outline: remap really low stuff [eventually] to SuperIO,
104 * stuff in PCI IO space (at or above window at pci.h:PCIBIOS_MIN_IO)
105 * is mapped through the PCI IO window. Stuff with high bits (PXSEG)
106 * should be way beyond the window, and is used w/o translation for
107 * compatibility.
108 */
109unsigned char rts7751r2d_inb(unsigned long port)
110{
111 if (CHECK_AX88796L_PORT(port))
112 return (*(volatile unsigned short *)port88796l(port, 0)) & 0xff;
113 else if (PXSEG(port))
114 return *(volatile unsigned char *)port;
115 else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
116 return *(volatile unsigned char *)PCI_IOMAP(port);
117 else
118 return (*(volatile unsigned short *)port2adr(port) & 0xff);
119}
120
121unsigned char rts7751r2d_inb_p(unsigned long port)
122{
123 unsigned char v;
124
125 if (CHECK_AX88796L_PORT(port))
126 v = (*(volatile unsigned short *)port88796l(port, 0)) & 0xff;
127 else if (PXSEG(port))
128 v = *(volatile unsigned char *)port;
129 else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
130 v = *(volatile unsigned char *)PCI_IOMAP(port);
131 else
132 v = (*(volatile unsigned short *)port2adr(port) & 0xff);
133 delay();
134
135 return v;
136}
137
138unsigned short rts7751r2d_inw(unsigned long port)
139{
140 if (CHECK_AX88796L_PORT(port))
141 maybebadio(inw, port);
142 else if (PXSEG(port))
143 return *(volatile unsigned short *)port;
144 else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
145 return *(volatile unsigned short *)PCI_IOMAP(port);
146 else
147 maybebadio(inw, port);
148
149 return 0;
150}
151
152unsigned int rts7751r2d_inl(unsigned long port)
153{
154 if (CHECK_AX88796L_PORT(port))
155 maybebadio(inl, port);
156 else if (PXSEG(port))
157 return *(volatile unsigned long *)port;
158 else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
159 return *(volatile unsigned long *)PCI_IOMAP(port);
160 else
161 maybebadio(inl, port);
162
163 return 0;
164}
165
166void rts7751r2d_outb(unsigned char value, unsigned long port)
167{
168 if (CHECK_AX88796L_PORT(port))
169 *((volatile unsigned short *)port88796l(port, 0)) = value;
170 else if (PXSEG(port))
171 *(volatile unsigned char *)port = value;
172 else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
173 *(volatile unsigned char *)PCI_IOMAP(port) = value;
174 else
175 *(volatile unsigned short *)port2adr(port) = value;
176}
177
178void rts7751r2d_outb_p(unsigned char value, unsigned long port)
179{
180 if (CHECK_AX88796L_PORT(port))
181 *((volatile unsigned short *)port88796l(port, 0)) = value;
182 else if (PXSEG(port))
183 *(volatile unsigned char *)port = value;
184 else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
185 *(volatile unsigned char *)PCI_IOMAP(port) = value;
186 else
187 *(volatile unsigned short *)port2adr(port) = value;
188 delay();
189}
190
191void rts7751r2d_outw(unsigned short value, unsigned long port)
192{
193 if (CHECK_AX88796L_PORT(port))
194 maybebadio(outw, port);
195 else if (PXSEG(port))
196 *(volatile unsigned short *)port = value;
197 else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
198 *(volatile unsigned short *)PCI_IOMAP(port) = value;
199 else
200 maybebadio(outw, port);
201}
202
203void rts7751r2d_outl(unsigned int value, unsigned long port)
204{
205 if (CHECK_AX88796L_PORT(port))
206 maybebadio(outl, port);
207 else if (PXSEG(port))
208 *(volatile unsigned long *)port = value;
209 else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
210 *(volatile unsigned long *)PCI_IOMAP(port) = value;
211 else
212 maybebadio(outl, port);
213}
214
215void rts7751r2d_insb(unsigned long port, void *addr, unsigned long count)
216{
217 volatile __u8 *bp;
218 volatile __u16 *p;
219
220 if (CHECK_AX88796L_PORT(port)) {
221 p = (volatile unsigned short *)port88796l(port, 0);
222 while (count--) *((unsigned char *) addr)++ = *p & 0xff;
223 } else if (PXSEG(port))
224 while (count--) *((unsigned char *) addr)++ = *(volatile unsigned char *)port;
225 else if (CHECK_SH7751_PCIIO(port) || shifted_port(port)) {
226 bp = (__u8 *)PCI_IOMAP(port);
227 while (count--) *((volatile unsigned char *) addr)++ = *bp;
228 } else {
229 p = (volatile unsigned short *)port2adr(port);
230 while (count--) *((unsigned char *) addr)++ = *p & 0xff;
231 }
232}
233
234void rts7751r2d_insw(unsigned long port, void *addr, unsigned long count)
235{
236 volatile __u16 *p;
237
238 if (CHECK_AX88796L_PORT(port))
239 p = (volatile unsigned short *)port88796l(port, 1);
240 else if (PXSEG(port))
241 p = (volatile unsigned short *)port;
242 else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
243 p = (volatile unsigned short *)PCI_IOMAP(port);
244 else
245 p = (volatile unsigned short *)port2adr(port);
246 while (count--) *((__u16 *) addr)++ = *p;
247}
248
249void rts7751r2d_insl(unsigned long port, void *addr, unsigned long count)
250{
251 if (CHECK_AX88796L_PORT(port))
252 maybebadio(insl, port);
253 else if (CHECK_SH7751_PCIIO(port) || shifted_port(port)) {
254 volatile __u32 *p = (__u32 *)PCI_IOMAP(port);
255
256 while (count--) *((__u32 *) addr)++ = *p;
257 } else
258 maybebadio(insl, port);
259}
260
261void rts7751r2d_outsb(unsigned long port, const void *addr, unsigned long count)
262{
263 volatile __u8 *bp;
264 volatile __u16 *p;
265
266 if (CHECK_AX88796L_PORT(port)) {
267 p = (volatile unsigned short *)port88796l(port, 0);
268 while (count--) *p = *((unsigned char *) addr)++;
269 } else if (PXSEG(port))
270 while (count--) *(volatile unsigned char *)port = *((unsigned char *) addr)++;
271 else if (CHECK_SH7751_PCIIO(port) || shifted_port(port)) {
272 bp = (__u8 *)PCI_IOMAP(port);
273 while (count--) *bp = *((volatile unsigned char *) addr)++;
274 } else {
275 p = (volatile unsigned short *)port2adr(port);
276 while (count--) *p = *((unsigned char *) addr)++;
277 }
278}
279
280void rts7751r2d_outsw(unsigned long port, const void *addr, unsigned long count)
281{
282 volatile __u16 *p;
283
284 if (CHECK_AX88796L_PORT(port))
285 p = (volatile unsigned short *)port88796l(port, 1);
286 else if (PXSEG(port))
287 p = (volatile unsigned short *)port;
288 else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
289 p = (volatile unsigned short *)PCI_IOMAP(port);
290 else
291 p = (volatile unsigned short *)port2adr(port);
292 while (count--) *p = *((__u16 *) addr)++;
293}
294
295void rts7751r2d_outsl(unsigned long port, const void *addr, unsigned long count)
296{
297 if (CHECK_AX88796L_PORT(port))
298 maybebadio(outsl, port);
299 else if (CHECK_SH7751_PCIIO(port) || shifted_port(port)) {
300 volatile __u32 *p = (__u32 *)PCI_IOMAP(port);
301
302 while (count--) *p = *((__u32 *) addr)++;
303 } else
304 maybebadio(outsl, port);
305}
306
307void *rts7751r2d_ioremap(unsigned long offset, unsigned long size)
308{
309 if (offset >= 0xfd000000)
310 return (void *)offset;
311 else
312 return (void *)P2SEGADDR(offset);
313}
314EXPORT_SYMBOL(rts7751r2d_ioremap);
315
316unsigned long rts7751r2d_isa_port2addr(unsigned long offset)
317{
318 return port2adr(offset);
319}
diff --git a/arch/sh/boards/renesas/rts7751r2d/irq.c b/arch/sh/boards/renesas/rts7751r2d/irq.c
new file mode 100644
index 00000000000..95717f4f1e2
--- /dev/null
+++ b/arch/sh/boards/renesas/rts7751r2d/irq.c
@@ -0,0 +1,135 @@
1/*
2 * linux/arch/sh/boards/renesas/rts7751r2d/irq.c
3 *
4 * Copyright (C) 2000 Kazumoto Kojima
5 *
6 * Renesas Technology Sales RTS7751R2D Support.
7 *
8 * Modified for RTS7751R2D by
9 * Atom Create Engineering Co., Ltd. 2002.
10 */
11
12#include <linux/config.h>
13#include <linux/init.h>
14#include <linux/irq.h>
15#include <asm/io.h>
16#include <asm/irq.h>
17#include <asm/rts7751r2d/rts7751r2d.h>
18
19#if defined(CONFIG_RTS7751R2D_REV11)
20static int mask_pos[] = {11, 9, 8, 12, 10, 6, 5, 4, 7, 14, 13, 0, 0, 0, 0};
21#else
22static int mask_pos[] = {6, 11, 9, 8, 12, 10, 5, 4, 7, 14, 13, 0, 0, 0, 0};
23#endif
24
25extern int voyagergx_irq_demux(int irq);
26extern void setup_voyagergx_irq(void);
27
28static void enable_rts7751r2d_irq(unsigned int irq);
29static void disable_rts7751r2d_irq(unsigned int irq);
30
31/* shutdown is same as "disable" */
32#define shutdown_rts7751r2d_irq disable_rts7751r2d_irq
33
34static void ack_rts7751r2d_irq(unsigned int irq);
35static void end_rts7751r2d_irq(unsigned int irq);
36
37static unsigned int startup_rts7751r2d_irq(unsigned int irq)
38{
39 enable_rts7751r2d_irq(irq);
40 return 0; /* never anything pending */
41}
42
43static void disable_rts7751r2d_irq(unsigned int irq)
44{
45 unsigned long flags;
46 unsigned short val;
47 unsigned short mask = 0xffff ^ (0x0001 << mask_pos[irq]);
48
49 /* Set the priority in IPR to 0 */
50 local_irq_save(flags);
51 val = ctrl_inw(IRLCNTR1);
52 val &= mask;
53 ctrl_outw(val, IRLCNTR1);
54 local_irq_restore(flags);
55}
56
57static void enable_rts7751r2d_irq(unsigned int irq)
58{
59 unsigned long flags;
60 unsigned short val;
61 unsigned short value = (0x0001 << mask_pos[irq]);
62
63 /* Set priority in IPR back to original value */
64 local_irq_save(flags);
65 val = ctrl_inw(IRLCNTR1);
66 val |= value;
67 ctrl_outw(val, IRLCNTR1);
68 local_irq_restore(flags);
69}
70
71int rts7751r2d_irq_demux(int irq)
72{
73 int demux_irq;
74
75 demux_irq = voyagergx_irq_demux(irq);
76 return demux_irq;
77}
78
79static void ack_rts7751r2d_irq(unsigned int irq)
80{
81 disable_rts7751r2d_irq(irq);
82}
83
84static void end_rts7751r2d_irq(unsigned int irq)
85{
86 if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
87 enable_rts7751r2d_irq(irq);
88}
89
90static struct hw_interrupt_type rts7751r2d_irq_type = {
91 "RTS7751R2D IRQ",
92 startup_rts7751r2d_irq,
93 shutdown_rts7751r2d_irq,
94 enable_rts7751r2d_irq,
95 disable_rts7751r2d_irq,
96 ack_rts7751r2d_irq,
97 end_rts7751r2d_irq,
98};
99
100static void make_rts7751r2d_irq(unsigned int irq)
101{
102 disable_irq_nosync(irq);
103 irq_desc[irq].handler = &rts7751r2d_irq_type;
104 disable_rts7751r2d_irq(irq);
105}
106
107/*
108 * Initialize IRQ setting
109 */
110void __init init_rts7751r2d_IRQ(void)
111{
112 int i;
113
114 /* IRL0=KEY Input
115 * IRL1=Ethernet
116 * IRL2=CF Card
117 * IRL3=CF Card Insert
118 * IRL4=PCMCIA
119 * IRL5=VOYAGER
120 * IRL6=RTC Alarm
121 * IRL7=RTC Timer
122 * IRL8=SD Card
123 * IRL9=PCI Slot #1
124 * IRL10=PCI Slot #2
125 * IRL11=Extention #0
126 * IRL12=Extention #1
127 * IRL13=Extention #2
128 * IRL14=Extention #3
129 */
130
131 for (i=0; i<15; i++)
132 make_rts7751r2d_irq(i);
133
134 setup_voyagergx_irq();
135}
diff --git a/arch/sh/boards/renesas/rts7751r2d/led.c b/arch/sh/boards/renesas/rts7751r2d/led.c
new file mode 100644
index 00000000000..9993259a894
--- /dev/null
+++ b/arch/sh/boards/renesas/rts7751r2d/led.c
@@ -0,0 +1,67 @@
1/*
2 * linux/arch/sh/kernel/led_rts7751r2d.c
3 *
4 * Copyright (C) Atom Create Engineering Co., Ltd.
5 *
6 * May be copied or modified under the terms of GNU General Public
7 * License. See linux/COPYING for more information.
8 *
9 * This file contains Renesas Technology Sales RTS7751R2D specific LED code.
10 */
11
12#include <linux/config.h>
13#include <asm/io.h>
14#include <asm/rts7751r2d/rts7751r2d.h>
15
16extern unsigned int debug_counter;
17
18#ifdef CONFIG_HEARTBEAT
19
20#include <linux/sched.h>
21
22/* Cycle the LED's in the clasic Knightriger/Sun pattern */
23void heartbeat_rts7751r2d(void)
24{
25 static unsigned int cnt = 0, period = 0;
26 volatile unsigned short *p = (volatile unsigned short *)PA_OUTPORT;
27 static unsigned bit = 0, up = 1;
28
29 cnt += 1;
30 if (cnt < period)
31 return;
32
33 cnt = 0;
34
35 /* Go through the points (roughly!):
36 * f(0)=10, f(1)=16, f(2)=20, f(5)=35, f(int)->110
37 */
38 period = 110 - ((300 << FSHIFT)/((avenrun[0]/5) + (3<<FSHIFT)));
39
40 *p = 1 << bit;
41 if (up)
42 if (bit == 7) {
43 bit--;
44 up = 0;
45 } else
46 bit++;
47 else if (bit == 0)
48 up = 1;
49 else
50 bit--;
51}
52#endif /* CONFIG_HEARTBEAT */
53
54void rts7751r2d_led(unsigned short value)
55{
56 ctrl_outw(value, PA_OUTPORT);
57}
58
59void debug_led_disp(void)
60{
61 unsigned short value;
62
63 value = (unsigned short)debug_counter++;
64 rts7751r2d_led(value);
65 if (value == 0xff)
66 debug_counter = 0;
67}
diff --git a/arch/sh/boards/renesas/rts7751r2d/mach.c b/arch/sh/boards/renesas/rts7751r2d/mach.c
new file mode 100644
index 00000000000..1efc18e786d
--- /dev/null
+++ b/arch/sh/boards/renesas/rts7751r2d/mach.c
@@ -0,0 +1,70 @@
1/*
2 * linux/arch/sh/kernel/mach_rts7751r2d.c
3 *
4 * Minor tweak of mach_se.c file to reference rts7751r2d-specific items.
5 *
6 * May be copied or modified under the terms of the GNU General Public
7 * License. See linux/COPYING for more information.
8 *
9 * Machine vector for the Renesas Technology sales RTS7751R2D
10 */
11
12#include <linux/config.h>
13#include <linux/init.h>
14#include <linux/types.h>
15
16#include <asm/machvec.h>
17#include <asm/rtc.h>
18#include <asm/irq.h>
19#include <asm/rts7751r2d/io.h>
20
21extern void heartbeat_rts7751r2d(void);
22extern void init_rts7751r2d_IRQ(void);
23extern void *rts7751r2d_ioremap(unsigned long, unsigned long);
24extern int rts7751r2d_irq_demux(int irq);
25
26extern void *voyagergx_consistent_alloc(struct device *, size_t, dma_addr_t *, int);
27extern int voyagergx_consistent_free(struct device *, size_t, void *, dma_addr_t);
28
29/*
30 * The Machine Vector
31 */
32
33struct sh_machine_vector mv_rts7751r2d __initmv = {
34 .mv_nr_irqs = 72,
35
36 .mv_inb = rts7751r2d_inb,
37 .mv_inw = rts7751r2d_inw,
38 .mv_inl = rts7751r2d_inl,
39 .mv_outb = rts7751r2d_outb,
40 .mv_outw = rts7751r2d_outw,
41 .mv_outl = rts7751r2d_outl,
42
43 .mv_inb_p = rts7751r2d_inb_p,
44 .mv_inw_p = rts7751r2d_inw,
45 .mv_inl_p = rts7751r2d_inl,
46 .mv_outb_p = rts7751r2d_outb_p,
47 .mv_outw_p = rts7751r2d_outw,
48 .mv_outl_p = rts7751r2d_outl,
49
50 .mv_insb = rts7751r2d_insb,
51 .mv_insw = rts7751r2d_insw,
52 .mv_insl = rts7751r2d_insl,
53 .mv_outsb = rts7751r2d_outsb,
54 .mv_outsw = rts7751r2d_outsw,
55 .mv_outsl = rts7751r2d_outsl,
56
57 .mv_ioremap = rts7751r2d_ioremap,
58 .mv_isa_port2addr = rts7751r2d_isa_port2addr,
59 .mv_init_irq = init_rts7751r2d_IRQ,
60#ifdef CONFIG_HEARTBEAT
61 .mv_heartbeat = heartbeat_rts7751r2d,
62#endif
63 .mv_irq_demux = rts7751r2d_irq_demux,
64
65#ifdef CONFIG_USB_OHCI_HCD
66 .mv_consistent_alloc = voyagergx_consistent_alloc,
67 .mv_consistent_free = voyagergx_consistent_free,
68#endif
69};
70ALIAS_MV(rts7751r2d)
diff --git a/arch/sh/boards/renesas/rts7751r2d/setup.c b/arch/sh/boards/renesas/rts7751r2d/setup.c
new file mode 100644
index 00000000000..2587fd1a024
--- /dev/null
+++ b/arch/sh/boards/renesas/rts7751r2d/setup.c
@@ -0,0 +1,31 @@
1/*
2 * linux/arch/sh/kernel/setup_rts7751r2d.c
3 *
4 * Copyright (C) 2000 Kazumoto Kojima
5 *
6 * Renesas Technology Sales RTS7751R2D Support.
7 *
8 * Modified for RTS7751R2D by
9 * Atom Create Engineering Co., Ltd. 2002.
10 */
11
12#include <linux/init.h>
13#include <asm/io.h>
14#include <asm/rts7751r2d/rts7751r2d.h>
15
16unsigned int debug_counter;
17
18const char *get_system_type(void)
19{
20 return "RTS7751R2D";
21}
22
23/*
24 * Initialize the board
25 */
26void __init platform_setup(void)
27{
28 printk(KERN_INFO "Renesas Technology Sales RTS7751R2D support.\n");
29 ctrl_outw(0x0000, PA_OUTPORT);
30 debug_counter = 0;
31}
diff --git a/arch/sh/boards/renesas/systemh/Makefile b/arch/sh/boards/renesas/systemh/Makefile
new file mode 100644
index 00000000000..2cc6a23d9d3
--- /dev/null
+++ b/arch/sh/boards/renesas/systemh/Makefile
@@ -0,0 +1,13 @@
1#
2# Makefile for the SystemH specific parts of the kernel
3#
4
5obj-y := setup.o irq.o io.o
6
7# XXX: This wants to be consolidated in arch/sh/drivers/pci, and more
8# importantly, with the generic sh7751_pcic_init() code. For now, we'll
9# just abuse the hell out of kbuild, because we can..
10
11obj-$(CONFIG_PCI) += pci.o
12pci-y := ../../se/7751/pci.o
13
diff --git a/arch/sh/boards/renesas/systemh/io.c b/arch/sh/boards/renesas/systemh/io.c
new file mode 100644
index 00000000000..cf979011aa9
--- /dev/null
+++ b/arch/sh/boards/renesas/systemh/io.c
@@ -0,0 +1,283 @@
1/*
2 * linux/arch/sh/boards/systemh/io.c
3 *
4 * Copyright (C) 2001 Ian da Silva, Jeremy Siegel
5 * Based largely on io_se.c.
6 *
7 * I/O routine for Hitachi 7751 Systemh.
8 *
9 */
10
11#include <linux/kernel.h>
12#include <linux/types.h>
13#include <asm/systemh/7751systemh.h>
14#include <asm/addrspace.h>
15#include <asm/io.h>
16
17#include <linux/pci.h>
18#include "../../drivers/pci/pci-sh7751.h"
19
20/*
21 * The 7751 SystemH Engine uses the built-in PCI controller (PCIC)
22 * of the 7751 processor, and has a SuperIO accessible on its memory
23 * bus.
24 */
25
26#define PCIIOBR (volatile long *)PCI_REG(SH7751_PCIIOBR)
27#define PCIMBR (volatile long *)PCI_REG(SH7751_PCIMBR)
28#define PCI_IO_AREA SH7751_PCI_IO_BASE
29#define PCI_MEM_AREA SH7751_PCI_CONFIG_BASE
30
31#define PCI_IOMAP(adr) (PCI_IO_AREA + (adr & ~SH7751_PCIIOBR_MASK))
32#define ETHER_IOMAP(adr) (0xB3000000 + (adr)) /*map to 16bits access area
33 of smc lan chip*/
34
35#define maybebadio(name,port) \
36 printk("bad PC-like io %s for port 0x%lx at 0x%08x\n", \
37 #name, (port), (__u32) __builtin_return_address(0))
38
39static inline void delay(void)
40{
41 ctrl_inw(0xa0000000);
42}
43
44static inline volatile __u16 *
45port2adr(unsigned int port)
46{
47 if (port >= 0x2000)
48 return (volatile __u16 *) (PA_MRSHPC + (port - 0x2000));
49#if 0
50 else
51 return (volatile __u16 *) (PA_SUPERIO + (port << 1));
52#endif
53 maybebadio(name,(unsigned long)port);
54 return (volatile __u16*)port;
55}
56
57/* In case someone configures the kernel w/o PCI support: in that */
58/* scenario, don't ever bother to check for PCI-window addresses */
59
60/* NOTE: WINDOW CHECK MAY BE A BIT OFF, HIGH PCIBIOS_MIN_IO WRAPS? */
61#if defined(CONFIG_PCI)
62#define CHECK_SH7751_PCIIO(port) \
63 ((port >= PCIBIOS_MIN_IO) && (port < (PCIBIOS_MIN_IO + SH7751_PCI_IO_SIZE)))
64#else
65#define CHECK_SH7751_PCIIO(port) (0)
66#endif
67
68/*
69 * General outline: remap really low stuff [eventually] to SuperIO,
70 * stuff in PCI IO space (at or above window at pci.h:PCIBIOS_MIN_IO)
71 * is mapped through the PCI IO window. Stuff with high bits (PXSEG)
72 * should be way beyond the window, and is used w/o translation for
73 * compatibility.
74 */
75unsigned char sh7751systemh_inb(unsigned long port)
76{
77 if (PXSEG(port))
78 return *(volatile unsigned char *)port;
79 else if (CHECK_SH7751_PCIIO(port))
80 return *(volatile unsigned char *)PCI_IOMAP(port);
81 else if (port <= 0x3F1)
82 return *(volatile unsigned char *)ETHER_IOMAP(port);
83 else
84 return (*port2adr(port))&0xff;
85}
86
87unsigned char sh7751systemh_inb_p(unsigned long port)
88{
89 unsigned char v;
90
91 if (PXSEG(port))
92 v = *(volatile unsigned char *)port;
93 else if (CHECK_SH7751_PCIIO(port))
94 v = *(volatile unsigned char *)PCI_IOMAP(port);
95 else if (port <= 0x3F1)
96 v = *(volatile unsigned char *)ETHER_IOMAP(port);
97 else
98 v = (*port2adr(port))&0xff;
99 delay();
100 return v;
101}
102
103unsigned short sh7751systemh_inw(unsigned long port)
104{
105 if (PXSEG(port))
106 return *(volatile unsigned short *)port;
107 else if (CHECK_SH7751_PCIIO(port))
108 return *(volatile unsigned short *)PCI_IOMAP(port);
109 else if (port >= 0x2000)
110 return *port2adr(port);
111 else if (port <= 0x3F1)
112 return *(volatile unsigned int *)ETHER_IOMAP(port);
113 else
114 maybebadio(inw, port);
115 return 0;
116}
117
118unsigned int sh7751systemh_inl(unsigned long port)
119{
120 if (PXSEG(port))
121 return *(volatile unsigned long *)port;
122 else if (CHECK_SH7751_PCIIO(port))
123 return *(volatile unsigned int *)PCI_IOMAP(port);
124 else if (port >= 0x2000)
125 return *port2adr(port);
126 else if (port <= 0x3F1)
127 return *(volatile unsigned int *)ETHER_IOMAP(port);
128 else
129 maybebadio(inl, port);
130 return 0;
131}
132
133void sh7751systemh_outb(unsigned char value, unsigned long port)
134{
135
136 if (PXSEG(port))
137 *(volatile unsigned char *)port = value;
138 else if (CHECK_SH7751_PCIIO(port))
139 *((unsigned char*)PCI_IOMAP(port)) = value;
140 else if (port <= 0x3F1)
141 *(volatile unsigned char *)ETHER_IOMAP(port) = value;
142 else
143 *(port2adr(port)) = value;
144}
145
146void sh7751systemh_outb_p(unsigned char value, unsigned long port)
147{
148 if (PXSEG(port))
149 *(volatile unsigned char *)port = value;
150 else if (CHECK_SH7751_PCIIO(port))
151 *((unsigned char*)PCI_IOMAP(port)) = value;
152 else if (port <= 0x3F1)
153 *(volatile unsigned char *)ETHER_IOMAP(port) = value;
154 else
155 *(port2adr(port)) = value;
156 delay();
157}
158
159void sh7751systemh_outw(unsigned short value, unsigned long port)
160{
161 if (PXSEG(port))
162 *(volatile unsigned short *)port = value;
163 else if (CHECK_SH7751_PCIIO(port))
164 *((unsigned short *)PCI_IOMAP(port)) = value;
165 else if (port >= 0x2000)
166 *port2adr(port) = value;
167 else if (port <= 0x3F1)
168 *(volatile unsigned short *)ETHER_IOMAP(port) = value;
169 else
170 maybebadio(outw, port);
171}
172
173void sh7751systemh_outl(unsigned int value, unsigned long port)
174{
175 if (PXSEG(port))
176 *(volatile unsigned long *)port = value;
177 else if (CHECK_SH7751_PCIIO(port))
178 *((unsigned long*)PCI_IOMAP(port)) = value;
179 else
180 maybebadio(outl, port);
181}
182
183void sh7751systemh_insb(unsigned long port, void *addr, unsigned long count)
184{
185 unsigned char *p = addr;
186 while (count--) *p++ = sh7751systemh_inb(port);
187}
188
189void sh7751systemh_insw(unsigned long port, void *addr, unsigned long count)
190{
191 unsigned short *p = addr;
192 while (count--) *p++ = sh7751systemh_inw(port);
193}
194
195void sh7751systemh_insl(unsigned long port, void *addr, unsigned long count)
196{
197 maybebadio(insl, port);
198}
199
200void sh7751systemh_outsb(unsigned long port, const void *addr, unsigned long count)
201{
202 unsigned char *p = (unsigned char*)addr;
203 while (count--) sh7751systemh_outb(*p++, port);
204}
205
206void sh7751systemh_outsw(unsigned long port, const void *addr, unsigned long count)
207{
208 unsigned short *p = (unsigned short*)addr;
209 while (count--) sh7751systemh_outw(*p++, port);
210}
211
212void sh7751systemh_outsl(unsigned long port, const void *addr, unsigned long count)
213{
214 maybebadio(outsw, port);
215}
216
217/* For read/write calls, just copy generic (pass-thru); PCIMBR is */
218/* already set up. For a larger memory space, these would need to */
219/* reset PCIMBR as needed on a per-call basis... */
220
221unsigned char sh7751systemh_readb(unsigned long addr)
222{
223 return *(volatile unsigned char*)addr;
224}
225
226unsigned short sh7751systemh_readw(unsigned long addr)
227{
228 return *(volatile unsigned short*)addr;
229}
230
231unsigned int sh7751systemh_readl(unsigned long addr)
232{
233 return *(volatile unsigned long*)addr;
234}
235
236void sh7751systemh_writeb(unsigned char b, unsigned long addr)
237{
238 *(volatile unsigned char*)addr = b;
239}
240
241void sh7751systemh_writew(unsigned short b, unsigned long addr)
242{
243 *(volatile unsigned short*)addr = b;
244}
245
246void sh7751systemh_writel(unsigned int b, unsigned long addr)
247{
248 *(volatile unsigned long*)addr = b;
249}
250
251
252
253/* Map ISA bus address to the real address. Only for PCMCIA. */
254
255/* ISA page descriptor. */
256static __u32 sh_isa_memmap[256];
257
258#if 0
259static int
260sh_isa_mmap(__u32 start, __u32 length, __u32 offset)
261{
262 int idx;
263
264 if (start >= 0x100000 || (start & 0xfff) || (length != 0x1000))
265 return -1;
266
267 idx = start >> 12;
268 sh_isa_memmap[idx] = 0xb8000000 + (offset &~ 0xfff);
269 printk("sh_isa_mmap: start %x len %x offset %x (idx %x paddr %x)\n",
270 start, length, offset, idx, sh_isa_memmap[idx]);
271 return 0;
272}
273#endif
274
275unsigned long
276sh7751systemh_isa_port2addr(unsigned long offset)
277{
278 int idx;
279
280 idx = (offset >> 12) & 0xff;
281 offset &= 0xfff;
282 return sh_isa_memmap[idx] + offset;
283}
diff --git a/arch/sh/boards/renesas/systemh/irq.c b/arch/sh/boards/renesas/systemh/irq.c
new file mode 100644
index 00000000000..5675a4134ee
--- /dev/null
+++ b/arch/sh/boards/renesas/systemh/irq.c
@@ -0,0 +1,111 @@
1/*
2 * linux/arch/sh/boards/systemh/irq.c
3 *
4 * Copyright (C) 2000 Kazumoto Kojima
5 *
6 * Hitachi SystemH Support.
7 *
8 * Modified for 7751 SystemH by
9 * Jonathan Short.
10 */
11
12#include <linux/config.h>
13#include <linux/init.h>
14#include <linux/irq.h>
15
16#include <linux/hdreg.h>
17#include <linux/ide.h>
18#include <asm/io.h>
19#include <asm/mach/7751systemh.h>
20#include <asm/smc37c93x.h>
21
22/* address of external interrupt mask register
23 * address must be set prior to use these (maybe in init_XXX_irq())
24 * XXX : is it better to use .config than specifying it in code? */
25static unsigned long *systemh_irq_mask_register = (unsigned long *)0xB3F10004;
26static unsigned long *systemh_irq_request_register = (unsigned long *)0xB3F10000;
27
28/* forward declaration */
29static unsigned int startup_systemh_irq(unsigned int irq);
30static void shutdown_systemh_irq(unsigned int irq);
31static void enable_systemh_irq(unsigned int irq);
32static void disable_systemh_irq(unsigned int irq);
33static void mask_and_ack_systemh(unsigned int);
34static void end_systemh_irq(unsigned int irq);
35
36/* hw_interrupt_type */
37static struct hw_interrupt_type systemh_irq_type = {
38 " SystemH Register",
39 startup_systemh_irq,
40 shutdown_systemh_irq,
41 enable_systemh_irq,
42 disable_systemh_irq,
43 mask_and_ack_systemh,
44 end_systemh_irq
45};
46
47static unsigned int startup_systemh_irq(unsigned int irq)
48{
49 enable_systemh_irq(irq);
50 return 0; /* never anything pending */
51}
52
53static void shutdown_systemh_irq(unsigned int irq)
54{
55 disable_systemh_irq(irq);
56}
57
58static void disable_systemh_irq(unsigned int irq)
59{
60 if (systemh_irq_mask_register) {
61 unsigned long flags;
62 unsigned long val, mask = 0x01 << 1;
63
64 /* Clear the "irq"th bit in the mask and set it in the request */
65 local_irq_save(flags);
66
67 val = ctrl_inl((unsigned long)systemh_irq_mask_register);
68 val &= ~mask;
69 ctrl_outl(val, (unsigned long)systemh_irq_mask_register);
70
71 val = ctrl_inl((unsigned long)systemh_irq_request_register);
72 val |= mask;
73 ctrl_outl(val, (unsigned long)systemh_irq_request_register);
74
75 local_irq_restore(flags);
76 }
77}
78
79static void enable_systemh_irq(unsigned int irq)
80{
81 if (systemh_irq_mask_register) {
82 unsigned long flags;
83 unsigned long val, mask = 0x01 << 1;
84
85 /* Set "irq"th bit in the mask register */
86 local_irq_save(flags);
87 val = ctrl_inl((unsigned long)systemh_irq_mask_register);
88 val |= mask;
89 ctrl_outl(val, (unsigned long)systemh_irq_mask_register);
90 local_irq_restore(flags);
91 }
92}
93
94static void mask_and_ack_systemh(unsigned int irq)
95{
96 disable_systemh_irq(irq);
97}
98
99static void end_systemh_irq(unsigned int irq)
100{
101 if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
102 enable_systemh_irq(irq);
103}
104
105void make_systemh_irq(unsigned int irq)
106{
107 disable_irq_nosync(irq);
108 irq_desc[irq].handler = &systemh_irq_type;
109 disable_systemh_irq(irq);
110}
111
diff --git a/arch/sh/boards/renesas/systemh/setup.c b/arch/sh/boards/renesas/systemh/setup.c
new file mode 100644
index 00000000000..826fa3d7669
--- /dev/null
+++ b/arch/sh/boards/renesas/systemh/setup.c
@@ -0,0 +1,80 @@
1/*
2 * linux/arch/sh/boards/systemh/setup.c
3 *
4 * Copyright (C) 2000 Kazumoto Kojima
5 * Copyright (C) 2003 Paul Mundt
6 *
7 * Hitachi SystemH Support.
8 *
9 * Modified for 7751 SystemH by Jonathan Short.
10 *
11 * Rewritten for 2.6 by Paul Mundt.
12 *
13 * This file is subject to the terms and conditions of the GNU General Public
14 * License. See the file "COPYING" in the main directory of this archive
15 * for more details.
16 */
17#include <linux/init.h>
18#include <asm/mach/7751systemh.h>
19#include <asm/mach/io.h>
20#include <asm/machvec.h>
21
22extern void make_systemh_irq(unsigned int irq);
23
24const char *get_system_type(void)
25{
26 return "7751 SystemH";
27}
28
29/*
30 * Initialize IRQ setting
31 */
32void __init init_7751systemh_IRQ(void)
33{
34/* make_ipr_irq(10, BCR_ILCRD, 1, 0x0f-10); LAN */
35/* make_ipr_irq(14, BCR_ILCRA, 2, 0x0f-4); */
36 make_systemh_irq(0xb); /* Ethernet interrupt */
37}
38
39struct sh_machine_vector mv_7751systemh __initmv = {
40 .mv_nr_irqs = 72,
41
42 .mv_inb = sh7751systemh_inb,
43 .mv_inw = sh7751systemh_inw,
44 .mv_inl = sh7751systemh_inl,
45 .mv_outb = sh7751systemh_outb,
46 .mv_outw = sh7751systemh_outw,
47 .mv_outl = sh7751systemh_outl,
48
49 .mv_inb_p = sh7751systemh_inb_p,
50 .mv_inw_p = sh7751systemh_inw,
51 .mv_inl_p = sh7751systemh_inl,
52 .mv_outb_p = sh7751systemh_outb_p,
53 .mv_outw_p = sh7751systemh_outw,
54 .mv_outl_p = sh7751systemh_outl,
55
56 .mv_insb = sh7751systemh_insb,
57 .mv_insw = sh7751systemh_insw,
58 .mv_insl = sh7751systemh_insl,
59 .mv_outsb = sh7751systemh_outsb,
60 .mv_outsw = sh7751systemh_outsw,
61 .mv_outsl = sh7751systemh_outsl,
62
63 .mv_readb = sh7751systemh_readb,
64 .mv_readw = sh7751systemh_readw,
65 .mv_readl = sh7751systemh_readl,
66 .mv_writeb = sh7751systemh_writeb,
67 .mv_writew = sh7751systemh_writew,
68 .mv_writel = sh7751systemh_writel,
69
70 .mv_isa_port2addr = sh7751systemh_isa_port2addr,
71
72 .mv_init_irq = init_7751systemh_IRQ,
73};
74ALIAS_MV(7751systemh)
75
76int __init platform_setup(void)
77{
78 return 0;
79}
80
diff --git a/arch/sh/boards/saturn/Makefile b/arch/sh/boards/saturn/Makefile
new file mode 100644
index 00000000000..75a3042e252
--- /dev/null
+++ b/arch/sh/boards/saturn/Makefile
@@ -0,0 +1,8 @@
1#
2# Makefile for the Sega Saturn specific parts of the kernel
3#
4
5obj-y := setup.o io.o irq.o
6
7obj-$(CONFIG_SMP) += smp.o
8
diff --git a/arch/sh/boards/saturn/io.c b/arch/sh/boards/saturn/io.c
new file mode 100644
index 00000000000..c6e4f7f2e68
--- /dev/null
+++ b/arch/sh/boards/saturn/io.c
@@ -0,0 +1,26 @@
1/*
2 * arch/sh/boards/saturn/io.c
3 *
4 * I/O routines for the Sega Saturn.
5 *
6 * Copyright (C) 2002 Paul Mundt
7 *
8 * Released under the terms of the GNU GPL v2.0.
9 */
10#include <asm/saturn/io.h>
11#include <asm/machvec.h>
12
13unsigned long saturn_isa_port2addr(unsigned long offset)
14{
15 return offset;
16}
17
18void *saturn_ioremap(unsigned long offset, unsigned long size)
19{
20 return (void *)offset;
21}
22
23void saturn_iounmap(void *addr)
24{
25}
26
diff --git a/arch/sh/boards/saturn/irq.c b/arch/sh/boards/saturn/irq.c
new file mode 100644
index 00000000000..15d1d3f0f78
--- /dev/null
+++ b/arch/sh/boards/saturn/irq.c
@@ -0,0 +1,118 @@
1/*
2 * arch/sh/boards/saturn/irq.c
3 *
4 * Copyright (C) 2002 Paul Mundt
5 *
6 * Released under the terms of the GNU GPL v2.0.
7 */
8#include <linux/kernel.h>
9#include <linux/init.h>
10#include <linux/interrupt.h>
11#include <asm/irq.h>
12#include <asm/io.h>
13
14/*
15 * Interrupts map out as follows:
16 *
17 * Vector Name Mask
18 *
19 * 64 VBLANKIN 0x0001
20 * 65 VBLANKOUT 0x0002
21 * 66 HBLANKIN 0x0004
22 * 67 TIMER0 0x0008
23 * 68 TIMER1 0x0010
24 * 69 DSPEND 0x0020
25 * 70 SOUNDREQUEST 0x0040
26 * 71 SYSTEMMANAGER 0x0080
27 * 72 PAD 0x0100
28 * 73 LEVEL2DMAEND 0x0200
29 * 74 LEVEL1DMAEND 0x0400
30 * 75 LEVEL0DMAEND 0x0800
31 * 76 DMAILLEGAL 0x1000
32 * 77 SRITEDRAWEND 0x2000
33 * 78 ABUS 0x8000
34 *
35 */
36#define SATURN_IRQ_MIN 64 /* VBLANKIN */
37#define SATURN_IRQ_MAX 78 /* ABUS */
38
39#define SATURN_IRQ_MASK 0xbfff
40
41static inline u32 saturn_irq_mask(unsigned int irq_nr)
42{
43 u32 mask;
44
45 mask = (1 << (irq_nr - SATURN_IRQ_MIN));
46 mask <<= (irq_nr == SATURN_IRQ_MAX);
47 mask &= SATURN_IRQ_MASK;
48
49 return mask;
50}
51
52static inline void mask_saturn_irq(unsigned int irq_nr)
53{
54 u32 mask;
55
56 mask = ctrl_inl(SATURN_IMR);
57 mask |= saturn_irq_mask(irq_nr);
58 ctrl_outl(mask, SATURN_IMR);
59}
60
61static inline void unmask_saturn_irq(unsigned int irq_nr)
62{
63 u32 mask;
64
65 mask = ctrl_inl(SATURN_IMR);
66 mask &= ~saturn_irq_mask(irq_nr);
67 ctrl_outl(mask, SATURN_IMR);
68}
69
70static void disable_saturn_irq(unsigned int irq_nr)
71{
72 mask_saturn_irq(irq_nr);
73}
74
75static void enable_saturn_irq(unsigned int irq_nr)
76{
77 unmask_saturn_irq(irq_nr);
78}
79
80static void mask_and_ack_saturn_irq(unsigned int irq_nr)
81{
82 mask_saturn_irq(irq_nr);
83}
84
85static void end_saturn_irq(unsigned int irq_nr)
86{
87 if (!(irq_desc[irq_nr].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
88 unmask_saturn_irq(irq_nr);
89}
90
91static unsigned int startup_saturn_irq(unsigned int irq_nr)
92{
93 unmask_saturn_irq(irq_nr);
94
95 return 0;
96}
97
98static void shutdown_saturn_irq(unsigned int irq_nr)
99{
100 mask_saturn_irq(irq_nr);
101}
102
103static struct hw_interrupt_type saturn_int = {
104 .typename = "Saturn",
105 .enable = enable_saturn_irq,
106 .disable = disable_saturn_irq,
107 .ack = mask_and_ack_saturn_irq,
108 .end = end_saturn_irq,
109 .startup = startup_saturn_irq,
110 .shutdown = shutdown_saturn_irq,
111};
112
113int saturn_irq_demux(int irq_nr)
114{
115 /* FIXME */
116 return irq_nr;
117}
118
diff --git a/arch/sh/boards/saturn/setup.c b/arch/sh/boards/saturn/setup.c
new file mode 100644
index 00000000000..bea6c572ad8
--- /dev/null
+++ b/arch/sh/boards/saturn/setup.c
@@ -0,0 +1,43 @@
1/*
2 * arch/sh/boards/saturn/setup.c
3 *
4 * Hardware support for the Sega Saturn.
5 *
6 * Copyright (c) 2002 Paul Mundt
7 *
8 * Released under the terms of the GNU GPL v2.0.
9 */
10#include <linux/kernel.h>
11#include <linux/init.h>
12
13#include <asm/io.h>
14#include <asm/machvec.h>
15#include <asm/mach/io.h>
16
17extern int saturn_irq_demux(int irq_nr);
18
19const char *get_system_type(void)
20{
21 return "Sega Saturn";
22}
23
24/*
25 * The Machine Vector
26 */
27struct sh_machine_vector mv_saturn __initmv = {
28 .mv_nr_irqs = 80, /* Fix this later */
29
30 .mv_isa_port2addr = saturn_isa_port2addr,
31 .mv_irq_demux = saturn_irq_demux,
32
33 .mv_ioremap = saturn_ioremap,
34 .mv_iounmap = saturn_iounmap,
35};
36
37ALIAS_MV(saturn)
38
39int __init platform_setup(void)
40{
41 return 0;
42}
43
diff --git a/arch/sh/boards/saturn/smp.c b/arch/sh/boards/saturn/smp.c
new file mode 100644
index 00000000000..76460918c9c
--- /dev/null
+++ b/arch/sh/boards/saturn/smp.c
@@ -0,0 +1,68 @@
1/*
2 * arch/sh/boards/saturn/smp.c
3 *
4 * SMP support for the Sega Saturn.
5 *
6 * Copyright (c) 2002 Paul Mundt
7 *
8 * Released under the terms of the GNU GPL v2.0.
9 */
10#include <linux/kernel.h>
11#include <linux/init.h>
12#include <linux/smp.h>
13
14#include <asm/saturn/smpc.h>
15
16extern void start_secondary(void);
17
18void __smp_send_ipi(unsigned int cpu, unsigned int action)
19{
20 /* Nothing here yet .. */
21}
22
23unsigned int __smp_probe_cpus(void)
24{
25 /*
26 * This is just a straightforward master/slave configuration,
27 * and probing isn't really supported..
28 */
29 return 2;
30}
31
32/*
33 * We're only allowed to do byte-access to SMPC registers. In
34 * addition to which, we treat them as write-only, since
35 * reading from them will return undefined data.
36 */
37static inline void smpc_slave_stop(unsigned int cpu)
38{
39 smpc_barrier();
40 ctrl_outb(1, SMPC_STATUS);
41
42 ctrl_outb(SMPC_CMD_SSHOFF, SMPC_COMMAND);
43 smpc_barrier();
44}
45
46static inline void smpc_slave_start(unsigned int cpu)
47{
48 ctrl_outb(1, SMPC_STATUS);
49 ctrl_outb(SMPC_CMD_SSHON, SMPC_COMMAND);
50
51 smpc_barrier();
52}
53
54void __smp_slave_init(unsigned int cpu)
55{
56 register unsigned long vbr;
57 void **entry;
58
59 __asm__ __volatile__ ("stc vbr, %0\n\t" : "=r" (vbr));
60 entry = (void **)(vbr + 0x310 + 0x94);
61
62 smpc_slave_stop(cpu);
63
64 *(void **)entry = (void *)start_secondary;
65
66 smpc_slave_start(cpu);
67}
68
diff --git a/arch/sh/boards/se/7300/Makefile b/arch/sh/boards/se/7300/Makefile
new file mode 100644
index 00000000000..0fbd4f47815
--- /dev/null
+++ b/arch/sh/boards/se/7300/Makefile
@@ -0,0 +1,7 @@
1#
2# Makefile for the 7300 SolutionEngine specific parts of the kernel
3#
4
5obj-y := setup.o io.o irq.o
6
7obj-$(CONFIG_HEARTBEAT) += led.o
diff --git a/arch/sh/boards/se/7300/io.c b/arch/sh/boards/se/7300/io.c
new file mode 100644
index 00000000000..3c89def4648
--- /dev/null
+++ b/arch/sh/boards/se/7300/io.c
@@ -0,0 +1,265 @@
1/*
2 * arch/sh/boards/se/7300/io.c
3 *
4 * Copyright (C) 2003 YOSHII Takashi <yoshii-takashi@hitachi-ul.co.jp>
5 * Based on arch/sh/kernel/io_shmse.c
6 *
7 * I/O routine for SH-Mobile3 73180 SolutionEngine.
8 *
9 */
10
11#include <linux/config.h>
12#include <linux/kernel.h>
13#include <asm/mach/se7300.h>
14#include <asm/io.h>
15
16#define badio(fn, a) panic("bad i/o operation %s for %08lx.", #fn, a)
17
18struct iop {
19 unsigned long start, end;
20 unsigned long base;
21 struct iop *(*check) (struct iop * p, unsigned long port);
22 unsigned char (*inb) (struct iop * p, unsigned long port);
23 unsigned short (*inw) (struct iop * p, unsigned long port);
24 void (*outb) (struct iop * p, unsigned char value, unsigned long port);
25 void (*outw) (struct iop * p, unsigned short value, unsigned long port);
26};
27
28struct iop *
29simple_check(struct iop *p, unsigned long port)
30{
31 if ((p->start <= port) && (port <= p->end))
32 return p;
33 else
34 badio(check, port);
35}
36
37struct iop *
38ide_check(struct iop *p, unsigned long port)
39{
40 if (((0x1f0 <= port) && (port <= 0x1f7)) || (port == 0x3f7))
41 return p;
42 return NULL;
43}
44
45unsigned char
46simple_inb(struct iop *p, unsigned long port)
47{
48 return *(unsigned char *) (p->base + port);
49}
50
51unsigned short
52simple_inw(struct iop *p, unsigned long port)
53{
54 return *(unsigned short *) (p->base + port);
55}
56
57void
58simple_outb(struct iop *p, unsigned char value, unsigned long port)
59{
60 *(unsigned char *) (p->base + port) = value;
61}
62
63void
64simple_outw(struct iop *p, unsigned short value, unsigned long port)
65{
66 *(unsigned short *) (p->base + port) = value;
67}
68
69unsigned char
70pcc_inb(struct iop *p, unsigned long port)
71{
72 unsigned long addr = p->base + port + 0x40000;
73 unsigned long v;
74
75 if (port & 1)
76 addr += 0x00400000;
77 v = *(volatile unsigned char *) addr;
78 return v;
79}
80
81void
82pcc_outb(struct iop *p, unsigned char value, unsigned long port)
83{
84 unsigned long addr = p->base + port + 0x40000;
85
86 if (port & 1)
87 addr += 0x00400000;
88 *(volatile unsigned char *) addr = value;
89}
90
91unsigned char
92bad_inb(struct iop *p, unsigned long port)
93{
94 badio(inb, port);
95}
96
97void
98bad_outb(struct iop *p, unsigned char value, unsigned long port)
99{
100 badio(inw, port);
101}
102
103/* MSTLANEX01 LAN at 0xb400:0000 */
104static struct iop laniop = {
105 .start = 0x300,
106 .end = 0x30f,
107 .base = 0xb4000000,
108 .check = simple_check,
109 .inb = simple_inb,
110 .inw = simple_inw,
111 .outb = simple_outb,
112 .outw = simple_outw,
113};
114
115/* NE2000 pc card NIC */
116static struct iop neiop = {
117 .start = 0x280,
118 .end = 0x29f,
119 .base = 0xb0600000 + 0x80, /* soft 0x280 -> hard 0x300 */
120 .check = simple_check,
121 .inb = pcc_inb,
122 .inw = simple_inw,
123 .outb = pcc_outb,
124 .outw = simple_outw,
125};
126
127/* CF in CF slot */
128static struct iop cfiop = {
129 .base = 0xb0600000,
130 .check = ide_check,
131 .inb = pcc_inb,
132 .inw = simple_inw,
133 .outb = pcc_outb,
134 .outw = simple_outw,
135};
136
137static __inline__ struct iop *
138port2iop(unsigned long port)
139{
140 if (0) ;
141#if defined(CONFIG_SMC91111)
142 else if (laniop.check(&laniop, port))
143 return &laniop;
144#endif
145#if defined(CONFIG_NE2000)
146 else if (neiop.check(&neiop, port))
147 return &neiop;
148#endif
149#if defined(CONFIG_IDE)
150 else if (cfiop.check(&cfiop, port))
151 return &cfiop;
152#endif
153 else
154 return &neiop; /* fallback */
155}
156
157static inline void
158delay(void)
159{
160 ctrl_inw(0xac000000);
161 ctrl_inw(0xac000000);
162}
163
164unsigned char
165sh7300se_inb(unsigned long port)
166{
167 struct iop *p = port2iop(port);
168 return (p->inb) (p, port);
169}
170
171unsigned char
172sh7300se_inb_p(unsigned long port)
173{
174 unsigned char v = sh7300se_inb(port);
175 delay();
176 return v;
177}
178
179unsigned short
180sh7300se_inw(unsigned long port)
181{
182 struct iop *p = port2iop(port);
183 return (p->inw) (p, port);
184}
185
186unsigned int
187sh7300se_inl(unsigned long port)
188{
189 badio(inl, port);
190}
191
192void
193sh7300se_outb(unsigned char value, unsigned long port)
194{
195 struct iop *p = port2iop(port);
196 (p->outb) (p, value, port);
197}
198
199void
200sh7300se_outb_p(unsigned char value, unsigned long port)
201{
202 sh7300se_outb(value, port);
203 delay();
204}
205
206void
207sh7300se_outw(unsigned short value, unsigned long port)
208{
209 struct iop *p = port2iop(port);
210 (p->outw) (p, value, port);
211}
212
213void
214sh7300se_outl(unsigned int value, unsigned long port)
215{
216 badio(outl, port);
217}
218
219void
220sh7300se_insb(unsigned long port, void *addr, unsigned long count)
221{
222 unsigned char *a = addr;
223 struct iop *p = port2iop(port);
224 while (count--)
225 *a++ = (p->inb) (p, port);
226}
227
228void
229sh7300se_insw(unsigned long port, void *addr, unsigned long count)
230{
231 unsigned short *a = addr;
232 struct iop *p = port2iop(port);
233 while (count--)
234 *a++ = (p->inw) (p, port);
235}
236
237void
238sh7300se_insl(unsigned long port, void *addr, unsigned long count)
239{
240 badio(insl, port);
241}
242
243void
244sh7300se_outsb(unsigned long port, const void *addr, unsigned long count)
245{
246 unsigned char *a = (unsigned char *) addr;
247 struct iop *p = port2iop(port);
248 while (count--)
249 (p->outb) (p, *a++, port);
250}
251
252void
253sh7300se_outsw(unsigned long port, const void *addr, unsigned long count)
254{
255 unsigned short *a = (unsigned short *) addr;
256 struct iop *p = port2iop(port);
257 while (count--)
258 (p->outw) (p, *a++, port);
259}
260
261void
262sh7300se_outsl(unsigned long port, const void *addr, unsigned long count)
263{
264 badio(outsw, port);
265}
diff --git a/arch/sh/boards/se/7300/irq.c b/arch/sh/boards/se/7300/irq.c
new file mode 100644
index 00000000000..96c8c23d6c9
--- /dev/null
+++ b/arch/sh/boards/se/7300/irq.c
@@ -0,0 +1,37 @@
1/*
2 * linux/arch/sh/boards/se/7300/irq.c
3 *
4 * Copyright (C) 2003 Takashi Kusuda <kusuda-takashi@hitachi-ul.co.jp>
5 *
6 * SH-Mobile SolutionEngine 7300 Support.
7 *
8 */
9
10#include <linux/config.h>
11#include <linux/init.h>
12#include <linux/irq.h>
13#include <asm/irq.h>
14#include <asm/io.h>
15#include <asm/mach/se7300.h>
16
17/*
18 * Initialize IRQ setting
19 */
20void __init
21init_7300se_IRQ(void)
22{
23 ctrl_outw(0x0028, PA_EPLD_MODESET); /* mode set IRQ0,1 active low. */
24 ctrl_outw(0xa000, INTC_ICR1); /* IRQ mode; IRQ0,1 enable. */
25 ctrl_outw(0x0000, PORT_PFCR); /* use F for IRQ[3:0] and SIU. */
26
27 /* PC_IRQ[0-3] -> IRQ0 (32) */
28 make_ipr_irq(IRQ0_IRQ, IRQ0_IPR_ADDR, IRQ0_IPR_POS, 0x0f - IRQ0_IRQ);
29 /* A_IRQ[0-3] -> IRQ1 (33) */
30 make_ipr_irq(IRQ1_IRQ, IRQ1_IPR_ADDR, IRQ1_IPR_POS, 0x0f - IRQ1_IRQ);
31 make_ipr_irq(SIOF0_IRQ, SIOF0_IPR_ADDR, SIOF0_IPR_POS, SIOF0_PRIORITY);
32 make_ipr_irq(DMTE2_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY);
33 make_ipr_irq(DMTE3_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY);
34 make_ipr_irq(VIO_IRQ, VIO_IPR_ADDR, VIO_IPR_POS, VIO_PRIORITY);
35
36 ctrl_outw(0x2000, PA_MRSHPC + 0x0c); /* mrshpc irq enable */
37}
diff --git a/arch/sh/boards/se/7300/led.c b/arch/sh/boards/se/7300/led.c
new file mode 100644
index 00000000000..02c7f846c84
--- /dev/null
+++ b/arch/sh/boards/se/7300/led.c
@@ -0,0 +1,69 @@
1/*
2 * linux/arch/sh/boards/se/7300/led.c
3 *
4 * Derived from linux/arch/sh/boards/se/770x/led.c
5 *
6 * Copyright (C) 2000 Stuart Menefy <stuart.menefy@st.com>
7 *
8 * May be copied or modified under the terms of the GNU General Public
9 * License. See linux/COPYING for more information.
10 *
11 * This file contains Solution Engine specific LED code.
12 */
13
14#include <linux/config.h>
15#include <linux/sched.h>
16#include <asm/mach/se7300.h>
17
18static void
19mach_led(int position, int value)
20{
21 volatile unsigned short *p = (volatile unsigned short *) PA_LED;
22
23 if (value) {
24 *p |= (1 << 8);
25 } else {
26 *p &= ~(1 << 8);
27 }
28}
29
30
31/* Cycle the LED's in the clasic Knightrider/Sun pattern */
32void
33heartbeat_7300se(void)
34{
35 static unsigned int cnt = 0, period = 0;
36 volatile unsigned short *p = (volatile unsigned short *) PA_LED;
37 static unsigned bit = 0, up = 1;
38
39 cnt += 1;
40 if (cnt < period) {
41 return;
42 }
43
44 cnt = 0;
45
46 /* Go through the points (roughly!):
47 * f(0)=10, f(1)=16, f(2)=20, f(5)=35,f(inf)->110
48 */
49 period = 110 - ((300 << FSHIFT) / ((avenrun[0] / 5) + (3 << FSHIFT)));
50
51 if (up) {
52 if (bit == 7) {
53 bit--;
54 up = 0;
55 } else {
56 bit++;
57 }
58 } else {
59 if (bit == 0) {
60 bit++;
61 up = 1;
62 } else {
63 bit--;
64 }
65 }
66 *p = 1 << (bit + 8);
67
68}
69
diff --git a/arch/sh/boards/se/7300/setup.c b/arch/sh/boards/se/7300/setup.c
new file mode 100644
index 00000000000..08536bc224d
--- /dev/null
+++ b/arch/sh/boards/se/7300/setup.c
@@ -0,0 +1,66 @@
1/*
2 * linux/arch/sh/boards/se/7300/setup.c
3 *
4 * Copyright (C) 2003 Takashi Kusuda <kusuda-takashi@hitachi-ul.co.jp>
5 *
6 * SH-Mobile SolutionEngine 7300 Support.
7 *
8 */
9
10#include <linux/config.h>
11#include <linux/init.h>
12#include <asm/machvec.h>
13#include <asm/machvec_init.h>
14#include <asm/mach/io.h>
15
16void heartbeat_7300se(void);
17void init_7300se_IRQ(void);
18
19const char *
20get_system_type(void)
21{
22 return "SolutionEngine 7300";
23}
24
25/*
26 * The Machine Vector
27 */
28
29struct sh_machine_vector mv_7300se __initmv = {
30 .mv_nr_irqs = 109,
31 .mv_inb = sh7300se_inb,
32 .mv_inw = sh7300se_inw,
33 .mv_inl = sh7300se_inl,
34 .mv_outb = sh7300se_outb,
35 .mv_outw = sh7300se_outw,
36 .mv_outl = sh7300se_outl,
37
38 .mv_inb_p = sh7300se_inb_p,
39 .mv_inw_p = sh7300se_inw,
40 .mv_inl_p = sh7300se_inl,
41 .mv_outb_p = sh7300se_outb_p,
42 .mv_outw_p = sh7300se_outw,
43 .mv_outl_p = sh7300se_outl,
44
45 .mv_insb = sh7300se_insb,
46 .mv_insw = sh7300se_insw,
47 .mv_insl = sh7300se_insl,
48 .mv_outsb = sh7300se_outsb,
49 .mv_outsw = sh7300se_outsw,
50 .mv_outsl = sh7300se_outsl,
51
52 .mv_init_irq = init_7300se_IRQ,
53#ifdef CONFIG_HEARTBEAT
54 .mv_heartbeat = heartbeat_7300se,
55#endif
56};
57
58ALIAS_MV(7300se)
59/*
60 * Initialize the board
61 */
62void __init
63platform_setup(void)
64{
65
66}
diff --git a/arch/sh/boards/se/73180/Makefile b/arch/sh/boards/se/73180/Makefile
new file mode 100644
index 00000000000..8f63886a0f3
--- /dev/null
+++ b/arch/sh/boards/se/73180/Makefile
@@ -0,0 +1,7 @@
1#
2# Makefile for the 73180 SolutionEngine specific parts of the kernel
3#
4
5obj-y := setup.o io.o irq.o
6
7obj-$(CONFIG_HEARTBEAT) += led.o
diff --git a/arch/sh/boards/se/73180/io.c b/arch/sh/boards/se/73180/io.c
new file mode 100644
index 00000000000..73648cbe367
--- /dev/null
+++ b/arch/sh/boards/se/73180/io.c
@@ -0,0 +1,265 @@
1/*
2 * arch/sh/boards/se/73180/io.c
3 *
4 * Copyright (C) 2003 YOSHII Takashi <yoshii-takashi@hitachi-ul.co.jp>
5 * Based on arch/sh/boards/se/7300/io.c
6 *
7 * I/O routine for SH-Mobile3 73180 SolutionEngine.
8 *
9 */
10
11#include <linux/config.h>
12#include <linux/kernel.h>
13#include <asm/mach/se73180.h>
14#include <asm/io.h>
15
16#define badio(fn, a) panic("bad i/o operation %s for %08lx.", #fn, a)
17
18struct iop {
19 unsigned long start, end;
20 unsigned long base;
21 struct iop *(*check) (struct iop * p, unsigned long port);
22 unsigned char (*inb) (struct iop * p, unsigned long port);
23 unsigned short (*inw) (struct iop * p, unsigned long port);
24 void (*outb) (struct iop * p, unsigned char value, unsigned long port);
25 void (*outw) (struct iop * p, unsigned short value, unsigned long port);
26};
27
28struct iop *
29simple_check(struct iop *p, unsigned long port)
30{
31 if ((p->start <= port) && (port <= p->end))
32 return p;
33 else
34 badio(check, port);
35}
36
37struct iop *
38ide_check(struct iop *p, unsigned long port)
39{
40 if (((0x1f0 <= port) && (port <= 0x1f7)) || (port == 0x3f7))
41 return p;
42 return NULL;
43}
44
45unsigned char
46simple_inb(struct iop *p, unsigned long port)
47{
48 return *(unsigned char *) (p->base + port);
49}
50
51unsigned short
52simple_inw(struct iop *p, unsigned long port)
53{
54 return *(unsigned short *) (p->base + port);
55}
56
57void
58simple_outb(struct iop *p, unsigned char value, unsigned long port)
59{
60 *(unsigned char *) (p->base + port) = value;
61}
62
63void
64simple_outw(struct iop *p, unsigned short value, unsigned long port)
65{
66 *(unsigned short *) (p->base + port) = value;
67}
68
69unsigned char
70pcc_inb(struct iop *p, unsigned long port)
71{
72 unsigned long addr = p->base + port + 0x40000;
73 unsigned long v;
74
75 if (port & 1)
76 addr += 0x00400000;
77 v = *(volatile unsigned char *) addr;
78 return v;
79}
80
81void
82pcc_outb(struct iop *p, unsigned char value, unsigned long port)
83{
84 unsigned long addr = p->base + port + 0x40000;
85
86 if (port & 1)
87 addr += 0x00400000;
88 *(volatile unsigned char *) addr = value;
89}
90
91unsigned char
92bad_inb(struct iop *p, unsigned long port)
93{
94 badio(inb, port);
95}
96
97void
98bad_outb(struct iop *p, unsigned char value, unsigned long port)
99{
100 badio(inw, port);
101}
102
103/* MSTLANEX01 LAN at 0xb400:0000 */
104static struct iop laniop = {
105 .start = 0x300,
106 .end = 0x30f,
107 .base = 0xb4000000,
108 .check = simple_check,
109 .inb = simple_inb,
110 .inw = simple_inw,
111 .outb = simple_outb,
112 .outw = simple_outw,
113};
114
115/* NE2000 pc card NIC */
116static struct iop neiop = {
117 .start = 0x280,
118 .end = 0x29f,
119 .base = 0xb0600000 + 0x80, /* soft 0x280 -> hard 0x300 */
120 .check = simple_check,
121 .inb = pcc_inb,
122 .inw = simple_inw,
123 .outb = pcc_outb,
124 .outw = simple_outw,
125};
126
127/* CF in CF slot */
128static struct iop cfiop = {
129 .base = 0xb0600000,
130 .check = ide_check,
131 .inb = pcc_inb,
132 .inw = simple_inw,
133 .outb = pcc_outb,
134 .outw = simple_outw,
135};
136
137static __inline__ struct iop *
138port2iop(unsigned long port)
139{
140 if (0) ;
141#if defined(CONFIG_SMC91111)
142 else if (laniop.check(&laniop, port))
143 return &laniop;
144#endif
145#if defined(CONFIG_NE2000)
146 else if (neiop.check(&neiop, port))
147 return &neiop;
148#endif
149#if defined(CONFIG_IDE)
150 else if (cfiop.check(&cfiop, port))
151 return &cfiop;
152#endif
153 else
154 return &neiop; /* fallback */
155}
156
157static inline void
158delay(void)
159{
160 ctrl_inw(0xac000000);
161 ctrl_inw(0xac000000);
162}
163
164unsigned char
165sh73180se_inb(unsigned long port)
166{
167 struct iop *p = port2iop(port);
168 return (p->inb) (p, port);
169}
170
171unsigned char
172sh73180se_inb_p(unsigned long port)
173{
174 unsigned char v = sh73180se_inb(port);
175 delay();
176 return v;
177}
178
179unsigned short
180sh73180se_inw(unsigned long port)
181{
182 struct iop *p = port2iop(port);
183 return (p->inw) (p, port);
184}
185
186unsigned int
187sh73180se_inl(unsigned long port)
188{
189 badio(inl, port);
190}
191
192void
193sh73180se_outb(unsigned char value, unsigned long port)
194{
195 struct iop *p = port2iop(port);
196 (p->outb) (p, value, port);
197}
198
199void
200sh73180se_outb_p(unsigned char value, unsigned long port)
201{
202 sh73180se_outb(value, port);
203 delay();
204}
205
206void
207sh73180se_outw(unsigned short value, unsigned long port)
208{
209 struct iop *p = port2iop(port);
210 (p->outw) (p, value, port);
211}
212
213void
214sh73180se_outl(unsigned int value, unsigned long port)
215{
216 badio(outl, port);
217}
218
219void
220sh73180se_insb(unsigned long port, void *addr, unsigned long count)
221{
222 unsigned char *a = addr;
223 struct iop *p = port2iop(port);
224 while (count--)
225 *a++ = (p->inb) (p, port);
226}
227
228void
229sh73180se_insw(unsigned long port, void *addr, unsigned long count)
230{
231 unsigned short *a = addr;
232 struct iop *p = port2iop(port);
233 while (count--)
234 *a++ = (p->inw) (p, port);
235}
236
237void
238sh73180se_insl(unsigned long port, void *addr, unsigned long count)
239{
240 badio(insl, port);
241}
242
243void
244sh73180se_outsb(unsigned long port, const void *addr, unsigned long count)
245{
246 unsigned char *a = (unsigned char *) addr;
247 struct iop *p = port2iop(port);
248 while (count--)
249 (p->outb) (p, *a++, port);
250}
251
252void
253sh73180se_outsw(unsigned long port, const void *addr, unsigned long count)
254{
255 unsigned short *a = (unsigned short *) addr;
256 struct iop *p = port2iop(port);
257 while (count--)
258 (p->outw) (p, *a++, port);
259}
260
261void
262sh73180se_outsl(unsigned long port, const void *addr, unsigned long count)
263{
264 badio(outsw, port);
265}
diff --git a/arch/sh/boards/se/73180/irq.c b/arch/sh/boards/se/73180/irq.c
new file mode 100644
index 00000000000..70f04caad9a
--- /dev/null
+++ b/arch/sh/boards/se/73180/irq.c
@@ -0,0 +1,137 @@
1/*
2 * arch/sh/boards/se/73180/irq.c
3 *
4 * Copyright (C) 2003 Takashi Kusuda <kusuda-takashi@hitachi-ul.co.jp>
5 * Based on arch/sh/boards/se/7300/irq.c
6 *
7 * Modified for SH-Mobile SolutionEngine 73180 Support
8 * by YOSHII Takashi <yoshii-takashi@hitachi-ul.co.jp>
9 *
10 *
11 */
12
13#include <linux/config.h>
14#include <linux/init.h>
15#include <linux/irq.h>
16#include <asm/irq.h>
17#include <asm/io.h>
18#include <asm/mach/se73180.h>
19
20static int
21intreq2irq(int i)
22{
23 if (i == 5)
24 return 10;
25 return 32 + 7 - i;
26}
27
28static int
29irq2intreq(int irq)
30{
31 if (irq == 10)
32 return 5;
33 return 7 - (irq - 32);
34}
35
36static void
37disable_intreq_irq(unsigned int irq)
38{
39 ctrl_outb(1 << (7 - irq2intreq(irq)), INTMSK0);
40}
41
42static void
43enable_intreq_irq(unsigned int irq)
44{
45 ctrl_outb(1 << (7 - irq2intreq(irq)), INTMSKCLR0);
46}
47
48static void
49mask_and_ack_intreq_irq(unsigned int irq)
50{
51 disable_intreq_irq(irq);
52}
53
54static unsigned int
55startup_intreq_irq(unsigned int irq)
56{
57 enable_intreq_irq(irq);
58 return 0;
59}
60
61static void
62shutdown_intreq_irq(unsigned int irq)
63{
64 disable_intreq_irq(irq);
65}
66
67static void
68end_intreq_irq(unsigned int irq)
69{
70 if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
71 enable_intreq_irq(irq);
72}
73
74static struct hw_interrupt_type intreq_irq_type = {
75 .typename = "intreq",
76 .startup = startup_intreq_irq,
77 .shutdown = shutdown_intreq_irq,
78 .enable = enable_intreq_irq,
79 .disable = disable_intreq_irq,
80 .ack = mask_and_ack_intreq_irq,
81 .end = end_intreq_irq
82};
83
84void
85make_intreq_irq(unsigned int irq)
86{
87 disable_irq_nosync(irq);
88 irq_desc[irq].handler = &intreq_irq_type;
89 disable_intreq_irq(irq);
90}
91
92int
93shmse_irq_demux(int irq)
94{
95 if (irq == IRQ5_IRQ)
96 return 10;
97 return irq;
98}
99
100/*
101 * Initialize IRQ setting
102 */
103void __init
104init_73180se_IRQ(void)
105{
106 make_ipr_irq(SIOF0_IRQ, SIOF0_IPR_ADDR, SIOF0_IPR_POS, SIOF0_PRIORITY);
107
108 ctrl_outw(0x2000, 0xb03fffec); /* mrshpc irq enable */
109 ctrl_outw(0x2000, 0xb07fffec); /* mrshpc irq enable */
110 ctrl_outl(3 << ((7 - 5) * 4), INTC_INTPRI0); /* irq5 pri=3 */
111 ctrl_outw(2 << ((7 - 5) * 2), INTC_ICR1); /* low-level irq */
112 make_intreq_irq(10);
113
114 make_ipr_irq(VPU_IRQ, VPU_IPR_ADDR, VPU_IPR_POS, 8);
115
116 ctrl_outb(0x0f, INTC_IMCR5); /* enable SCIF IRQ */
117
118 make_ipr_irq(DMTE2_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY);
119 make_ipr_irq(DMTE3_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY);
120 make_ipr_irq(DMTE4_IRQ, DMA2_IPR_ADDR, DMA2_IPR_POS, DMA2_PRIORITY);
121 make_ipr_irq(IIC0_ALI_IRQ, IIC0_IPR_ADDR, IIC0_IPR_POS, IIC0_PRIORITY);
122 make_ipr_irq(IIC0_TACKI_IRQ, IIC0_IPR_ADDR, IIC0_IPR_POS,
123 IIC0_PRIORITY);
124 make_ipr_irq(IIC0_WAITI_IRQ, IIC0_IPR_ADDR, IIC0_IPR_POS,
125 IIC0_PRIORITY);
126 make_ipr_irq(IIC0_DTEI_IRQ, IIC0_IPR_ADDR, IIC0_IPR_POS, IIC0_PRIORITY);
127 make_ipr_irq(SIOF0_IRQ, SIOF0_IPR_ADDR, SIOF0_IPR_POS, SIOF0_PRIORITY);
128 make_ipr_irq(SIU_IRQ, SIU_IPR_ADDR, SIU_IPR_POS, SIU_PRIORITY);
129
130 /* VIO interrupt */
131 make_ipr_irq(CEU_IRQ, VIO_IPR_ADDR, VIO_IPR_POS, VIO_PRIORITY);
132 make_ipr_irq(BEU_IRQ, VIO_IPR_ADDR, VIO_IPR_POS, VIO_PRIORITY);
133 make_ipr_irq(VEU_IRQ, VIO_IPR_ADDR, VIO_IPR_POS, VIO_PRIORITY);
134
135 make_ipr_irq(LCDC_IRQ, LCDC_IPR_ADDR, LCDC_IPR_POS, LCDC_PRIORITY);
136 ctrl_outw(0x2000, PA_MRSHPC + 0x0c); /* mrshpc irq enable */
137}
diff --git a/arch/sh/boards/se/73180/led.c b/arch/sh/boards/se/73180/led.c
new file mode 100644
index 00000000000..1e8f1cf3e10
--- /dev/null
+++ b/arch/sh/boards/se/73180/led.c
@@ -0,0 +1,67 @@
1/*
2 * arch/sh/boards/se/73180/led.c
3 *
4 * Derived from arch/sh/boards/se/770x/led.c
5 *
6 * Copyright (C) 2000 Stuart Menefy <stuart.menefy@st.com>
7 *
8 * May be copied or modified under the terms of the GNU General Public
9 * License. See linux/COPYING for more information.
10 *
11 * This file contains Solution Engine specific LED code.
12 */
13
14#include <linux/config.h>
15#include <linux/sched.h>
16#include <asm/mach/se73180.h>
17
18static void
19mach_led(int position, int value)
20{
21 volatile unsigned short *p = (volatile unsigned short *) PA_LED;
22
23 if (value) {
24 *p |= (1 << LED_SHIFT);
25 } else {
26 *p &= ~(1 << LED_SHIFT);
27 }
28}
29
30/* Cycle the LED's in the clasic Knightrider/Sun pattern */
31void
32heartbeat_73180se(void)
33{
34 static unsigned int cnt = 0, period = 0;
35 volatile unsigned short *p = (volatile unsigned short *) PA_LED;
36 static unsigned bit = 0, up = 1;
37
38 cnt += 1;
39 if (cnt < period) {
40 return;
41 }
42
43 cnt = 0;
44
45 /* Go through the points (roughly!):
46 * f(0)=10, f(1)=16, f(2)=20, f(5)=35,f(inf)->110
47 */
48 period = 110 - ((300 << FSHIFT) / ((avenrun[0] / 5) + (3 << FSHIFT)));
49
50 if (up) {
51 if (bit == 7) {
52 bit--;
53 up = 0;
54 } else {
55 bit++;
56 }
57 } else {
58 if (bit == 0) {
59 bit++;
60 up = 1;
61 } else {
62 bit--;
63 }
64 }
65 *p = 1 << (bit + LED_SHIFT);
66
67}
diff --git a/arch/sh/boards/se/73180/setup.c b/arch/sh/boards/se/73180/setup.c
new file mode 100644
index 00000000000..07fa90c38a0
--- /dev/null
+++ b/arch/sh/boards/se/73180/setup.c
@@ -0,0 +1,68 @@
1/*
2 * arch/sh/boards/se/73180/setup.c
3 *
4 * Copyright (C) 2003 Takashi Kusuda <kusuda-takashi@hitachi-ul.co.jp>
5 * Based on arch/sh/setup_shmse.c
6 *
7 * Modified for 73180 SolutionEngine
8 * by YOSHII Takashi <yoshii-takashi@hitachi-ul.co.jp>
9 *
10 */
11
12#include <linux/config.h>
13#include <linux/init.h>
14#include <asm/machvec.h>
15#include <asm/machvec_init.h>
16#include <asm/mach/io.h>
17
18void heartbeat_73180se(void);
19void init_73180se_IRQ(void);
20
21const char *
22get_system_type(void)
23{
24 return "SolutionEngine 73180";
25}
26
27/*
28 * The Machine Vector
29 */
30
31struct sh_machine_vector mv_73180se __initmv = {
32 .mv_nr_irqs = 108,
33 .mv_inb = sh73180se_inb,
34 .mv_inw = sh73180se_inw,
35 .mv_inl = sh73180se_inl,
36 .mv_outb = sh73180se_outb,
37 .mv_outw = sh73180se_outw,
38 .mv_outl = sh73180se_outl,
39
40 .mv_inb_p = sh73180se_inb_p,
41 .mv_inw_p = sh73180se_inw,
42 .mv_inl_p = sh73180se_inl,
43 .mv_outb_p = sh73180se_outb_p,
44 .mv_outw_p = sh73180se_outw,
45 .mv_outl_p = sh73180se_outl,
46
47 .mv_insb = sh73180se_insb,
48 .mv_insw = sh73180se_insw,
49 .mv_insl = sh73180se_insl,
50 .mv_outsb = sh73180se_outsb,
51 .mv_outsw = sh73180se_outsw,
52 .mv_outsl = sh73180se_outsl,
53
54 .mv_init_irq = init_73180se_IRQ,
55#ifdef CONFIG_HEARTBEAT
56 .mv_heartbeat = heartbeat_73180se,
57#endif
58};
59
60ALIAS_MV(73180se)
61/*
62 * Initialize the board
63 */
64void __init
65platform_setup(void)
66{
67
68}
diff --git a/arch/sh/boards/se/770x/Makefile b/arch/sh/boards/se/770x/Makefile
new file mode 100644
index 00000000000..be89a73cc41
--- /dev/null
+++ b/arch/sh/boards/se/770x/Makefile
@@ -0,0 +1,6 @@
1#
2# Makefile for the 770x SolutionEngine specific parts of the kernel
3#
4
5obj-y := mach.o setup.o io.o irq.o led.o
6
diff --git a/arch/sh/boards/se/770x/io.c b/arch/sh/boards/se/770x/io.c
new file mode 100644
index 00000000000..9a39ee96314
--- /dev/null
+++ b/arch/sh/boards/se/770x/io.c
@@ -0,0 +1,226 @@
1/* $Id: io.c,v 1.5 2004/02/22 23:08:43 kkojima Exp $
2 *
3 * linux/arch/sh/kernel/io_se.c
4 *
5 * Copyright (C) 2000 Kazumoto Kojima
6 *
7 * I/O routine for Hitachi SolutionEngine.
8 *
9 */
10
11#include <linux/kernel.h>
12#include <linux/types.h>
13#include <asm/io.h>
14#include <asm/se/se.h>
15
16/* SH pcmcia io window base, start and end. */
17int sh_pcic_io_wbase = 0xb8400000;
18int sh_pcic_io_start;
19int sh_pcic_io_stop;
20int sh_pcic_io_type;
21int sh_pcic_io_dummy;
22
23static inline void delay(void)
24{
25 ctrl_inw(0xa0000000);
26}
27
28/* MS7750 requires special versions of in*, out* routines, since
29 PC-like io ports are located at upper half byte of 16-bit word which
30 can be accessed only with 16-bit wide. */
31
32static inline volatile __u16 *
33port2adr(unsigned int port)
34{
35 if (port >= 0x2000)
36 return (volatile __u16 *) (PA_MRSHPC + (port - 0x2000));
37 else if (port >= 0x1000)
38 return (volatile __u16 *) (PA_83902 + (port << 1));
39 else if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)
40 return (volatile __u16 *) (sh_pcic_io_wbase + (port &~ 1));
41 else
42 return (volatile __u16 *) (PA_SUPERIO + (port << 1));
43}
44
45static inline int
46shifted_port(unsigned long port)
47{
48 /* For IDE registers, value is not shifted */
49 if ((0x1f0 <= port && port < 0x1f8) || port == 0x3f6)
50 return 0;
51 else
52 return 1;
53}
54
55#define maybebadio(name,port) \
56 printk("bad PC-like io %s for port 0x%lx at 0x%08x\n", \
57 #name, (port), (__u32) __builtin_return_address(0))
58
59unsigned char se_inb(unsigned long port)
60{
61 if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)
62 return *(__u8 *) (sh_pcic_io_wbase + 0x40000 + port);
63 else if (shifted_port(port))
64 return (*port2adr(port) >> 8);
65 else
66 return (*port2adr(port))&0xff;
67}
68
69unsigned char se_inb_p(unsigned long port)
70{
71 unsigned long v;
72
73 if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)
74 v = *(__u8 *) (sh_pcic_io_wbase + 0x40000 + port);
75 else if (shifted_port(port))
76 v = (*port2adr(port) >> 8);
77 else
78 v = (*port2adr(port))&0xff;
79 delay();
80 return v;
81}
82
83unsigned short se_inw(unsigned long port)
84{
85 if (port >= 0x2000 ||
86 (sh_pcic_io_start <= port && port <= sh_pcic_io_stop))
87 return *port2adr(port);
88 else
89 maybebadio(inw, port);
90 return 0;
91}
92
93unsigned int se_inl(unsigned long port)
94{
95 maybebadio(inl, port);
96 return 0;
97}
98
99void se_outb(unsigned char value, unsigned long port)
100{
101 if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)
102 *(__u8 *)(sh_pcic_io_wbase + port) = value;
103 else if (shifted_port(port))
104 *(port2adr(port)) = value << 8;
105 else
106 *(port2adr(port)) = value;
107}
108
109void se_outb_p(unsigned char value, unsigned long port)
110{
111 if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)
112 *(__u8 *)(sh_pcic_io_wbase + port) = value;
113 else if (shifted_port(port))
114 *(port2adr(port)) = value << 8;
115 else
116 *(port2adr(port)) = value;
117 delay();
118}
119
120void se_outw(unsigned short value, unsigned long port)
121{
122 if (port >= 0x2000 ||
123 (sh_pcic_io_start <= port && port <= sh_pcic_io_stop))
124 *port2adr(port) = value;
125 else
126 maybebadio(outw, port);
127}
128
129void se_outl(unsigned int value, unsigned long port)
130{
131 maybebadio(outl, port);
132}
133
134void se_insb(unsigned long port, void *addr, unsigned long count)
135{
136 volatile __u16 *p = port2adr(port);
137 __u8 *ap = addr;
138
139 if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop) {
140 volatile __u8 *bp = (__u8 *) (sh_pcic_io_wbase + 0x40000 + port);
141 while (count--)
142 *ap++ = *bp;
143 } else if (shifted_port(port)) {
144 while (count--)
145 *ap++ = *p >> 8;
146 } else {
147 while (count--)
148 *ap++ = *p;
149 }
150}
151
152void se_insw(unsigned long port, void *addr, unsigned long count)
153{
154 volatile __u16 *p = port2adr(port);
155 __u16 *ap = addr;
156 while (count--)
157 *ap++ = *p;
158}
159
160void se_insl(unsigned long port, void *addr, unsigned long count)
161{
162 maybebadio(insl, port);
163}
164
165void se_outsb(unsigned long port, const void *addr, unsigned long count)
166{
167 volatile __u16 *p = port2adr(port);
168 const __u8 *ap = addr;
169
170 if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop) {
171 volatile __u8 *bp = (__u8 *) (sh_pcic_io_wbase + port);
172 while (count--)
173 *bp = *ap++;
174 } else if (shifted_port(port)) {
175 while (count--)
176 *p = *ap++ << 8;
177 } else {
178 while (count--)
179 *p = *ap++;
180 }
181}
182
183void se_outsw(unsigned long port, const void *addr, unsigned long count)
184{
185 volatile __u16 *p = port2adr(port);
186 const __u16 *ap = addr;
187 while (count--)
188 *p = *ap++;
189}
190
191void se_outsl(unsigned long port, const void *addr, unsigned long count)
192{
193 maybebadio(outsw, port);
194}
195
196/* Map ISA bus address to the real address. Only for PCMCIA. */
197
198/* ISA page descriptor. */
199static __u32 sh_isa_memmap[256];
200
201static int
202sh_isa_mmap(__u32 start, __u32 length, __u32 offset)
203{
204 int idx;
205
206 if (start >= 0x100000 || (start & 0xfff) || (length != 0x1000))
207 return -1;
208
209 idx = start >> 12;
210 sh_isa_memmap[idx] = 0xb8000000 + (offset &~ 0xfff);
211#if 0
212 printk("sh_isa_mmap: start %x len %x offset %x (idx %x paddr %x)\n",
213 start, length, offset, idx, sh_isa_memmap[idx]);
214#endif
215 return 0;
216}
217
218unsigned long
219se_isa_port2addr(unsigned long offset)
220{
221 int idx;
222
223 idx = (offset >> 12) & 0xff;
224 offset &= 0xfff;
225 return sh_isa_memmap[idx] + offset;
226}
diff --git a/arch/sh/boards/se/770x/irq.c b/arch/sh/boards/se/770x/irq.c
new file mode 100644
index 00000000000..210897b315f
--- /dev/null
+++ b/arch/sh/boards/se/770x/irq.c
@@ -0,0 +1,80 @@
1/*
2 * linux/arch/sh/boards/se/770x/irq.c
3 *
4 * Copyright (C) 2000 Kazumoto Kojima
5 *
6 * Hitachi SolutionEngine Support.
7 *
8 */
9
10#include <linux/config.h>
11#include <linux/init.h>
12#include <linux/irq.h>
13#include <asm/irq.h>
14#include <asm/io.h>
15#include <asm/se/se.h>
16
17/*
18 * Initialize IRQ setting
19 */
20void __init init_se_IRQ(void)
21{
22 /*
23 * Super I/O (Just mimic PC):
24 * 1: keyboard
25 * 3: serial 0
26 * 4: serial 1
27 * 5: printer
28 * 6: floppy
29 * 8: rtc
30 * 12: mouse
31 * 14: ide0
32 */
33#if defined(CONFIG_CPU_SUBTYPE_SH7705)
34 /* Disable all interrupts */
35 ctrl_outw(0, BCR_ILCRA);
36 ctrl_outw(0, BCR_ILCRB);
37 ctrl_outw(0, BCR_ILCRC);
38 ctrl_outw(0, BCR_ILCRD);
39 ctrl_outw(0, BCR_ILCRE);
40 ctrl_outw(0, BCR_ILCRF);
41 ctrl_outw(0, BCR_ILCRG);
42 /* This is default value */
43 make_ipr_irq(0xf-0x2, BCR_ILCRA, 2, 0x2);
44 make_ipr_irq(0xf-0xa, BCR_ILCRA, 1, 0xa);
45 make_ipr_irq(0xf-0x5, BCR_ILCRB, 0, 0x5);
46 make_ipr_irq(0xf-0x8, BCR_ILCRC, 1, 0x8);
47 make_ipr_irq(0xf-0xc, BCR_ILCRC, 0, 0xc);
48 make_ipr_irq(0xf-0xe, BCR_ILCRD, 3, 0xe);
49 make_ipr_irq(0xf-0x3, BCR_ILCRD, 1, 0x3); /* LAN */
50 make_ipr_irq(0xf-0xd, BCR_ILCRE, 2, 0xd);
51 make_ipr_irq(0xf-0x9, BCR_ILCRE, 1, 0x9);
52 make_ipr_irq(0xf-0x1, BCR_ILCRE, 0, 0x1);
53 make_ipr_irq(0xf-0xf, BCR_ILCRF, 3, 0xf);
54 make_ipr_irq(0xf-0xb, BCR_ILCRF, 1, 0xb);
55 make_ipr_irq(0xf-0x7, BCR_ILCRG, 3, 0x7);
56 make_ipr_irq(0xf-0x6, BCR_ILCRG, 2, 0x6);
57 make_ipr_irq(0xf-0x4, BCR_ILCRG, 1, 0x4);
58#else
59 make_ipr_irq(14, BCR_ILCRA, 2, 0x0f-14);
60 make_ipr_irq(12, BCR_ILCRA, 1, 0x0f-12);
61 make_ipr_irq( 8, BCR_ILCRB, 1, 0x0f- 8);
62 make_ipr_irq( 6, BCR_ILCRC, 3, 0x0f- 6);
63 make_ipr_irq( 5, BCR_ILCRC, 2, 0x0f- 5);
64 make_ipr_irq( 4, BCR_ILCRC, 1, 0x0f- 4);
65 make_ipr_irq( 3, BCR_ILCRC, 0, 0x0f- 3);
66 make_ipr_irq( 1, BCR_ILCRD, 3, 0x0f- 1);
67
68 make_ipr_irq(10, BCR_ILCRD, 1, 0x0f-10); /* LAN */
69
70 make_ipr_irq( 0, BCR_ILCRE, 3, 0x0f- 0); /* PCIRQ3 */
71 make_ipr_irq(11, BCR_ILCRE, 2, 0x0f-11); /* PCIRQ2 */
72 make_ipr_irq( 9, BCR_ILCRE, 1, 0x0f- 9); /* PCIRQ1 */
73 make_ipr_irq( 7, BCR_ILCRE, 0, 0x0f- 7); /* PCIRQ0 */
74
75 /* #2, #13 are allocated for SLOT IRQ #1 and #2 (for now) */
76 /* NOTE: #2 and #13 are not used on PC */
77 make_ipr_irq(13, BCR_ILCRG, 1, 0x0f-13); /* SLOTIRQ2 */
78 make_ipr_irq( 2, BCR_ILCRG, 0, 0x0f- 2); /* SLOTIRQ1 */
79#endif
80}
diff --git a/arch/sh/boards/se/770x/led.c b/arch/sh/boards/se/770x/led.c
new file mode 100644
index 00000000000..5c64e8ab2cf
--- /dev/null
+++ b/arch/sh/boards/se/770x/led.c
@@ -0,0 +1,68 @@
1/*
2 * linux/arch/sh/kernel/led_se.c
3 *
4 * Copyright (C) 2000 Stuart Menefy <stuart.menefy@st.com>
5 *
6 * May be copied or modified under the terms of the GNU General Public
7 * License. See linux/COPYING for more information.
8 *
9 * This file contains Solution Engine specific LED code.
10 */
11
12#include <linux/config.h>
13#include <asm/se/se.h>
14
15static void mach_led(int position, int value)
16{
17 volatile unsigned short* p = (volatile unsigned short*)PA_LED;
18
19 if (value) {
20 *p |= (1<<8);
21 } else {
22 *p &= ~(1<<8);
23 }
24}
25
26#ifdef CONFIG_HEARTBEAT
27
28#include <linux/sched.h>
29
30/* Cycle the LED's in the clasic Knightrider/Sun pattern */
31void heartbeat_se(void)
32{
33 static unsigned int cnt = 0, period = 0;
34 volatile unsigned short* p = (volatile unsigned short*)PA_LED;
35 static unsigned bit = 0, up = 1;
36
37 cnt += 1;
38 if (cnt < period) {
39 return;
40 }
41
42 cnt = 0;
43
44 /* Go through the points (roughly!):
45 * f(0)=10, f(1)=16, f(2)=20, f(5)=35,f(inf)->110
46 */
47 period = 110 - ( (300<<FSHIFT)/
48 ((avenrun[0]/5) + (3<<FSHIFT)) );
49
50 if (up) {
51 if (bit == 7) {
52 bit--;
53 up=0;
54 } else {
55 bit ++;
56 }
57 } else {
58 if (bit == 0) {
59 bit++;
60 up=1;
61 } else {
62 bit--;
63 }
64 }
65 *p = 1<<(bit+8);
66
67}
68#endif /* CONFIG_HEARTBEAT */
diff --git a/arch/sh/boards/se/770x/mach.c b/arch/sh/boards/se/770x/mach.c
new file mode 100644
index 00000000000..f9b4c56cc47
--- /dev/null
+++ b/arch/sh/boards/se/770x/mach.c
@@ -0,0 +1,68 @@
1/*
2 * linux/arch/sh/kernel/mach_se.c
3 *
4 * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com)
5 *
6 * May be copied or modified under the terms of the GNU General Public
7 * License. See linux/COPYING for more information.
8 *
9 * Machine vector for the Hitachi SolutionEngine
10 */
11
12#include <linux/config.h>
13#include <linux/init.h>
14
15#include <asm/machvec.h>
16#include <asm/rtc.h>
17#include <asm/machvec_init.h>
18
19#include <asm/se/io.h>
20
21void heartbeat_se(void);
22void setup_se(void);
23void init_se_IRQ(void);
24
25/*
26 * The Machine Vector
27 */
28
29struct sh_machine_vector mv_se __initmv = {
30#if defined(CONFIG_CPU_SH4)
31 .mv_nr_irqs = 48,
32#elif defined(CONFIG_CPU_SUBTYPE_SH7708)
33 .mv_nr_irqs = 32,
34#elif defined(CONFIG_CPU_SUBTYPE_SH7709)
35 .mv_nr_irqs = 61,
36#elif defined(CONFIG_CPU_SUBTYPE_SH7705)
37 .mv_nr_irqs = 86,
38#endif
39
40 .mv_inb = se_inb,
41 .mv_inw = se_inw,
42 .mv_inl = se_inl,
43 .mv_outb = se_outb,
44 .mv_outw = se_outw,
45 .mv_outl = se_outl,
46
47 .mv_inb_p = se_inb_p,
48 .mv_inw_p = se_inw,
49 .mv_inl_p = se_inl,
50 .mv_outb_p = se_outb_p,
51 .mv_outw_p = se_outw,
52 .mv_outl_p = se_outl,
53
54 .mv_insb = se_insb,
55 .mv_insw = se_insw,
56 .mv_insl = se_insl,
57 .mv_outsb = se_outsb,
58 .mv_outsw = se_outsw,
59 .mv_outsl = se_outsl,
60
61 .mv_isa_port2addr = se_isa_port2addr,
62
63 .mv_init_irq = init_se_IRQ,
64#ifdef CONFIG_HEARTBEAT
65 .mv_heartbeat = heartbeat_se,
66#endif
67};
68ALIAS_MV(se)
diff --git a/arch/sh/boards/se/770x/setup.c b/arch/sh/boards/se/770x/setup.c
new file mode 100644
index 00000000000..2bed46fb607
--- /dev/null
+++ b/arch/sh/boards/se/770x/setup.c
@@ -0,0 +1,85 @@
1/* $Id: setup.c,v 1.1.2.4 2002/03/02 21:57:07 lethal Exp $
2 *
3 * linux/arch/sh/boards/se/770x/setup.c
4 *
5 * Copyright (C) 2000 Kazumoto Kojima
6 *
7 * Hitachi SolutionEngine Support.
8 *
9 */
10
11#include <linux/config.h>
12#include <linux/init.h>
13#include <linux/irq.h>
14
15#include <linux/hdreg.h>
16#include <linux/ide.h>
17#include <asm/io.h>
18#include <asm/se/se.h>
19#include <asm/se/smc37c93x.h>
20
21/*
22 * Configure the Super I/O chip
23 */
24static void __init smsc_config(int index, int data)
25{
26 outb_p(index, INDEX_PORT);
27 outb_p(data, DATA_PORT);
28}
29
30static void __init init_smsc(void)
31{
32 outb_p(CONFIG_ENTER, CONFIG_PORT);
33 outb_p(CONFIG_ENTER, CONFIG_PORT);
34
35 /* FDC */
36 smsc_config(CURRENT_LDN_INDEX, LDN_FDC);
37 smsc_config(ACTIVATE_INDEX, 0x01);
38 smsc_config(IRQ_SELECT_INDEX, 6); /* IRQ6 */
39
40 /* IDE1 */
41 smsc_config(CURRENT_LDN_INDEX, LDN_IDE1);
42 smsc_config(ACTIVATE_INDEX, 0x01);
43 smsc_config(IRQ_SELECT_INDEX, 14); /* IRQ14 */
44
45 /* AUXIO (GPIO): to use IDE1 */
46 smsc_config(CURRENT_LDN_INDEX, LDN_AUXIO);
47 smsc_config(GPIO46_INDEX, 0x00); /* nIOROP */
48 smsc_config(GPIO47_INDEX, 0x00); /* nIOWOP */
49
50 /* COM1 */
51 smsc_config(CURRENT_LDN_INDEX, LDN_COM1);
52 smsc_config(ACTIVATE_INDEX, 0x01);
53 smsc_config(IO_BASE_HI_INDEX, 0x03);
54 smsc_config(IO_BASE_LO_INDEX, 0xf8);
55 smsc_config(IRQ_SELECT_INDEX, 4); /* IRQ4 */
56
57 /* COM2 */
58 smsc_config(CURRENT_LDN_INDEX, LDN_COM2);
59 smsc_config(ACTIVATE_INDEX, 0x01);
60 smsc_config(IO_BASE_HI_INDEX, 0x02);
61 smsc_config(IO_BASE_LO_INDEX, 0xf8);
62 smsc_config(IRQ_SELECT_INDEX, 3); /* IRQ3 */
63
64 /* RTC */
65 smsc_config(CURRENT_LDN_INDEX, LDN_RTC);
66 smsc_config(ACTIVATE_INDEX, 0x01);
67 smsc_config(IRQ_SELECT_INDEX, 8); /* IRQ8 */
68
69 /* XXX: PARPORT, KBD, and MOUSE will come here... */
70 outb_p(CONFIG_EXIT, CONFIG_PORT);
71}
72
73const char *get_system_type(void)
74{
75 return "SolutionEngine";
76}
77
78/*
79 * Initialize the board
80 */
81void __init platform_setup(void)
82{
83 init_smsc();
84 /* XXX: RTC setting comes here */
85}
diff --git a/arch/sh/boards/se/7751/Makefile b/arch/sh/boards/se/7751/Makefile
new file mode 100644
index 00000000000..ce7ca247f84
--- /dev/null
+++ b/arch/sh/boards/se/7751/Makefile
@@ -0,0 +1,8 @@
1#
2# Makefile for the 7751 SolutionEngine specific parts of the kernel
3#
4
5obj-y := mach.o setup.o io.o irq.o led.o
6
7obj-$(CONFIG_PCI) += pci.o
8
diff --git a/arch/sh/boards/se/7751/io.c b/arch/sh/boards/se/7751/io.c
new file mode 100644
index 00000000000..99041b26926
--- /dev/null
+++ b/arch/sh/boards/se/7751/io.c
@@ -0,0 +1,244 @@
1/*
2 * linux/arch/sh/kernel/io_7751se.c
3 *
4 * Copyright (C) 2001 Ian da Silva, Jeremy Siegel
5 * Based largely on io_se.c.
6 *
7 * I/O routine for Hitachi 7751 SolutionEngine.
8 *
9 * Initial version only to support LAN access; some
10 * placeholder code from io_se.c left in with the
11 * expectation of later SuperIO and PCMCIA access.
12 */
13
14#include <linux/kernel.h>
15#include <linux/types.h>
16#include <asm/io.h>
17#include <asm/se7751/se7751.h>
18#include <asm/addrspace.h>
19
20#include <linux/pci.h>
21#include "../../../drivers/pci/pci-sh7751.h"
22
23#if 0
24/******************************************************************
25 * Variables from io_se.c, related to PCMCIA (not PCI); we're not
26 * compiling them in, and have removed references from functions
27 * which follow. [Many checked for IO ports in the range bounded
28 * by sh_pcic_io_start/stop, and used sh_pcic_io_wbase as offset.
29 * As start/stop are uninitialized, only port 0x0 would match?]
30 * When used, remember to adjust names to avoid clash with io_se?
31 *****************************************************************/
32/* SH pcmcia io window base, start and end. */
33int sh_pcic_io_wbase = 0xb8400000;
34int sh_pcic_io_start;
35int sh_pcic_io_stop;
36int sh_pcic_io_type;
37int sh_pcic_io_dummy;
38/*************************************************************/
39#endif
40
41/*
42 * The 7751 Solution Engine uses the built-in PCI controller (PCIC)
43 * of the 7751 processor, and has a SuperIO accessible via the PCI.
44 * The board also includes a PCMCIA controller on its memory bus,
45 * like the other Solution Engine boards.
46 */
47
48#define PCIIOBR (volatile long *)PCI_REG(SH7751_PCIIOBR)
49#define PCIMBR (volatile long *)PCI_REG(SH7751_PCIMBR)
50#define PCI_IO_AREA SH7751_PCI_IO_BASE
51#define PCI_MEM_AREA SH7751_PCI_CONFIG_BASE
52
53#define PCI_IOMAP(adr) (PCI_IO_AREA + (adr & ~SH7751_PCIIOBR_MASK))
54
55#define maybebadio(name,port) \
56 printk("bad PC-like io %s for port 0x%lx at 0x%08x\n", \
57 #name, (port), (__u32) __builtin_return_address(0))
58
59static inline void delay(void)
60{
61 ctrl_inw(0xa0000000);
62}
63
64static inline volatile __u16 *
65port2adr(unsigned int port)
66{
67 if (port >= 0x2000)
68 return (volatile __u16 *) (PA_MRSHPC + (port - 0x2000));
69#if 0
70 else
71 return (volatile __u16 *) (PA_SUPERIO + (port << 1));
72#endif
73 maybebadio(name,(unsigned long)port);
74 return (volatile __u16*)port;
75}
76
77#if 0
78/* The 7751 Solution Engine seems to have everything hooked */
79/* up pretty normally (nothing on high-bytes only...) so this */
80/* shouldn't be needed */
81static inline int
82shifted_port(unsigned long port)
83{
84 /* For IDE registers, value is not shifted */
85 if ((0x1f0 <= port && port < 0x1f8) || port == 0x3f6)
86 return 0;
87 else
88 return 1;
89}
90#endif
91
92/* In case someone configures the kernel w/o PCI support: in that */
93/* scenario, don't ever bother to check for PCI-window addresses */
94
95/* NOTE: WINDOW CHECK MAY BE A BIT OFF, HIGH PCIBIOS_MIN_IO WRAPS? */
96#if defined(CONFIG_PCI)
97#define CHECK_SH7751_PCIIO(port) \
98 ((port >= PCIBIOS_MIN_IO) && (port < (PCIBIOS_MIN_IO + SH7751_PCI_IO_SIZE)))
99#else
100#define CHECK_SH7751_PCIIO(port) (0)
101#endif
102
103/*
104 * General outline: remap really low stuff [eventually] to SuperIO,
105 * stuff in PCI IO space (at or above window at pci.h:PCIBIOS_MIN_IO)
106 * is mapped through the PCI IO window. Stuff with high bits (PXSEG)
107 * should be way beyond the window, and is used w/o translation for
108 * compatibility.
109 */
110unsigned char sh7751se_inb(unsigned long port)
111{
112 if (PXSEG(port))
113 return *(volatile unsigned char *)port;
114 else if (CHECK_SH7751_PCIIO(port))
115 return *(volatile unsigned char *)PCI_IOMAP(port);
116 else
117 return (*port2adr(port))&0xff;
118}
119
120unsigned char sh7751se_inb_p(unsigned long port)
121{
122 unsigned char v;
123
124 if (PXSEG(port))
125 v = *(volatile unsigned char *)port;
126 else if (CHECK_SH7751_PCIIO(port))
127 v = *(volatile unsigned char *)PCI_IOMAP(port);
128 else
129 v = (*port2adr(port))&0xff;
130 delay();
131 return v;
132}
133
134unsigned short sh7751se_inw(unsigned long port)
135{
136 if (PXSEG(port))
137 return *(volatile unsigned short *)port;
138 else if (CHECK_SH7751_PCIIO(port))
139 return *(volatile unsigned short *)PCI_IOMAP(port);
140 else if (port >= 0x2000)
141 return *port2adr(port);
142 else
143 maybebadio(inw, port);
144 return 0;
145}
146
147unsigned int sh7751se_inl(unsigned long port)
148{
149 if (PXSEG(port))
150 return *(volatile unsigned long *)port;
151 else if (CHECK_SH7751_PCIIO(port))
152 return *(volatile unsigned int *)PCI_IOMAP(port);
153 else if (port >= 0x2000)
154 return *port2adr(port);
155 else
156 maybebadio(inl, port);
157 return 0;
158}
159
160void sh7751se_outb(unsigned char value, unsigned long port)
161{
162
163 if (PXSEG(port))
164 *(volatile unsigned char *)port = value;
165 else if (CHECK_SH7751_PCIIO(port))
166 *((unsigned char*)PCI_IOMAP(port)) = value;
167 else
168 *(port2adr(port)) = value;
169}
170
171void sh7751se_outb_p(unsigned char value, unsigned long port)
172{
173 if (PXSEG(port))
174 *(volatile unsigned char *)port = value;
175 else if (CHECK_SH7751_PCIIO(port))
176 *((unsigned char*)PCI_IOMAP(port)) = value;
177 else
178 *(port2adr(port)) = value;
179 delay();
180}
181
182void sh7751se_outw(unsigned short value, unsigned long port)
183{
184 if (PXSEG(port))
185 *(volatile unsigned short *)port = value;
186 else if (CHECK_SH7751_PCIIO(port))
187 *((unsigned short *)PCI_IOMAP(port)) = value;
188 else if (port >= 0x2000)
189 *port2adr(port) = value;
190 else
191 maybebadio(outw, port);
192}
193
194void sh7751se_outl(unsigned int value, unsigned long port)
195{
196 if (PXSEG(port))
197 *(volatile unsigned long *)port = value;
198 else if (CHECK_SH7751_PCIIO(port))
199 *((unsigned long*)PCI_IOMAP(port)) = value;
200 else
201 maybebadio(outl, port);
202}
203
204void sh7751se_insl(unsigned long port, void *addr, unsigned long count)
205{
206 maybebadio(insl, port);
207}
208
209void sh7751se_outsl(unsigned long port, const void *addr, unsigned long count)
210{
211 maybebadio(outsw, port);
212}
213
214/* Map ISA bus address to the real address. Only for PCMCIA. */
215
216/* ISA page descriptor. */
217static __u32 sh_isa_memmap[256];
218
219#if 0
220static int
221sh_isa_mmap(__u32 start, __u32 length, __u32 offset)
222{
223 int idx;
224
225 if (start >= 0x100000 || (start & 0xfff) || (length != 0x1000))
226 return -1;
227
228 idx = start >> 12;
229 sh_isa_memmap[idx] = 0xb8000000 + (offset &~ 0xfff);
230 printk("sh_isa_mmap: start %x len %x offset %x (idx %x paddr %x)\n",
231 start, length, offset, idx, sh_isa_memmap[idx]);
232 return 0;
233}
234#endif
235
236unsigned long
237sh7751se_isa_port2addr(unsigned long offset)
238{
239 int idx;
240
241 idx = (offset >> 12) & 0xff;
242 offset &= 0xfff;
243 return sh_isa_memmap[idx] + offset;
244}
diff --git a/arch/sh/boards/se/7751/irq.c b/arch/sh/boards/se/7751/irq.c
new file mode 100644
index 00000000000..ad71f3e66c1
--- /dev/null
+++ b/arch/sh/boards/se/7751/irq.c
@@ -0,0 +1,67 @@
1/*
2 * linux/arch/sh/boards/se/7751/irq.c
3 *
4 * Copyright (C) 2000 Kazumoto Kojima
5 *
6 * Hitachi SolutionEngine Support.
7 *
8 * Modified for 7751 Solution Engine by
9 * Ian da Silva and Jeremy Siegel, 2001.
10 */
11
12#include <linux/config.h>
13#include <linux/init.h>
14#include <linux/irq.h>
15#include <asm/irq.h>
16#include <asm/se7751/se7751.h>
17
18/*
19 * Initialize IRQ setting
20 */
21void __init init_7751se_IRQ(void)
22{
23
24 /* Leave old Solution Engine code in for reference. */
25#if defined(CONFIG_SH_SOLUTION_ENGINE)
26 /*
27 * Super I/O (Just mimic PC):
28 * 1: keyboard
29 * 3: serial 0
30 * 4: serial 1
31 * 5: printer
32 * 6: floppy
33 * 8: rtc
34 * 12: mouse
35 * 14: ide0
36 */
37 make_ipr_irq(14, BCR_ILCRA, 2, 0x0f-14);
38 make_ipr_irq(12, BCR_ILCRA, 1, 0x0f-12);
39 make_ipr_irq( 8, BCR_ILCRB, 1, 0x0f- 8);
40 make_ipr_irq( 6, BCR_ILCRC, 3, 0x0f- 6);
41 make_ipr_irq( 5, BCR_ILCRC, 2, 0x0f- 5);
42 make_ipr_irq( 4, BCR_ILCRC, 1, 0x0f- 4);
43 make_ipr_irq( 3, BCR_ILCRC, 0, 0x0f- 3);
44 make_ipr_irq( 1, BCR_ILCRD, 3, 0x0f- 1);
45
46 make_ipr_irq(10, BCR_ILCRD, 1, 0x0f-10); /* LAN */
47
48 make_ipr_irq( 0, BCR_ILCRE, 3, 0x0f- 0); /* PCIRQ3 */
49 make_ipr_irq(11, BCR_ILCRE, 2, 0x0f-11); /* PCIRQ2 */
50 make_ipr_irq( 9, BCR_ILCRE, 1, 0x0f- 9); /* PCIRQ1 */
51 make_ipr_irq( 7, BCR_ILCRE, 0, 0x0f- 7); /* PCIRQ0 */
52
53 /* #2, #13 are allocated for SLOT IRQ #1 and #2 (for now) */
54 /* NOTE: #2 and #13 are not used on PC */
55 make_ipr_irq(13, BCR_ILCRG, 1, 0x0f-13); /* SLOTIRQ2 */
56 make_ipr_irq( 2, BCR_ILCRG, 0, 0x0f- 2); /* SLOTIRQ1 */
57
58#elif defined(CONFIG_SH_7751_SOLUTION_ENGINE)
59
60 make_ipr_irq(13, BCR_ILCRD, 3, 2);
61
62 /* Add additional calls to make_ipr_irq() as drivers are added
63 * and tested.
64 */
65#endif
66
67}
diff --git a/arch/sh/boards/se/7751/led.c b/arch/sh/boards/se/7751/led.c
new file mode 100644
index 00000000000..0c788230cf8
--- /dev/null
+++ b/arch/sh/boards/se/7751/led.c
@@ -0,0 +1,68 @@
1/*
2 * linux/arch/sh/kernel/led_se.c
3 *
4 * Copyright (C) 2000 Stuart Menefy <stuart.menefy@st.com>
5 *
6 * May be copied or modified under the terms of the GNU General Public
7 * License. See linux/COPYING for more information.
8 *
9 * This file contains Solution Engine specific LED code.
10 */
11
12#include <linux/config.h>
13#include <asm/se7751/se7751.h>
14
15static void mach_led(int position, int value)
16{
17 volatile unsigned short* p = (volatile unsigned short*)PA_LED;
18
19 if (value) {
20 *p |= (1<<8);
21 } else {
22 *p &= ~(1<<8);
23 }
24}
25
26#ifdef CONFIG_HEARTBEAT
27
28#include <linux/sched.h>
29
30/* Cycle the LED's in the clasic Knightrider/Sun pattern */
31void heartbeat_7751se(void)
32{
33 static unsigned int cnt = 0, period = 0;
34 volatile unsigned short* p = (volatile unsigned short*)PA_LED;
35 static unsigned bit = 0, up = 1;
36
37 cnt += 1;
38 if (cnt < period) {
39 return;
40 }
41
42 cnt = 0;
43
44 /* Go through the points (roughly!):
45 * f(0)=10, f(1)=16, f(2)=20, f(5)=35,f(inf)->110
46 */
47 period = 110 - ( (300<<FSHIFT)/
48 ((avenrun[0]/5) + (3<<FSHIFT)) );
49
50 if (up) {
51 if (bit == 7) {
52 bit--;
53 up=0;
54 } else {
55 bit ++;
56 }
57 } else {
58 if (bit == 0) {
59 bit++;
60 up=1;
61 } else {
62 bit--;
63 }
64 }
65 *p = 1<<(bit+8);
66
67}
68#endif /* CONFIG_HEARTBEAT */
diff --git a/arch/sh/boards/se/7751/mach.c b/arch/sh/boards/se/7751/mach.c
new file mode 100644
index 00000000000..16d386b7e3b
--- /dev/null
+++ b/arch/sh/boards/se/7751/mach.c
@@ -0,0 +1,55 @@
1/*
2 * linux/arch/sh/kernel/mach_7751se.c
3 *
4 * Minor tweak of mach_se.c file to reference 7751se-specific items.
5 *
6 * May be copied or modified under the terms of the GNU General Public
7 * License. See linux/COPYING for more information.
8 *
9 * Machine vector for the Hitachi 7751 SolutionEngine
10 */
11
12#include <linux/config.h>
13#include <linux/init.h>
14
15#include <asm/machvec.h>
16#include <asm/rtc.h>
17#include <asm/machvec_init.h>
18
19#include <asm/se7751/io.h>
20
21void heartbeat_7751se(void);
22void init_7751se_IRQ(void);
23
24/*
25 * The Machine Vector
26 */
27
28struct sh_machine_vector mv_7751se __initmv = {
29 .mv_nr_irqs = 72,
30
31 .mv_inb = sh7751se_inb,
32 .mv_inw = sh7751se_inw,
33 .mv_inl = sh7751se_inl,
34 .mv_outb = sh7751se_outb,
35 .mv_outw = sh7751se_outw,
36 .mv_outl = sh7751se_outl,
37
38 .mv_inb_p = sh7751se_inb_p,
39 .mv_inw_p = sh7751se_inw,
40 .mv_inl_p = sh7751se_inl,
41 .mv_outb_p = sh7751se_outb_p,
42 .mv_outw_p = sh7751se_outw,
43 .mv_outl_p = sh7751se_outl,
44
45 .mv_insl = sh7751se_insl,
46 .mv_outsl = sh7751se_outsl,
47
48 .mv_isa_port2addr = sh7751se_isa_port2addr,
49
50 .mv_init_irq = init_7751se_IRQ,
51#ifdef CONFIG_HEARTBEAT
52 .mv_heartbeat = heartbeat_7751se,
53#endif
54};
55ALIAS_MV(7751se)
diff --git a/arch/sh/boards/se/7751/pci.c b/arch/sh/boards/se/7751/pci.c
new file mode 100644
index 00000000000..1f273efd2cf
--- /dev/null
+++ b/arch/sh/boards/se/7751/pci.c
@@ -0,0 +1,148 @@
1/*
2 * linux/arch/sh/kernel/pci-7751se.c
3 *
4 * Author: Ian DaSilva (idasilva@mvista.com)
5 *
6 * Highly leveraged from pci-bigsur.c, written by Dustin McIntire.
7 *
8 * May be copied or modified under the terms of the GNU General Public
9 * License. See linux/COPYING for more information.
10 *
11 * PCI initialization for the Hitachi SH7751 Solution Engine board (MS7751SE01)
12 */
13
14#include <linux/config.h>
15#include <linux/kernel.h>
16#include <linux/types.h>
17#include <linux/init.h>
18#include <linux/delay.h>
19#include <linux/pci.h>
20
21#include <asm/io.h>
22#include "../../../drivers/pci/pci-sh7751.h"
23
24#define PCIMCR_MRSET_OFF 0xBFFFFFFF
25#define PCIMCR_RFSH_OFF 0xFFFFFFFB
26
27/*
28 * Only long word accesses of the PCIC's internal local registers and the
29 * configuration registers from the CPU is supported.
30 */
31#define PCIC_WRITE(x,v) writel((v), PCI_REG(x))
32#define PCIC_READ(x) readl(PCI_REG(x))
33
34/*
35 * Description: This function sets up and initializes the pcic, sets
36 * up the BARS, maps the DRAM into the address space etc, etc.
37 */
38int __init pcibios_init_platform(void)
39{
40 unsigned long bcr1, wcr1, wcr2, wcr3, mcr;
41 unsigned short bcr2;
42
43 /*
44 * Initialize the slave bus controller on the pcic. The values used
45 * here should not be hardcoded, but they should be taken from the bsc
46 * on the processor, to make this function as generic as possible.
47 * (i.e. Another sbc may usr different SDRAM timing settings -- in order
48 * for the pcic to work, its settings need to be exactly the same.)
49 */
50 bcr1 = (*(volatile unsigned long*)(SH7751_BCR1));
51 bcr2 = (*(volatile unsigned short*)(SH7751_BCR2));
52 wcr1 = (*(volatile unsigned long*)(SH7751_WCR1));
53 wcr2 = (*(volatile unsigned long*)(SH7751_WCR2));
54 wcr3 = (*(volatile unsigned long*)(SH7751_WCR3));
55 mcr = (*(volatile unsigned long*)(SH7751_MCR));
56
57 bcr1 = bcr1 | 0x00080000; /* Enable Bit 19, BREQEN */
58 (*(volatile unsigned long*)(SH7751_BCR1)) = bcr1;
59
60 bcr1 = bcr1 | 0x40080000; /* Enable Bit 19 BREQEN, set PCIC to slave */
61 PCIC_WRITE(SH7751_PCIBCR1, bcr1); /* PCIC BCR1 */
62 PCIC_WRITE(SH7751_PCIBCR2, bcr2); /* PCIC BCR2 */
63 PCIC_WRITE(SH7751_PCIWCR1, wcr1); /* PCIC WCR1 */
64 PCIC_WRITE(SH7751_PCIWCR2, wcr2); /* PCIC WCR2 */
65 PCIC_WRITE(SH7751_PCIWCR3, wcr3); /* PCIC WCR3 */
66 mcr = (mcr & PCIMCR_MRSET_OFF) & PCIMCR_RFSH_OFF;
67 PCIC_WRITE(SH7751_PCIMCR, mcr); /* PCIC MCR */
68
69
70 /* Enable all interrupts, so we know what to fix */
71 PCIC_WRITE(SH7751_PCIINTM, 0x0000c3ff);
72 PCIC_WRITE(SH7751_PCIAINTM, 0x0000380f);
73
74 /* Set up standard PCI config registers */
75 PCIC_WRITE(SH7751_PCICONF1, 0xF39000C7); /* Bus Master, Mem & I/O access */
76 PCIC_WRITE(SH7751_PCICONF2, 0x00000000); /* PCI Class code & Revision ID */
77 PCIC_WRITE(SH7751_PCICONF4, 0xab000001); /* PCI I/O address (local regs) */
78 PCIC_WRITE(SH7751_PCICONF5, 0x0c000000); /* PCI MEM address (local RAM) */
79 PCIC_WRITE(SH7751_PCICONF6, 0xd0000000); /* PCI MEM address (unused) */
80 PCIC_WRITE(SH7751_PCICONF11, 0x35051054); /* PCI Subsystem ID & Vendor ID */
81 PCIC_WRITE(SH7751_PCILSR0, 0x03f00000); /* MEM (full 64M exposed) */
82 PCIC_WRITE(SH7751_PCILSR1, 0x00000000); /* MEM (unused) */
83 PCIC_WRITE(SH7751_PCILAR0, 0x0c000000); /* MEM (direct map from PCI) */
84 PCIC_WRITE(SH7751_PCILAR1, 0x00000000); /* MEM (unused) */
85
86 /* Now turn it on... */
87 PCIC_WRITE(SH7751_PCICR, 0xa5000001);
88
89 /*
90 * Set PCIMBR and PCIIOBR here, assuming a single window
91 * (16M MEM, 256K IO) is enough. If a larger space is
92 * needed, the readx/writex and inx/outx functions will
93 * have to do more (e.g. setting registers for each call).
94 */
95
96 /*
97 * Set the MBR so PCI address is one-to-one with window,
98 * meaning all calls go straight through... use BUG_ON to
99 * catch erroneous assumption.
100 */
101 BUG_ON(PCIBIOS_MIN_MEM != SH7751_PCI_MEMORY_BASE);
102
103 PCIC_WRITE(SH7751_PCIMBR, PCIBIOS_MIN_MEM);
104
105 /* Set IOBR for window containing area specified in pci.h */
106 PCIC_WRITE(SH7751_PCIIOBR, (PCIBIOS_MIN_IO & SH7751_PCIIOBR_MASK));
107
108 /* All done, may as well say so... */
109 printk("SH7751 PCI: Finished initialization of the PCI controller\n");
110
111 return 1;
112}
113
114int __init pcibios_map_platform_irq(u8 slot, u8 pin)
115{
116 switch (slot) {
117 case 0: return 13;
118 case 1: return 13; /* AMD Ethernet controller */
119 case 2: return -1;
120 case 3: return -1;
121 case 4: return -1;
122 default:
123 printk("PCI: Bad IRQ mapping request for slot %d\n", slot);
124 return -1;
125 }
126}
127
128static struct resource sh7751_io_resource = {
129 .name = "SH7751 IO",
130 .start = SH7751_PCI_IO_BASE,
131 .end = SH7751_PCI_IO_BASE + SH7751_PCI_IO_SIZE - 1,
132 .flags = IORESOURCE_IO
133};
134
135static struct resource sh7751_mem_resource = {
136 .name = "SH7751 mem",
137 .start = SH7751_PCI_MEMORY_BASE,
138 .end = SH7751_PCI_MEMORY_BASE + SH7751_PCI_MEM_SIZE - 1,
139 .flags = IORESOURCE_MEM
140};
141
142extern struct pci_ops sh7751_pci_ops;
143
144struct pci_channel board_pci_channels[] = {
145 { &sh7751_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0xff },
146 { NULL, NULL, NULL, 0, 0 },
147};
148
diff --git a/arch/sh/boards/se/7751/setup.c b/arch/sh/boards/se/7751/setup.c
new file mode 100644
index 00000000000..9d111bb884f
--- /dev/null
+++ b/arch/sh/boards/se/7751/setup.c
@@ -0,0 +1,228 @@
1/*
2 * linux/arch/sh/kernel/setup_7751se.c
3 *
4 * Copyright (C) 2000 Kazumoto Kojima
5 *
6 * Hitachi SolutionEngine Support.
7 *
8 * Modified for 7751 Solution Engine by
9 * Ian da Silva and Jeremy Siegel, 2001.
10 */
11
12#include <linux/config.h>
13#include <linux/init.h>
14#include <linux/irq.h>
15
16#include <linux/hdreg.h>
17#include <linux/ide.h>
18#include <asm/io.h>
19#include <asm/se7751/se7751.h>
20
21#ifdef CONFIG_SH_KGDB
22#include <asm/kgdb.h>
23#endif
24
25/*
26 * Configure the Super I/O chip
27 */
28#if 0
29/* Leftover code from regular Solution Engine, for reference. */
30/* The SH7751 Solution Engine has a different SuperIO. */
31static void __init smsc_config(int index, int data)
32{
33 outb_p(index, INDEX_PORT);
34 outb_p(data, DATA_PORT);
35}
36
37static void __init init_smsc(void)
38{
39 outb_p(CONFIG_ENTER, CONFIG_PORT);
40 outb_p(CONFIG_ENTER, CONFIG_PORT);
41
42 /* FDC */
43 smsc_config(CURRENT_LDN_INDEX, LDN_FDC);
44 smsc_config(ACTIVATE_INDEX, 0x01);
45 smsc_config(IRQ_SELECT_INDEX, 6); /* IRQ6 */
46
47 /* IDE1 */
48 smsc_config(CURRENT_LDN_INDEX, LDN_IDE1);
49 smsc_config(ACTIVATE_INDEX, 0x01);
50 smsc_config(IRQ_SELECT_INDEX, 14); /* IRQ14 */
51
52 /* AUXIO (GPIO): to use IDE1 */
53 smsc_config(CURRENT_LDN_INDEX, LDN_AUXIO);
54 smsc_config(GPIO46_INDEX, 0x00); /* nIOROP */
55 smsc_config(GPIO47_INDEX, 0x00); /* nIOWOP */
56
57 /* COM1 */
58 smsc_config(CURRENT_LDN_INDEX, LDN_COM1);
59 smsc_config(ACTIVATE_INDEX, 0x01);
60 smsc_config(IO_BASE_HI_INDEX, 0x03);
61 smsc_config(IO_BASE_LO_INDEX, 0xf8);
62 smsc_config(IRQ_SELECT_INDEX, 4); /* IRQ4 */
63
64 /* COM2 */
65 smsc_config(CURRENT_LDN_INDEX, LDN_COM2);
66 smsc_config(ACTIVATE_INDEX, 0x01);
67 smsc_config(IO_BASE_HI_INDEX, 0x02);
68 smsc_config(IO_BASE_LO_INDEX, 0xf8);
69 smsc_config(IRQ_SELECT_INDEX, 3); /* IRQ3 */
70
71 /* RTC */
72 smsc_config(CURRENT_LDN_INDEX, LDN_RTC);
73 smsc_config(ACTIVATE_INDEX, 0x01);
74 smsc_config(IRQ_SELECT_INDEX, 8); /* IRQ8 */
75
76 /* XXX: PARPORT, KBD, and MOUSE will come here... */
77 outb_p(CONFIG_EXIT, CONFIG_PORT);
78}
79#endif
80
81const char *get_system_type(void)
82{
83 return "7751 SolutionEngine";
84}
85
86#ifdef CONFIG_SH_KGDB
87static int kgdb_uart_setup(void);
88static struct kgdb_sermap kgdb_uart_sermap =
89{ "ttyS", 0, kgdb_uart_setup, NULL };
90#endif
91
92/*
93 * Initialize the board
94 */
95void __init platform_setup(void)
96{
97 /* Call init_smsc() replacement to set up SuperIO. */
98 /* XXX: RTC setting comes here */
99#ifdef CONFIG_SH_KGDB
100 kgdb_register_sermap(&kgdb_uart_sermap);
101#endif
102}
103
104/*********************************************************************
105 * Currently a hack (e.g. does not interact well w/serial.c, lots of *
106 * hardcoded stuff) but may be useful if SCI/F needs debugging. *
107 * Mostly copied from x86 code (see files asm-i386/kgdb_local.h and *
108 * arch/i386/lib/kgdb_serial.c). *
109 *********************************************************************/
110
111#ifdef CONFIG_SH_KGDB
112#include <linux/types.h>
113#include <linux/serial.h>
114#include <linux/serialP.h>
115#include <linux/serial_reg.h>
116
117#define COM1_PORT 0x3f8 /* Base I/O address */
118#define COM1_IRQ 4 /* IRQ not used yet */
119#define COM2_PORT 0x2f8 /* Base I/O address */
120#define COM2_IRQ 3 /* IRQ not used yet */
121
122#define SB_CLOCK 1843200 /* Serial baud clock */
123#define SB_BASE (SB_CLOCK/16)
124#define SB_MCR UART_MCR_OUT2 | UART_MCR_DTR | UART_MCR_RTS
125
126struct uart_port {
127 int base;
128};
129#define UART_NPORTS 2
130struct uart_port uart_ports[] = {
131 { COM1_PORT },
132 { COM2_PORT },
133};
134struct uart_port *kgdb_uart_port;
135
136#define UART_IN(reg) inb_p(kgdb_uart_port->base + reg)
137#define UART_OUT(reg,v) outb_p((v), kgdb_uart_port->base + reg)
138
139/* Basic read/write functions for the UART */
140#define UART_LSR_RXCERR (UART_LSR_BI | UART_LSR_FE | UART_LSR_PE)
141static int kgdb_uart_getchar(void)
142{
143 int lsr;
144 int c = -1;
145
146 while (c == -1) {
147 lsr = UART_IN(UART_LSR);
148 if (lsr & UART_LSR_DR)
149 c = UART_IN(UART_RX);
150 if ((lsr & UART_LSR_RXCERR))
151 c = -1;
152 }
153 return c;
154}
155
156static void kgdb_uart_putchar(int c)
157{
158 while ((UART_IN(UART_LSR) & UART_LSR_THRE) == 0)
159 ;
160 UART_OUT(UART_TX, c);
161}
162
163/*
164 * Initialize UART to configured/requested values.
165 * (But we don't interrupts yet, or interact w/serial.c)
166 */
167static int kgdb_uart_setup(void)
168{
169 int port;
170 int lcr = 0;
171 int bdiv = 0;
172
173 if (kgdb_portnum >= UART_NPORTS) {
174 KGDB_PRINTK("uart port %d invalid.\n", kgdb_portnum);
175 return -1;
176 }
177
178 kgdb_uart_port = &uart_ports[kgdb_portnum];
179
180 /* Init sequence from gdb_hook_interrupt */
181 UART_IN(UART_RX);
182 UART_OUT(UART_IER, 0);
183
184 UART_IN(UART_RX); /* Serial driver comments say */
185 UART_IN(UART_IIR); /* this clears interrupt regs */
186 UART_IN(UART_MSR);
187
188 /* Figure basic LCR values */
189 switch (kgdb_bits) {
190 case '7':
191 lcr |= UART_LCR_WLEN7;
192 break;
193 default: case '8':
194 lcr |= UART_LCR_WLEN8;
195 break;
196 }
197 switch (kgdb_parity) {
198 case 'O':
199 lcr |= UART_LCR_PARITY;
200 break;
201 case 'E':
202 lcr |= (UART_LCR_PARITY | UART_LCR_EPAR);
203 break;
204 default: break;
205 }
206
207 /* Figure the baud rate divisor */
208 bdiv = (SB_BASE/kgdb_baud);
209
210 /* Set the baud rate and LCR values */
211 UART_OUT(UART_LCR, (lcr | UART_LCR_DLAB));
212 UART_OUT(UART_DLL, (bdiv & 0xff));
213 UART_OUT(UART_DLM, ((bdiv >> 8) & 0xff));
214 UART_OUT(UART_LCR, lcr);
215
216 /* Set the MCR */
217 UART_OUT(UART_MCR, SB_MCR);
218
219 /* Turn off FIFOs for now */
220 UART_OUT(UART_FCR, 0);
221
222 /* Setup complete: initialize function pointers */
223 kgdb_getchar = kgdb_uart_getchar;
224 kgdb_putchar = kgdb_uart_putchar;
225
226 return 0;
227}
228#endif /* CONFIG_SH_KGDB */
diff --git a/arch/sh/boards/sh03/Makefile b/arch/sh/boards/sh03/Makefile
new file mode 100644
index 00000000000..321be50e36a
--- /dev/null
+++ b/arch/sh/boards/sh03/Makefile
@@ -0,0 +1,6 @@
1#
2# Makefile for the Interface (CTP/PCI-SH03) specific parts of the kernel
3#
4
5obj-y := setup.o rtc.o
6obj-$(CONFIG_HEARTBEAT) += led.o
diff --git a/arch/sh/boards/sh03/led.c b/arch/sh/boards/sh03/led.c
new file mode 100644
index 00000000000..c851b0bec80
--- /dev/null
+++ b/arch/sh/boards/sh03/led.c
@@ -0,0 +1,49 @@
1/*
2 * linux/arch/sh/boards/sh03/led.c
3 *
4 * Copyright (C) 2004 Saito.K Interface Corporation.
5 *
6 * This file contains Interface CTP/PCI-SH03 specific LED code.
7 */
8
9#include <linux/config.h>
10#include <linux/sched.h>
11
12/* Cycle the LED's in the clasic Knightrider/Sun pattern */
13void heartbeat_sh03(void)
14{
15 static unsigned int cnt = 0, period = 0;
16 volatile unsigned char* p = (volatile unsigned char*)0xa0800000;
17 static unsigned bit = 0, up = 1;
18
19 cnt += 1;
20 if (cnt < period) {
21 return;
22 }
23
24 cnt = 0;
25
26 /* Go through the points (roughly!):
27 * f(0)=10, f(1)=16, f(2)=20, f(5)=35,f(inf)->110
28 */
29 period = 110 - ( (300<<FSHIFT)/
30 ((avenrun[0]/5) + (3<<FSHIFT)) );
31
32 if (up) {
33 if (bit == 7) {
34 bit--;
35 up=0;
36 } else {
37 bit ++;
38 }
39 } else {
40 if (bit == 0) {
41 bit++;
42 up=1;
43 } else {
44 bit--;
45 }
46 }
47 *p = 1<<bit;
48
49}
diff --git a/arch/sh/boards/sh03/rtc.c b/arch/sh/boards/sh03/rtc.c
new file mode 100644
index 00000000000..cbeca7037ba
--- /dev/null
+++ b/arch/sh/boards/sh03/rtc.c
@@ -0,0 +1,144 @@
1/*
2 * linux/arch/sh/boards/sh03/rtc.c -- CTP/PCI-SH03 on-chip RTC support
3 *
4 * Copyright (C) 2004 Saito.K & Jeanne(ksaito@interface.co.jp)
5 *
6 */
7
8#include <linux/init.h>
9#include <linux/kernel.h>
10#include <linux/sched.h>
11#include <linux/time.h>
12#include <asm/io.h>
13#include <linux/rtc.h>
14#include <linux/spinlock.h>
15
16#define RTC_BASE 0xb0000000
17#define RTC_SEC1 (RTC_BASE + 0)
18#define RTC_SEC10 (RTC_BASE + 1)
19#define RTC_MIN1 (RTC_BASE + 2)
20#define RTC_MIN10 (RTC_BASE + 3)
21#define RTC_HOU1 (RTC_BASE + 4)
22#define RTC_HOU10 (RTC_BASE + 5)
23#define RTC_WEE1 (RTC_BASE + 6)
24#define RTC_DAY1 (RTC_BASE + 7)
25#define RTC_DAY10 (RTC_BASE + 8)
26#define RTC_MON1 (RTC_BASE + 9)
27#define RTC_MON10 (RTC_BASE + 10)
28#define RTC_YEA1 (RTC_BASE + 11)
29#define RTC_YEA10 (RTC_BASE + 12)
30#define RTC_YEA100 (RTC_BASE + 13)
31#define RTC_YEA1000 (RTC_BASE + 14)
32#define RTC_CTL (RTC_BASE + 15)
33#define RTC_BUSY 1
34#define RTC_STOP 2
35
36#ifndef BCD_TO_BIN
37#define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10)
38#endif
39
40#ifndef BIN_TO_BCD
41#define BIN_TO_BCD(val) ((val)=(((val)/10)<<4) + (val)%10)
42#endif
43
44extern void (*rtc_get_time)(struct timespec *);
45extern int (*rtc_set_time)(const time_t);
46extern spinlock_t rtc_lock;
47
48unsigned long get_cmos_time(void)
49{
50 unsigned int year, mon, day, hour, min, sec;
51 int i;
52
53 spin_lock(&rtc_lock);
54 again:
55 for (i = 0 ; i < 1000000 ; i++) /* may take up to 1 second... */
56 if (!(ctrl_inb(RTC_CTL) & RTC_BUSY))
57 break;
58 do {
59 sec = (ctrl_inb(RTC_SEC1) & 0xf) + (ctrl_inb(RTC_SEC10) & 0x7) * 10;
60 min = (ctrl_inb(RTC_MIN1) & 0xf) + (ctrl_inb(RTC_MIN10) & 0xf) * 10;
61 hour = (ctrl_inb(RTC_HOU1) & 0xf) + (ctrl_inb(RTC_HOU10) & 0xf) * 10;
62 day = (ctrl_inb(RTC_DAY1) & 0xf) + (ctrl_inb(RTC_DAY10) & 0xf) * 10;
63 mon = (ctrl_inb(RTC_MON1) & 0xf) + (ctrl_inb(RTC_MON10) & 0xf) * 10;
64 year = (ctrl_inb(RTC_YEA1) & 0xf) + (ctrl_inb(RTC_YEA10) & 0xf) * 10
65 + (ctrl_inb(RTC_YEA100 ) & 0xf) * 100
66 + (ctrl_inb(RTC_YEA1000) & 0xf) * 1000;
67 } while (sec != (ctrl_inb(RTC_SEC1) & 0xf) + (ctrl_inb(RTC_SEC10) & 0x7) * 10);
68 if (year == 0 || mon < 1 || mon > 12 || day > 31 || day < 1 ||
69 hour > 23 || min > 59 || sec > 59) {
70 printk(KERN_ERR
71 "SH-03 RTC: invalid value, resetting to 1 Jan 2000\n");
72 printk("year=%d, mon=%d, day=%d, hour=%d, min=%d, sec=%d\n",
73 year, mon, day, hour, min, sec);
74
75 ctrl_outb(0, RTC_SEC1); ctrl_outb(0, RTC_SEC10);
76 ctrl_outb(0, RTC_MIN1); ctrl_outb(0, RTC_MIN10);
77 ctrl_outb(0, RTC_HOU1); ctrl_outb(0, RTC_HOU10);
78 ctrl_outb(6, RTC_WEE1);
79 ctrl_outb(1, RTC_DAY1); ctrl_outb(0, RTC_DAY10);
80 ctrl_outb(1, RTC_MON1); ctrl_outb(0, RTC_MON10);
81 ctrl_outb(0, RTC_YEA1); ctrl_outb(0, RTC_YEA10);
82 ctrl_outb(0, RTC_YEA100);
83 ctrl_outb(2, RTC_YEA1000);
84 ctrl_outb(0, RTC_CTL);
85 goto again;
86 }
87
88 spin_unlock(&rtc_lock);
89 return mktime(year, mon, day, hour, min, sec);
90}
91
92void sh03_rtc_gettimeofday(struct timespec *tv)
93{
94
95 tv->tv_sec = get_cmos_time();
96 tv->tv_nsec = 0;
97}
98
99static int set_rtc_mmss(unsigned long nowtime)
100{
101 int retval = 0;
102 int real_seconds, real_minutes, cmos_minutes;
103 int i;
104
105 /* gets recalled with irq locally disabled */
106 spin_lock(&rtc_lock);
107 for (i = 0 ; i < 1000000 ; i++) /* may take up to 1 second... */
108 if (!(ctrl_inb(RTC_CTL) & RTC_BUSY))
109 break;
110 cmos_minutes = (ctrl_inb(RTC_MIN1) & 0xf) + (ctrl_inb(RTC_MIN10) & 0xf) * 10;
111 real_seconds = nowtime % 60;
112 real_minutes = nowtime / 60;
113 if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1)
114 real_minutes += 30; /* correct for half hour time zone */
115 real_minutes %= 60;
116
117 if (abs(real_minutes - cmos_minutes) < 30) {
118 ctrl_outb(real_seconds % 10, RTC_SEC1);
119 ctrl_outb(real_seconds / 10, RTC_SEC10);
120 ctrl_outb(real_minutes % 10, RTC_MIN1);
121 ctrl_outb(real_minutes / 10, RTC_MIN10);
122 } else {
123 printk(KERN_WARNING
124 "set_rtc_mmss: can't update from %d to %d\n",
125 cmos_minutes, real_minutes);
126 retval = -1;
127 }
128 spin_unlock(&rtc_lock);
129
130 return retval;
131}
132
133int sh03_rtc_settimeofday(const time_t secs)
134{
135 unsigned long nowtime = secs;
136
137 return set_rtc_mmss(nowtime);
138}
139
140void sh03_time_init(void)
141{
142 rtc_get_time = sh03_rtc_gettimeofday;
143 rtc_set_time = sh03_rtc_settimeofday;
144}
diff --git a/arch/sh/boards/sh03/setup.c b/arch/sh/boards/sh03/setup.c
new file mode 100644
index 00000000000..d2a08ca5eb8
--- /dev/null
+++ b/arch/sh/boards/sh03/setup.c
@@ -0,0 +1,72 @@
1/*
2 * linux/arch/sh/boards/sh03/setup.c
3 *
4 * Copyright (C) 2004 Interface Co.,Ltd. Saito.K
5 *
6 */
7
8#include <linux/config.h>
9#include <linux/init.h>
10#include <linux/irq.h>
11#include <linux/hdreg.h>
12#include <linux/ide.h>
13#include <asm/io.h>
14#include <asm/sh03/io.h>
15#include <asm/sh03/sh03.h>
16#include <asm/addrspace.h>
17#include "../../drivers/pci/pci-sh7751.h"
18
19extern void (*board_time_init)(void);
20
21const char *get_system_type(void)
22{
23 return "Interface CTP/PCI-SH03)";
24}
25
26void init_sh03_IRQ(void)
27{
28 ctrl_outw(ctrl_inw(INTC_ICR) | INTC_ICR_IRLM, INTC_ICR);
29
30 make_ipr_irq(IRL0_IRQ, IRL0_IPR_ADDR, IRL0_IPR_POS, IRL0_PRIORITY);
31 make_ipr_irq(IRL1_IRQ, IRL1_IPR_ADDR, IRL1_IPR_POS, IRL1_PRIORITY);
32 make_ipr_irq(IRL2_IRQ, IRL2_IPR_ADDR, IRL2_IPR_POS, IRL2_PRIORITY);
33 make_ipr_irq(IRL3_IRQ, IRL3_IPR_ADDR, IRL3_IPR_POS, IRL3_PRIORITY);
34}
35
36extern void *cf_io_base;
37
38unsigned long sh03_isa_port2addr(unsigned long port)
39{
40 if (PXSEG(port))
41 return port;
42 /* CompactFlash (IDE) */
43 if (((port >= 0x1f0) && (port <= 0x1f7)) || (port == 0x3f6)) {
44 return (unsigned long)cf_io_base + port;
45 }
46 return port + SH7751_PCI_IO_BASE;
47}
48
49/*
50 * The Machine Vector
51 */
52
53struct sh_machine_vector mv_sh03 __initmv = {
54 .mv_nr_irqs = 48,
55 .mv_isa_port2addr = sh03_isa_port2addr,
56 .mv_init_irq = init_sh03_IRQ,
57
58#ifdef CONFIG_HEARTBEAT
59 .mv_heartbeat = heartbeat_sh03,
60#endif
61};
62
63ALIAS_MV(sh03)
64
65/* arch/sh/boards/sh03/rtc.c */
66void sh03_time_init(void);
67
68int __init platform_setup(void)
69{
70 board_time_init = sh03_time_init;
71 return 0;
72}
diff --git a/arch/sh/boards/sh2000/Makefile b/arch/sh/boards/sh2000/Makefile
new file mode 100644
index 00000000000..05d390c3599
--- /dev/null
+++ b/arch/sh/boards/sh2000/Makefile
@@ -0,0 +1,6 @@
1#
2# Makefile for the SH2000 specific parts of the kernel
3#
4
5obj-y := setup.o
6
diff --git a/arch/sh/boards/sh2000/setup.c b/arch/sh/boards/sh2000/setup.c
new file mode 100644
index 00000000000..a290b1d09fb
--- /dev/null
+++ b/arch/sh/boards/sh2000/setup.c
@@ -0,0 +1,71 @@
1/*
2 * linux/arch/sh/kernel/setup_sh2000.c
3 *
4 * Copyright (C) 2001 SUGIOKA Tochinobu
5 *
6 * SH-2000 Support.
7 *
8 */
9
10#include <linux/config.h>
11#include <linux/init.h>
12#include <linux/irq.h>
13
14#include <asm/io.h>
15#include <asm/machvec.h>
16#include <asm/mach/sh2000.h>
17
18#define CF_CIS_BASE 0xb4200000
19
20#define PORT_PECR 0xa4000108
21#define PORT_PHCR 0xa400010E
22#define PORT_ICR1 0xa4000010
23#define PORT_IRR0 0xa4000004
24
25#define IDE_OFFSET 0xb6200000
26#define NIC_OFFSET 0xb6000000
27#define EXTBUS_OFFSET 0xba000000
28
29
30const char *get_system_type(void)
31{
32 return "sh2000";
33}
34
35static unsigned long sh2000_isa_port2addr(unsigned long offset)
36{
37 if((offset & ~7) == 0x1f0 || offset == 0x3f6)
38 return IDE_OFFSET + offset;
39 else if((offset & ~0x1f) == 0x300)
40 return NIC_OFFSET + offset;
41 return EXTBUS_OFFSET + offset;
42}
43
44/*
45 * The Machine Vector
46 */
47struct sh_machine_vector mv_sh2000 __initmv = {
48 .mv_nr_irqs = 80,
49 .mv_isa_port2addr = sh2000_isa_port2addr,
50};
51ALIAS_MV(sh2000)
52
53/*
54 * Initialize the board
55 */
56int __init platform_setup(void)
57{
58 /* XXX: RTC setting comes here */
59
60 /* These should be done by BIOS/IPL ... */
61 /* Enable nCE2A, nCE2B output */
62 ctrl_outw(ctrl_inw(PORT_PECR) & ~0xf00, PORT_PECR);
63 /* Enable the Compact Flash card, and set the level interrupt */
64 ctrl_outw(0x0042, CF_CIS_BASE+0x0200);
65 /* Enable interrupt */
66 ctrl_outw(ctrl_inw(PORT_PHCR) & ~0x03f3, PORT_PHCR);
67 ctrl_outw(1, PORT_ICR1);
68 ctrl_outw(ctrl_inw(PORT_IRR0) & ~0xff3f, PORT_IRR0);
69 printk(KERN_INFO "SH-2000 Setup...done\n");
70 return 0;
71}
diff --git a/arch/sh/boards/snapgear/Makefile b/arch/sh/boards/snapgear/Makefile
new file mode 100644
index 00000000000..59fc976bfc2
--- /dev/null
+++ b/arch/sh/boards/snapgear/Makefile
@@ -0,0 +1,6 @@
1#
2# Makefile for the SnapGear specific parts of the kernel
3#
4
5obj-y := setup.o io.o rtc.o
6
diff --git a/arch/sh/boards/snapgear/io.c b/arch/sh/boards/snapgear/io.c
new file mode 100644
index 00000000000..e2eb78fc381
--- /dev/null
+++ b/arch/sh/boards/snapgear/io.c
@@ -0,0 +1,226 @@
1/*
2 * linux/arch/sh/kernel/io_7751se.c
3 *
4 * Copyright (C) 2002 David McCullough <davidm@snapgear.com>
5 * Copyright (C) 2001 Ian da Silva, Jeremy Siegel
6 * Based largely on io_se.c.
7 *
8 * I/O routine for Hitachi 7751 SolutionEngine.
9 *
10 * Initial version only to support LAN access; some
11 * placeholder code from io_se.c left in with the
12 * expectation of later SuperIO and PCMCIA access.
13 */
14
15#include <linux/kernel.h>
16#include <linux/types.h>
17#include <linux/pci.h>
18#include <asm/io.h>
19#include <asm/addrspace.h>
20
21#include <asm/pci.h>
22#include "../../drivers/pci/pci-sh7751.h"
23
24#ifdef CONFIG_SH_SECUREEDGE5410
25unsigned short secureedge5410_ioport;
26#endif
27
28/*
29 * The SnapGear uses the built-in PCI controller (PCIC)
30 * of the 7751 processor
31 */
32
33#define PCIIOBR (volatile long *)PCI_REG(SH7751_PCIIOBR)
34#define PCIMBR (volatile long *)PCI_REG(SH7751_PCIMBR)
35#define PCI_IO_AREA SH7751_PCI_IO_BASE
36#define PCI_MEM_AREA SH7751_PCI_CONFIG_BASE
37
38
39#define PCI_IOMAP(adr) (PCI_IO_AREA + (adr & ~SH7751_PCIIOBR_MASK))
40
41
42#define maybebadio(name,port) \
43 printk("bad PC-like io %s for port 0x%lx at 0x%08x\n", \
44 #name, (port), (__u32) __builtin_return_address(0))
45
46
47static inline void delay(void)
48{
49 ctrl_inw(0xa0000000);
50}
51
52
53static inline volatile __u16 *port2adr(unsigned int port)
54{
55#if 0
56 if (port >= 0x2000)
57 return (volatile __u16 *) (PA_MRSHPC + (port - 0x2000));
58#endif
59 maybebadio(name,(unsigned long)port);
60 return (volatile __u16*)port;
61}
62
63
64/* In case someone configures the kernel w/o PCI support: in that */
65/* scenario, don't ever bother to check for PCI-window addresses */
66
67/* NOTE: WINDOW CHECK MAY BE A BIT OFF, HIGH PCIBIOS_MIN_IO WRAPS? */
68#if defined(CONFIG_PCI)
69#define CHECK_SH7751_PCIIO(port) \
70 ((port >= PCIBIOS_MIN_IO) && (port < (PCIBIOS_MIN_IO + SH7751_PCI_IO_SIZE)))
71#else
72#define CHECK_SH7751_PCIIO(port) (0)
73#endif
74
75/*
76 * General outline: remap really low stuff [eventually] to SuperIO,
77 * stuff in PCI IO space (at or above window at pci.h:PCIBIOS_MIN_IO)
78 * is mapped through the PCI IO window. Stuff with high bits (PXSEG)
79 * should be way beyond the window, and is used w/o translation for
80 * compatibility.
81 */
82
83unsigned char snapgear_inb(unsigned long port)
84{
85 if (PXSEG(port))
86 return *(volatile unsigned char *)port;
87 else if (CHECK_SH7751_PCIIO(port))
88 return *(volatile unsigned char *)PCI_IOMAP(port);
89 else
90 return (*port2adr(port))&0xff;
91}
92
93
94unsigned char snapgear_inb_p(unsigned long port)
95{
96 unsigned char v;
97
98 if (PXSEG(port))
99 v = *(volatile unsigned char *)port;
100 else if (CHECK_SH7751_PCIIO(port))
101 v = *(volatile unsigned char *)PCI_IOMAP(port);
102 else
103 v = (*port2adr(port))&0xff;
104 delay();
105 return v;
106}
107
108
109unsigned short snapgear_inw(unsigned long port)
110{
111 if (PXSEG(port))
112 return *(volatile unsigned short *)port;
113 else if (CHECK_SH7751_PCIIO(port))
114 return *(volatile unsigned short *)PCI_IOMAP(port);
115 else if (port >= 0x2000)
116 return *port2adr(port);
117 else
118 maybebadio(inw, port);
119 return 0;
120}
121
122
123unsigned int snapgear_inl(unsigned long port)
124{
125 if (PXSEG(port))
126 return *(volatile unsigned long *)port;
127 else if (CHECK_SH7751_PCIIO(port))
128 return *(volatile unsigned int *)PCI_IOMAP(port);
129 else if (port >= 0x2000)
130 return *port2adr(port);
131 else
132 maybebadio(inl, port);
133 return 0;
134}
135
136
137void snapgear_outb(unsigned char value, unsigned long port)
138{
139
140 if (PXSEG(port))
141 *(volatile unsigned char *)port = value;
142 else if (CHECK_SH7751_PCIIO(port))
143 *((unsigned char*)PCI_IOMAP(port)) = value;
144 else
145 *(port2adr(port)) = value;
146}
147
148
149void snapgear_outb_p(unsigned char value, unsigned long port)
150{
151 if (PXSEG(port))
152 *(volatile unsigned char *)port = value;
153 else if (CHECK_SH7751_PCIIO(port))
154 *((unsigned char*)PCI_IOMAP(port)) = value;
155 else
156 *(port2adr(port)) = value;
157 delay();
158}
159
160
161void snapgear_outw(unsigned short value, unsigned long port)
162{
163 if (PXSEG(port))
164 *(volatile unsigned short *)port = value;
165 else if (CHECK_SH7751_PCIIO(port))
166 *((unsigned short *)PCI_IOMAP(port)) = value;
167 else if (port >= 0x2000)
168 *port2adr(port) = value;
169 else
170 maybebadio(outw, port);
171}
172
173
174void snapgear_outl(unsigned int value, unsigned long port)
175{
176 if (PXSEG(port))
177 *(volatile unsigned long *)port = value;
178 else if (CHECK_SH7751_PCIIO(port))
179 *((unsigned long*)PCI_IOMAP(port)) = value;
180 else
181 maybebadio(outl, port);
182}
183
184void snapgear_insl(unsigned long port, void *addr, unsigned long count)
185{
186 maybebadio(insl, port);
187}
188
189void snapgear_outsl(unsigned long port, const void *addr, unsigned long count)
190{
191 maybebadio(outsw, port);
192}
193
194/* Map ISA bus address to the real address. Only for PCMCIA. */
195
196
197/* ISA page descriptor. */
198static __u32 sh_isa_memmap[256];
199
200
201#if 0
202static int sh_isa_mmap(__u32 start, __u32 length, __u32 offset)
203{
204 int idx;
205
206 if (start >= 0x100000 || (start & 0xfff) || (length != 0x1000))
207 return -1;
208
209 idx = start >> 12;
210 sh_isa_memmap[idx] = 0xb8000000 + (offset &~ 0xfff);
211#if 0
212 printk("sh_isa_mmap: start %x len %x offset %x (idx %x paddr %x)\n",
213 start, length, offset, idx, sh_isa_memmap[idx]);
214#endif
215 return 0;
216}
217#endif
218
219unsigned long snapgear_isa_port2addr(unsigned long offset)
220{
221 int idx;
222
223 idx = (offset >> 12) & 0xff;
224 offset &= 0xfff;
225 return sh_isa_memmap[idx] + offset;
226}
diff --git a/arch/sh/boards/snapgear/rtc.c b/arch/sh/boards/snapgear/rtc.c
new file mode 100644
index 00000000000..b71e009da35
--- /dev/null
+++ b/arch/sh/boards/snapgear/rtc.c
@@ -0,0 +1,333 @@
1/****************************************************************************/
2/*
3 * linux/arch/sh/boards/snapgear/rtc.c -- Secureedge5410 RTC code
4 *
5 * Copyright (C) 2002 David McCullough <davidm@snapgear.com>
6 * Copyright (C) 2003 Paul Mundt <lethal@linux-sh.org>
7 *
8 * The SecureEdge5410 can have one of 2 real time clocks, the SH
9 * built in version or the preferred external DS1302. Here we work out
10 * each to see what we have and then run with it.
11 */
12/****************************************************************************/
13
14#include <linux/init.h>
15#include <linux/kernel.h>
16#include <linux/sched.h>
17#include <linux/time.h>
18#include <linux/rtc.h>
19#include <linux/mc146818rtc.h>
20
21#include <asm/io.h>
22#include <asm/rtc.h>
23#include <asm/mc146818rtc.h>
24
25/****************************************************************************/
26
27static int use_ds1302 = 0;
28
29/****************************************************************************/
30/*
31 * we need to implement a DS1302 driver here that can operate in
32 * conjunction with the builtin rtc driver which is already quite friendly
33 */
34/*****************************************************************************/
35
36#define RTC_CMD_READ 0x81 /* Read command */
37#define RTC_CMD_WRITE 0x80 /* Write command */
38
39#define RTC_ADDR_YEAR 0x06 /* Address of year register */
40#define RTC_ADDR_DAY 0x05 /* Address of day of week register */
41#define RTC_ADDR_MON 0x04 /* Address of month register */
42#define RTC_ADDR_DATE 0x03 /* Address of day of month register */
43#define RTC_ADDR_HOUR 0x02 /* Address of hour register */
44#define RTC_ADDR_MIN 0x01 /* Address of minute register */
45#define RTC_ADDR_SEC 0x00 /* Address of second register */
46
47#define RTC_RESET 0x1000
48#define RTC_IODATA 0x0800
49#define RTC_SCLK 0x0400
50
51#define set_dirp(x)
52#define get_dirp(x) 0
53#define set_dp(x) SECUREEDGE_WRITE_IOPORT(x, 0x1c00)
54#define get_dp(x) SECUREEDGE_READ_IOPORT()
55
56static void ds1302_sendbits(unsigned int val)
57{
58 int i;
59
60 for (i = 8; (i); i--, val >>= 1) {
61 set_dp((get_dp() & ~RTC_IODATA) | ((val & 0x1) ? RTC_IODATA : 0));
62 set_dp(get_dp() | RTC_SCLK); // clock high
63 set_dp(get_dp() & ~RTC_SCLK); // clock low
64 }
65}
66
67static unsigned int ds1302_recvbits(void)
68{
69 unsigned int val;
70 int i;
71
72 for (i = 0, val = 0; (i < 8); i++) {
73 val |= (((get_dp() & RTC_IODATA) ? 1 : 0) << i);
74 set_dp(get_dp() | RTC_SCLK); // clock high
75 set_dp(get_dp() & ~RTC_SCLK); // clock low
76 }
77 return(val);
78}
79
80static unsigned int ds1302_readbyte(unsigned int addr)
81{
82 unsigned int val;
83 unsigned long flags;
84
85#if 0
86 printk("SnapGear RTC: ds1302_readbyte(addr=%x)\n", addr);
87#endif
88
89 local_irq_save(flags);
90 set_dirp(get_dirp() | RTC_RESET | RTC_IODATA | RTC_SCLK);
91 set_dp(get_dp() & ~(RTC_RESET | RTC_IODATA | RTC_SCLK));
92
93 set_dp(get_dp() | RTC_RESET);
94 ds1302_sendbits(((addr & 0x3f) << 1) | RTC_CMD_READ);
95 set_dirp(get_dirp() & ~RTC_IODATA);
96 val = ds1302_recvbits();
97 set_dp(get_dp() & ~RTC_RESET);
98 local_irq_restore(flags);
99
100 return(val);
101}
102
103static void ds1302_writebyte(unsigned int addr, unsigned int val)
104{
105 unsigned long flags;
106
107#if 0
108 printk("SnapGear RTC: ds1302_writebyte(addr=%x)\n", addr);
109#endif
110
111 local_irq_save(flags);
112 set_dirp(get_dirp() | RTC_RESET | RTC_IODATA | RTC_SCLK);
113 set_dp(get_dp() & ~(RTC_RESET | RTC_IODATA | RTC_SCLK));
114 set_dp(get_dp() | RTC_RESET);
115 ds1302_sendbits(((addr & 0x3f) << 1) | RTC_CMD_WRITE);
116 ds1302_sendbits(val);
117 set_dp(get_dp() & ~RTC_RESET);
118 local_irq_restore(flags);
119}
120
121static void ds1302_reset(void)
122{
123 unsigned long flags;
124 /* Hardware dependant reset/init */
125 local_irq_save(flags);
126 set_dirp(get_dirp() | RTC_RESET | RTC_IODATA | RTC_SCLK);
127 set_dp(get_dp() & ~(RTC_RESET | RTC_IODATA | RTC_SCLK));
128 local_irq_restore(flags);
129}
130
131/*****************************************************************************/
132
133static inline int bcd2int(int val)
134{
135 return((((val & 0xf0) >> 4) * 10) + (val & 0xf));
136}
137
138static inline int int2bcd(int val)
139{
140 return(((val / 10) << 4) + (val % 10));
141}
142
143/*****************************************************************************/
144/*
145 * Write and Read some RAM in the DS1302, if it works assume it's there
146 * Otherwise use the SH4 internal RTC
147 */
148
149void snapgear_rtc_gettimeofday(struct timespec *);
150int snapgear_rtc_settimeofday(const time_t);
151
152void __init secureedge5410_rtc_init(void)
153{
154 unsigned char *test = "snapgear";
155 int i;
156
157 ds1302_reset();
158
159 use_ds1302 = 1;
160
161 for (i = 0; test[i]; i++)
162 ds1302_writebyte(32 + i, test[i]);
163
164 for (i = 0; test[i]; i++)
165 if (ds1302_readbyte(32 + i) != test[i]) {
166 use_ds1302 = 0;
167 break;
168 }
169
170 if (use_ds1302) {
171 rtc_get_time = snapgear_rtc_gettimeofday;
172 rtc_set_time = snapgear_rtc_settimeofday;
173 } else {
174 rtc_get_time = sh_rtc_gettimeofday;
175 rtc_set_time = sh_rtc_settimeofday;
176 }
177
178 printk("SnapGear RTC: using %s rtc.\n", use_ds1302 ? "ds1302" : "internal");
179}
180
181/****************************************************************************/
182/*
183 * our generic interface that chooses the correct code to use
184 */
185
186void snapgear_rtc_gettimeofday(struct timespec *ts)
187{
188 unsigned int sec, min, hr, day, mon, yr;
189
190 if (!use_ds1302) {
191 sh_rtc_gettimeofday(ts);
192 return;
193 }
194
195 sec = bcd2int(ds1302_readbyte(RTC_ADDR_SEC));
196 min = bcd2int(ds1302_readbyte(RTC_ADDR_MIN));
197 hr = bcd2int(ds1302_readbyte(RTC_ADDR_HOUR));
198 day = bcd2int(ds1302_readbyte(RTC_ADDR_DATE));
199 mon = bcd2int(ds1302_readbyte(RTC_ADDR_MON));
200 yr = bcd2int(ds1302_readbyte(RTC_ADDR_YEAR));
201
202bad_time:
203 if (yr > 99 || mon < 1 || mon > 12 || day > 31 || day < 1 ||
204 hr > 23 || min > 59 || sec > 59) {
205 printk(KERN_ERR
206 "SnapGear RTC: invalid value, resetting to 1 Jan 2000\n");
207 ds1302_writebyte(RTC_ADDR_MIN, min = 0);
208 ds1302_writebyte(RTC_ADDR_HOUR, hr = 0);
209 ds1302_writebyte(RTC_ADDR_DAY, 7);
210 ds1302_writebyte(RTC_ADDR_DATE, day = 1);
211 ds1302_writebyte(RTC_ADDR_MON, mon = 1);
212 ds1302_writebyte(RTC_ADDR_YEAR, yr = 0);
213 ds1302_writebyte(RTC_ADDR_SEC, sec = 0);
214 }
215
216 ts->tv_sec = mktime(2000 + yr, mon, day, hr, min, sec);
217 if (ts->tv_sec < 0) {
218#if 0
219 printk("BAD TIME %d %d %d %d %d %d\n", yr, mon, day, hr, min, sec);
220#endif
221 yr = 100;
222 goto bad_time;
223 }
224 ts->tv_nsec = 0;
225}
226
227int snapgear_rtc_settimeofday(const time_t secs)
228{
229 int retval = 0;
230 int real_seconds, real_minutes, cmos_minutes;
231 unsigned long nowtime;
232
233 if (!use_ds1302)
234 return sh_rtc_settimeofday(secs);
235
236/*
237 * This is called direct from the kernel timer handling code.
238 * It is supposed to synchronize the kernel clock to the RTC.
239 */
240
241 nowtime = secs;
242
243#if 1
244 printk("SnapGear RTC: snapgear_rtc_settimeofday(nowtime=%ld)\n", nowtime);
245#endif
246
247 /* STOP RTC */
248 ds1302_writebyte(RTC_ADDR_SEC, ds1302_readbyte(RTC_ADDR_SEC) | 0x80);
249
250 cmos_minutes = bcd2int(ds1302_readbyte(RTC_ADDR_MIN));
251
252 /*
253 * since we're only adjusting minutes and seconds,
254 * don't interfere with hour overflow. This avoids
255 * messing with unknown time zones but requires your
256 * RTC not to be off by more than 15 minutes
257 */
258 real_seconds = nowtime % 60;
259 real_minutes = nowtime / 60;
260 if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1)
261 real_minutes += 30; /* correct for half hour time zone */
262 real_minutes %= 60;
263
264 if (abs(real_minutes - cmos_minutes) < 30) {
265 ds1302_writebyte(RTC_ADDR_MIN, int2bcd(real_minutes));
266 ds1302_writebyte(RTC_ADDR_SEC, int2bcd(real_seconds));
267 } else {
268 printk(KERN_WARNING
269 "SnapGear RTC: can't update from %d to %d\n",
270 cmos_minutes, real_minutes);
271 retval = -1;
272 }
273
274 /* START RTC */
275 ds1302_writebyte(RTC_ADDR_SEC, ds1302_readbyte(RTC_ADDR_SEC) & ~0x80);
276 return(0);
277}
278
279unsigned char secureedge5410_cmos_read(int addr)
280{
281 unsigned char val = 0;
282
283 if (!use_ds1302)
284 return(__CMOS_READ(addr, w));
285
286 switch(addr) {
287 case RTC_SECONDS: val = ds1302_readbyte(RTC_ADDR_SEC); break;
288 case RTC_SECONDS_ALARM: break;
289 case RTC_MINUTES: val = ds1302_readbyte(RTC_ADDR_MIN); break;
290 case RTC_MINUTES_ALARM: break;
291 case RTC_HOURS: val = ds1302_readbyte(RTC_ADDR_HOUR); break;
292 case RTC_HOURS_ALARM: break;
293 case RTC_DAY_OF_WEEK: val = ds1302_readbyte(RTC_ADDR_DAY); break;
294 case RTC_DAY_OF_MONTH: val = ds1302_readbyte(RTC_ADDR_DATE); break;
295 case RTC_MONTH: val = ds1302_readbyte(RTC_ADDR_MON); break;
296 case RTC_YEAR: val = ds1302_readbyte(RTC_ADDR_YEAR); break;
297 case RTC_REG_A: /* RTC_FREQ_SELECT */ break;
298 case RTC_REG_B: /* RTC_CONTROL */ break;
299 case RTC_REG_C: /* RTC_INTR_FLAGS */ break;
300 case RTC_REG_D: val = RTC_VRT /* RTC_VALID */; break;
301 default: break;
302 }
303
304 return(val);
305}
306
307void secureedge5410_cmos_write(unsigned char val, int addr)
308{
309 if (!use_ds1302) {
310 __CMOS_WRITE(val, addr, w);
311 return;
312 }
313
314 switch(addr) {
315 case RTC_SECONDS: ds1302_writebyte(RTC_ADDR_SEC, val); break;
316 case RTC_SECONDS_ALARM: break;
317 case RTC_MINUTES: ds1302_writebyte(RTC_ADDR_MIN, val); break;
318 case RTC_MINUTES_ALARM: break;
319 case RTC_HOURS: ds1302_writebyte(RTC_ADDR_HOUR, val); break;
320 case RTC_HOURS_ALARM: break;
321 case RTC_DAY_OF_WEEK: ds1302_writebyte(RTC_ADDR_DAY, val); break;
322 case RTC_DAY_OF_MONTH: ds1302_writebyte(RTC_ADDR_DATE, val); break;
323 case RTC_MONTH: ds1302_writebyte(RTC_ADDR_MON, val); break;
324 case RTC_YEAR: ds1302_writebyte(RTC_ADDR_YEAR, val); break;
325 case RTC_REG_A: /* RTC_FREQ_SELECT */ break;
326 case RTC_REG_B: /* RTC_CONTROL */ break;
327 case RTC_REG_C: /* RTC_INTR_FLAGS */ break;
328 case RTC_REG_D: /* RTC_VALID */ break;
329 default: break;
330 }
331}
332
333/****************************************************************************/
diff --git a/arch/sh/boards/snapgear/setup.c b/arch/sh/boards/snapgear/setup.c
new file mode 100644
index 00000000000..08fc98342a0
--- /dev/null
+++ b/arch/sh/boards/snapgear/setup.c
@@ -0,0 +1,216 @@
1/****************************************************************************/
2/*
3 * linux/arch/sh/boards/snapgear/setup.c
4 *
5 * Copyright (C) 2002 David McCullough <davidm@snapgear.com>
6 * Copyright (C) 2003 Paul Mundt <lethal@linux-sh.org>
7 *
8 * Based on files with the following comments:
9 *
10 * Copyright (C) 2000 Kazumoto Kojima
11 *
12 * Modified for 7751 Solution Engine by
13 * Ian da Silva and Jeremy Siegel, 2001.
14 */
15/****************************************************************************/
16
17#include <linux/config.h>
18#include <linux/init.h>
19#include <linux/irq.h>
20#include <linux/interrupt.h>
21#include <linux/timer.h>
22#include <linux/delay.h>
23#include <linux/module.h>
24#include <linux/sched.h>
25
26#include <asm/machvec.h>
27#include <asm/mach/io.h>
28#include <asm/irq.h>
29#include <asm/io.h>
30#include <asm/cpu/timer.h>
31
32extern void (*board_time_init)(void);
33extern void secureedge5410_rtc_init(void);
34extern void pcibios_init(void);
35
36/****************************************************************************/
37/*
38 * EraseConfig handling functions
39 */
40
41static irqreturn_t eraseconfig_interrupt(int irq, void *dev_id, struct pt_regs *regs)
42{
43 volatile char dummy __attribute__((unused)) = * (volatile char *) 0xb8000000;
44
45 printk("SnapGear: erase switch interrupt!\n");
46
47 return IRQ_HANDLED;
48}
49
50static int __init eraseconfig_init(void)
51{
52 printk("SnapGear: EraseConfig init\n");
53 /* Setup "EraseConfig" switch on external IRQ 0 */
54 if (request_irq(IRL0_IRQ, eraseconfig_interrupt, SA_INTERRUPT,
55 "Erase Config", NULL))
56 printk("SnapGear: failed to register IRQ%d for Reset witch\n",
57 IRL0_IRQ);
58 else
59 printk("SnapGear: registered EraseConfig switch on IRQ%d\n",
60 IRL0_IRQ);
61 return(0);
62}
63
64module_init(eraseconfig_init);
65
66/****************************************************************************/
67/*
68 * Initialize IRQ setting
69 *
70 * IRL0 = erase switch
71 * IRL1 = eth0
72 * IRL2 = eth1
73 * IRL3 = crypto
74 */
75
76static void __init init_snapgear_IRQ(void)
77{
78 /* enable individual interrupt mode for externals */
79 ctrl_outw(ctrl_inw(INTC_ICR) | INTC_ICR_IRLM, INTC_ICR);
80
81 printk("Setup SnapGear IRQ/IPR ...\n");
82
83 make_ipr_irq(IRL0_IRQ, IRL0_IPR_ADDR, IRL0_IPR_POS, IRL0_PRIORITY);
84 make_ipr_irq(IRL1_IRQ, IRL1_IPR_ADDR, IRL1_IPR_POS, IRL1_PRIORITY);
85 make_ipr_irq(IRL2_IRQ, IRL2_IPR_ADDR, IRL2_IPR_POS, IRL2_PRIORITY);
86 make_ipr_irq(IRL3_IRQ, IRL3_IPR_ADDR, IRL3_IPR_POS, IRL3_PRIORITY);
87}
88
89/****************************************************************************/
90/*
91 * Fast poll interrupt simulator.
92 */
93
94/*
95 * Leave all of the fast timer/fast poll stuff commented out for now, since
96 * it's not clear whether it actually works or not. Since it wasn't being used
97 * at all in 2.4, we'll assume it's not sane for 2.6 either.. -- PFM
98 */
99#if 0
100#define FAST_POLL 1000
101//#define FAST_POLL_INTR
102
103#define FASTTIMER_IRQ 17
104#define FASTTIMER_IPR_ADDR INTC_IPRA
105#define FASTTIMER_IPR_POS 2
106#define FASTTIMER_PRIORITY 3
107
108#ifdef FAST_POLL_INTR
109#define TMU1_TCR_INIT 0x0020
110#else
111#define TMU1_TCR_INIT 0
112#endif
113#define TMU_TSTR_INIT 1
114#define TMU1_TCR_CALIB 0x0000
115
116
117#ifdef FAST_POLL_INTR
118static void fast_timer_irq(int irq, void *dev_instance, struct pt_regs *regs)
119{
120 unsigned long timer_status;
121 timer_status = ctrl_inw(TMU1_TCR);
122 timer_status &= ~0x100;
123 ctrl_outw(timer_status, TMU1_TCR);
124}
125#endif
126
127/*
128 * return the current ticks on the fast timer
129 */
130
131unsigned long fast_timer_count(void)
132{
133 return(ctrl_inl(TMU1_TCNT));
134}
135
136/*
137 * setup a fast timer for profiling etc etc
138 */
139
140static void setup_fast_timer()
141{
142 unsigned long interval;
143
144#ifdef FAST_POLL_INTR
145 interval = (current_cpu_data.module_clock/4 + FAST_POLL/2) / FAST_POLL;
146
147 make_ipr_irq(FASTTIMER_IRQ, FASTTIMER_IPR_ADDR, FASTTIMER_IPR_POS,
148 FASTTIMER_PRIORITY);
149
150 printk("SnapGear: %dHz fast timer on IRQ %d\n",FAST_POLL,FASTTIMER_IRQ);
151
152 if (request_irq(FASTTIMER_IRQ, fast_timer_irq, 0, "SnapGear fast timer",
153 NULL) != 0)
154 printk("%s(%d): request_irq() failed?\n", __FILE__, __LINE__);
155#else
156 printk("SnapGear: fast timer running\n",FAST_POLL,FASTTIMER_IRQ);
157 interval = 0xffffffff;
158#endif
159
160 ctrl_outb(ctrl_inb(TMU_TSTR) & ~0x2, TMU_TSTR); /* disable timer 1 */
161 ctrl_outw(TMU1_TCR_INIT, TMU1_TCR);
162 ctrl_outl(interval, TMU1_TCOR);
163 ctrl_outl(interval, TMU1_TCNT);
164 ctrl_outb(ctrl_inb(TMU_TSTR) | 0x2, TMU_TSTR); /* enable timer 1 */
165
166 printk("Timer count 1 = 0x%x\n", fast_timer_count());
167 udelay(1000);
168 printk("Timer count 2 = 0x%x\n", fast_timer_count());
169}
170#endif
171
172/****************************************************************************/
173
174const char *get_system_type(void)
175{
176 return "SnapGear SecureEdge5410";
177}
178
179/*
180 * The Machine Vector
181 */
182
183struct sh_machine_vector mv_snapgear __initmv = {
184 .mv_nr_irqs = 72,
185
186 .mv_inb = snapgear_inb,
187 .mv_inw = snapgear_inw,
188 .mv_inl = snapgear_inl,
189 .mv_outb = snapgear_outb,
190 .mv_outw = snapgear_outw,
191 .mv_outl = snapgear_outl,
192
193 .mv_inb_p = snapgear_inb_p,
194 .mv_inw_p = snapgear_inw,
195 .mv_inl_p = snapgear_inl,
196 .mv_outb_p = snapgear_outb_p,
197 .mv_outw_p = snapgear_outw,
198 .mv_outl_p = snapgear_outl,
199
200 .mv_isa_port2addr = snapgear_isa_port2addr,
201
202 .mv_init_irq = init_snapgear_IRQ,
203};
204ALIAS_MV(snapgear)
205
206/*
207 * Initialize the board
208 */
209
210int __init platform_setup(void)
211{
212 board_time_init = secureedge5410_rtc_init;
213
214 return 0;
215}
216
diff --git a/arch/sh/boards/superh/microdev/Makefile b/arch/sh/boards/superh/microdev/Makefile
new file mode 100644
index 00000000000..1387dd6c85e
--- /dev/null
+++ b/arch/sh/boards/superh/microdev/Makefile
@@ -0,0 +1,8 @@
1#
2# Makefile for the SuperH MicroDev specific parts of the kernel
3#
4
5obj-y := setup.o irq.o io.o
6
7obj-$(CONFIG_HEARTBEAT) += led.o
8
diff --git a/arch/sh/boards/superh/microdev/io.c b/arch/sh/boards/superh/microdev/io.c
new file mode 100644
index 00000000000..fe83b2c0307
--- /dev/null
+++ b/arch/sh/boards/superh/microdev/io.c
@@ -0,0 +1,370 @@
1/*
2 * linux/arch/sh/kernel/io_microdev.c
3 *
4 * Copyright (C) 2003 Sean McGoogan (Sean.McGoogan@superh.com)
5 * Copyright (C) 2003, 2004 SuperH, Inc.
6 * Copyright (C) 2004 Paul Mundt
7 *
8 * SuperH SH4-202 MicroDev board support.
9 *
10 * May be copied or modified under the terms of the GNU General Public
11 * License. See linux/COPYING for more information.
12 */
13
14#include <linux/config.h>
15#include <linux/init.h>
16#include <linux/pci.h>
17#include <linux/wait.h>
18#include <asm/io.h>
19#include <asm/mach/io.h>
20
21 /*
22 * we need to have a 'safe' address to re-direct all I/O requests
23 * that we do not explicitly wish to handle. This safe address
24 * must have the following properies:
25 *
26 * * writes are ignored (no exception)
27 * * reads are benign (no side-effects)
28 * * accesses of width 1, 2 and 4-bytes are all valid.
29 *
30 * The Processor Version Register (PVR) has these properties.
31 */
32#define PVR 0xff000030 /* Processor Version Register */
33
34
35#define IO_IDE2_BASE 0x170ul /* I/O base for SMSC FDC37C93xAPM IDE #2 */
36#define IO_IDE1_BASE 0x1f0ul /* I/O base for SMSC FDC37C93xAPM IDE #1 */
37#define IO_ISP1161_BASE 0x290ul /* I/O port for Philips ISP1161x USB chip */
38#define IO_SERIAL2_BASE 0x2f8ul /* I/O base for SMSC FDC37C93xAPM Serial #2 */
39#define IO_LAN91C111_BASE 0x300ul /* I/O base for SMSC LAN91C111 Ethernet chip */
40#define IO_IDE2_MISC 0x376ul /* I/O misc for SMSC FDC37C93xAPM IDE #2 */
41#define IO_SUPERIO_BASE 0x3f0ul /* I/O base for SMSC FDC37C93xAPM SuperIO chip */
42#define IO_IDE1_MISC 0x3f6ul /* I/O misc for SMSC FDC37C93xAPM IDE #1 */
43#define IO_SERIAL1_BASE 0x3f8ul /* I/O base for SMSC FDC37C93xAPM Serial #1 */
44
45#define IO_ISP1161_EXTENT 0x04ul /* I/O extent for Philips ISP1161x USB chip */
46#define IO_LAN91C111_EXTENT 0x10ul /* I/O extent for SMSC LAN91C111 Ethernet chip */
47#define IO_SUPERIO_EXTENT 0x02ul /* I/O extent for SMSC FDC37C93xAPM SuperIO chip */
48#define IO_IDE_EXTENT 0x08ul /* I/O extent for IDE Task Register set */
49#define IO_SERIAL_EXTENT 0x10ul
50
51#define IO_LAN91C111_PHYS 0xa7500000ul /* Physical address of SMSC LAN91C111 Ethernet chip */
52#define IO_ISP1161_PHYS 0xa7700000ul /* Physical address of Philips ISP1161x USB chip */
53#define IO_SUPERIO_PHYS 0xa7800000ul /* Physical address of SMSC FDC37C93xAPM SuperIO chip */
54
55#define PORT2ADDR(x) (microdev_isa_port2addr(x))
56
57
58static inline void delay(void)
59{
60#if defined(CONFIG_PCI)
61 /* System board present, just make a dummy SRAM access. (CS0 will be
62 mapped to PCI memory, probably good to avoid it.) */
63 ctrl_inw(0xa6800000);
64#else
65 /* CS0 will be mapped to flash, ROM etc so safe to access it. */
66 ctrl_inw(0xa0000000);
67#endif
68}
69
70unsigned char microdev_inb(unsigned long port)
71{
72#ifdef CONFIG_PCI
73 if (port >= PCIBIOS_MIN_IO)
74 return microdev_pci_inb(port);
75#endif
76 return *(volatile unsigned char*)PORT2ADDR(port);
77}
78
79unsigned short microdev_inw(unsigned long port)
80{
81#ifdef CONFIG_PCI
82 if (port >= PCIBIOS_MIN_IO)
83 return microdev_pci_inw(port);
84#endif
85 return *(volatile unsigned short*)PORT2ADDR(port);
86}
87
88unsigned int microdev_inl(unsigned long port)
89{
90#ifdef CONFIG_PCI
91 if (port >= PCIBIOS_MIN_IO)
92 return microdev_pci_inl(port);
93#endif
94 return *(volatile unsigned int*)PORT2ADDR(port);
95}
96
97void microdev_outb(unsigned char b, unsigned long port)
98{
99#ifdef CONFIG_PCI
100 if (port >= PCIBIOS_MIN_IO) {
101 microdev_pci_outb(b, port);
102 return;
103 }
104#endif
105
106 /*
107 * There is a board feature with the current SH4-202 MicroDev in
108 * that the 2 byte enables (nBE0 and nBE1) are tied together (and
109 * to the Chip Select Line (Ethernet_CS)). Due to this conectivity,
110 * it is not possible to safely perform 8-bit writes to the
111 * Ethernet registers, as 16-bits will be consumed from the Data
112 * lines (corrupting the other byte). Hence, this function is
113 * written to impliment 16-bit read/modify/write for all byte-wide
114 * acceses.
115 *
116 * Note: there is no problem with byte READS (even or odd).
117 *
118 * Sean McGoogan - 16th June 2003.
119 */
120 if ((port >= IO_LAN91C111_BASE) &&
121 (port < IO_LAN91C111_BASE + IO_LAN91C111_EXTENT)) {
122 /*
123 * Then are trying to perform a byte-write to the
124 * LAN91C111. This needs special care.
125 */
126 if (port % 2 == 1) { /* is the port odd ? */
127 /* unset bit-0, i.e. make even */
128 const unsigned long evenPort = port-1;
129 unsigned short word;
130
131 /*
132 * do a 16-bit read/write to write to 'port',
133 * preserving even byte.
134 *
135 * Even addresses are bits 0-7
136 * Odd addresses are bits 8-15
137 */
138 word = microdev_inw(evenPort);
139 word = (word & 0xffu) | (b << 8);
140 microdev_outw(word, evenPort);
141 } else {
142 /* else, we are trying to do an even byte write */
143 unsigned short word;
144
145 /*
146 * do a 16-bit read/write to write to 'port',
147 * preserving odd byte.
148 *
149 * Even addresses are bits 0-7
150 * Odd addresses are bits 8-15
151 */
152 word = microdev_inw(port);
153 word = (word & 0xff00u) | (b);
154 microdev_outw(word, port);
155 }
156 } else {
157 *(volatile unsigned char*)PORT2ADDR(port) = b;
158 }
159}
160
161void microdev_outw(unsigned short b, unsigned long port)
162{
163#ifdef CONFIG_PCI
164 if (port >= PCIBIOS_MIN_IO) {
165 microdev_pci_outw(b, port);
166 return;
167 }
168#endif
169 *(volatile unsigned short*)PORT2ADDR(port) = b;
170}
171
172void microdev_outl(unsigned int b, unsigned long port)
173{
174#ifdef CONFIG_PCI
175 if (port >= PCIBIOS_MIN_IO) {
176 microdev_pci_outl(b, port);
177 return;
178 }
179#endif
180 *(volatile unsigned int*)PORT2ADDR(port) = b;
181}
182
183unsigned char microdev_inb_p(unsigned long port)
184{
185 unsigned char v = microdev_inb(port);
186 delay();
187 return v;
188}
189
190unsigned short microdev_inw_p(unsigned long port)
191{
192 unsigned short v = microdev_inw(port);
193 delay();
194 return v;
195}
196
197unsigned int microdev_inl_p(unsigned long port)
198{
199 unsigned int v = microdev_inl(port);
200 delay();
201 return v;
202}
203
204void microdev_outb_p(unsigned char b, unsigned long port)
205{
206 microdev_outb(b, port);
207 delay();
208}
209
210void microdev_outw_p(unsigned short b, unsigned long port)
211{
212 microdev_outw(b, port);
213 delay();
214}
215
216void microdev_outl_p(unsigned int b, unsigned long port)
217{
218 microdev_outl(b, port);
219 delay();
220}
221
222void microdev_insb(unsigned long port, void *buffer, unsigned long count)
223{
224 volatile unsigned char *port_addr;
225 unsigned char *buf = buffer;
226
227 port_addr = (volatile unsigned char *)PORT2ADDR(port);
228
229 while (count--)
230 *buf++ = *port_addr;
231}
232
233void microdev_insw(unsigned long port, void *buffer, unsigned long count)
234{
235 volatile unsigned short *port_addr;
236 unsigned short *buf = buffer;
237
238 port_addr = (volatile unsigned short *)PORT2ADDR(port);
239
240 while (count--)
241 *buf++ = *port_addr;
242}
243
244void microdev_insl(unsigned long port, void *buffer, unsigned long count)
245{
246 volatile unsigned long *port_addr;
247 unsigned int *buf = buffer;
248
249 port_addr = (volatile unsigned long *)PORT2ADDR(port);
250
251 while (count--)
252 *buf++ = *port_addr;
253}
254
255void microdev_outsb(unsigned long port, const void *buffer, unsigned long count)
256{
257 volatile unsigned char *port_addr;
258 const unsigned char *buf = buffer;
259
260 port_addr = (volatile unsigned char *)PORT2ADDR(port);
261
262 while (count--)
263 *port_addr = *buf++;
264}
265
266void microdev_outsw(unsigned long port, const void *buffer, unsigned long count)
267{
268 volatile unsigned short *port_addr;
269 const unsigned short *buf = buffer;
270
271 port_addr = (volatile unsigned short *)PORT2ADDR(port);
272
273 while (count--)
274 *port_addr = *buf++;
275}
276
277void microdev_outsl(unsigned long port, const void *buffer, unsigned long count)
278{
279 volatile unsigned long *port_addr;
280 const unsigned int *buf = buffer;
281
282 port_addr = (volatile unsigned long *)PORT2ADDR(port);
283
284 while (count--)
285 *port_addr = *buf++;
286}
287
288/*
289 * map I/O ports to memory-mapped addresses
290 */
291unsigned long microdev_isa_port2addr(unsigned long offset)
292{
293 unsigned long result;
294
295 if ((offset >= IO_LAN91C111_BASE) &&
296 (offset < IO_LAN91C111_BASE + IO_LAN91C111_EXTENT)) {
297 /*
298 * SMSC LAN91C111 Ethernet chip
299 */
300 result = IO_LAN91C111_PHYS + offset - IO_LAN91C111_BASE;
301 } else if ((offset >= IO_SUPERIO_BASE) &&
302 (offset < IO_SUPERIO_BASE + IO_SUPERIO_EXTENT)) {
303 /*
304 * SMSC FDC37C93xAPM SuperIO chip
305 *
306 * Configuration Registers
307 */
308 result = IO_SUPERIO_PHYS + (offset << 1);
309#if 0
310 } else if (offset == KBD_DATA_REG || offset == KBD_CNTL_REG ||
311 offset == KBD_STATUS_REG) {
312 /*
313 * SMSC FDC37C93xAPM SuperIO chip
314 *
315 * PS/2 Keyboard + Mouse (ports 0x60 and 0x64).
316 */
317 result = IO_SUPERIO_PHYS + (offset << 1);
318#endif
319 } else if (((offset >= IO_IDE1_BASE) &&
320 (offset < IO_IDE1_BASE + IO_IDE_EXTENT)) ||
321 (offset == IO_IDE1_MISC)) {
322 /*
323 * SMSC FDC37C93xAPM SuperIO chip
324 *
325 * IDE #1
326 */
327 result = IO_SUPERIO_PHYS + (offset << 1);
328 } else if (((offset >= IO_IDE2_BASE) &&
329 (offset < IO_IDE2_BASE + IO_IDE_EXTENT)) ||
330 (offset == IO_IDE2_MISC)) {
331 /*
332 * SMSC FDC37C93xAPM SuperIO chip
333 *
334 * IDE #2
335 */
336 result = IO_SUPERIO_PHYS + (offset << 1);
337 } else if ((offset >= IO_SERIAL1_BASE) &&
338 (offset < IO_SERIAL1_BASE + IO_SERIAL_EXTENT)) {
339 /*
340 * SMSC FDC37C93xAPM SuperIO chip
341 *
342 * Serial #1
343 */
344 result = IO_SUPERIO_PHYS + (offset << 1);
345 } else if ((offset >= IO_SERIAL2_BASE) &&
346 (offset < IO_SERIAL2_BASE + IO_SERIAL_EXTENT)) {
347 /*
348 * SMSC FDC37C93xAPM SuperIO chip
349 *
350 * Serial #2
351 */
352 result = IO_SUPERIO_PHYS + (offset << 1);
353 } else if ((offset >= IO_ISP1161_BASE) &&
354 (offset < IO_ISP1161_BASE + IO_ISP1161_EXTENT)) {
355 /*
356 * Philips USB ISP1161x chip
357 */
358 result = IO_ISP1161_PHYS + offset - IO_ISP1161_BASE;
359 } else {
360 /*
361 * safe default.
362 */
363 printk("Warning: unexpected port in %s( offset = 0x%lx )\n",
364 __FUNCTION__, offset);
365 result = PVR;
366 }
367
368 return result;
369}
370
diff --git a/arch/sh/boards/superh/microdev/irq.c b/arch/sh/boards/superh/microdev/irq.c
new file mode 100644
index 00000000000..1298883eca4
--- /dev/null
+++ b/arch/sh/boards/superh/microdev/irq.c
@@ -0,0 +1,200 @@
1/*
2 * arch/sh/boards/superh/microdev/irq.c
3 *
4 * Copyright (C) 2003 Sean McGoogan (Sean.McGoogan@superh.com)
5 *
6 * SuperH SH4-202 MicroDev board support.
7 *
8 * May be copied or modified under the terms of the GNU General Public
9 * License. See linux/COPYING for more information.
10 */
11
12#include <linux/config.h>
13#include <linux/init.h>
14#include <linux/irq.h>
15
16#include <asm/system.h>
17#include <asm/io.h>
18#include <asm/mach/irq.h>
19
20#define NUM_EXTERNAL_IRQS 16 /* IRL0 .. IRL15 */
21
22
23static const struct {
24 unsigned char fpgaIrq;
25 unsigned char mapped;
26 const char *name;
27} fpgaIrqTable[NUM_EXTERNAL_IRQS] = {
28 { 0, 0, "unused" }, /* IRQ #0 IRL=15 0x200 */
29 { MICRODEV_FPGA_IRQ_KEYBOARD, 1, "keyboard" }, /* IRQ #1 IRL=14 0x220 */
30 { MICRODEV_FPGA_IRQ_SERIAL1, 1, "Serial #1"}, /* IRQ #2 IRL=13 0x240 */
31 { MICRODEV_FPGA_IRQ_ETHERNET, 1, "Ethernet" }, /* IRQ #3 IRL=12 0x260 */
32 { MICRODEV_FPGA_IRQ_SERIAL2, 0, "Serial #2"}, /* IRQ #4 IRL=11 0x280 */
33 { 0, 0, "unused" }, /* IRQ #5 IRL=10 0x2a0 */
34 { 0, 0, "unused" }, /* IRQ #6 IRL=9 0x2c0 */
35 { MICRODEV_FPGA_IRQ_USB_HC, 1, "USB" }, /* IRQ #7 IRL=8 0x2e0 */
36 { MICRODEV_IRQ_PCI_INTA, 1, "PCI INTA" }, /* IRQ #8 IRL=7 0x300 */
37 { MICRODEV_IRQ_PCI_INTB, 1, "PCI INTB" }, /* IRQ #9 IRL=6 0x320 */
38 { MICRODEV_IRQ_PCI_INTC, 1, "PCI INTC" }, /* IRQ #10 IRL=5 0x340 */
39 { MICRODEV_IRQ_PCI_INTD, 1, "PCI INTD" }, /* IRQ #11 IRL=4 0x360 */
40 { MICRODEV_FPGA_IRQ_MOUSE, 1, "mouse" }, /* IRQ #12 IRL=3 0x380 */
41 { MICRODEV_FPGA_IRQ_IDE2, 1, "IDE #2" }, /* IRQ #13 IRL=2 0x3a0 */
42 { MICRODEV_FPGA_IRQ_IDE1, 1, "IDE #1" }, /* IRQ #14 IRL=1 0x3c0 */
43 { 0, 0, "unused" }, /* IRQ #15 IRL=0 0x3e0 */
44};
45
46#if (MICRODEV_LINUX_IRQ_KEYBOARD != 1)
47# error Inconsistancy in defining the IRQ# for Keyboard!
48#endif
49
50#if (MICRODEV_LINUX_IRQ_ETHERNET != 3)
51# error Inconsistancy in defining the IRQ# for Ethernet!
52#endif
53
54#if (MICRODEV_LINUX_IRQ_USB_HC != 7)
55# error Inconsistancy in defining the IRQ# for USB!
56#endif
57
58#if (MICRODEV_LINUX_IRQ_MOUSE != 12)
59# error Inconsistancy in defining the IRQ# for PS/2 Mouse!
60#endif
61
62#if (MICRODEV_LINUX_IRQ_IDE2 != 13)
63# error Inconsistancy in defining the IRQ# for secondary IDE!
64#endif
65
66#if (MICRODEV_LINUX_IRQ_IDE1 != 14)
67# error Inconsistancy in defining the IRQ# for primary IDE!
68#endif
69
70static void enable_microdev_irq(unsigned int irq);
71static void disable_microdev_irq(unsigned int irq);
72
73 /* shutdown is same as "disable" */
74#define shutdown_microdev_irq disable_microdev_irq
75
76static void mask_and_ack_microdev(unsigned int);
77static void end_microdev_irq(unsigned int irq);
78
79static unsigned int startup_microdev_irq(unsigned int irq)
80{
81 enable_microdev_irq(irq);
82 return 0; /* never anything pending */
83}
84
85static struct hw_interrupt_type microdev_irq_type = {
86 "MicroDev-IRQ",
87 startup_microdev_irq,
88 shutdown_microdev_irq,
89 enable_microdev_irq,
90 disable_microdev_irq,
91 mask_and_ack_microdev,
92 end_microdev_irq
93};
94
95static void disable_microdev_irq(unsigned int irq)
96{
97 unsigned int flags;
98 unsigned int fpgaIrq;
99
100 if (irq >= NUM_EXTERNAL_IRQS) return;
101 if (!fpgaIrqTable[irq].mapped) return;
102
103 fpgaIrq = fpgaIrqTable[irq].fpgaIrq;
104
105 /* disable interrupts */
106 local_irq_save(flags);
107
108 /* disable interupts on the FPGA INTC register */
109 ctrl_outl(MICRODEV_FPGA_INTC_MASK(fpgaIrq), MICRODEV_FPGA_INTDSB_REG);
110
111 /* restore interrupts */
112 local_irq_restore(flags);
113}
114
115static void enable_microdev_irq(unsigned int irq)
116{
117 unsigned long priorityReg, priorities, pri;
118 unsigned int flags;
119 unsigned int fpgaIrq;
120
121
122 if (irq >= NUM_EXTERNAL_IRQS) return;
123 if (!fpgaIrqTable[irq].mapped) return;
124
125 pri = 15 - irq;
126
127 fpgaIrq = fpgaIrqTable[irq].fpgaIrq;
128 priorityReg = MICRODEV_FPGA_INTPRI_REG(fpgaIrq);
129
130 /* disable interrupts */
131 local_irq_save(flags);
132
133 /* set priority for the interrupt */
134 priorities = ctrl_inl(priorityReg);
135 priorities &= ~MICRODEV_FPGA_INTPRI_MASK(fpgaIrq);
136 priorities |= MICRODEV_FPGA_INTPRI_LEVEL(fpgaIrq, pri);
137 ctrl_outl(priorities, priorityReg);
138
139 /* enable interupts on the FPGA INTC register */
140 ctrl_outl(MICRODEV_FPGA_INTC_MASK(fpgaIrq), MICRODEV_FPGA_INTENB_REG);
141
142 /* restore interrupts */
143 local_irq_restore(flags);
144}
145
146 /* This functions sets the desired irq handler to be a MicroDev type */
147static void __init make_microdev_irq(unsigned int irq)
148{
149 disable_irq_nosync(irq);
150 irq_desc[irq].handler = &microdev_irq_type;
151 disable_microdev_irq(irq);
152}
153
154static void mask_and_ack_microdev(unsigned int irq)
155{
156 disable_microdev_irq(irq);
157}
158
159static void end_microdev_irq(unsigned int irq)
160{
161 if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
162 {
163 enable_microdev_irq(irq);
164 }
165}
166
167extern void __init init_microdev_irq(void)
168{
169 int i;
170
171 /* disable interupts on the FPGA INTC register */
172 ctrl_outl(~0ul, MICRODEV_FPGA_INTDSB_REG);
173
174 for (i = 0; i < NUM_EXTERNAL_IRQS; i++)
175 {
176 make_microdev_irq(i);
177 }
178}
179
180extern void microdev_print_fpga_intc_status(void)
181{
182 volatile unsigned int * const intenb = (unsigned int*)MICRODEV_FPGA_INTENB_REG;
183 volatile unsigned int * const intdsb = (unsigned int*)MICRODEV_FPGA_INTDSB_REG;
184 volatile unsigned int * const intpria = (unsigned int*)MICRODEV_FPGA_INTPRI_REG(0);
185 volatile unsigned int * const intprib = (unsigned int*)MICRODEV_FPGA_INTPRI_REG(8);
186 volatile unsigned int * const intpric = (unsigned int*)MICRODEV_FPGA_INTPRI_REG(16);
187 volatile unsigned int * const intprid = (unsigned int*)MICRODEV_FPGA_INTPRI_REG(24);
188 volatile unsigned int * const intsrc = (unsigned int*)MICRODEV_FPGA_INTSRC_REG;
189 volatile unsigned int * const intreq = (unsigned int*)MICRODEV_FPGA_INTREQ_REG;
190
191 printk("-------------------------- microdev_print_fpga_intc_status() ------------------\n");
192 printk("FPGA_INTENB = 0x%08x\n", *intenb);
193 printk("FPGA_INTDSB = 0x%08x\n", *intdsb);
194 printk("FPGA_INTSRC = 0x%08x\n", *intsrc);
195 printk("FPGA_INTREQ = 0x%08x\n", *intreq);
196 printk("FPGA_INTPRI[3..0] = %08x:%08x:%08x:%08x\n", *intprid, *intpric, *intprib, *intpria);
197 printk("-------------------------------------------------------------------------------\n");
198}
199
200
diff --git a/arch/sh/boards/superh/microdev/led.c b/arch/sh/boards/superh/microdev/led.c
new file mode 100644
index 00000000000..52a98e69d3f
--- /dev/null
+++ b/arch/sh/boards/superh/microdev/led.c
@@ -0,0 +1,102 @@
1/*
2 * linux/arch/sh/kernel/led_microdev.c
3 *
4 * Copyright (C) 2002 Stuart Menefy <stuart.menefy@st.com>
5 * Copyright (C) 2003 Richard Curnow (Richard.Curnow@superh.com)
6 *
7 * May be copied or modified under the terms of the GNU General Public
8 * License. See linux/COPYING for more information.
9 *
10 */
11
12#include <linux/config.h>
13#include <asm/io.h>
14
15#define LED_REGISTER 0xa6104d20
16
17static void mach_led_d9(int value)
18{
19 unsigned long reg;
20 reg = ctrl_inl(LED_REGISTER);
21 reg &= ~1;
22 reg |= (value & 1);
23 ctrl_outl(reg, LED_REGISTER);
24 return;
25}
26
27static void mach_led_d10(int value)
28{
29 unsigned long reg;
30 reg = ctrl_inl(LED_REGISTER);
31 reg &= ~2;
32 reg |= ((value & 1) << 1);
33 ctrl_outl(reg, LED_REGISTER);
34 return;
35}
36
37
38#ifdef CONFIG_HEARTBEAT
39#include <linux/sched.h>
40
41static unsigned char banner_table[] = {
42 0x11, 0x01, 0x11, 0x01, 0x11, 0x03,
43 0x11, 0x01, 0x11, 0x01, 0x13, 0x03,
44 0x11, 0x01, 0x13, 0x01, 0x13, 0x01, 0x11, 0x03,
45 0x11, 0x03,
46 0x11, 0x01, 0x13, 0x01, 0x11, 0x03,
47 0x11, 0x01, 0x11, 0x01, 0x11, 0x01, 0x11, 0x07,
48 0x13, 0x01, 0x13, 0x03,
49 0x11, 0x01, 0x11, 0x03,
50 0x13, 0x01, 0x11, 0x01, 0x13, 0x01, 0x11, 0x03,
51 0x11, 0x01, 0x13, 0x01, 0x11, 0x03,
52 0x13, 0x01, 0x13, 0x01, 0x13, 0x03,
53 0x13, 0x01, 0x11, 0x01, 0x11, 0x03,
54 0x11, 0x03,
55 0x11, 0x01, 0x11, 0x01, 0x11, 0x01, 0x13, 0x07,
56 0xff
57};
58
59static void banner(void)
60{
61 static int pos = 0;
62 static int count = 0;
63
64 if (count) {
65 count--;
66 } else {
67 int val = banner_table[pos];
68 if (val == 0xff) {
69 pos = 0;
70 val = banner_table[pos];
71 }
72 pos++;
73 mach_led_d10((val >> 4) & 1);
74 count = 10 * (val & 0xf);
75 }
76}
77
78/* From heartbeat_harp in the stboards directory */
79/* acts like an actual heart beat -- ie thump-thump-pause... */
80void microdev_heartbeat(void)
81{
82 static unsigned cnt = 0, period = 0, dist = 0;
83
84 if (cnt == 0 || cnt == dist)
85 mach_led_d9(1);
86 else if (cnt == 7 || cnt == dist+7)
87 mach_led_d9(0);
88
89 if (++cnt > period) {
90 cnt = 0;
91 /* The hyperbolic function below modifies the heartbeat period
92 * length in dependency of the current (5min) load. It goes
93 * through the points f(0)=126, f(1)=86, f(5)=51,
94 * f(inf)->30. */
95 period = ((672<<FSHIFT)/(5*avenrun[0]+(7<<FSHIFT))) + 30;
96 dist = period / 4;
97 }
98
99 banner();
100}
101
102#endif
diff --git a/arch/sh/boards/superh/microdev/setup.c b/arch/sh/boards/superh/microdev/setup.c
new file mode 100644
index 00000000000..c18919941ec
--- /dev/null
+++ b/arch/sh/boards/superh/microdev/setup.c
@@ -0,0 +1,278 @@
1/*
2 * arch/sh/boards/superh/microdev/setup.c
3 *
4 * Copyright (C) 2003 Sean McGoogan (Sean.McGoogan@superh.com)
5 * Copyright (C) 2003, 2004 SuperH, Inc.
6 * Copyright (C) 2004 Paul Mundt
7 *
8 * SuperH SH4-202 MicroDev board support.
9 *
10 * May be copied or modified under the terms of the GNU General Public
11 * License. See linux/COPYING for more information.
12 */
13
14#include <linux/config.h>
15#include <linux/init.h>
16#include <linux/device.h>
17#include <linux/ioport.h>
18#include <asm/io.h>
19#include <asm/mach/irq.h>
20#include <asm/mach/io.h>
21#include <asm/machvec.h>
22#include <asm/machvec_init.h>
23
24extern void microdev_heartbeat(void);
25
26/*
27 * The Machine Vector
28 */
29
30struct sh_machine_vector mv_sh4202_microdev __initmv = {
31 .mv_nr_irqs = 72, /* QQQ need to check this - use the MACRO */
32
33 .mv_inb = microdev_inb,
34 .mv_inw = microdev_inw,
35 .mv_inl = microdev_inl,
36 .mv_outb = microdev_outb,
37 .mv_outw = microdev_outw,
38 .mv_outl = microdev_outl,
39
40 .mv_inb_p = microdev_inb_p,
41 .mv_inw_p = microdev_inw_p,
42 .mv_inl_p = microdev_inl_p,
43 .mv_outb_p = microdev_outb_p,
44 .mv_outw_p = microdev_outw_p,
45 .mv_outl_p = microdev_outl_p,
46
47 .mv_insb = microdev_insb,
48 .mv_insw = microdev_insw,
49 .mv_insl = microdev_insl,
50 .mv_outsb = microdev_outsb,
51 .mv_outsw = microdev_outsw,
52 .mv_outsl = microdev_outsl,
53
54 .mv_isa_port2addr = microdev_isa_port2addr,
55
56 .mv_init_irq = init_microdev_irq,
57
58#ifdef CONFIG_HEARTBEAT
59 .mv_heartbeat = microdev_heartbeat,
60#endif
61};
62ALIAS_MV(sh4202_microdev)
63
64/****************************************************************************/
65
66
67 /*
68 * Setup for the SMSC FDC37C93xAPM
69 */
70#define SMSC_CONFIG_PORT_ADDR (0x3F0)
71#define SMSC_INDEX_PORT_ADDR SMSC_CONFIG_PORT_ADDR
72#define SMSC_DATA_PORT_ADDR (SMSC_INDEX_PORT_ADDR + 1)
73
74#define SMSC_ENTER_CONFIG_KEY 0x55
75#define SMSC_EXIT_CONFIG_KEY 0xaa
76
77#define SMCS_LOGICAL_DEV_INDEX 0x07 /* Logical Device Number */
78#define SMSC_DEVICE_ID_INDEX 0x20 /* Device ID */
79#define SMSC_DEVICE_REV_INDEX 0x21 /* Device Revision */
80#define SMSC_ACTIVATE_INDEX 0x30 /* Activate */
81#define SMSC_PRIMARY_BASE_INDEX 0x60 /* Primary Base Address */
82#define SMSC_SECONDARY_BASE_INDEX 0x62 /* Secondary Base Address */
83#define SMSC_PRIMARY_INT_INDEX 0x70 /* Primary Interrupt Select */
84#define SMSC_SECONDARY_INT_INDEX 0x72 /* Secondary Interrupt Select */
85#define SMSC_HDCS0_INDEX 0xf0 /* HDCS0 Address Decoder */
86#define SMSC_HDCS1_INDEX 0xf1 /* HDCS1 Address Decoder */
87
88#define SMSC_IDE1_DEVICE 1 /* IDE #1 logical device */
89#define SMSC_IDE2_DEVICE 2 /* IDE #2 logical device */
90#define SMSC_PARALLEL_DEVICE 3 /* Parallel Port logical device */
91#define SMSC_SERIAL1_DEVICE 4 /* Serial #1 logical device */
92#define SMSC_SERIAL2_DEVICE 5 /* Serial #2 logical device */
93#define SMSC_KEYBOARD_DEVICE 7 /* Keyboard logical device */
94#define SMSC_CONFIG_REGISTERS 8 /* Configuration Registers (Aux I/O) */
95
96#define SMSC_READ_INDEXED(index) ({ \
97 outb((index), SMSC_INDEX_PORT_ADDR); \
98 inb(SMSC_DATA_PORT_ADDR); })
99#define SMSC_WRITE_INDEXED(val, index) ({ \
100 outb((index), SMSC_INDEX_PORT_ADDR); \
101 outb((val), SMSC_DATA_PORT_ADDR); })
102
103#define IDE1_PRIMARY_BASE 0x01f0 /* Task File Registe base for IDE #1 */
104#define IDE1_SECONDARY_BASE 0x03f6 /* Miscellaneous AT registers for IDE #1 */
105#define IDE2_PRIMARY_BASE 0x0170 /* Task File Registe base for IDE #2 */
106#define IDE2_SECONDARY_BASE 0x0376 /* Miscellaneous AT registers for IDE #2 */
107
108#define SERIAL1_PRIMARY_BASE 0x03f8
109#define SERIAL2_PRIMARY_BASE 0x02f8
110
111#define MSB(x) ( (x) >> 8 )
112#define LSB(x) ( (x) & 0xff )
113
114 /* General-Purpose base address on CPU-board FPGA */
115#define MICRODEV_FPGA_GP_BASE 0xa6100000ul
116
117 /* assume a Keyboard Controller is present */
118int microdev_kbd_controller_present = 1;
119
120const char *get_system_type(void)
121{
122 return "SH4-202 MicroDev";
123}
124
125static struct resource smc91x_resources[] = {
126 [0] = {
127 .start = 0x300,
128 .end = 0x300 + 0x0001000 - 1,
129 .flags = IORESOURCE_MEM,
130 },
131 [1] = {
132 .start = MICRODEV_LINUX_IRQ_ETHERNET,
133 .end = MICRODEV_LINUX_IRQ_ETHERNET,
134 .flags = IORESOURCE_IRQ,
135 },
136};
137
138static struct platform_device smc91x_device = {
139 .name = "smc91x",
140 .id = -1,
141 .num_resources = ARRAY_SIZE(smc91x_resources),
142 .resource = smc91x_resources,
143};
144
145static int __init smc91x_setup(void)
146{
147 return platform_device_register(&smc91x_device);
148}
149
150__initcall(smc91x_setup);
151
152 /*
153 * Initialize the board
154 */
155void __init platform_setup(void)
156{
157 int * const fpgaRevisionRegister = (int*)(MICRODEV_FPGA_GP_BASE + 0x8ul);
158 const int fpgaRevision = *fpgaRevisionRegister;
159 int * const CacheControlRegister = (int*)CCR;
160
161 printk("SuperH %s board (FPGA rev: 0x%0x, CCR: 0x%0x)\n",
162 get_system_type(), fpgaRevision, *CacheControlRegister);
163}
164
165
166/****************************************************************************/
167
168
169 /*
170 * Setup for the SMSC FDC37C93xAPM
171 */
172static int __init smsc_superio_setup(void)
173{
174
175 unsigned char devid, devrev;
176
177 /* Initially the chip is in run state */
178 /* Put it into configuration state */
179 outb(SMSC_ENTER_CONFIG_KEY, SMSC_CONFIG_PORT_ADDR);
180
181 /* Read device ID info */
182 devid = SMSC_READ_INDEXED(SMSC_DEVICE_ID_INDEX);
183 devrev = SMSC_READ_INDEXED(SMSC_DEVICE_REV_INDEX);
184 if ( (devid==0x30) && (devrev==0x01) )
185 {
186 printk("SMSC FDC37C93xAPM SuperIO device detected\n");
187 }
188 else
189 { /* not the device identity we expected */
190 printk("Not detected a SMSC FDC37C93xAPM SuperIO device (devid=0x%02x, rev=0x%02x)\n",
191 devid, devrev);
192 /* inform the keyboard driver that we have no keyboard controller */
193 microdev_kbd_controller_present = 0;
194 /* little point in doing anything else in this functon */
195 return 0;
196 }
197
198 /* Select the keyboard device */
199 SMSC_WRITE_INDEXED(SMSC_KEYBOARD_DEVICE, SMCS_LOGICAL_DEV_INDEX);
200 /* enable it */
201 SMSC_WRITE_INDEXED(1, SMSC_ACTIVATE_INDEX);
202 /* enable the interrupts */
203 SMSC_WRITE_INDEXED(MICRODEV_FPGA_IRQ_KEYBOARD, SMSC_PRIMARY_INT_INDEX);
204 SMSC_WRITE_INDEXED(MICRODEV_FPGA_IRQ_MOUSE, SMSC_SECONDARY_INT_INDEX);
205
206 /* Select the Serial #1 device */
207 SMSC_WRITE_INDEXED(SMSC_SERIAL1_DEVICE, SMCS_LOGICAL_DEV_INDEX);
208 /* enable it */
209 SMSC_WRITE_INDEXED(1, SMSC_ACTIVATE_INDEX);
210 /* program with port addresses */
211 SMSC_WRITE_INDEXED(MSB(SERIAL1_PRIMARY_BASE), SMSC_PRIMARY_BASE_INDEX+0);
212 SMSC_WRITE_INDEXED(LSB(SERIAL1_PRIMARY_BASE), SMSC_PRIMARY_BASE_INDEX+1);
213 SMSC_WRITE_INDEXED(0x00, SMSC_HDCS0_INDEX);
214 /* enable the interrupts */
215 SMSC_WRITE_INDEXED(MICRODEV_FPGA_IRQ_SERIAL1, SMSC_PRIMARY_INT_INDEX);
216
217 /* Select the Serial #2 device */
218 SMSC_WRITE_INDEXED(SMSC_SERIAL2_DEVICE, SMCS_LOGICAL_DEV_INDEX);
219 /* enable it */
220 SMSC_WRITE_INDEXED(1, SMSC_ACTIVATE_INDEX);
221 /* program with port addresses */
222 SMSC_WRITE_INDEXED(MSB(SERIAL2_PRIMARY_BASE), SMSC_PRIMARY_BASE_INDEX+0);
223 SMSC_WRITE_INDEXED(LSB(SERIAL2_PRIMARY_BASE), SMSC_PRIMARY_BASE_INDEX+1);
224 SMSC_WRITE_INDEXED(0x00, SMSC_HDCS0_INDEX);
225 /* enable the interrupts */
226 SMSC_WRITE_INDEXED(MICRODEV_FPGA_IRQ_SERIAL2, SMSC_PRIMARY_INT_INDEX);
227
228 /* Select the IDE#1 device */
229 SMSC_WRITE_INDEXED(SMSC_IDE1_DEVICE, SMCS_LOGICAL_DEV_INDEX);
230 /* enable it */
231 SMSC_WRITE_INDEXED(1, SMSC_ACTIVATE_INDEX);
232 /* program with port addresses */
233 SMSC_WRITE_INDEXED(MSB(IDE1_PRIMARY_BASE), SMSC_PRIMARY_BASE_INDEX+0);
234 SMSC_WRITE_INDEXED(LSB(IDE1_PRIMARY_BASE), SMSC_PRIMARY_BASE_INDEX+1);
235 SMSC_WRITE_INDEXED(MSB(IDE1_SECONDARY_BASE), SMSC_SECONDARY_BASE_INDEX+0);
236 SMSC_WRITE_INDEXED(LSB(IDE1_SECONDARY_BASE), SMSC_SECONDARY_BASE_INDEX+1);
237 SMSC_WRITE_INDEXED(0x0c, SMSC_HDCS0_INDEX);
238 SMSC_WRITE_INDEXED(0x00, SMSC_HDCS1_INDEX);
239 /* select the interrupt */
240 SMSC_WRITE_INDEXED(MICRODEV_FPGA_IRQ_IDE1, SMSC_PRIMARY_INT_INDEX);
241
242 /* Select the IDE#2 device */
243 SMSC_WRITE_INDEXED(SMSC_IDE2_DEVICE, SMCS_LOGICAL_DEV_INDEX);
244 /* enable it */
245 SMSC_WRITE_INDEXED(1, SMSC_ACTIVATE_INDEX);
246 /* program with port addresses */
247 SMSC_WRITE_INDEXED(MSB(IDE2_PRIMARY_BASE), SMSC_PRIMARY_BASE_INDEX+0);
248 SMSC_WRITE_INDEXED(LSB(IDE2_PRIMARY_BASE), SMSC_PRIMARY_BASE_INDEX+1);
249 SMSC_WRITE_INDEXED(MSB(IDE2_SECONDARY_BASE), SMSC_SECONDARY_BASE_INDEX+0);
250 SMSC_WRITE_INDEXED(LSB(IDE2_SECONDARY_BASE), SMSC_SECONDARY_BASE_INDEX+1);
251 /* select the interrupt */
252 SMSC_WRITE_INDEXED(MICRODEV_FPGA_IRQ_IDE2, SMSC_PRIMARY_INT_INDEX);
253
254 /* Select the configuration registers */
255 SMSC_WRITE_INDEXED(SMSC_CONFIG_REGISTERS, SMCS_LOGICAL_DEV_INDEX);
256 /* enable the appropriate GPIO pins for IDE functionality:
257 * bit[0] In/Out 1==input; 0==output
258 * bit[1] Polarity 1==invert; 0==no invert
259 * bit[2] Int Enb #1 1==Enable Combined IRQ #1; 0==disable
260 * bit[3:4] Function Select 00==original; 01==Alternate Function #1
261 */
262 SMSC_WRITE_INDEXED(0x00, 0xc2); /* GP42 = nIDE1_OE */
263 SMSC_WRITE_INDEXED(0x01, 0xc5); /* GP45 = IDE1_IRQ */
264 SMSC_WRITE_INDEXED(0x00, 0xc6); /* GP46 = nIOROP */
265 SMSC_WRITE_INDEXED(0x00, 0xc7); /* GP47 = nIOWOP */
266 SMSC_WRITE_INDEXED(0x08, 0xe8); /* GP20 = nIDE2_OE */
267
268 /* Exit the configuraton state */
269 outb(SMSC_EXIT_CONFIG_KEY, SMSC_CONFIG_PORT_ADDR);
270
271 return 0;
272}
273
274
275/* This is grotty, but, because kernel is always referenced on the link line
276 * before any devices, this is safe.
277 */
278__initcall(smsc_superio_setup);
diff --git a/arch/sh/boards/unknown/Makefile b/arch/sh/boards/unknown/Makefile
new file mode 100644
index 00000000000..cffc21031e7
--- /dev/null
+++ b/arch/sh/boards/unknown/Makefile
@@ -0,0 +1,6 @@
1#
2# Makefile for unknown SH boards
3#
4
5obj-y := mach.o io.o setup.o
6
diff --git a/arch/sh/boards/unknown/io.c b/arch/sh/boards/unknown/io.c
new file mode 100644
index 00000000000..8f3f17267bd
--- /dev/null
+++ b/arch/sh/boards/unknown/io.c
@@ -0,0 +1,46 @@
1/*
2 * linux/arch/sh/kernel/io_unknown.c
3 *
4 * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com)
5 *
6 * May be copied or modified under the terms of the GNU General Public
7 * License. See linux/COPYING for more information.
8 *
9 * I/O routine for unknown hardware.
10 */
11
12static unsigned int unknown_handler(void)
13{
14 return 0;
15}
16
17#define UNKNOWN_ALIAS(fn) \
18 void unknown_##fn(void) __attribute__ ((alias ("unknown_handler")));
19
20UNKNOWN_ALIAS(inb)
21UNKNOWN_ALIAS(inw)
22UNKNOWN_ALIAS(inl)
23UNKNOWN_ALIAS(outb)
24UNKNOWN_ALIAS(outw)
25UNKNOWN_ALIAS(outl)
26UNKNOWN_ALIAS(inb_p)
27UNKNOWN_ALIAS(inw_p)
28UNKNOWN_ALIAS(inl_p)
29UNKNOWN_ALIAS(outb_p)
30UNKNOWN_ALIAS(outw_p)
31UNKNOWN_ALIAS(outl_p)
32UNKNOWN_ALIAS(insb)
33UNKNOWN_ALIAS(insw)
34UNKNOWN_ALIAS(insl)
35UNKNOWN_ALIAS(outsb)
36UNKNOWN_ALIAS(outsw)
37UNKNOWN_ALIAS(outsl)
38UNKNOWN_ALIAS(readb)
39UNKNOWN_ALIAS(readw)
40UNKNOWN_ALIAS(readl)
41UNKNOWN_ALIAS(writeb)
42UNKNOWN_ALIAS(writew)
43UNKNOWN_ALIAS(writel)
44UNKNOWN_ALIAS(isa_port2addr)
45UNKNOWN_ALIAS(ioremap)
46UNKNOWN_ALIAS(iounmap)
diff --git a/arch/sh/boards/unknown/mach.c b/arch/sh/boards/unknown/mach.c
new file mode 100644
index 00000000000..ad0bcc60a64
--- /dev/null
+++ b/arch/sh/boards/unknown/mach.c
@@ -0,0 +1,67 @@
1/*
2 * linux/arch/sh/kernel/mach_unknown.c
3 *
4 * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com)
5 *
6 * May be copied or modified under the terms of the GNU General Public
7 * License. See linux/COPYING for more information.
8 *
9 * Machine specific code for an unknown machine (internal peripherials only)
10 */
11
12#include <linux/config.h>
13#include <linux/init.h>
14
15#include <asm/machvec.h>
16#include <asm/machvec_init.h>
17
18#include <asm/io_unknown.h>
19
20#include <asm/rtc.h>
21/*
22 * The Machine Vector
23 */
24
25struct sh_machine_vector mv_unknown __initmv = {
26#if defined(CONFIG_CPU_SH4)
27 .mv_nr_irqs = 48,
28#elif defined(CONFIG_CPU_SUBTYPE_SH7708)
29 .mv_nr_irqs = 32,
30#elif defined(CONFIG_CPU_SUBTYPE_SH7709)
31 .mv_nr_irqs = 61,
32#endif
33
34 .mv_inb = unknown_inb,
35 .mv_inw = unknown_inw,
36 .mv_inl = unknown_inl,
37 .mv_outb = unknown_outb,
38 .mv_outw = unknown_outw,
39 .mv_outl = unknown_outl,
40
41 .mv_inb_p = unknown_inb_p,
42 .mv_inw_p = unknown_inw_p,
43 .mv_inl_p = unknown_inl_p,
44 .mv_outb_p = unknown_outb_p,
45 .mv_outw_p = unknown_outw_p,
46 .mv_outl_p = unknown_outl_p,
47
48 .mv_insb = unknown_insb,
49 .mv_insw = unknown_insw,
50 .mv_insl = unknown_insl,
51 .mv_outsb = unknown_outsb,
52 .mv_outsw = unknown_outsw,
53 .mv_outsl = unknown_outsl,
54
55 .mv_readb = unknown_readb,
56 .mv_readw = unknown_readw,
57 .mv_readl = unknown_readl,
58 .mv_writeb = unknown_writeb,
59 .mv_writew = unknown_writew,
60 .mv_writel = unknown_writel,
61
62 .mv_ioremap = unknown_ioremap,
63 .mv_iounmap = unknown_iounmap,
64
65 .mv_isa_port2addr = unknown_isa_port2addr,
66};
67ALIAS_MV(unknown)
diff --git a/arch/sh/boards/unknown/setup.c b/arch/sh/boards/unknown/setup.c
new file mode 100644
index 00000000000..7d772a6f886
--- /dev/null
+++ b/arch/sh/boards/unknown/setup.c
@@ -0,0 +1,23 @@
1/*
2 * linux/arch/sh/boards/unknown/setup.c
3 *
4 * Copyright (C) 2002 Paul Mundt
5 *
6 * May be copied or modified under the terms of the GNU General Public
7 * License. See linux/COPYING for more information.
8 *
9 * Setup code for an unknown machine (internal peripherials only)
10 */
11
12#include <linux/config.h>
13#include <linux/init.h>
14
15const char *get_system_type(void)
16{
17 return "Unknown";
18}
19
20void __init platform_setup(void)
21{
22}
23