aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh64
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sh64')
-rw-r--r--arch/sh64/kernel/Makefile36
-rw-r--r--arch/sh64/kernel/alphanum.c43
-rw-r--r--arch/sh64/kernel/dma.c297
-rw-r--r--arch/sh64/kernel/early_printk.c99
-rw-r--r--arch/sh64/kernel/led.c40
-rw-r--r--arch/sh64/kernel/pci_sh5.c536
-rw-r--r--arch/sh64/kernel/pci_sh5.h107
-rw-r--r--arch/sh64/kernel/pcibios.c168
-rw-r--r--arch/sh64/kernel/setup.c379
-rw-r--r--arch/sh64/kernel/time.c531
10 files changed, 0 insertions, 2236 deletions
diff --git a/arch/sh64/kernel/Makefile b/arch/sh64/kernel/Makefile
deleted file mode 100644
index e3467bda6167..000000000000
--- a/arch/sh64/kernel/Makefile
+++ /dev/null
@@ -1,36 +0,0 @@
1#
2# This file is subject to the terms and conditions of the GNU General Public
3# License. See the file "COPYING" in the main directory of this archive
4# for more details.
5#
6# Copyright (C) 2000, 2001 Paolo Alberelli
7# Copyright (C) 2003 Paul Mundt
8#
9# Makefile for the Linux sh64 kernel.
10#
11# Note! Dependencies are done automagically by 'make dep', which also
12# removes any old dependencies. DON'T put your own dependencies here
13# unless it's something special (ie not a .c file).
14#
15
16extra-y := head.o init_task.o vmlinux.lds
17
18obj-y := process.o signal.o entry.o traps.o irq.o irq_intc.o \
19 ptrace.o setup.o time.o sys_sh64.o semaphore.o sh_ksyms.o \
20 switchto.o syscalls.o
21
22obj-$(CONFIG_HEARTBEAT) += led.o
23obj-$(CONFIG_SH_ALPHANUMERIC) += alphanum.o
24obj-$(CONFIG_SH_DMA) += dma.o
25obj-$(CONFIG_SH_FPU) += fpu.o
26obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
27obj-$(CONFIG_KALLSYMS) += unwind.o
28obj-$(CONFIG_PCI) += pcibios.o
29obj-$(CONFIG_MODULES) += module.o
30
31ifeq ($(CONFIG_PCI),y)
32obj-$(CONFIG_CPU_SH5) += pci_sh5.o
33endif
34
35USE_STANDARD_AS_RULE := true
36
diff --git a/arch/sh64/kernel/alphanum.c b/arch/sh64/kernel/alphanum.c
deleted file mode 100644
index d1619d95fbaa..000000000000
--- a/arch/sh64/kernel/alphanum.c
+++ /dev/null
@@ -1,43 +0,0 @@
1/*
2 * arch/sh64/kernel/alphanum.c
3 *
4 * Copyright (C) 2002 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-independent functions for handling 8-digit alphanumeric display
10 * (e.g. Agilent HDSP-253x)
11 */
12#include <linux/stddef.h>
13#include <linux/sched.h>
14
15void mach_alphanum(int pos, unsigned char val);
16
17void print_seg(char *file, int line)
18{
19 int i;
20 unsigned int nibble;
21
22 for (i = 0; i < 5; i++) {
23 mach_alphanum(i, file[i]);
24 }
25
26 for (i = 0; i < 3; i++) {
27 nibble = ((line >> (i * 4)) & 0xf);
28 mach_alphanum(7 - i, nibble + ((nibble > 9) ? 55 : 48));
29 }
30}
31
32void print_seg_num(unsigned num)
33{
34 int i;
35 unsigned int nibble;
36
37 for (i = 0; i < 8; i++) {
38 nibble = ((num >> (i * 4)) & 0xf);
39
40 mach_alphanum(7 - i, nibble + ((nibble > 9) ? 55 : 48));
41 }
42}
43
diff --git a/arch/sh64/kernel/dma.c b/arch/sh64/kernel/dma.c
deleted file mode 100644
index 32c6f0549bf1..000000000000
--- a/arch/sh64/kernel/dma.c
+++ /dev/null
@@ -1,297 +0,0 @@
1/*
2 * arch/sh64/kernel/dma.c
3 *
4 * DMA routines for the SH-5 DMAC.
5 *
6 * Copyright (C) 2003 Paul Mundt
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#include <linux/init.h>
13#include <linux/module.h>
14#include <linux/interrupt.h>
15#include <linux/types.h>
16#include <linux/irq.h>
17#include <linux/spinlock.h>
18#include <linux/mm.h>
19#include <asm/hardware.h>
20#include <asm/dma.h>
21#include <asm/signal.h>
22#include <asm/errno.h>
23#include <asm/io.h>
24
25typedef struct {
26 unsigned long dev_addr;
27 unsigned long mem_addr;
28
29 unsigned int mode;
30 unsigned int count;
31} dma_info_t;
32
33static dma_info_t dma_info[MAX_DMA_CHANNELS];
34static DEFINE_SPINLOCK(dma_spin_lock);
35
36/* arch/sh64/kernel/irq_intc.c */
37extern void make_intc_irq(unsigned int irq);
38
39/* DMAC Interrupts */
40#define DMA_IRQ_DMTE0 18
41#define DMA_IRQ_DERR 22
42
43#define DMAC_COMMON_BASE (dmac_base + 0x08)
44#define DMAC_SAR_BASE (dmac_base + 0x10)
45#define DMAC_DAR_BASE (dmac_base + 0x18)
46#define DMAC_COUNT_BASE (dmac_base + 0x20)
47#define DMAC_CTRL_BASE (dmac_base + 0x28)
48#define DMAC_STATUS_BASE (dmac_base + 0x30)
49
50#define DMAC_SAR(n) (DMAC_SAR_BASE + ((n) * 0x28))
51#define DMAC_DAR(n) (DMAC_DAR_BASE + ((n) * 0x28))
52#define DMAC_COUNT(n) (DMAC_COUNT_BASE + ((n) * 0x28))
53#define DMAC_CTRL(n) (DMAC_CTRL_BASE + ((n) * 0x28))
54#define DMAC_STATUS(n) (DMAC_STATUS_BASE + ((n) * 0x28))
55
56/* DMAC.COMMON Bit Definitions */
57#define DMAC_COMMON_PR 0x00000001 /* Priority */
58 /* Bits 1-2 Reserved */
59#define DMAC_COMMON_ME 0x00000008 /* Master Enable */
60#define DMAC_COMMON_NMI 0x00000010 /* NMI Flag */
61 /* Bits 5-6 Reserved */
62#define DMAC_COMMON_ER 0x00000780 /* Error Response */
63#define DMAC_COMMON_AAE 0x00007800 /* Address Alignment Error */
64 /* Bits 15-63 Reserved */
65
66/* DMAC.SAR Bit Definitions */
67#define DMAC_SAR_ADDR 0xffffffff /* Source Address */
68
69/* DMAC.DAR Bit Definitions */
70#define DMAC_DAR_ADDR 0xffffffff /* Destination Address */
71
72/* DMAC.COUNT Bit Definitions */
73#define DMAC_COUNT_CNT 0xffffffff /* Transfer Count */
74
75/* DMAC.CTRL Bit Definitions */
76#define DMAC_CTRL_TS 0x00000007 /* Transfer Size */
77#define DMAC_CTRL_SI 0x00000018 /* Source Increment */
78#define DMAC_CTRL_DI 0x00000060 /* Destination Increment */
79#define DMAC_CTRL_RS 0x00000780 /* Resource Select */
80#define DMAC_CTRL_IE 0x00000800 /* Interrupt Enable */
81#define DMAC_CTRL_TE 0x00001000 /* Transfer Enable */
82 /* Bits 15-63 Reserved */
83
84/* DMAC.STATUS Bit Definitions */
85#define DMAC_STATUS_TE 0x00000001 /* Transfer End */
86#define DMAC_STATUS_AAE 0x00000002 /* Address Alignment Error */
87 /* Bits 2-63 Reserved */
88
89static unsigned long dmac_base;
90
91void set_dma_count(unsigned int chan, unsigned int count);
92void set_dma_addr(unsigned int chan, unsigned int addr);
93
94static irqreturn_t dma_mte(int irq, void *dev_id, struct pt_regs *regs)
95{
96 unsigned int chan = irq - DMA_IRQ_DMTE0;
97 dma_info_t *info = dma_info + chan;
98 u64 status;
99
100 if (info->mode & DMA_MODE_WRITE) {
101 sh64_out64(info->mem_addr & DMAC_SAR_ADDR, DMAC_SAR(chan));
102 } else {
103 sh64_out64(info->mem_addr & DMAC_DAR_ADDR, DMAC_DAR(chan));
104 }
105
106 set_dma_count(chan, info->count);
107
108 /* Clear the TE bit */
109 status = sh64_in64(DMAC_STATUS(chan));
110 status &= ~DMAC_STATUS_TE;
111 sh64_out64(status, DMAC_STATUS(chan));
112
113 return IRQ_HANDLED;
114}
115
116static struct irqaction irq_dmte = {
117 .handler = dma_mte,
118 .flags = IRQF_DISABLED,
119 .name = "DMA MTE",
120};
121
122static irqreturn_t dma_err(int irq, void *dev_id, struct pt_regs *regs)
123{
124 u64 tmp;
125 u8 chan;
126
127 printk(KERN_NOTICE "DMAC: Got a DMA Error!\n");
128
129 tmp = sh64_in64(DMAC_COMMON_BASE);
130
131 /* Check for the type of error */
132 if ((chan = tmp & DMAC_COMMON_AAE)) {
133 /* It's an address alignment error.. */
134 printk(KERN_NOTICE "DMAC: Alignment error on channel %d, ", chan);
135
136 printk(KERN_NOTICE "SAR: 0x%08llx, DAR: 0x%08llx, COUNT: %lld\n",
137 (sh64_in64(DMAC_SAR(chan)) & DMAC_SAR_ADDR),
138 (sh64_in64(DMAC_DAR(chan)) & DMAC_DAR_ADDR),
139 (sh64_in64(DMAC_COUNT(chan)) & DMAC_COUNT_CNT));
140
141 } else if ((chan = tmp & DMAC_COMMON_ER)) {
142 /* Something else went wrong.. */
143 printk(KERN_NOTICE "DMAC: Error on channel %d\n", chan);
144 }
145
146 /* Reset the ME bit to clear the interrupt */
147 tmp |= DMAC_COMMON_ME;
148 sh64_out64(tmp, DMAC_COMMON_BASE);
149
150 return IRQ_HANDLED;
151}
152
153static struct irqaction irq_derr = {
154 .handler = dma_err,
155 .flags = IRQF_DISABLED,
156 .name = "DMA Error",
157};
158
159static inline unsigned long calc_xmit_shift(unsigned int chan)
160{
161 return sh64_in64(DMAC_CTRL(chan)) & 0x03;
162}
163
164void setup_dma(unsigned int chan, dma_info_t *info)
165{
166 unsigned int irq = DMA_IRQ_DMTE0 + chan;
167 dma_info_t *dma = dma_info + chan;
168
169 make_intc_irq(irq);
170 setup_irq(irq, &irq_dmte);
171 dma = info;
172}
173
174void enable_dma(unsigned int chan)
175{
176 u64 ctrl;
177
178 ctrl = sh64_in64(DMAC_CTRL(chan));
179 ctrl |= DMAC_CTRL_TE;
180 sh64_out64(ctrl, DMAC_CTRL(chan));
181}
182
183void disable_dma(unsigned int chan)
184{
185 u64 ctrl;
186
187 ctrl = sh64_in64(DMAC_CTRL(chan));
188 ctrl &= ~DMAC_CTRL_TE;
189 sh64_out64(ctrl, DMAC_CTRL(chan));
190}
191
192void set_dma_mode(unsigned int chan, char mode)
193{
194 dma_info_t *info = dma_info + chan;
195
196 info->mode = mode;
197
198 set_dma_addr(chan, info->mem_addr);
199 set_dma_count(chan, info->count);
200}
201
202void set_dma_addr(unsigned int chan, unsigned int addr)
203{
204 dma_info_t *info = dma_info + chan;
205 unsigned long sar, dar;
206
207 info->mem_addr = addr;
208 sar = (info->mode & DMA_MODE_WRITE) ? info->mem_addr : info->dev_addr;
209 dar = (info->mode & DMA_MODE_WRITE) ? info->dev_addr : info->mem_addr;
210
211 sh64_out64(sar & DMAC_SAR_ADDR, DMAC_SAR(chan));
212 sh64_out64(dar & DMAC_SAR_ADDR, DMAC_DAR(chan));
213}
214
215void set_dma_count(unsigned int chan, unsigned int count)
216{
217 dma_info_t *info = dma_info + chan;
218 u64 tmp;
219
220 info->count = count;
221
222 tmp = (info->count >> calc_xmit_shift(chan)) & DMAC_COUNT_CNT;
223
224 sh64_out64(tmp, DMAC_COUNT(chan));
225}
226
227unsigned long claim_dma_lock(void)
228{
229 unsigned long flags;
230
231 spin_lock_irqsave(&dma_spin_lock, flags);
232
233 return flags;
234}
235
236void release_dma_lock(unsigned long flags)
237{
238 spin_unlock_irqrestore(&dma_spin_lock, flags);
239}
240
241int get_dma_residue(unsigned int chan)
242{
243 return sh64_in64(DMAC_COUNT(chan) << calc_xmit_shift(chan));
244}
245
246int __init init_dma(void)
247{
248 struct vcr_info vcr;
249 u64 tmp;
250
251 /* Remap the DMAC */
252 dmac_base = onchip_remap(PHYS_DMAC_BLOCK, 1024, "DMAC");
253 if (!dmac_base) {
254 printk(KERN_ERR "Unable to remap DMAC\n");
255 return -ENOMEM;
256 }
257
258 /* Report DMAC.VCR Info */
259 vcr = sh64_get_vcr_info(dmac_base);
260 printk("DMAC: Module ID: 0x%04x, Module version: 0x%04x\n",
261 vcr.mod_id, vcr.mod_vers);
262
263 /* Set the ME bit */
264 tmp = sh64_in64(DMAC_COMMON_BASE);
265 tmp |= DMAC_COMMON_ME;
266 sh64_out64(tmp, DMAC_COMMON_BASE);
267
268 /* Enable the DMAC Error Interrupt */
269 make_intc_irq(DMA_IRQ_DERR);
270 setup_irq(DMA_IRQ_DERR, &irq_derr);
271
272 return 0;
273}
274
275static void __exit exit_dma(void)
276{
277 onchip_unmap(dmac_base);
278 free_irq(DMA_IRQ_DERR, 0);
279}
280
281module_init(init_dma);
282module_exit(exit_dma);
283
284MODULE_AUTHOR("Paul Mundt");
285MODULE_DESCRIPTION("DMA API for SH-5 DMAC");
286MODULE_LICENSE("GPL");
287
288EXPORT_SYMBOL(setup_dma);
289EXPORT_SYMBOL(claim_dma_lock);
290EXPORT_SYMBOL(release_dma_lock);
291EXPORT_SYMBOL(enable_dma);
292EXPORT_SYMBOL(disable_dma);
293EXPORT_SYMBOL(set_dma_mode);
294EXPORT_SYMBOL(set_dma_addr);
295EXPORT_SYMBOL(set_dma_count);
296EXPORT_SYMBOL(get_dma_residue);
297
diff --git a/arch/sh64/kernel/early_printk.c b/arch/sh64/kernel/early_printk.c
deleted file mode 100644
index 4f9131123672..000000000000
--- a/arch/sh64/kernel/early_printk.c
+++ /dev/null
@@ -1,99 +0,0 @@
1/*
2 * arch/sh64/kernel/early_printk.c
3 *
4 * SH-5 Early SCIF console (cloned and hacked from sh implementation)
5 *
6 * Copyright (C) 2003, 2004 Paul Mundt <lethal@linux-sh.org>
7 * Copyright (C) 2002 M. R. Brown <mrbrown@0xd6.org>
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#include <linux/console.h>
14#include <linux/tty.h>
15#include <linux/init.h>
16#include <asm/io.h>
17#include <asm/hardware.h>
18
19#define SCIF_BASE_ADDR 0x01030000
20#define SCIF_ADDR_SH5 PHYS_PERIPHERAL_BLOCK+SCIF_BASE_ADDR
21
22/*
23 * Fixed virtual address where SCIF is mapped (should already be done
24 * in arch/sh64/kernel/head.S!).
25 */
26#define SCIF_REG 0xfa030000
27
28enum {
29 SCIF_SCSMR2 = SCIF_REG + 0x00,
30 SCIF_SCBRR2 = SCIF_REG + 0x04,
31 SCIF_SCSCR2 = SCIF_REG + 0x08,
32 SCIF_SCFTDR2 = SCIF_REG + 0x0c,
33 SCIF_SCFSR2 = SCIF_REG + 0x10,
34 SCIF_SCFRDR2 = SCIF_REG + 0x14,
35 SCIF_SCFCR2 = SCIF_REG + 0x18,
36 SCIF_SCFDR2 = SCIF_REG + 0x1c,
37 SCIF_SCSPTR2 = SCIF_REG + 0x20,
38 SCIF_SCLSR2 = SCIF_REG + 0x24,
39};
40
41static void sh_console_putc(int c)
42{
43 while (!(ctrl_inw(SCIF_SCFSR2) & 0x20))
44 cpu_relax();
45
46 ctrl_outb(c, SCIF_SCFTDR2);
47 ctrl_outw((ctrl_inw(SCIF_SCFSR2) & 0x9f), SCIF_SCFSR2);
48
49 if (c == '\n')
50 sh_console_putc('\r');
51}
52
53static void sh_console_flush(void)
54{
55 ctrl_outw((ctrl_inw(SCIF_SCFSR2) & 0xbf), SCIF_SCFSR2);
56
57 while (!(ctrl_inw(SCIF_SCFSR2) & 0x40))
58 cpu_relax();
59
60 ctrl_outw((ctrl_inw(SCIF_SCFSR2) & 0xbf), SCIF_SCFSR2);
61}
62
63static void sh_console_write(struct console *con, const char *s, unsigned count)
64{
65 while (count-- > 0)
66 sh_console_putc(*s++);
67
68 sh_console_flush();
69}
70
71static int __init sh_console_setup(struct console *con, char *options)
72{
73 con->cflag = CREAD | HUPCL | CLOCAL | B19200 | CS8;
74
75 return 0;
76}
77
78static struct console sh_console = {
79 .name = "scifcon",
80 .write = sh_console_write,
81 .setup = sh_console_setup,
82 .flags = CON_PRINTBUFFER | CON_BOOT,
83 .index = -1,
84};
85
86void __init enable_early_printk(void)
87{
88 ctrl_outb(0x2a, SCIF_SCBRR2); /* 19200bps */
89
90 ctrl_outw(0x04, SCIF_SCFCR2); /* Reset TFRST */
91 ctrl_outw(0x10, SCIF_SCFCR2); /* TTRG0=1 */
92
93 ctrl_outw(0, SCIF_SCSPTR2);
94 ctrl_outw(0x60, SCIF_SCFSR2);
95 ctrl_outw(0, SCIF_SCLSR2);
96 ctrl_outw(0x30, SCIF_SCSCR2);
97
98 register_console(&sh_console);
99}
diff --git a/arch/sh64/kernel/led.c b/arch/sh64/kernel/led.c
deleted file mode 100644
index e35d3f667fb4..000000000000
--- a/arch/sh64/kernel/led.c
+++ /dev/null
@@ -1,40 +0,0 @@
1/*
2 * arch/sh64/kernel/led.c
3 *
4 * Copyright (C) 2002 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 * Flash the LEDs
10 */
11#include <linux/stddef.h>
12#include <linux/sched.h>
13
14void mach_led(int pos, int val);
15
16/* acts like an actual heart beat -- ie thump-thump-pause... */
17void heartbeat(void)
18{
19 static unsigned int cnt = 0, period = 0, dist = 0;
20
21 if (cnt == 0 || cnt == dist) {
22 mach_led(-1, 1);
23 } else if (cnt == 7 || cnt == dist + 7) {
24 mach_led(-1, 0);
25 }
26
27 if (++cnt > period) {
28 cnt = 0;
29
30 /*
31 * The hyperbolic function below modifies the heartbeat period
32 * length in dependency of the current (5min) load. It goes
33 * through the points f(0)=126, f(1)=86, f(5)=51, f(inf)->30.
34 */
35 period = ((672 << FSHIFT) / (5 * avenrun[0] +
36 (7 << FSHIFT))) + 30;
37 dist = period / 4;
38 }
39}
40
diff --git a/arch/sh64/kernel/pci_sh5.c b/arch/sh64/kernel/pci_sh5.c
deleted file mode 100644
index b4d9534d2b0e..000000000000
--- a/arch/sh64/kernel/pci_sh5.c
+++ /dev/null
@@ -1,536 +0,0 @@
1/*
2 * Copyright (C) 2001 David J. Mckay (david.mckay@st.com)
3 * Copyright (C) 2003, 2004 Paul Mundt
4 * Copyright (C) 2004 Richard Curnow
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 * Support functions for the SH5 PCI hardware.
10 */
11
12#include <linux/kernel.h>
13#include <linux/rwsem.h>
14#include <linux/smp.h>
15#include <linux/interrupt.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 <asm/pci.h>
22#include <linux/irq.h>
23
24#include <asm/io.h>
25#include <asm/hardware.h>
26#include "pci_sh5.h"
27
28static unsigned long pcicr_virt;
29unsigned long pciio_virt;
30
31static void __init pci_fixup_ide_bases(struct pci_dev *d)
32{
33 int i;
34
35 /*
36 * PCI IDE controllers use non-standard I/O port decoding, respect it.
37 */
38 if ((d->class >> 8) != PCI_CLASS_STORAGE_IDE)
39 return;
40 printk("PCI: IDE base address fixup for %s\n", pci_name(d));
41 for(i=0; i<4; i++) {
42 struct resource *r = &d->resource[i];
43 if ((r->start & ~0x80) == 0x374) {
44 r->start |= 2;
45 r->end = r->start;
46 }
47 }
48}
49DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases);
50
51char * __devinit pcibios_setup(char *str)
52{
53 return str;
54}
55
56/* Rounds a number UP to the nearest power of two. Used for
57 * sizing the PCI window.
58 */
59static u32 __init r2p2(u32 num)
60{
61 int i = 31;
62 u32 tmp = num;
63
64 if (num == 0)
65 return 0;
66
67 do {
68 if (tmp & (1 << 31))
69 break;
70 i--;
71 tmp <<= 1;
72 } while (i >= 0);
73
74 tmp = 1 << i;
75 /* If the original number isn't a power of 2, round it up */
76 if (tmp != num)
77 tmp <<= 1;
78
79 return tmp;
80}
81
82extern unsigned long long memory_start, memory_end;
83
84int __init sh5pci_init(unsigned memStart, unsigned memSize)
85{
86 u32 lsr0;
87 u32 uval;
88
89 pcicr_virt = onchip_remap(SH5PCI_ICR_BASE, 1024, "PCICR");
90 if (!pcicr_virt) {
91 panic("Unable to remap PCICR\n");
92 }
93
94 pciio_virt = onchip_remap(SH5PCI_IO_BASE, 0x10000, "PCIIO");
95 if (!pciio_virt) {
96 panic("Unable to remap PCIIO\n");
97 }
98
99 pr_debug("Register base addres is 0x%08lx\n", pcicr_virt);
100
101 /* Clear snoop registers */
102 SH5PCI_WRITE(CSCR0, 0);
103 SH5PCI_WRITE(CSCR1, 0);
104
105 pr_debug("Wrote to reg\n");
106
107 /* Switch off interrupts */
108 SH5PCI_WRITE(INTM, 0);
109 SH5PCI_WRITE(AINTM, 0);
110 SH5PCI_WRITE(PINTM, 0);
111
112 /* Set bus active, take it out of reset */
113 uval = SH5PCI_READ(CR);
114
115 /* Set command Register */
116 SH5PCI_WRITE(CR, uval | CR_LOCK_MASK | CR_CFINT| CR_FTO | CR_PFE | CR_PFCS | CR_BMAM);
117
118 uval=SH5PCI_READ(CR);
119 pr_debug("CR is actually 0x%08x\n",uval);
120
121 /* Allow it to be a master */
122 /* NB - WE DISABLE I/O ACCESS to stop overlap */
123 /* set WAIT bit to enable stepping, an attempt to improve stability */
124 SH5PCI_WRITE_SHORT(CSR_CMD,
125 PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_WAIT);
126
127 /*
128 ** Set translation mapping memory in order to convert the address
129 ** used for the main bus, to the PCI internal address.
130 */
131 SH5PCI_WRITE(MBR,0x40000000);
132
133 /* Always set the max size 512M */
134 SH5PCI_WRITE(MBMR, PCISH5_MEM_SIZCONV(512*1024*1024));
135
136 /*
137 ** I/O addresses are mapped at internal PCI specific address
138 ** as is described into the configuration bridge table.
139 ** These are changed to 0, to allow cards that have legacy
140 ** io such as vga to function correctly. We set the SH5 IOBAR to
141 ** 256K, which is a bit big as we can only have 64K of address space
142 */
143
144 SH5PCI_WRITE(IOBR,0x0);
145
146 pr_debug("PCI:Writing 0x%08x to IOBR\n",0);
147
148 /* Set up a 256K window. Totally pointless waste of address space */
149 SH5PCI_WRITE(IOBMR,0);
150 pr_debug("PCI:Writing 0x%08x to IOBMR\n",0);
151
152 /* The SH5 has a HUGE 256K I/O region, which breaks the PCI spec. Ideally,
153 * we would want to map the I/O region somewhere, but it is so big this is not
154 * that easy!
155 */
156 SH5PCI_WRITE(CSR_IBAR0,~0);
157 /* Set memory size value */
158 memSize = memory_end - memory_start;
159
160 /* Now we set up the mbars so the PCI bus can see the memory of the machine */
161 if (memSize < (1024 * 1024)) {
162 printk(KERN_ERR "PCISH5: Ridiculous memory size of 0x%x?\n", memSize);
163 return -EINVAL;
164 }
165
166 /* Set LSR 0 */
167 lsr0 = (memSize > (512 * 1024 * 1024)) ? 0x1ff00001 : ((r2p2(memSize) - 0x100000) | 0x1);
168 SH5PCI_WRITE(LSR0, lsr0);
169
170 pr_debug("PCI:Writing 0x%08x to LSR0\n",lsr0);
171
172 /* Set MBAR 0 */
173 SH5PCI_WRITE(CSR_MBAR0, memory_start);
174 SH5PCI_WRITE(LAR0, memory_start);
175
176 SH5PCI_WRITE(CSR_MBAR1,0);
177 SH5PCI_WRITE(LAR1,0);
178 SH5PCI_WRITE(LSR1,0);
179
180 pr_debug("PCI:Writing 0x%08llx to CSR_MBAR0\n",memory_start);
181 pr_debug("PCI:Writing 0x%08llx to LAR0\n",memory_start);
182
183 /* Enable the PCI interrupts on the device */
184 SH5PCI_WRITE(INTM, ~0);
185 SH5PCI_WRITE(AINTM, ~0);
186 SH5PCI_WRITE(PINTM, ~0);
187
188 pr_debug("Switching on all error interrupts\n");
189
190 return(0);
191}
192
193static int sh5pci_read(struct pci_bus *bus, unsigned int devfn, int where,
194 int size, u32 *val)
195{
196 SH5PCI_WRITE(PAR, CONFIG_CMD(bus, devfn, where));
197
198 switch (size) {
199 case 1:
200 *val = (u8)SH5PCI_READ_BYTE(PDR + (where & 3));
201 break;
202 case 2:
203 *val = (u16)SH5PCI_READ_SHORT(PDR + (where & 2));
204 break;
205 case 4:
206 *val = SH5PCI_READ(PDR);
207 break;
208 }
209
210 return PCIBIOS_SUCCESSFUL;
211}
212
213static int sh5pci_write(struct pci_bus *bus, unsigned int devfn, int where,
214 int size, u32 val)
215{
216 SH5PCI_WRITE(PAR, CONFIG_CMD(bus, devfn, where));
217
218 switch (size) {
219 case 1:
220 SH5PCI_WRITE_BYTE(PDR + (where & 3), (u8)val);
221 break;
222 case 2:
223 SH5PCI_WRITE_SHORT(PDR + (where & 2), (u16)val);
224 break;
225 case 4:
226 SH5PCI_WRITE(PDR, val);
227 break;
228 }
229
230 return PCIBIOS_SUCCESSFUL;
231}
232
233static struct pci_ops pci_config_ops = {
234 .read = sh5pci_read,
235 .write = sh5pci_write,
236};
237
238/* Everything hangs off this */
239static struct pci_bus *pci_root_bus;
240
241
242static u8 __init no_swizzle(struct pci_dev *dev, u8 * pin)
243{
244 pr_debug("swizzle for dev %d on bus %d slot %d pin is %d\n",
245 dev->devfn,dev->bus->number, PCI_SLOT(dev->devfn),*pin);
246 return PCI_SLOT(dev->devfn);
247}
248
249static inline u8 bridge_swizzle(u8 pin, u8 slot)
250{
251 return (((pin-1) + slot) % 4) + 1;
252}
253
254u8 __init common_swizzle(struct pci_dev *dev, u8 *pinp)
255{
256 if (dev->bus->number != 0) {
257 u8 pin = *pinp;
258 do {
259 pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn));
260 /* Move up the chain of bridges. */
261 dev = dev->bus->self;
262 } while (dev->bus->self);
263 *pinp = pin;
264
265 /* The slot is the slot of the last bridge. */
266 }
267
268 return PCI_SLOT(dev->devfn);
269}
270
271/* This needs to be shunted out of here into the board specific bit */
272
273static int __init map_cayman_irq(struct pci_dev *dev, u8 slot, u8 pin)
274{
275 int result = -1;
276
277 /* The complication here is that the PCI IRQ lines from the Cayman's 2
278 5V slots get into the CPU via a different path from the IRQ lines
279 from the 3 3.3V slots. Thus, we have to detect whether the card's
280 interrupts go via the 5V or 3.3V path, i.e. the 'bridge swizzling'
281 at the point where we cross from 5V to 3.3V is not the normal case.
282
283 The added complication is that we don't know that the 5V slots are
284 always bus 2, because a card containing a PCI-PCI bridge may be
285 plugged into a 3.3V slot, and this changes the bus numbering.
286
287 Also, the Cayman has an intermediate PCI bus that goes a custom
288 expansion board header (and to the secondary bridge). This bus has
289 never been used in practice.
290
291 The 1ary onboard PCI-PCI bridge is device 3 on bus 0
292 The 2ary onboard PCI-PCI bridge is device 0 on the 2ary bus of the 1ary bridge.
293 */
294
295 struct slot_pin {
296 int slot;
297 int pin;
298 } path[4];
299 int i=0;
300
301 while (dev->bus->number > 0) {
302
303 slot = path[i].slot = PCI_SLOT(dev->devfn);
304 pin = path[i].pin = bridge_swizzle(pin, slot);
305 dev = dev->bus->self;
306 i++;
307 if (i > 3) panic("PCI path to root bus too long!\n");
308 }
309
310 slot = PCI_SLOT(dev->devfn);
311 /* This is the slot on bus 0 through which the device is eventually
312 reachable. */
313
314 /* Now work back up. */
315 if ((slot < 3) || (i == 0)) {
316 /* Bus 0 (incl. PCI-PCI bridge itself) : perform the final
317 swizzle now. */
318 result = IRQ_INTA + bridge_swizzle(pin, slot) - 1;
319 } else {
320 i--;
321 slot = path[i].slot;
322 pin = path[i].pin;
323 if (slot > 0) {
324 panic("PCI expansion bus device found - not handled!\n");
325 } else {
326 if (i > 0) {
327 /* 5V slots */
328 i--;
329 slot = path[i].slot;
330 pin = path[i].pin;
331 /* 'pin' was swizzled earlier wrt slot, don't do it again. */
332 result = IRQ_P2INTA + (pin - 1);
333 } else {
334 /* IRQ for 2ary PCI-PCI bridge : unused */
335 result = -1;
336 }
337 }
338 }
339
340 return result;
341}
342
343static irqreturn_t pcish5_err_irq(int irq, void *dev_id)
344{
345 struct pt_regs *regs = get_irq_regs();
346 unsigned pci_int, pci_air, pci_cir, pci_aint;
347
348 pci_int = SH5PCI_READ(INT);
349 pci_cir = SH5PCI_READ(CIR);
350 pci_air = SH5PCI_READ(AIR);
351
352 if (pci_int) {
353 printk("PCI INTERRUPT (at %08llx)!\n", regs->pc);
354 printk("PCI INT -> 0x%x\n", pci_int & 0xffff);
355 printk("PCI AIR -> 0x%x\n", pci_air);
356 printk("PCI CIR -> 0x%x\n", pci_cir);
357 SH5PCI_WRITE(INT, ~0);
358 }
359
360 pci_aint = SH5PCI_READ(AINT);
361 if (pci_aint) {
362 printk("PCI ARB INTERRUPT!\n");
363 printk("PCI AINT -> 0x%x\n", pci_aint);
364 printk("PCI AIR -> 0x%x\n", pci_air);
365 printk("PCI CIR -> 0x%x\n", pci_cir);
366 SH5PCI_WRITE(AINT, ~0);
367 }
368
369 return IRQ_HANDLED;
370}
371
372static irqreturn_t pcish5_serr_irq(int irq, void *dev_id)
373{
374 printk("SERR IRQ\n");
375
376 return IRQ_NONE;
377}
378
379static void __init
380pcibios_size_bridge(struct pci_bus *bus, struct resource *ior,
381 struct resource *memr)
382{
383 struct resource io_res, mem_res;
384 struct pci_dev *dev;
385 struct pci_dev *bridge = bus->self;
386 struct list_head *ln;
387
388 if (!bridge)
389 return; /* host bridge, nothing to do */
390
391 /* set reasonable default locations for pcibios_align_resource */
392 io_res.start = PCIBIOS_MIN_IO;
393 mem_res.start = PCIBIOS_MIN_MEM;
394
395 io_res.end = io_res.start;
396 mem_res.end = mem_res.start;
397
398 /* Collect information about how our direct children are layed out. */
399 for (ln=bus->devices.next; ln != &bus->devices; ln=ln->next) {
400 int i;
401 dev = pci_dev_b(ln);
402
403 /* Skip bridges for now */
404 if (dev->class >> 8 == PCI_CLASS_BRIDGE_PCI)
405 continue;
406
407 for (i = 0; i < PCI_NUM_RESOURCES; i++) {
408 struct resource res;
409 unsigned long size;
410
411 memcpy(&res, &dev->resource[i], sizeof(res));
412 size = res.end - res.start + 1;
413
414 if (res.flags & IORESOURCE_IO) {
415 res.start = io_res.end;
416 pcibios_align_resource(dev, &res, size, 0);
417 io_res.end = res.start + size;
418 } else if (res.flags & IORESOURCE_MEM) {
419 res.start = mem_res.end;
420 pcibios_align_resource(dev, &res, size, 0);
421 mem_res.end = res.start + size;
422 }
423 }
424 }
425
426 /* And for all of the subordinate busses. */
427 for (ln=bus->children.next; ln != &bus->children; ln=ln->next)
428 pcibios_size_bridge(pci_bus_b(ln), &io_res, &mem_res);
429
430 /* turn the ending locations into sizes (subtract start) */
431 io_res.end -= io_res.start;
432 mem_res.end -= mem_res.start;
433
434 /* Align the sizes up by bridge rules */
435 io_res.end = ALIGN(io_res.end, 4*1024) - 1;
436 mem_res.end = ALIGN(mem_res.end, 1*1024*1024) - 1;
437
438 /* Adjust the bridge's allocation requirements */
439 bridge->resource[0].end = bridge->resource[0].start + io_res.end;
440 bridge->resource[1].end = bridge->resource[1].start + mem_res.end;
441
442 bridge->resource[PCI_BRIDGE_RESOURCES].end =
443 bridge->resource[PCI_BRIDGE_RESOURCES].start + io_res.end;
444 bridge->resource[PCI_BRIDGE_RESOURCES+1].end =
445 bridge->resource[PCI_BRIDGE_RESOURCES+1].start + mem_res.end;
446
447 /* adjust parent's resource requirements */
448 if (ior) {
449 ior->end = ALIGN(ior->end, 4*1024);
450 ior->end += io_res.end;
451 }
452
453 if (memr) {
454 memr->end = ALIGN(memr->end, 1*1024*1024);
455 memr->end += mem_res.end;
456 }
457}
458
459static void __init pcibios_size_bridges(void)
460{
461 struct resource io_res, mem_res;
462
463 memset(&io_res, 0, sizeof(io_res));
464 memset(&mem_res, 0, sizeof(mem_res));
465
466 pcibios_size_bridge(pci_root_bus, &io_res, &mem_res);
467}
468
469static int __init pcibios_init(void)
470{
471 if (request_irq(IRQ_ERR, pcish5_err_irq,
472 IRQF_DISABLED, "PCI Error",NULL) < 0) {
473 printk(KERN_ERR "PCISH5: Cannot hook PCI_PERR interrupt\n");
474 return -EINVAL;
475 }
476
477 if (request_irq(IRQ_SERR, pcish5_serr_irq,
478 IRQF_DISABLED, "PCI SERR interrupt", NULL) < 0) {
479 printk(KERN_ERR "PCISH5: Cannot hook PCI_SERR interrupt\n");
480 return -EINVAL;
481 }
482
483 /* The pci subsystem needs to know where memory is and how much
484 * of it there is. I've simply made these globals. A better mechanism
485 * is probably needed.
486 */
487 sh5pci_init(__pa(memory_start),
488 __pa(memory_end) - __pa(memory_start));
489
490 pci_root_bus = pci_scan_bus(0, &pci_config_ops, NULL);
491 pcibios_size_bridges();
492 pci_assign_unassigned_resources();
493 pci_fixup_irqs(no_swizzle, map_cayman_irq);
494
495 return 0;
496}
497
498subsys_initcall(pcibios_init);
499
500void __devinit pcibios_fixup_bus(struct pci_bus *bus)
501{
502 struct pci_dev *dev = bus->self;
503 int i;
504
505#if 1
506 if(dev) {
507 for(i=0; i<3; i++) {
508 bus->resource[i] =
509 &dev->resource[PCI_BRIDGE_RESOURCES+i];
510 bus->resource[i]->name = bus->name;
511 }
512 bus->resource[0]->flags |= IORESOURCE_IO;
513 bus->resource[1]->flags |= IORESOURCE_MEM;
514
515 /* For now, propagate host limits to the bus;
516 * we'll adjust them later. */
517
518#if 1
519 bus->resource[0]->end = 64*1024 - 1 ;
520 bus->resource[1]->end = PCIBIOS_MIN_MEM+(256*1024*1024)-1;
521 bus->resource[0]->start = PCIBIOS_MIN_IO;
522 bus->resource[1]->start = PCIBIOS_MIN_MEM;
523#else
524 bus->resource[0]->end = 0;
525 bus->resource[1]->end = 0;
526 bus->resource[0]->start =0;
527 bus->resource[1]->start = 0;
528#endif
529 /* Turn off downstream PF memory address range by default */
530 bus->resource[2]->start = 1024*1024;
531 bus->resource[2]->end = bus->resource[2]->start - 1;
532 }
533#endif
534
535}
536
diff --git a/arch/sh64/kernel/pci_sh5.h b/arch/sh64/kernel/pci_sh5.h
deleted file mode 100644
index c71159dd04b9..000000000000
--- a/arch/sh64/kernel/pci_sh5.h
+++ /dev/null
@@ -1,107 +0,0 @@
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 * Definitions for the SH5 PCI hardware.
8 */
9
10/* Product ID */
11#define PCISH5_PID 0x350d
12
13/* vendor ID */
14#define PCISH5_VID 0x1054
15
16/* Configuration types */
17#define ST_TYPE0 0x00 /* Configuration cycle type 0 */
18#define ST_TYPE1 0x01 /* Configuration cycle type 1 */
19
20/* VCR data */
21#define PCISH5_VCR_STATUS 0x00
22#define PCISH5_VCR_VERSION 0x08
23
24/*
25** ICR register offsets and bits
26*/
27#define PCISH5_ICR_CR 0x100 /* PCI control register values */
28#define CR_PBAM (1<<12)
29#define CR_PFCS (1<<11)
30#define CR_FTO (1<<10)
31#define CR_PFE (1<<9)
32#define CR_TBS (1<<8)
33#define CR_SPUE (1<<7)
34#define CR_BMAM (1<<6)
35#define CR_HOST (1<<5)
36#define CR_CLKEN (1<<4)
37#define CR_SOCS (1<<3)
38#define CR_IOCS (1<<2)
39#define CR_RSTCTL (1<<1)
40#define CR_CFINT (1<<0)
41#define CR_LOCK_MASK 0xa5000000
42
43#define PCISH5_ICR_INT 0x114 /* Interrupt registert values */
44#define INT_MADIM (1<<2)
45
46#define PCISH5_ICR_LSR0 0X104 /* Local space register values */
47#define PCISH5_ICR_LSR1 0X108 /* Local space register values */
48#define PCISH5_ICR_LAR0 0x10c /* Local address register values */
49#define PCISH5_ICR_LAR1 0x110 /* Local address register values */
50#define PCISH5_ICR_INTM 0x118 /* Interrupt mask register values */
51#define PCISH5_ICR_AIR 0x11c /* Interrupt error address information register values */
52#define PCISH5_ICR_CIR 0x120 /* Interrupt error command information register values */
53#define PCISH5_ICR_AINT 0x130 /* Interrupt error arbiter interrupt register values */
54#define PCISH5_ICR_AINTM 0x134 /* Interrupt error arbiter interrupt mask register values */
55#define PCISH5_ICR_BMIR 0x138 /* Interrupt error info register of bus master values */
56#define PCISH5_ICR_PAR 0x1c0 /* Pio address register values */
57#define PCISH5_ICR_MBR 0x1c4 /* Memory space bank register values */
58#define PCISH5_ICR_IOBR 0x1c8 /* I/O space bank register values */
59#define PCISH5_ICR_PINT 0x1cc /* power management interrupt register values */
60#define PCISH5_ICR_PINTM 0x1d0 /* power management interrupt mask register values */
61#define PCISH5_ICR_MBMR 0x1d8 /* memory space bank mask register values */
62#define PCISH5_ICR_IOBMR 0x1dc /* I/O space bank mask register values */
63#define PCISH5_ICR_CSCR0 0x210 /* PCI cache snoop control register 0 */
64#define PCISH5_ICR_CSCR1 0x214 /* PCI cache snoop control register 1 */
65#define PCISH5_ICR_PDR 0x220 /* Pio data register values */
66
67/* These are configs space registers */
68#define PCISH5_ICR_CSR_VID 0x000 /* Vendor id */
69#define PCISH5_ICR_CSR_DID 0x002 /* Device id */
70#define PCISH5_ICR_CSR_CMD 0x004 /* Command register */
71#define PCISH5_ICR_CSR_STATUS 0x006 /* Stautus */
72#define PCISH5_ICR_CSR_IBAR0 0x010 /* I/O base address register */
73#define PCISH5_ICR_CSR_MBAR0 0x014 /* First Memory base address register */
74#define PCISH5_ICR_CSR_MBAR1 0x018 /* Second Memory base address register */
75
76
77
78/* Base address of registers */
79#define SH5PCI_ICR_BASE (PHYS_PCI_BLOCK + 0x00040000)
80#define SH5PCI_IO_BASE (PHYS_PCI_BLOCK + 0x00800000)
81/* #define SH5PCI_VCR_BASE (P2SEG_PCICB_BLOCK + P2SEG) */
82
83/* Register selection macro */
84#define PCISH5_ICR_REG(x) ( pcicr_virt + (PCISH5_ICR_##x))
85/* #define PCISH5_VCR_REG(x) ( SH5PCI_VCR_BASE (PCISH5_VCR_##x)) */
86
87/* Write I/O functions */
88#define SH5PCI_WRITE(reg,val) ctrl_outl((u32)(val),PCISH5_ICR_REG(reg))
89#define SH5PCI_WRITE_SHORT(reg,val) ctrl_outw((u16)(val),PCISH5_ICR_REG(reg))
90#define SH5PCI_WRITE_BYTE(reg,val) ctrl_outb((u8)(val),PCISH5_ICR_REG(reg))
91
92/* Read I/O functions */
93#define SH5PCI_READ(reg) ctrl_inl(PCISH5_ICR_REG(reg))
94#define SH5PCI_READ_SHORT(reg) ctrl_inw(PCISH5_ICR_REG(reg))
95#define SH5PCI_READ_BYTE(reg) ctrl_inb(PCISH5_ICR_REG(reg))
96
97/* Set PCI config bits */
98#define SET_CONFIG_BITS(bus,devfn,where) ((((bus) << 16) | ((devfn) << 8) | ((where) & ~3)) | 0x80000000)
99
100/* Set PCI command register */
101#define CONFIG_CMD(bus, devfn, where) SET_CONFIG_BITS(bus->number,devfn,where)
102
103/* Size converters */
104#define PCISH5_MEM_SIZCONV(x) (((x / 0x40000) - 1) << 18)
105#define PCISH5_IO_SIZCONV(x) (((x / 0x40000) - 1) << 18)
106
107
diff --git a/arch/sh64/kernel/pcibios.c b/arch/sh64/kernel/pcibios.c
deleted file mode 100644
index 945920bc24db..000000000000
--- a/arch/sh64/kernel/pcibios.c
+++ /dev/null
@@ -1,168 +0,0 @@
1/*
2 * $Id: pcibios.c,v 1.1 2001/08/24 12:38:19 dwmw2 Exp $
3 *
4 * arch/sh/kernel/pcibios.c
5 *
6 * Copyright (C) 2002 STMicroelectronics Limited
7 * Author : David J. McKay
8 *
9 * Copyright (C) 2004 Richard Curnow, SuperH UK Limited
10 *
11 * This file is subject to the terms and conditions of the GNU General Public
12 * License. See the file "COPYING" in the main directory of this archive
13 * for more details.
14 * This is GPL'd.
15 *
16 * Provided here are generic versions of:
17 * pcibios_update_resource()
18 * pcibios_align_resource()
19 * pcibios_enable_device()
20 * pcibios_set_master()
21 * pcibios_update_irq()
22 *
23 * These functions are collected here to reduce duplication of common
24 * code amongst the many platform-specific PCI support code files.
25 *
26 * Platform-specific files are expected to provide:
27 * pcibios_fixup_bus()
28 * pcibios_init()
29 * pcibios_setup()
30 * pcibios_fixup_pbus_ranges()
31 */
32
33#include <linux/kernel.h>
34#include <linux/pci.h>
35#include <linux/init.h>
36
37void
38pcibios_update_resource(struct pci_dev *dev, struct resource *root,
39 struct resource *res, int resource)
40{
41 u32 new, check;
42 int reg;
43
44 new = res->start | (res->flags & PCI_REGION_FLAG_MASK);
45 if (resource < 6) {
46 reg = PCI_BASE_ADDRESS_0 + 4*resource;
47 } else if (resource == PCI_ROM_RESOURCE) {
48 res->flags |= IORESOURCE_ROM_ENABLE;
49 new |= PCI_ROM_ADDRESS_ENABLE;
50 reg = dev->rom_base_reg;
51 } else {
52 /* Somebody might have asked allocation of a non-standard resource */
53 return;
54 }
55
56 pci_write_config_dword(dev, reg, new);
57 pci_read_config_dword(dev, reg, &check);
58 if ((new ^ check) & ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK)) {
59 printk(KERN_ERR "PCI: Error while updating region "
60 "%s/%d (%08x != %08x)\n", pci_name(dev), resource,
61 new, check);
62 }
63}
64
65/*
66 * We need to avoid collisions with `mirrored' VGA ports
67 * and other strange ISA hardware, so we always want the
68 * addresses to be allocated in the 0x000-0x0ff region
69 * modulo 0x400.
70 */
71void pcibios_align_resource(void *data, struct resource *res,
72 resource_size_t size, resource_size_t align)
73{
74 if (res->flags & IORESOURCE_IO) {
75 resource_size_t start = res->start;
76
77 if (start & 0x300) {
78 start = (start + 0x3ff) & ~0x3ff;
79 res->start = start;
80 }
81 }
82}
83
84static void pcibios_enable_bridge(struct pci_dev *dev)
85{
86 struct pci_bus *bus = dev->subordinate;
87 u16 cmd, old_cmd;
88
89 pci_read_config_word(dev, PCI_COMMAND, &cmd);
90 old_cmd = cmd;
91
92 if (bus->resource[0]->flags & IORESOURCE_IO) {
93 cmd |= PCI_COMMAND_IO;
94 }
95 if ((bus->resource[1]->flags & IORESOURCE_MEM) ||
96 (bus->resource[2]->flags & IORESOURCE_PREFETCH)) {
97 cmd |= PCI_COMMAND_MEMORY;
98 }
99
100 if (cmd != old_cmd) {
101 pci_write_config_word(dev, PCI_COMMAND, cmd);
102 }
103
104 printk("PCI bridge %s, command register -> %04x\n",
105 pci_name(dev), cmd);
106
107}
108
109
110
111int pcibios_enable_device(struct pci_dev *dev, int mask)
112{
113 u16 cmd, old_cmd;
114 int idx;
115 struct resource *r;
116
117 if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
118 pcibios_enable_bridge(dev);
119 }
120
121 pci_read_config_word(dev, PCI_COMMAND, &cmd);
122 old_cmd = cmd;
123 for(idx=0; idx<6; idx++) {
124 if (!(mask & (1 << idx)))
125 continue;
126 r = &dev->resource[idx];
127 if (!r->start && r->end) {
128 printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", pci_name(dev));
129 return -EINVAL;
130 }
131 if (r->flags & IORESOURCE_IO)
132 cmd |= PCI_COMMAND_IO;
133 if (r->flags & IORESOURCE_MEM)
134 cmd |= PCI_COMMAND_MEMORY;
135 }
136 if (dev->resource[PCI_ROM_RESOURCE].start)
137 cmd |= PCI_COMMAND_MEMORY;
138 if (cmd != old_cmd) {
139 printk(KERN_INFO "PCI: Enabling device %s (%04x -> %04x)\n", pci_name(dev), old_cmd, cmd);
140 pci_write_config_word(dev, PCI_COMMAND, cmd);
141 }
142 return 0;
143}
144
145/*
146 * If we set up a device for bus mastering, we need to check and set
147 * the latency timer as it may not be properly set.
148 */
149unsigned int pcibios_max_latency = 255;
150
151void pcibios_set_master(struct pci_dev *dev)
152{
153 u8 lat;
154 pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
155 if (lat < 16)
156 lat = (64 <= pcibios_max_latency) ? 64 : pcibios_max_latency;
157 else if (lat > pcibios_max_latency)
158 lat = pcibios_max_latency;
159 else
160 return;
161 printk(KERN_INFO "PCI: Setting latency timer of device %s to %d\n", pci_name(dev), lat);
162 pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat);
163}
164
165void __init pcibios_update_irq(struct pci_dev *dev, int irq)
166{
167 pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
168}
diff --git a/arch/sh64/kernel/setup.c b/arch/sh64/kernel/setup.c
deleted file mode 100644
index 2b7264c0c6f7..000000000000
--- a/arch/sh64/kernel/setup.c
+++ /dev/null
@@ -1,379 +0,0 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * arch/sh64/kernel/setup.c
7 *
8 * sh64 Arch Support
9 *
10 * This file handles the architecture-dependent parts of initialization
11 *
12 * Copyright (C) 2000, 2001 Paolo Alberelli
13 * Copyright (C) 2003, 2004 Paul Mundt
14 *
15 * benedict.gaster@superh.com: 2nd May 2002
16 * Modified to use the empty_zero_page to pass command line arguments.
17 *
18 * benedict.gaster@superh.com: 3rd May 2002
19 * Added support for ramdisk, removing statically linked romfs at the same time.
20 *
21 * lethal@linux-sh.org: 15th May 2003
22 * Added generic procfs cpuinfo reporting. Make boards just export their name.
23 *
24 * lethal@linux-sh.org: 25th May 2003
25 * Added generic get_cpu_subtype() for subtype reporting from cpu_data->type.
26 *
27 */
28#include <linux/errno.h>
29#include <linux/rwsem.h>
30#include <linux/sched.h>
31#include <linux/kernel.h>
32#include <linux/mm.h>
33#include <linux/stddef.h>
34#include <linux/unistd.h>
35#include <linux/ptrace.h>
36#include <linux/slab.h>
37#include <linux/user.h>
38#include <linux/a.out.h>
39#include <linux/screen_info.h>
40#include <linux/ioport.h>
41#include <linux/delay.h>
42#include <linux/init.h>
43#include <linux/seq_file.h>
44#include <linux/blkdev.h>
45#include <linux/bootmem.h>
46#include <linux/console.h>
47#include <linux/root_dev.h>
48#include <linux/cpu.h>
49#include <linux/initrd.h>
50#include <linux/pfn.h>
51#include <asm/processor.h>
52#include <asm/page.h>
53#include <asm/pgtable.h>
54#include <asm/platform.h>
55#include <asm/uaccess.h>
56#include <asm/system.h>
57#include <asm/io.h>
58#include <asm/sections.h>
59#include <asm/setup.h>
60#include <asm/smp.h>
61
62struct screen_info screen_info;
63
64#ifdef CONFIG_BLK_DEV_RAM
65extern int rd_doload; /* 1 = load ramdisk, 0 = don't load */
66extern int rd_prompt; /* 1 = prompt for ramdisk, 0 = don't prompt */
67extern int rd_image_start; /* starting block # of image */
68#endif
69
70extern int root_mountflags;
71extern char *get_system_type(void);
72extern void platform_setup(void);
73extern void platform_monitor(void);
74extern void platform_reserve(void);
75extern int sh64_cache_init(void);
76extern int sh64_tlb_init(void);
77
78#define RAMDISK_IMAGE_START_MASK 0x07FF
79#define RAMDISK_PROMPT_FLAG 0x8000
80#define RAMDISK_LOAD_FLAG 0x4000
81
82static char __initdata command_line[COMMAND_LINE_SIZE] = { 0, };
83unsigned long long memory_start = CONFIG_MEMORY_START;
84unsigned long long memory_end = CONFIG_MEMORY_START + (CONFIG_MEMORY_SIZE_IN_MB * 1024 * 1024);
85
86struct sh_cpuinfo boot_cpu_data;
87
88static inline void parse_mem_cmdline (char ** cmdline_p)
89{
90 char c = ' ', *to = command_line, *from = COMMAND_LINE;
91 int len = 0;
92
93 /* Save unparsed command line copy for /proc/cmdline */
94 memcpy(boot_command_line, COMMAND_LINE, COMMAND_LINE_SIZE);
95 boot_command_line[COMMAND_LINE_SIZE-1] = '\0';
96
97 for (;;) {
98 /*
99 * "mem=XXX[kKmM]" defines a size of memory.
100 */
101 if (c == ' ' && !memcmp(from, "mem=", 4)) {
102 if (to != command_line)
103 to--;
104 {
105 unsigned long mem_size;
106
107 mem_size = memparse(from+4, &from);
108 memory_end = memory_start + mem_size;
109 }
110 }
111 c = *(from++);
112 if (!c)
113 break;
114 if (COMMAND_LINE_SIZE <= ++len)
115 break;
116 *(to++) = c;
117 }
118 *to = '\0';
119
120 *cmdline_p = command_line;
121}
122
123static void __init sh64_cpu_type_detect(void)
124{
125 extern unsigned long long peek_real_address_q(unsigned long long addr);
126 unsigned long long cir;
127 /* Do peeks in real mode to avoid having to set up a mapping for the
128 WPC registers. On SH5-101 cut2, such a mapping would be exposed to
129 an address translation erratum which would make it hard to set up
130 correctly. */
131 cir = peek_real_address_q(0x0d000008);
132
133 if ((cir & 0xffff) == 0x5103) {
134 boot_cpu_data.type = CPU_SH5_103;
135 } else if (((cir >> 32) & 0xffff) == 0x51e2) {
136 /* CPU.VCR aliased at CIR address on SH5-101 */
137 boot_cpu_data.type = CPU_SH5_101;
138 } else {
139 boot_cpu_data.type = CPU_SH_NONE;
140 }
141}
142
143void __init setup_arch(char **cmdline_p)
144{
145 unsigned long bootmap_size, i;
146 unsigned long first_pfn, start_pfn, last_pfn, pages;
147
148#ifdef CONFIG_EARLY_PRINTK
149 extern void enable_early_printk(void);
150
151 /*
152 * Setup Early SCIF console
153 */
154 enable_early_printk();
155#endif
156
157 /*
158 * Setup TLB mappings
159 */
160 sh64_tlb_init();
161
162 /*
163 * Caches are already initialized by the time we get here, so we just
164 * fill in cpu_data info for the caches.
165 */
166 sh64_cache_init();
167
168 platform_setup();
169 platform_monitor();
170
171 sh64_cpu_type_detect();
172
173 ROOT_DEV = old_decode_dev(ORIG_ROOT_DEV);
174
175#ifdef CONFIG_BLK_DEV_RAM
176 rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK;
177 rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0);
178 rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0);
179#endif
180
181 if (!MOUNT_ROOT_RDONLY)
182 root_mountflags &= ~MS_RDONLY;
183 init_mm.start_code = (unsigned long) _text;
184 init_mm.end_code = (unsigned long) _etext;
185 init_mm.end_data = (unsigned long) _edata;
186 init_mm.brk = (unsigned long) _end;
187
188 code_resource.start = __pa(_text);
189 code_resource.end = __pa(_etext)-1;
190 data_resource.start = __pa(_etext);
191 data_resource.end = __pa(_edata)-1;
192
193 parse_mem_cmdline(cmdline_p);
194
195 /*
196 * Find the lowest and highest page frame numbers we have available
197 */
198 first_pfn = PFN_DOWN(memory_start);
199 last_pfn = PFN_DOWN(memory_end);
200 pages = last_pfn - first_pfn;
201
202 /*
203 * Partially used pages are not usable - thus
204 * we are rounding upwards:
205 */
206 start_pfn = PFN_UP(__pa(_end));
207
208 /*
209 * Find a proper area for the bootmem bitmap. After this
210 * bootstrap step all allocations (until the page allocator
211 * is intact) must be done via bootmem_alloc().
212 */
213 bootmap_size = init_bootmem_node(NODE_DATA(0), start_pfn,
214 first_pfn,
215 last_pfn);
216 /*
217 * Round it up.
218 */
219 bootmap_size = PFN_PHYS(PFN_UP(bootmap_size));
220
221 /*
222 * Register fully available RAM pages with the bootmem allocator.
223 */
224 free_bootmem_node(NODE_DATA(0), PFN_PHYS(first_pfn), PFN_PHYS(pages));
225
226 /*
227 * Reserve all kernel sections + bootmem bitmap + a guard page.
228 */
229 reserve_bootmem_node(NODE_DATA(0), PFN_PHYS(first_pfn),
230 (PFN_PHYS(start_pfn) + bootmap_size + PAGE_SIZE) - PFN_PHYS(first_pfn));
231
232 /*
233 * Reserve platform dependent sections
234 */
235 platform_reserve();
236
237#ifdef CONFIG_BLK_DEV_INITRD
238 if (LOADER_TYPE && INITRD_START) {
239 if (INITRD_START + INITRD_SIZE <= (PFN_PHYS(last_pfn))) {
240 reserve_bootmem_node(NODE_DATA(0), INITRD_START + __MEMORY_START, INITRD_SIZE);
241
242 initrd_start = (long) INITRD_START + PAGE_OFFSET + __MEMORY_START;
243 initrd_end = initrd_start + INITRD_SIZE;
244 } else {
245 printk("initrd extends beyond end of memory "
246 "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
247 (long) INITRD_START + INITRD_SIZE,
248 PFN_PHYS(last_pfn));
249 initrd_start = 0;
250 }
251 }
252#endif
253
254 /*
255 * Claim all RAM, ROM, and I/O resources.
256 */
257
258 /* Kernel RAM */
259 request_resource(&iomem_resource, &code_resource);
260 request_resource(&iomem_resource, &data_resource);
261
262 /* Other KRAM space */
263 for (i = 0; i < STANDARD_KRAM_RESOURCES - 2; i++)
264 request_resource(&iomem_resource,
265 &platform_parms.kram_res_p[i]);
266
267 /* XRAM space */
268 for (i = 0; i < STANDARD_XRAM_RESOURCES; i++)
269 request_resource(&iomem_resource,
270 &platform_parms.xram_res_p[i]);
271
272 /* ROM space */
273 for (i = 0; i < STANDARD_ROM_RESOURCES; i++)
274 request_resource(&iomem_resource,
275 &platform_parms.rom_res_p[i]);
276
277 /* I/O space */
278 for (i = 0; i < STANDARD_IO_RESOURCES; i++)
279 request_resource(&ioport_resource,
280 &platform_parms.io_res_p[i]);
281
282
283#ifdef CONFIG_VT
284#if defined(CONFIG_VGA_CONSOLE)
285 conswitchp = &vga_con;
286#elif defined(CONFIG_DUMMY_CONSOLE)
287 conswitchp = &dummy_con;
288#endif
289#endif
290
291 printk("Hardware FPU: %s\n", fpu_in_use ? "enabled" : "disabled");
292
293 paging_init();
294}
295
296void __xchg_called_with_bad_pointer(void)
297{
298 printk(KERN_EMERG "xchg() called with bad pointer !\n");
299}
300
301static struct cpu cpu[1];
302
303static int __init topology_init(void)
304{
305 return register_cpu(cpu, 0);
306}
307
308subsys_initcall(topology_init);
309
310/*
311 * Get CPU information
312 */
313static const char *cpu_name[] = {
314 [CPU_SH5_101] = "SH5-101",
315 [CPU_SH5_103] = "SH5-103",
316 [CPU_SH_NONE] = "Unknown",
317};
318
319const char *get_cpu_subtype(void)
320{
321 return cpu_name[boot_cpu_data.type];
322}
323
324#ifdef CONFIG_PROC_FS
325static int show_cpuinfo(struct seq_file *m,void *v)
326{
327 unsigned int cpu = smp_processor_id();
328
329 if (!cpu)
330 seq_printf(m, "machine\t\t: %s\n", get_system_type());
331
332 seq_printf(m, "processor\t: %d\n", cpu);
333 seq_printf(m, "cpu family\t: SH-5\n");
334 seq_printf(m, "cpu type\t: %s\n", get_cpu_subtype());
335
336 seq_printf(m, "icache size\t: %dK-bytes\n",
337 (boot_cpu_data.icache.ways *
338 boot_cpu_data.icache.sets *
339 boot_cpu_data.icache.linesz) >> 10);
340 seq_printf(m, "dcache size\t: %dK-bytes\n",
341 (boot_cpu_data.dcache.ways *
342 boot_cpu_data.dcache.sets *
343 boot_cpu_data.dcache.linesz) >> 10);
344 seq_printf(m, "itlb entries\t: %d\n", boot_cpu_data.itlb.entries);
345 seq_printf(m, "dtlb entries\t: %d\n", boot_cpu_data.dtlb.entries);
346
347#define PRINT_CLOCK(name, value) \
348 seq_printf(m, name " clock\t: %d.%02dMHz\n", \
349 ((value) / 1000000), ((value) % 1000000)/10000)
350
351 PRINT_CLOCK("cpu", boot_cpu_data.cpu_clock);
352 PRINT_CLOCK("bus", boot_cpu_data.bus_clock);
353 PRINT_CLOCK("module", boot_cpu_data.module_clock);
354
355 seq_printf(m, "bogomips\t: %lu.%02lu\n\n",
356 (loops_per_jiffy*HZ+2500)/500000,
357 ((loops_per_jiffy*HZ+2500)/5000) % 100);
358
359 return 0;
360}
361
362static void *c_start(struct seq_file *m, loff_t *pos)
363{
364 return (void*)(*pos == 0);
365}
366static void *c_next(struct seq_file *m, void *v, loff_t *pos)
367{
368 return NULL;
369}
370static void c_stop(struct seq_file *m, void *v)
371{
372}
373struct seq_operations cpuinfo_op = {
374 .start = c_start,
375 .next = c_next,
376 .stop = c_stop,
377 .show = show_cpuinfo,
378};
379#endif /* CONFIG_PROC_FS */
diff --git a/arch/sh64/kernel/time.c b/arch/sh64/kernel/time.c
deleted file mode 100644
index d1a9b5b078bd..000000000000
--- a/arch/sh64/kernel/time.c
+++ /dev/null
@@ -1,531 +0,0 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * arch/sh64/kernel/time.c
7 *
8 * Copyright (C) 2000, 2001 Paolo Alberelli
9 * Copyright (C) 2003 - 2007 Paul Mundt
10 * Copyright (C) 2003 Richard Curnow
11 *
12 * Original TMU/RTC code taken from sh version.
13 * Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka
14 * Some code taken from i386 version.
15 * Copyright (C) 1991, 1992, 1995 Linus Torvalds
16 */
17#include <linux/errno.h>
18#include <linux/rwsem.h>
19#include <linux/sched.h>
20#include <linux/kernel.h>
21#include <linux/param.h>
22#include <linux/string.h>
23#include <linux/mm.h>
24#include <linux/interrupt.h>
25#include <linux/time.h>
26#include <linux/delay.h>
27#include <linux/init.h>
28#include <linux/profile.h>
29#include <linux/smp.h>
30#include <linux/module.h>
31#include <linux/bcd.h>
32#include <linux/timex.h>
33#include <linux/irq.h>
34#include <linux/platform_device.h>
35#include <asm/registers.h> /* required by inline __asm__ stmt. */
36#include <asm/processor.h>
37#include <asm/uaccess.h>
38#include <asm/io.h>
39#include <asm/irq.h>
40#include <asm/delay.h>
41#include <asm/hardware.h>
42
43#define TMU_TOCR_INIT 0x00
44#define TMU0_TCR_INIT 0x0020
45#define TMU_TSTR_INIT 1
46#define TMU_TSTR_OFF 0
47
48/* Real Time Clock */
49#define RTC_BLOCK_OFF 0x01040000
50#define RTC_BASE PHYS_PERIPHERAL_BLOCK + RTC_BLOCK_OFF
51#define RTC_RCR1_CIE 0x10 /* Carry Interrupt Enable */
52#define RTC_RCR1 (rtc_base + 0x38)
53
54/* Clock, Power and Reset Controller */
55#define CPRC_BLOCK_OFF 0x01010000
56#define CPRC_BASE PHYS_PERIPHERAL_BLOCK + CPRC_BLOCK_OFF
57
58#define FRQCR (cprc_base+0x0)
59#define WTCSR (cprc_base+0x0018)
60#define STBCR (cprc_base+0x0030)
61
62/* Time Management Unit */
63#define TMU_BLOCK_OFF 0x01020000
64#define TMU_BASE PHYS_PERIPHERAL_BLOCK + TMU_BLOCK_OFF
65#define TMU0_BASE tmu_base + 0x8 + (0xc * 0x0)
66#define TMU1_BASE tmu_base + 0x8 + (0xc * 0x1)
67#define TMU2_BASE tmu_base + 0x8 + (0xc * 0x2)
68
69#define TMU_TOCR tmu_base+0x0 /* Byte access */
70#define TMU_TSTR tmu_base+0x4 /* Byte access */
71
72#define TMU0_TCOR TMU0_BASE+0x0 /* Long access */
73#define TMU0_TCNT TMU0_BASE+0x4 /* Long access */
74#define TMU0_TCR TMU0_BASE+0x8 /* Word access */
75
76#define TICK_SIZE (tick_nsec / 1000)
77
78static unsigned long tmu_base, rtc_base;
79unsigned long cprc_base;
80
81/* Variables to allow interpolation of time of day to resolution better than a
82 * jiffy. */
83
84/* This is effectively protected by xtime_lock */
85static unsigned long ctc_last_interrupt;
86static unsigned long long usecs_per_jiffy = 1000000/HZ; /* Approximation */
87
88#define CTC_JIFFY_SCALE_SHIFT 40
89
90/* 2**CTC_JIFFY_SCALE_SHIFT / ctc_ticks_per_jiffy */
91static unsigned long long scaled_recip_ctc_ticks_per_jiffy;
92
93/* Estimate number of microseconds that have elapsed since the last timer tick,
94 by scaling the delta that has occurred in the CTC register.
95
96 WARNING WARNING WARNING : This algorithm relies on the CTC decrementing at
97 the CPU clock rate. If the CPU sleeps, the CTC stops counting. Bear this
98 in mind if enabling SLEEP_WORKS in process.c. In that case, this algorithm
99 probably needs to use TMU.TCNT0 instead. This will work even if the CPU is
100 sleeping, though will be coarser.
101
102 FIXME : What if usecs_per_tick is moving around too much, e.g. if an adjtime
103 is running or if the freq or tick arguments of adjtimex are modified after
104 we have calibrated the scaling factor? This will result in either a jump at
105 the end of a tick period, or a wrap backwards at the start of the next one,
106 if the application is reading the time of day often enough. I think we
107 ought to do better than this. For this reason, usecs_per_jiffy is left
108 separated out in the calculation below. This allows some future hook into
109 the adjtime-related stuff in kernel/timer.c to remove this hazard.
110
111*/
112
113static unsigned long usecs_since_tick(void)
114{
115 unsigned long long current_ctc;
116 long ctc_ticks_since_interrupt;
117 unsigned long long ull_ctc_ticks_since_interrupt;
118 unsigned long result;
119
120 unsigned long long mul1_out;
121 unsigned long long mul1_out_high;
122 unsigned long long mul2_out_low, mul2_out_high;
123
124 /* Read CTC register */
125 asm ("getcon cr62, %0" : "=r" (current_ctc));
126 /* Note, the CTC counts down on each CPU clock, not up.
127 Note(2), use long type to get correct wraparound arithmetic when
128 the counter crosses zero. */
129 ctc_ticks_since_interrupt = (long) ctc_last_interrupt - (long) current_ctc;
130 ull_ctc_ticks_since_interrupt = (unsigned long long) ctc_ticks_since_interrupt;
131
132 /* Inline assembly to do 32x32x32->64 multiplier */
133 asm volatile ("mulu.l %1, %2, %0" :
134 "=r" (mul1_out) :
135 "r" (ull_ctc_ticks_since_interrupt), "r" (usecs_per_jiffy));
136
137 mul1_out_high = mul1_out >> 32;
138
139 asm volatile ("mulu.l %1, %2, %0" :
140 "=r" (mul2_out_low) :
141 "r" (mul1_out), "r" (scaled_recip_ctc_ticks_per_jiffy));
142
143#if 1
144 asm volatile ("mulu.l %1, %2, %0" :
145 "=r" (mul2_out_high) :
146 "r" (mul1_out_high), "r" (scaled_recip_ctc_ticks_per_jiffy));
147#endif
148
149 result = (unsigned long) (((mul2_out_high << 32) + mul2_out_low) >> CTC_JIFFY_SCALE_SHIFT);
150
151 return result;
152}
153
154void do_gettimeofday(struct timeval *tv)
155{
156 unsigned long flags;
157 unsigned long seq;
158 unsigned long usec, sec;
159
160 do {
161 seq = read_seqbegin_irqsave(&xtime_lock, flags);
162 usec = usecs_since_tick();
163 sec = xtime.tv_sec;
164 usec += xtime.tv_nsec / 1000;
165 } while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
166
167 while (usec >= 1000000) {
168 usec -= 1000000;
169 sec++;
170 }
171
172 tv->tv_sec = sec;
173 tv->tv_usec = usec;
174}
175
176int do_settimeofday(struct timespec *tv)
177{
178 time_t wtm_sec, sec = tv->tv_sec;
179 long wtm_nsec, nsec = tv->tv_nsec;
180
181 if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
182 return -EINVAL;
183
184 write_seqlock_irq(&xtime_lock);
185 /*
186 * This is revolting. We need to set "xtime" correctly. However, the
187 * value in this location is the value at the most recent update of
188 * wall time. Discover what correction gettimeofday() would have
189 * made, and then undo it!
190 */
191 nsec -= 1000 * usecs_since_tick();
192
193 wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
194 wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
195
196 set_normalized_timespec(&xtime, sec, nsec);
197 set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
198
199 ntp_clear();
200 write_sequnlock_irq(&xtime_lock);
201 clock_was_set();
202
203 return 0;
204}
205EXPORT_SYMBOL(do_settimeofday);
206
207/* Dummy RTC ops */
208static void null_rtc_get_time(struct timespec *tv)
209{
210 tv->tv_sec = mktime(2000, 1, 1, 0, 0, 0);
211 tv->tv_nsec = 0;
212}
213
214static int null_rtc_set_time(const time_t secs)
215{
216 return 0;
217}
218
219void (*rtc_sh_get_time)(struct timespec *) = null_rtc_get_time;
220int (*rtc_sh_set_time)(const time_t) = null_rtc_set_time;
221
222/* last time the RTC clock got updated */
223static long last_rtc_update;
224
225/*
226 * timer_interrupt() needs to keep up the real-time clock,
227 * as well as call the "do_timer()" routine every clocktick
228 */
229static inline void do_timer_interrupt(void)
230{
231 unsigned long long current_ctc;
232 asm ("getcon cr62, %0" : "=r" (current_ctc));
233 ctc_last_interrupt = (unsigned long) current_ctc;
234
235 do_timer(1);
236#ifndef CONFIG_SMP
237 update_process_times(user_mode(get_irq_regs()));
238#endif
239 if (current->pid)
240 profile_tick(CPU_PROFILING);
241
242#ifdef CONFIG_HEARTBEAT
243 {
244 extern void heartbeat(void);
245
246 heartbeat();
247 }
248#endif
249
250 /*
251 * If we have an externally synchronized Linux clock, then update
252 * RTC clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
253 * called as close as possible to 500 ms before the new second starts.
254 */
255 if (ntp_synced() &&
256 xtime.tv_sec > last_rtc_update + 660 &&
257 (xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 &&
258 (xtime.tv_nsec / 1000) <= 500000 + ((unsigned) TICK_SIZE) / 2) {
259 if (rtc_sh_set_time(xtime.tv_sec) == 0)
260 last_rtc_update = xtime.tv_sec;
261 else
262 /* do it again in 60 s */
263 last_rtc_update = xtime.tv_sec - 600;
264 }
265}
266
267/*
268 * This is the same as the above, except we _also_ save the current
269 * Time Stamp Counter value at the time of the timer interrupt, so that
270 * we later on can estimate the time of day more exactly.
271 */
272static irqreturn_t timer_interrupt(int irq, void *dev_id)
273{
274 unsigned long timer_status;
275
276 /* Clear UNF bit */
277 timer_status = ctrl_inw(TMU0_TCR);
278 timer_status &= ~0x100;
279 ctrl_outw(timer_status, TMU0_TCR);
280
281 /*
282 * Here we are in the timer irq handler. We just have irqs locally
283 * disabled but we don't know if the timer_bh is running on the other
284 * CPU. We need to avoid to SMP race with it. NOTE: we don' t need
285 * the irq version of write_lock because as just said we have irq
286 * locally disabled. -arca
287 */
288 write_lock(&xtime_lock);
289 do_timer_interrupt();
290 write_unlock(&xtime_lock);
291
292 return IRQ_HANDLED;
293}
294
295
296static __init unsigned int get_cpu_hz(void)
297{
298 unsigned int count;
299 unsigned long __dummy;
300 unsigned long ctc_val_init, ctc_val;
301
302 /*
303 ** Regardless the toolchain, force the compiler to use the
304 ** arbitrary register r3 as a clock tick counter.
305 ** NOTE: r3 must be in accordance with sh64_rtc_interrupt()
306 */
307 register unsigned long long __rtc_irq_flag __asm__ ("r3");
308
309 local_irq_enable();
310 do {} while (ctrl_inb(rtc_base) != 0);
311 ctrl_outb(RTC_RCR1_CIE, RTC_RCR1); /* Enable carry interrupt */
312
313 /*
314 * r3 is arbitrary. CDC does not support "=z".
315 */
316 ctc_val_init = 0xffffffff;
317 ctc_val = ctc_val_init;
318
319 asm volatile("gettr tr0, %1\n\t"
320 "putcon %0, " __CTC "\n\t"
321 "and %2, r63, %2\n\t"
322 "pta $+4, tr0\n\t"
323 "beq/l %2, r63, tr0\n\t"
324 "ptabs %1, tr0\n\t"
325 "getcon " __CTC ", %0\n\t"
326 : "=r"(ctc_val), "=r" (__dummy), "=r" (__rtc_irq_flag)
327 : "0" (0));
328 local_irq_disable();
329 /*
330 * SH-3:
331 * CPU clock = 4 stages * loop
332 * tst rm,rm if id ex
333 * bt/s 1b if id ex
334 * add #1,rd if id ex
335 * (if) pipe line stole
336 * tst rm,rm if id ex
337 * ....
338 *
339 *
340 * SH-4:
341 * CPU clock = 6 stages * loop
342 * I don't know why.
343 * ....
344 *
345 * SH-5:
346 * Use CTC register to count. This approach returns the right value
347 * even if the I-cache is disabled (e.g. whilst debugging.)
348 *
349 */
350
351 count = ctc_val_init - ctc_val; /* CTC counts down */
352
353#if defined (CONFIG_SH_SIMULATOR)
354 /*
355 * Let's pretend we are a 5MHz SH-5 to avoid a too
356 * little timer interval. Also to keep delay
357 * calibration within a reasonable time.
358 */
359 return 5000000;
360#else
361 /*
362 * This really is count by the number of clock cycles
363 * by the ratio between a complete R64CNT
364 * wrap-around (128) and CUI interrupt being raised (64).
365 */
366 return count*2;
367#endif
368}
369
370static irqreturn_t sh64_rtc_interrupt(int irq, void *dev_id)
371{
372 struct pt_regs *regs = get_irq_regs();
373
374 ctrl_outb(0, RTC_RCR1); /* Disable Carry Interrupts */
375 regs->regs[3] = 1; /* Using r3 */
376
377 return IRQ_HANDLED;
378}
379
380static struct irqaction irq0 = {
381 .handler = timer_interrupt,
382 .flags = IRQF_DISABLED,
383 .mask = CPU_MASK_NONE,
384 .name = "timer",
385};
386static struct irqaction irq1 = {
387 .handler = sh64_rtc_interrupt,
388 .flags = IRQF_DISABLED,
389 .mask = CPU_MASK_NONE,
390 .name = "rtc",
391};
392
393void __init time_init(void)
394{
395 unsigned int cpu_clock, master_clock, bus_clock, module_clock;
396 unsigned long interval;
397 unsigned long frqcr, ifc, pfc;
398 static int ifc_table[] = { 2, 4, 6, 8, 10, 12, 16, 24 };
399#define bfc_table ifc_table /* Same */
400#define pfc_table ifc_table /* Same */
401
402 tmu_base = onchip_remap(TMU_BASE, 1024, "TMU");
403 if (!tmu_base) {
404 panic("Unable to remap TMU\n");
405 }
406
407 rtc_base = onchip_remap(RTC_BASE, 1024, "RTC");
408 if (!rtc_base) {
409 panic("Unable to remap RTC\n");
410 }
411
412 cprc_base = onchip_remap(CPRC_BASE, 1024, "CPRC");
413 if (!cprc_base) {
414 panic("Unable to remap CPRC\n");
415 }
416
417 rtc_sh_get_time(&xtime);
418
419 setup_irq(TIMER_IRQ, &irq0);
420 setup_irq(RTC_IRQ, &irq1);
421
422 /* Check how fast it is.. */
423 cpu_clock = get_cpu_hz();
424
425 /* Note careful order of operations to maintain reasonable precision and avoid overflow. */
426 scaled_recip_ctc_ticks_per_jiffy = ((1ULL << CTC_JIFFY_SCALE_SHIFT) / (unsigned long long)(cpu_clock / HZ));
427
428 free_irq(RTC_IRQ, NULL);
429
430 printk("CPU clock: %d.%02dMHz\n",
431 (cpu_clock / 1000000), (cpu_clock % 1000000)/10000);
432 {
433 unsigned short bfc;
434 frqcr = ctrl_inl(FRQCR);
435 ifc = ifc_table[(frqcr>> 6) & 0x0007];
436 bfc = bfc_table[(frqcr>> 3) & 0x0007];
437 pfc = pfc_table[(frqcr>> 12) & 0x0007];
438 master_clock = cpu_clock * ifc;
439 bus_clock = master_clock/bfc;
440 }
441
442 printk("Bus clock: %d.%02dMHz\n",
443 (bus_clock/1000000), (bus_clock % 1000000)/10000);
444 module_clock = master_clock/pfc;
445 printk("Module clock: %d.%02dMHz\n",
446 (module_clock/1000000), (module_clock % 1000000)/10000);
447 interval = (module_clock/(HZ*4));
448
449 printk("Interval = %ld\n", interval);
450
451 current_cpu_data.cpu_clock = cpu_clock;
452 current_cpu_data.master_clock = master_clock;
453 current_cpu_data.bus_clock = bus_clock;
454 current_cpu_data.module_clock = module_clock;
455
456 /* Start TMU0 */
457 ctrl_outb(TMU_TSTR_OFF, TMU_TSTR);
458 ctrl_outb(TMU_TOCR_INIT, TMU_TOCR);
459 ctrl_outw(TMU0_TCR_INIT, TMU0_TCR);
460 ctrl_outl(interval, TMU0_TCOR);
461 ctrl_outl(interval, TMU0_TCNT);
462 ctrl_outb(TMU_TSTR_INIT, TMU_TSTR);
463}
464
465void enter_deep_standby(void)
466{
467 /* Disable watchdog timer */
468 ctrl_outl(0xa5000000, WTCSR);
469 /* Configure deep standby on sleep */
470 ctrl_outl(0x03, STBCR);
471
472#ifdef CONFIG_SH_ALPHANUMERIC
473 {
474 extern void mach_alphanum(int position, unsigned char value);
475 extern void mach_alphanum_brightness(int setting);
476 char halted[] = "Halted. ";
477 int i;
478 mach_alphanum_brightness(6); /* dimmest setting above off */
479 for (i=0; i<8; i++) {
480 mach_alphanum(i, halted[i]);
481 }
482 asm __volatile__ ("synco");
483 }
484#endif
485
486 asm __volatile__ ("sleep");
487 asm __volatile__ ("synci");
488 asm __volatile__ ("nop");
489 asm __volatile__ ("nop");
490 asm __volatile__ ("nop");
491 asm __volatile__ ("nop");
492 panic("Unexpected wakeup!\n");
493}
494
495static struct resource rtc_resources[] = {
496 [0] = {
497 /* RTC base, filled in by rtc_init */
498 .flags = IORESOURCE_IO,
499 },
500 [1] = {
501 /* Period IRQ */
502 .start = IRQ_PRI,
503 .flags = IORESOURCE_IRQ,
504 },
505 [2] = {
506 /* Carry IRQ */
507 .start = IRQ_CUI,
508 .flags = IORESOURCE_IRQ,
509 },
510 [3] = {
511 /* Alarm IRQ */
512 .start = IRQ_ATI,
513 .flags = IORESOURCE_IRQ,
514 },
515};
516
517static struct platform_device rtc_device = {
518 .name = "sh-rtc",
519 .id = -1,
520 .num_resources = ARRAY_SIZE(rtc_resources),
521 .resource = rtc_resources,
522};
523
524static int __init rtc_init(void)
525{
526 rtc_resources[0].start = rtc_base;
527 rtc_resources[0].end = rtc_resources[0].start + 0x58 - 1;
528
529 return platform_device_register(&rtc_device);
530}
531device_initcall(rtc_init);