aboutsummaryrefslogtreecommitdiff
path: root/arch/arm/mach-footbridge
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-footbridge')
-rw-r--r--arch/arm/mach-footbridge/Kconfig8
-rw-r--r--arch/arm/mach-footbridge/Makefile9
-rw-r--r--arch/arm/mach-footbridge/Makefile.boot2
-rw-r--r--arch/arm/mach-footbridge/cats-hw.c17
-rw-r--r--arch/arm/mach-footbridge/cats-pci.c14
-rw-r--r--arch/arm/mach-footbridge/common.c100
-rw-r--r--arch/arm/mach-footbridge/common.h9
-rw-r--r--arch/arm/mach-footbridge/dc21285-timer.c123
-rw-r--r--arch/arm/mach-footbridge/dc21285.c52
-rw-r--r--arch/arm/mach-footbridge/dma.c15
-rw-r--r--arch/arm/mach-footbridge/ebsa285-leds.c139
-rw-r--r--arch/arm/mach-footbridge/ebsa285-pci.c11
-rw-r--r--arch/arm/mach-footbridge/ebsa285.c105
-rw-r--r--arch/arm/mach-footbridge/include/mach/debug-macro.S42
-rw-r--r--arch/arm/mach-footbridge/include/mach/entry-macro.S107
-rw-r--r--arch/arm/mach-footbridge/include/mach/hardware.h99
-rw-r--r--arch/arm/mach-footbridge/include/mach/io.h23
-rw-r--r--arch/arm/mach-footbridge/include/mach/irqs.h96
-rw-r--r--arch/arm/mach-footbridge/include/mach/isa-dma.h25
-rw-r--r--arch/arm/mach-footbridge/include/mach/memory.h69
-rw-r--r--arch/arm/mach-footbridge/include/mach/uncompress.h37
-rw-r--r--arch/arm/mach-footbridge/isa-irq.c56
-rw-r--r--arch/arm/mach-footbridge/isa-rtc.c57
-rw-r--r--arch/arm/mach-footbridge/isa-timer.c85
-rw-r--r--arch/arm/mach-footbridge/isa.c18
-rw-r--r--arch/arm/mach-footbridge/netwinder-hw.c199
-rw-r--r--arch/arm/mach-footbridge/netwinder-leds.c140
-rw-r--r--arch/arm/mach-footbridge/netwinder-pci.c5
-rw-r--r--arch/arm/mach-footbridge/personal-pci.c5
-rw-r--r--arch/arm/mach-footbridge/personal.c8
-rw-r--r--arch/arm/mach-footbridge/time.c164
31 files changed, 1125 insertions, 714 deletions
diff --git a/arch/arm/mach-footbridge/Kconfig b/arch/arm/mach-footbridge/Kconfig
index bdd257921cf..07152d00fc5 100644
--- a/arch/arm/mach-footbridge/Kconfig
+++ b/arch/arm/mach-footbridge/Kconfig
@@ -4,6 +4,8 @@ menu "Footbridge Implementations"
config ARCH_CATS
bool "CATS"
+ select CLKEVT_I8253
+ select CLKSRC_I8253
select FOOTBRIDGE_HOST
select ISA
select ISA_DMA
@@ -50,6 +52,7 @@ config ARCH_EBSA285_HOST
select FOOTBRIDGE_HOST
select ISA
select ISA_DMA
+ select ARCH_MAY_HAVE_PC_FDC
select PCI
help
Say Y here if you intend to run this kernel on the EBSA285 card
@@ -59,10 +62,13 @@ config ARCH_EBSA285_HOST
config ARCH_NETWINDER
bool "NetWinder"
+ select CLKEVT_I8253
+ select CLKSRC_I8253
select FOOTBRIDGE_HOST
select ISA
select ISA_DMA
select PCI
+ select VIRT_TO_BUS
help
Say Y here if you intend to run this kernel on the Rebel.COM
NetWinder. Information about this machine can be found at:
@@ -80,6 +86,7 @@ config FOOTBRIDGE
# Footbridge in host mode
config FOOTBRIDGE_HOST
bool
+ select ARCH_MIGHT_HAVE_PC_SERIO
# Footbridge in addin mode
config FOOTBRIDGE_ADDIN
@@ -87,7 +94,6 @@ config FOOTBRIDGE_ADDIN
# EBSA285 board in either host or addin mode
config ARCH_EBSA285
- select ARCH_MAY_HAVE_PC_FDC
bool
endif
diff --git a/arch/arm/mach-footbridge/Makefile b/arch/arm/mach-footbridge/Makefile
index 32f8609e4f8..c3faa3bc84d 100644
--- a/arch/arm/mach-footbridge/Makefile
+++ b/arch/arm/mach-footbridge/Makefile
@@ -4,25 +4,22 @@
# Object file lists.
-obj-y := common.o dc21285.o dma.o isa-irq.o time.o
+obj-y := common.o dma.o isa-irq.o
obj-m :=
obj-n :=
obj- :=
+pci-y += dc21285.o
pci-$(CONFIG_ARCH_CATS) += cats-pci.o
pci-$(CONFIG_ARCH_EBSA285_HOST) += ebsa285-pci.o
pci-$(CONFIG_ARCH_NETWINDER) += netwinder-pci.o
pci-$(CONFIG_ARCH_PERSONAL_SERVER) += personal-pci.o
-leds-$(CONFIG_ARCH_EBSA285) += ebsa285-leds.o
-leds-$(CONFIG_ARCH_NETWINDER) += netwinder-leds.o
-
obj-$(CONFIG_ARCH_CATS) += cats-hw.o isa-timer.o
obj-$(CONFIG_ARCH_EBSA285) += ebsa285.o dc21285-timer.o
obj-$(CONFIG_ARCH_NETWINDER) += netwinder-hw.o isa-timer.o
obj-$(CONFIG_ARCH_PERSONAL_SERVER) += personal.o dc21285-timer.o
obj-$(CONFIG_PCI) +=$(pci-y)
-obj-$(CONFIG_LEDS) +=$(leds-y)
-obj-$(CONFIG_ISA) += isa.o
+obj-$(CONFIG_ISA) += isa.o isa-rtc.o
diff --git a/arch/arm/mach-footbridge/Makefile.boot b/arch/arm/mach-footbridge/Makefile.boot
index c7e75acfe6c..ff0a4b5b0a8 100644
--- a/arch/arm/mach-footbridge/Makefile.boot
+++ b/arch/arm/mach-footbridge/Makefile.boot
@@ -1,4 +1,4 @@
- zreladdr-y := 0x00008000
+ zreladdr-y += 0x00008000
params_phys-y := 0x00000100
initrd_phys-y := 0x00800000
diff --git a/arch/arm/mach-footbridge/cats-hw.c b/arch/arm/mach-footbridge/cats-hw.c
index c261472208c..8f05489671b 100644
--- a/arch/arm/mach-footbridge/cats-hw.c
+++ b/arch/arm/mach-footbridge/cats-hw.c
@@ -9,9 +9,10 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/screen_info.h>
+#include <linux/io.h>
+#include <linux/spinlock.h>
#include <asm/hardware/dec21285.h>
-#include <asm/io.h>
#include <asm/mach-types.h>
#include <asm/setup.h>
@@ -75,22 +76,22 @@ __initcall(cats_hw_init);
* hard reboots fail on early boards.
*/
static void __init
-fixup_cats(struct machine_desc *desc, struct tag *tags,
- char **cmdline, struct meminfo *mi)
+fixup_cats(struct tag *tags, char **cmdline)
{
+#if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE)
screen_info.orig_video_lines = 25;
screen_info.orig_video_points = 16;
screen_info.orig_y = 24;
+#endif
}
MACHINE_START(CATS, "Chalice-CATS")
/* Maintainer: Philip Blundell */
- .phys_io = DC21285_ARMCSR_BASE,
- .io_pg_offst = ((0xfe000000) >> 18) & 0xfffc,
- .boot_params = 0x00000100,
- .soft_reboot = 1,
+ .atag_offset = 0x100,
+ .reboot_mode = REBOOT_SOFT,
.fixup = fixup_cats,
.map_io = footbridge_map_io,
.init_irq = footbridge_init_irq,
- .timer = &isa_timer,
+ .init_time = isa_timer_init,
+ .restart = footbridge_restart,
MACHINE_END
diff --git a/arch/arm/mach-footbridge/cats-pci.c b/arch/arm/mach-footbridge/cats-pci.c
index 35eb232a649..5cec2567c9c 100644
--- a/arch/arm/mach-footbridge/cats-pci.c
+++ b/arch/arm/mach-footbridge/cats-pci.c
@@ -16,8 +16,16 @@
/* cats host-specific stuff */
static int irqmap_cats[] __initdata = { IRQ_PCI, IRQ_IN0, IRQ_IN1, IRQ_IN3 };
-static int __init cats_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+static u8 cats_no_swizzle(struct pci_dev *dev, u8 *pin)
{
+ return 0;
+}
+
+static int __init cats_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+{
+ if (dev->irq >= 255)
+ return -1; /* not a valid interrupt. */
+
if (dev->irq >= 128)
return dev->irq & 0x1f;
@@ -36,11 +44,11 @@ static int __init cats_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
* cards being used (ie, pci-pci bridge based cards)?
*/
static struct hw_pci cats_pci __initdata = {
- .swizzle = NULL,
+ .swizzle = cats_no_swizzle,
.map_irq = cats_map_irq,
.nr_controllers = 1,
+ .ops = &dc21285_ops,
.setup = dc21285_setup,
- .scan = dc21285_scan_bus,
.preinit = dc21285_preinit,
.postinit = dc21285_postinit,
};
diff --git a/arch/arm/mach-footbridge/common.c b/arch/arm/mach-footbridge/common.c
index b08ab507c05..9e8220e3839 100644
--- a/arch/arm/mach-footbridge/common.c
+++ b/arch/arm/mach-footbridge/common.c
@@ -13,26 +13,36 @@
#include <linux/ioport.h>
#include <linux/list.h>
#include <linux/init.h>
-
+#include <linux/io.h>
+#include <linux/spinlock.h>
+#include <video/vga.h>
+
#include <asm/pgtable.h>
#include <asm/page.h>
#include <asm/irq.h>
-#include <asm/io.h>
#include <asm/mach-types.h>
#include <asm/setup.h>
+#include <asm/system_misc.h>
#include <asm/hardware/dec21285.h>
#include <asm/mach/irq.h>
#include <asm/mach/map.h>
+#include <asm/mach/pci.h>
#include "common.h"
-extern void __init isa_init_irq(unsigned int irq);
-
unsigned int mem_fclk_21285 = 50000000;
EXPORT_SYMBOL(mem_fclk_21285);
+static int __init early_fclk(char *arg)
+{
+ mem_fclk_21285 = simple_strtoul(arg, NULL, 0);
+ return 0;
+}
+
+early_param("mem_fclk_21285", early_fclk);
+
static int __init parse_tag_memclk(const struct tag *tag)
{
mem_fclk_21285 = tag->u.memclk.fmemclk;
@@ -68,20 +78,20 @@ static const int fb_irq_mask[] = {
IRQ_MASK_PCI_PERR, /* 19 */
};
-static void fb_mask_irq(unsigned int irq)
+static void fb_mask_irq(struct irq_data *d)
{
- *CSR_IRQ_DISABLE = fb_irq_mask[_DC21285_INR(irq)];
+ *CSR_IRQ_DISABLE = fb_irq_mask[_DC21285_INR(d->irq)];
}
-static void fb_unmask_irq(unsigned int irq)
+static void fb_unmask_irq(struct irq_data *d)
{
- *CSR_IRQ_ENABLE = fb_irq_mask[_DC21285_INR(irq)];
+ *CSR_IRQ_ENABLE = fb_irq_mask[_DC21285_INR(d->irq)];
}
static struct irq_chip fb_chip = {
- .ack = fb_mask_irq,
- .mask = fb_mask_irq,
- .unmask = fb_unmask_irq,
+ .irq_ack = fb_mask_irq,
+ .irq_mask = fb_mask_irq,
+ .irq_unmask = fb_unmask_irq,
};
static void __init __fb_init_irq(void)
@@ -95,8 +105,7 @@ static void __init __fb_init_irq(void)
*CSR_FIQ_DISABLE = -1;
for (irq = _DC21285_IRQ(0); irq < _DC21285_IRQ(20); irq++) {
- set_irq_chip(irq, &fb_chip);
- set_irq_handler(irq, handle_level_irq);
+ irq_set_chip_and_handler(irq, &fb_chip, handle_level_irq);
set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
}
}
@@ -134,11 +143,6 @@ static struct map_desc fb_common_io_desc[] __initdata = {
.pfn = __phys_to_pfn(DC21285_ARMCSR_BASE),
.length = ARMCSR_SIZE,
.type = MT_DEVICE,
- }, {
- .virtual = XBUS_BASE,
- .pfn = __phys_to_pfn(0x40000000),
- .length = XBUS_SIZE,
- .type = MT_DEVICE,
}
};
@@ -168,11 +172,6 @@ static struct map_desc ebsa285_host_io_desc[] __initdata = {
.pfn = __phys_to_pfn(DC21285_PCI_IACK),
.length = PCIIACK_SIZE,
.type = MT_DEVICE,
- }, {
- .virtual = PCIO_BASE,
- .pfn = __phys_to_pfn(DC21285_PCI_IO),
- .length = PCIO_SIZE,
- .type = MT_DEVICE,
},
#endif
};
@@ -189,12 +188,48 @@ void __init footbridge_map_io(void)
* Now, work out what we've got to map in addition on this
* platform.
*/
- if (footbridge_cfn_mode())
+ if (footbridge_cfn_mode()) {
iotable_init(ebsa285_host_io_desc, ARRAY_SIZE(ebsa285_host_io_desc));
+ pci_map_io_early(__phys_to_pfn(DC21285_PCI_IO));
+ }
+
+ vga_base = PCIMEM_BASE;
+}
+
+void footbridge_restart(enum reboot_mode mode, const char *cmd)
+{
+ if (mode == REBOOT_SOFT) {
+ /* Jump into the ROM */
+ soft_restart(0x41000000);
+ } else {
+ /*
+ * Force the watchdog to do a CPU reset.
+ *
+ * After making sure that the watchdog is disabled
+ * (so we can change the timer registers) we first
+ * enable the timer to autoreload itself. Next, the
+ * timer interval is set really short and any
+ * current interrupt request is cleared (so we can
+ * see an edge transition). Finally, TIMER4 is
+ * enabled as the watchdog.
+ */
+ *CSR_SA110_CNTL &= ~(1 << 13);
+ *CSR_TIMER4_CNTL = TIMER_CNTL_ENABLE |
+ TIMER_CNTL_AUTORELOAD |
+ TIMER_CNTL_DIV16;
+ *CSR_TIMER4_LOAD = 0x2;
+ *CSR_TIMER4_CLR = 0;
+ *CSR_SA110_CNTL |= (1 << 13);
+ }
}
#ifdef CONFIG_FOOTBRIDGE_ADDIN
+static inline unsigned long fb_bus_sdram_offset(void)
+{
+ return *CSR_PCISDRAMBASE & 0xfffffff0;
+}
+
/*
* These two functions convert virtual addresses to PCI addresses and PCI
* addresses to virtual addresses. Note that it is only legal to use these
@@ -204,14 +239,13 @@ unsigned long __virt_to_bus(unsigned long res)
{
WARN_ON(res < PAGE_OFFSET || res >= (unsigned long)high_memory);
- return (res - PAGE_OFFSET) + (*CSR_PCISDRAMBASE & 0xfffffff0);
+ return res + (fb_bus_sdram_offset() - PAGE_OFFSET);
}
EXPORT_SYMBOL(__virt_to_bus);
unsigned long __bus_to_virt(unsigned long res)
{
- res -= (*CSR_PCISDRAMBASE & 0xfffffff0);
- res += PAGE_OFFSET;
+ res = res - (fb_bus_sdram_offset() - PAGE_OFFSET);
WARN_ON(res < PAGE_OFFSET || res >= (unsigned long)high_memory);
@@ -219,4 +253,16 @@ unsigned long __bus_to_virt(unsigned long res)
}
EXPORT_SYMBOL(__bus_to_virt);
+unsigned long __pfn_to_bus(unsigned long pfn)
+{
+ return __pfn_to_phys(pfn) + (fb_bus_sdram_offset() - PHYS_OFFSET);
+}
+EXPORT_SYMBOL(__pfn_to_bus);
+
+unsigned long __bus_to_pfn(unsigned long bus)
+{
+ return __phys_to_pfn(bus - (fb_bus_sdram_offset() - PHYS_OFFSET));
+}
+EXPORT_SYMBOL(__bus_to_pfn);
+
#endif
diff --git a/arch/arm/mach-footbridge/common.h b/arch/arm/mach-footbridge/common.h
index 580e31bbc71..b911e5587ec 100644
--- a/arch/arm/mach-footbridge/common.h
+++ b/arch/arm/mach-footbridge/common.h
@@ -1,9 +1,14 @@
+#include <linux/reboot.h>
-extern struct sys_timer footbridge_timer;
-extern struct sys_timer isa_timer;
+extern void footbridge_timer_init(void);
+extern void isa_timer_init(void);
extern void isa_rtc_init(void);
extern void footbridge_map_io(void);
extern void footbridge_init_irq(void);
+extern void isa_init_irq(unsigned int irq);
+extern void footbridge_restart(enum reboot_mode, const char *);
+
+extern void footbridge_sched_clock(void);
diff --git a/arch/arm/mach-footbridge/dc21285-timer.c b/arch/arm/mach-footbridge/dc21285-timer.c
index b2a21189dd8..bf7aa7d298e 100644
--- a/arch/arm/mach-footbridge/dc21285-timer.c
+++ b/arch/arm/mach-footbridge/dc21285-timer.c
@@ -4,62 +4,139 @@
* Copyright (C) 1998 Russell King.
* Copyright (C) 1998 Phil Blundell
*/
+#include <linux/clockchips.h>
+#include <linux/clocksource.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
+#include <linux/sched_clock.h>
#include <asm/irq.h>
#include <asm/hardware/dec21285.h>
#include <asm/mach/time.h>
+#include <asm/system_info.h>
#include "common.h"
-/*
- * Footbridge timer 1 support.
- */
-static unsigned long timer1_latch;
+static cycle_t cksrc_dc21285_read(struct clocksource *cs)
+{
+ return cs->mask - *CSR_TIMER2_VALUE;
+}
-static unsigned long timer1_gettimeoffset (void)
+static int cksrc_dc21285_enable(struct clocksource *cs)
{
- unsigned long value = timer1_latch - *CSR_TIMER1_VALUE;
+ *CSR_TIMER2_LOAD = cs->mask;
+ *CSR_TIMER2_CLR = 0;
+ *CSR_TIMER2_CNTL = TIMER_CNTL_ENABLE | TIMER_CNTL_DIV16;
+ return 0;
+}
- return ((tick_nsec / 1000) * value) / timer1_latch;
+static void cksrc_dc21285_disable(struct clocksource *cs)
+{
+ *CSR_TIMER2_CNTL = 0;
}
-static irqreturn_t
-timer1_interrupt(int irq, void *dev_id)
+static struct clocksource cksrc_dc21285 = {
+ .name = "dc21285_timer2",
+ .rating = 200,
+ .read = cksrc_dc21285_read,
+ .enable = cksrc_dc21285_enable,
+ .disable = cksrc_dc21285_disable,
+ .mask = CLOCKSOURCE_MASK(24),
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static int ckevt_dc21285_set_next_event(unsigned long delta,
+ struct clock_event_device *c)
{
*CSR_TIMER1_CLR = 0;
+ *CSR_TIMER1_LOAD = delta;
+ *CSR_TIMER1_CNTL = TIMER_CNTL_ENABLE | TIMER_CNTL_DIV16;
- timer_tick();
+ return 0;
+}
+
+static void ckevt_dc21285_set_mode(enum clock_event_mode mode,
+ struct clock_event_device *c)
+{
+ switch (mode) {
+ case CLOCK_EVT_MODE_RESUME:
+ case CLOCK_EVT_MODE_PERIODIC:
+ *CSR_TIMER1_CLR = 0;
+ *CSR_TIMER1_LOAD = (mem_fclk_21285 + 8 * HZ) / (16 * HZ);
+ *CSR_TIMER1_CNTL = TIMER_CNTL_ENABLE | TIMER_CNTL_AUTORELOAD |
+ TIMER_CNTL_DIV16;
+ break;
+
+ case CLOCK_EVT_MODE_ONESHOT:
+ case CLOCK_EVT_MODE_UNUSED:
+ case CLOCK_EVT_MODE_SHUTDOWN:
+ *CSR_TIMER1_CNTL = 0;
+ break;
+ }
+}
+
+static struct clock_event_device ckevt_dc21285 = {
+ .name = "dc21285_timer1",
+ .features = CLOCK_EVT_FEAT_PERIODIC |
+ CLOCK_EVT_FEAT_ONESHOT,
+ .rating = 200,
+ .irq = IRQ_TIMER1,
+ .set_next_event = ckevt_dc21285_set_next_event,
+ .set_mode = ckevt_dc21285_set_mode,
+};
+
+static irqreturn_t timer1_interrupt(int irq, void *dev_id)
+{
+ struct clock_event_device *ce = dev_id;
+
+ *CSR_TIMER1_CLR = 0;
+
+ /* Stop the timer if in one-shot mode */
+ if (ce->mode == CLOCK_EVT_MODE_ONESHOT)
+ *CSR_TIMER1_CNTL = 0;
+
+ ce->event_handler(ce);
return IRQ_HANDLED;
}
static struct irqaction footbridge_timer_irq = {
- .name = "Timer1 timer tick",
+ .name = "dc21285_timer1",
.handler = timer1_interrupt,
- .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+ .flags = IRQF_TIMER | IRQF_IRQPOLL,
+ .dev_id = &ckevt_dc21285,
};
/*
* Set up timer interrupt.
*/
-static void __init footbridge_timer_init(void)
+void __init footbridge_timer_init(void)
{
- timer1_latch = (mem_fclk_21285 + 8 * HZ) / (16 * HZ);
+ struct clock_event_device *ce = &ckevt_dc21285;
+ unsigned rate = DIV_ROUND_CLOSEST(mem_fclk_21285, 16);
- *CSR_TIMER1_CLR = 0;
- *CSR_TIMER1_LOAD = timer1_latch;
- *CSR_TIMER1_CNTL = TIMER_CNTL_ENABLE | TIMER_CNTL_AUTORELOAD | TIMER_CNTL_DIV16;
+ clocksource_register_hz(&cksrc_dc21285, rate);
- setup_irq(IRQ_TIMER1, &footbridge_timer_irq);
+ setup_irq(ce->irq, &footbridge_timer_irq);
- isa_rtc_init();
+ ce->cpumask = cpumask_of(smp_processor_id());
+ clockevents_config_and_register(ce, rate, 0x4, 0xffffff);
}
-struct sys_timer footbridge_timer = {
- .init = footbridge_timer_init,
- .offset = timer1_gettimeoffset,
-};
+static u64 notrace footbridge_read_sched_clock(void)
+{
+ return ~*CSR_TIMER3_VALUE;
+}
+
+void __init footbridge_sched_clock(void)
+{
+ unsigned rate = DIV_ROUND_CLOSEST(mem_fclk_21285, 16);
+
+ *CSR_TIMER3_LOAD = 0;
+ *CSR_TIMER3_CLR = 0;
+ *CSR_TIMER3_CNTL = TIMER_CNTL_ENABLE | TIMER_CNTL_DIV16;
+
+ sched_clock_register(footbridge_read_sched_clock, 24, rate);
+}
diff --git a/arch/arm/mach-footbridge/dc21285.c b/arch/arm/mach-footbridge/dc21285.c
index d0dc51e8133..96a3d73ef4b 100644
--- a/arch/arm/mach-footbridge/dc21285.c
+++ b/arch/arm/mach-footbridge/dc21285.c
@@ -16,10 +16,10 @@
#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/spinlock.h>
-#include <asm/io.h>
#include <asm/irq.h>
-#include <asm/system.h>
#include <asm/mach/pci.h>
#include <asm/hardware/dec21285.h>
@@ -128,7 +128,7 @@ dc21285_write_config(struct pci_bus *bus, unsigned int devfn, int where,
return PCIBIOS_SUCCESSFUL;
}
-static struct pci_ops dc21285_ops = {
+struct pci_ops dc21285_ops = {
.read = dc21285_read_config,
.write = dc21285_write_config,
};
@@ -273,28 +273,28 @@ int __init dc21285_setup(int nr, struct pci_sys_data *sys)
allocate_resource(&iomem_resource, &res[0], 0x40000000,
0x80000000, 0xffffffff, 0x40000000, NULL, NULL);
- sys->resource[0] = &ioport_resource;
- sys->resource[1] = &res[0];
- sys->resource[2] = &res[1];
sys->mem_offset = DC21285_PCI_MEM;
+ pci_add_resource_offset(&sys->resources, &res[0], sys->mem_offset);
+ pci_add_resource_offset(&sys->resources, &res[1], sys->mem_offset);
+
return 1;
}
-struct pci_bus * __init dc21285_scan_bus(int nr, struct pci_sys_data *sys)
-{
- return pci_scan_bus(0, &dc21285_ops, sys);
-}
+#define dc21285_request_irq(_a, _b, _c, _d, _e) \
+ WARN_ON(request_irq(_a, _b, _c, _d, _e) < 0)
void __init dc21285_preinit(void)
{
unsigned int mem_size, mem_mask;
int cfn_mode;
+ pcibios_min_mem = 0x81000000;
+
mem_size = (unsigned int)high_memory - PAGE_OFFSET;
for (mem_mask = 0x00100000; mem_mask < 0x10000000; mem_mask <<= 1)
if (mem_mask >= mem_size)
- break;
+ break;
/*
* These registers need to be set up whether we're the
@@ -334,26 +334,18 @@ void __init dc21285_preinit(void)
/*
* We don't care if these fail.
*/
- request_irq(IRQ_PCI_SERR, dc21285_serr_irq, IRQF_DISABLED,
- "PCI system error", &serr_timer);
- request_irq(IRQ_PCI_PERR, dc21285_parity_irq, IRQF_DISABLED,
- "PCI parity error", &perr_timer);
- request_irq(IRQ_PCI_ABORT, dc21285_abort_irq, IRQF_DISABLED,
- "PCI abort", NULL);
- request_irq(IRQ_DISCARD_TIMER, dc21285_discard_irq, IRQF_DISABLED,
- "Discard timer", NULL);
- request_irq(IRQ_PCI_DPERR, dc21285_dparity_irq, IRQF_DISABLED,
- "PCI data parity", NULL);
+ dc21285_request_irq(IRQ_PCI_SERR, dc21285_serr_irq, 0,
+ "PCI system error", &serr_timer);
+ dc21285_request_irq(IRQ_PCI_PERR, dc21285_parity_irq, 0,
+ "PCI parity error", &perr_timer);
+ dc21285_request_irq(IRQ_PCI_ABORT, dc21285_abort_irq, 0,
+ "PCI abort", NULL);
+ dc21285_request_irq(IRQ_DISCARD_TIMER, dc21285_discard_irq, 0,
+ "Discard timer", NULL);
+ dc21285_request_irq(IRQ_PCI_DPERR, dc21285_dparity_irq, 0,
+ "PCI data parity", NULL);
if (cfn_mode) {
- static struct resource csrio;
-
- csrio.flags = IORESOURCE_IO;
- csrio.name = "Footbridge";
-
- allocate_resource(&ioport_resource, &csrio, 128,
- 0xff00, 0xffff, 128, NULL, NULL);
-
/*
* Map our SDRAM at a known address in PCI space, just in case
* the firmware had other ideas. Using a nonzero base is
@@ -361,7 +353,7 @@ void __init dc21285_preinit(void)
* in the range 0x000a0000 to 0x000c0000. (eg, S3 cards).
*/
*CSR_PCICSRBASE = 0xf4000000;
- *CSR_PCICSRIOBASE = csrio.start;
+ *CSR_PCICSRIOBASE = 0;
*CSR_PCISDRAMBASE = __virt_to_bus(PAGE_OFFSET);
*CSR_PCIROMBASE = 0;
*CSR_PCICMD = PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |
diff --git a/arch/arm/mach-footbridge/dma.c b/arch/arm/mach-footbridge/dma.c
index 1f9b09b8ed8..e2e0df8bcee 100644
--- a/arch/arm/mach-footbridge/dma.c
+++ b/arch/arm/mach-footbridge/dma.c
@@ -11,25 +11,26 @@
* ISA DMA controllers.
*/
#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/spinlock.h>
#include <asm/dma.h>
-#include <asm/io.h>
#include <asm/scatterlist.h>
#include <asm/mach/dma.h>
#include <asm/hardware/dec21285.h>
#if 0
-static int fb_dma_request(dmach_t channel, dma_t *dma)
+static int fb_dma_request(unsigned int chan, dma_t *dma)
{
return -EINVAL;
}
-static void fb_dma_enable(dmach_t channel, dma_t *dma)
+static void fb_dma_enable(unsigned int chan, dma_t *dma)
{
}
-static void fb_dma_disable(dmach_t channel, dma_t *dma)
+static void fb_dma_disable(unsigned int chan, dma_t *dma)
{
}
@@ -41,7 +42,7 @@ static struct dma_ops fb_dma_ops = {
};
#endif
-void __init arch_dma_init(dma_t *dma)
+static int __init fb_dma_init(void)
{
#if 0
dma[_DC21285_DMA(0)].d_ops = &fb_dma_ops;
@@ -49,6 +50,8 @@ void __init arch_dma_init(dma_t *dma)
#endif
#ifdef CONFIG_ISA_DMA
if (footbridge_cfn_mode())
- isa_init_dma(dma + _ISA_DMA(0));
+ isa_init_dma();
#endif
+ return 0;
}
+core_initcall(fb_dma_init);
diff --git a/arch/arm/mach-footbridge/ebsa285-leds.c b/arch/arm/mach-footbridge/ebsa285-leds.c
deleted file mode 100644
index 09c1fbc5187..00000000000
--- a/arch/arm/mach-footbridge/ebsa285-leds.c
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * linux/arch/arm/mach-footbridge/ebsa285-leds.c
- *
- * Copyright (C) 1998-1999 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- * EBSA-285 control routines.
- *
- * The EBSA-285 uses the leds as follows:
- * - Green - toggles state every 50 timer interrupts
- * - Amber - On if system is not idle
- * - Red - currently unused
- *
- * Changelog:
- * 02-05-1999 RMK Various cleanups
- */
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/spinlock.h>
-
-#include <asm/hardware.h>
-#include <asm/leds.h>
-#include <asm/mach-types.h>
-#include <asm/system.h>
-
-#define LED_STATE_ENABLED 1
-#define LED_STATE_CLAIMED 2
-static char led_state;
-static char hw_led_state;
-
-static DEFINE_SPINLOCK(leds_lock);
-
-static void ebsa285_leds_event(led_event_t evt)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&leds_lock, flags);
-
- switch (evt) {
- case led_start:
- hw_led_state = XBUS_LED_RED | XBUS_LED_GREEN;
-#ifndef CONFIG_LEDS_CPU
- hw_led_state |= XBUS_LED_AMBER;
-#endif
- led_state |= LED_STATE_ENABLED;
- break;
-
- case led_stop:
- led_state &= ~LED_STATE_ENABLED;
- break;
-
- case led_claim:
- led_state |= LED_STATE_CLAIMED;
- hw_led_state = XBUS_LED_RED | XBUS_LED_GREEN | XBUS_LED_AMBER;
- break;
-
- case led_release:
- led_state &= ~LED_STATE_CLAIMED;
- hw_led_state = XBUS_LED_RED | XBUS_LED_GREEN | XBUS_LED_AMBER;
- break;
-
-#ifdef CONFIG_LEDS_TIMER
- case led_timer:
- if (!(led_state & LED_STATE_CLAIMED))
- hw_led_state ^= XBUS_LED_GREEN;
- break;
-#endif
-
-#ifdef CONFIG_LEDS_CPU
- case led_idle_start:
- if (!(led_state & LED_STATE_CLAIMED))
- hw_led_state |= XBUS_LED_AMBER;
- break;
-
- case led_idle_end:
- if (!(led_state & LED_STATE_CLAIMED))
- hw_led_state &= ~XBUS_LED_AMBER;
- break;
-#endif
-
- case led_halted:
- if (!(led_state & LED_STATE_CLAIMED))
- hw_led_state &= ~XBUS_LED_RED;
- break;
-
- case led_green_on:
- if (led_state & LED_STATE_CLAIMED)
- hw_led_state &= ~XBUS_LED_GREEN;
- break;
-
- case led_green_off:
- if (led_state & LED_STATE_CLAIMED)
- hw_led_state |= XBUS_LED_GREEN;
- break;
-
- case led_amber_on:
- if (led_state & LED_STATE_CLAIMED)
- hw_led_state &= ~XBUS_LED_AMBER;
- break;
-
- case led_amber_off:
- if (led_state & LED_STATE_CLAIMED)
- hw_led_state |= XBUS_LED_AMBER;
- break;
-
- case led_red_on:
- if (led_state & LED_STATE_CLAIMED)
- hw_led_state &= ~XBUS_LED_RED;
- break;
-
- case led_red_off:
- if (led_state & LED_STATE_CLAIMED)
- hw_led_state |= XBUS_LED_RED;
- break;
-
- default:
- break;
- }
-
- if (led_state & LED_STATE_ENABLED)
- *XBUS_LEDS = hw_led_state;
-
- spin_unlock_irqrestore(&leds_lock, flags);
-}
-
-static int __init leds_init(void)
-{
- if (machine_is_ebsa285())
- leds_event = ebsa285_leds_event;
-
- leds_event(led_start);
-
- return 0;
-}
-
-__initcall(leds_init);
diff --git a/arch/arm/mach-footbridge/ebsa285-pci.c b/arch/arm/mach-footbridge/ebsa285-pci.c
index 720c0bac170..fd12d8a36dc 100644
--- a/arch/arm/mach-footbridge/ebsa285-pci.c
+++ b/arch/arm/mach-footbridge/ebsa285-pci.c
@@ -15,25 +15,24 @@
static int irqmap_ebsa285[] __initdata = { IRQ_IN3, IRQ_IN1, IRQ_IN0, IRQ_PCI };
-static int __init ebsa285_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+static int __init ebsa285_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
if (dev->vendor == PCI_VENDOR_ID_CONTAQ &&
dev->device == PCI_DEVICE_ID_CONTAQ_82C693)
switch (PCI_FUNC(dev->devfn)) {
- case 1: return 14;
- case 2: return 15;
- case 3: return 12;
+ case 1: return 14;
+ case 2: return 15;
+ case 3: return 12;
}
return irqmap_ebsa285[(slot + pin) & 3];
}
static struct hw_pci ebsa285_pci __initdata = {
- .swizzle = pci_std_swizzle,
.map_irq = ebsa285_map_irq,
.nr_controllers = 1,
+ .ops = &dc21285_ops,
.setup = dc21285_setup,
- .scan = dc21285_scan_bus,
.preinit = dc21285_preinit,
.postinit = dc21285_postinit,
};
diff --git a/arch/arm/mach-footbridge/ebsa285.c b/arch/arm/mach-footbridge/ebsa285.c
index b1d3bf20a41..aee8300f349 100644
--- a/arch/arm/mach-footbridge/ebsa285.c
+++ b/arch/arm/mach-footbridge/ebsa285.c
@@ -4,6 +4,10 @@
* EBSA285 machine fixup
*/
#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <linux/leds.h>
#include <asm/hardware/dec21285.h>
#include <asm/mach-types.h>
@@ -12,15 +16,108 @@
#include "common.h"
+/* LEDs */
+#if defined(CONFIG_NEW_LEDS) && defined(CONFIG_LEDS_CLASS)
+#define XBUS_AMBER_L BIT(0)
+#define XBUS_GREEN_L BIT(1)
+#define XBUS_RED_L BIT(2)
+#define XBUS_TOGGLE BIT(7)
+
+struct ebsa285_led {
+ struct led_classdev cdev;
+ u8 mask;
+};
+
+/*
+ * The triggers lines up below will only be used if the
+ * LED triggers are compiled in.
+ */
+static const struct {
+ const char *name;
+ const char *trigger;
+} ebsa285_leds[] = {
+ { "ebsa285:amber", "cpu0", },
+ { "ebsa285:green", "heartbeat", },
+ { "ebsa285:red",},
+};
+
+static unsigned char hw_led_state;
+static void __iomem *xbus;
+
+static void ebsa285_led_set(struct led_classdev *cdev,
+ enum led_brightness b)
+{
+ struct ebsa285_led *led = container_of(cdev,
+ struct ebsa285_led, cdev);
+
+ if (b == LED_OFF)
+ hw_led_state |= led->mask;
+ else
+ hw_led_state &= ~led->mask;
+ writeb(hw_led_state, xbus);
+}
+
+static enum led_brightness ebsa285_led_get(struct led_classdev *cdev)
+{
+ struct ebsa285_led *led = container_of(cdev,
+ struct ebsa285_led, cdev);
+
+ return hw_led_state & led->mask ? LED_OFF : LED_FULL;
+}
+
+static int __init ebsa285_leds_init(void)
+{
+ int i;
+
+ if (!machine_is_ebsa285())
+ return -ENODEV;
+
+ xbus = ioremap(XBUS_CS2, SZ_4K);
+ if (!xbus)
+ return -ENOMEM;
+
+ /* 3 LEDS all off */
+ hw_led_state = XBUS_AMBER_L | XBUS_GREEN_L | XBUS_RED_L;
+ writeb(hw_led_state, xbus);
+
+ for (i = 0; i < ARRAY_SIZE(ebsa285_leds); i++) {
+ struct ebsa285_led *led;
+
+ led = kzalloc(sizeof(*led), GFP_KERNEL);
+ if (!led)
+ break;
+
+ led->cdev.name = ebsa285_leds[i].name;
+ led->cdev.brightness_set = ebsa285_led_set;
+ led->cdev.brightness_get = ebsa285_led_get;
+ led->cdev.default_trigger = ebsa285_leds[i].trigger;
+ led->mask = BIT(i);
+
+ if (led_classdev_register(NULL, &led->cdev) < 0) {
+ kfree(led);
+ break;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * Since we may have triggers on any subsystem, defer registration
+ * until after subsystem_init.
+ */
+fs_initcall(ebsa285_leds_init);
+#endif
+
MACHINE_START(EBSA285, "EBSA285")
/* Maintainer: Russell King */
- .phys_io = DC21285_ARMCSR_BASE,
- .io_pg_offst = ((0xfe000000) >> 18) & 0xfffc,
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.video_start = 0x000a0000,
.video_end = 0x000bffff,
.map_io = footbridge_map_io,
+ .init_early = footbridge_sched_clock,
.init_irq = footbridge_init_irq,
- .timer = &footbridge_timer,
+ .init_time = footbridge_timer_init,
+ .restart = footbridge_restart,
MACHINE_END
diff --git a/arch/arm/mach-footbridge/include/mach/debug-macro.S b/arch/arm/mach-footbridge/include/mach/debug-macro.S
new file mode 100644
index 00000000000..02247f313e9
--- /dev/null
+++ b/arch/arm/mach-footbridge/include/mach/debug-macro.S
@@ -0,0 +1,42 @@
+/* arch/arm/mach-footbridge/include/mach/debug-macro.S
+ *
+ * Debugging macro include header
+ *
+ * Copyright (C) 1994-1999 Russell King
+ * Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+*/
+
+#include <asm/hardware/dec21285.h>
+
+#include <mach/hardware.h>
+ /* For EBSA285 debugging */
+ .equ dc21285_high, ARMCSR_BASE & 0xff000000
+ .equ dc21285_low, ARMCSR_BASE & 0x00ffffff
+
+ .macro addruart, rp, rv, tmp
+ .if dc21285_low
+ mov \rp, #dc21285_low
+ .else
+ mov \rp, #0
+ .endif
+ orr \rv, \rp, #dc21285_high
+ orr \rp, \rp, #0x42000000
+ .endm
+
+ .macro senduart,rd,rx
+ str \rd, [\rx, #0x160] @ UARTDR
+ .endm
+
+ .macro busyuart,rd,rx
+1001: ldr \rd, [\rx, #0x178] @ UARTFLG
+ tst \rd, #1 << 3
+ bne 1001b
+ .endm
+
+ .macro waituart,rd,rx
+ .endm
diff --git a/arch/arm/mach-footbridge/include/mach/entry-macro.S b/arch/arm/mach-footbridge/include/mach/entry-macro.S
new file mode 100644
index 00000000000..dabbd5c54a7
--- /dev/null
+++ b/arch/arm/mach-footbridge/include/mach/entry-macro.S
@@ -0,0 +1,107 @@
+/*
+ * arch/arm/mach-footbridge/include/mach/entry-macro.S
+ *
+ * Low-level IRQ helper macros for footbridge-based platforms
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+#include <mach/hardware.h>
+#include <mach/irqs.h>
+#include <asm/hardware/dec21285.h>
+
+ .equ dc21285_high, ARMCSR_BASE & 0xff000000
+ .equ dc21285_low, ARMCSR_BASE & 0x00ffffff
+
+ .macro get_irqnr_preamble, base, tmp
+ mov \base, #dc21285_high
+ .if dc21285_low
+ orr \base, \base, #dc21285_low
+ .endif
+ .endm
+
+ .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
+ ldr \irqstat, [\base, #0x180] @ get interrupts
+
+ mov \irqnr, #IRQ_SDRAMPARITY
+ tst \irqstat, #IRQ_MASK_SDRAMPARITY
+ bne 1001f
+
+ tst \irqstat, #IRQ_MASK_UART_RX
+ movne \irqnr, #IRQ_CONRX
+ bne 1001f
+
+ tst \irqstat, #IRQ_MASK_DMA1
+ movne \irqnr, #IRQ_DMA1
+ bne 1001f
+
+ tst \irqstat, #IRQ_MASK_DMA2
+ movne \irqnr, #IRQ_DMA2
+ bne 1001f
+
+ tst \irqstat, #IRQ_MASK_IN0
+ movne \irqnr, #IRQ_IN0
+ bne 1001f
+
+ tst \irqstat, #IRQ_MASK_IN1
+ movne \irqnr, #IRQ_IN1
+ bne 1001f
+
+ tst \irqstat, #IRQ_MASK_IN2
+ movne \irqnr, #IRQ_IN2
+ bne 1001f
+
+ tst \irqstat, #IRQ_MASK_IN3
+ movne \irqnr, #IRQ_IN3
+ bne 1001f
+
+ tst \irqstat, #IRQ_MASK_PCI
+ movne \irqnr, #IRQ_PCI
+ bne 1001f
+
+ tst \irqstat, #IRQ_MASK_DOORBELLHOST
+ movne \irqnr, #IRQ_DOORBELLHOST
+ bne 1001f
+
+ tst \irqstat, #IRQ_MASK_I2OINPOST
+ movne \irqnr, #IRQ_I2OINPOST
+ bne 1001f
+
+ tst \irqstat, #IRQ_MASK_TIMER1
+ movne \irqnr, #IRQ_TIMER1
+ bne 1001f
+
+ tst \irqstat, #IRQ_MASK_TIMER2
+ movne \irqnr, #IRQ_TIMER2
+ bne 1001f
+
+ tst \irqstat, #IRQ_MASK_TIMER3
+ movne \irqnr, #IRQ_TIMER3
+ bne 1001f
+
+ tst \irqstat, #IRQ_MASK_UART_TX
+ movne \irqnr, #IRQ_CONTX
+ bne 1001f
+
+ tst \irqstat, #IRQ_MASK_PCI_ABORT
+ movne \irqnr, #IRQ_PCI_ABORT
+ bne 1001f
+
+ tst \irqstat, #IRQ_MASK_PCI_SERR
+ movne \irqnr, #IRQ_PCI_SERR
+ bne 1001f
+
+ tst \irqstat, #IRQ_MASK_DISCARD_TIMER
+ movne \irqnr, #IRQ_DISCARD_TIMER
+ bne 1001f
+
+ tst \irqstat, #IRQ_MASK_PCI_DPERR
+ movne \irqnr, #IRQ_PCI_DPERR
+ bne 1001f
+
+ tst \irqstat, #IRQ_MASK_PCI_PERR
+ movne \irqnr, #IRQ_PCI_PERR
+1001:
+ .endm
+
diff --git a/arch/arm/mach-footbridge/include/mach/hardware.h b/arch/arm/mach-footbridge/include/mach/hardware.h
new file mode 100644
index 00000000000..02f6d7a706b
--- /dev/null
+++ b/arch/arm/mach-footbridge/include/mach/hardware.h
@@ -0,0 +1,99 @@
+/*
+ * arch/arm/mach-footbridge/include/mach/hardware.h
+ *
+ * Copyright (C) 1998-1999 Russell King.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This file contains the hardware definitions of the EBSA-285.
+ */
+#ifndef __ASM_ARCH_HARDWARE_H
+#define __ASM_ARCH_HARDWARE_H
+
+/* Virtual Physical Size
+ * 0xff800000 0x40000000 1MB X-Bus
+ * 0xff000000 0x7c000000 1MB PCI I/O space
+ * 0xfe000000 0x42000000 1MB CSR
+ * 0xfd000000 0x78000000 1MB Outbound write flush (not supported)
+ * 0xfc000000 0x79000000 1MB PCI IACK/special space
+ * 0xfb000000 0x7a000000 16MB PCI Config type 1
+ * 0xfa000000 0x7b000000 16MB PCI Config type 0
+ * 0xf9000000 0x50000000 1MB Cache flush
+ * 0xf0000000 0x80000000 16MB ISA memory
+ */
+
+#ifdef CONFIG_MMU
+#define MMU_IO(a, b) (a)
+#else
+#define MMU_IO(a, b) (b)
+#endif
+
+#define XBUS_SIZE 0x00100000
+#define XBUS_BASE MMU_IO(0xff800000, 0x40000000)
+
+#define ARMCSR_SIZE 0x00100000
+#define ARMCSR_BASE MMU_IO(0xfe000000, 0x42000000)
+
+#define WFLUSH_SIZE 0x00100000
+#define WFLUSH_BASE MMU_IO(0xfd000000, 0x78000000)
+
+#define PCIIACK_SIZE 0x00100000
+#define PCIIACK_BASE MMU_IO(0xfc000000, 0x79000000)
+
+#define PCICFG1_SIZE 0x01000000
+#define PCICFG1_BASE MMU_IO(0xfb000000, 0x7a000000)
+
+#define PCICFG0_SIZE 0x01000000
+#define PCICFG0_BASE MMU_IO(0xfa000000, 0x7b000000)
+
+#define PCIMEM_SIZE 0x01000000
+#define PCIMEM_BASE MMU_IO(0xf0000000, 0x80000000)
+
+#define XBUS_CS2 0x40012000
+
+#define XBUS_SWITCH ((volatile unsigned char *)(XBUS_BASE + 0x12000))
+#define XBUS_SWITCH_SWITCH ((*XBUS_SWITCH) & 15)
+#define XBUS_SWITCH_J17_13 ((*XBUS_SWITCH) & (1 << 4))
+#define XBUS_SWITCH_J17_11 ((*XBUS_SWITCH) & (1 << 5))
+#define XBUS_SWITCH_J17_9 ((*XBUS_SWITCH) & (1 << 6))
+
+#define UNCACHEABLE_ADDR (ARMCSR_BASE + 0x108)
+
+
+/* PIC irq control */
+#define PIC_LO 0x20
+#define PIC_MASK_LO 0x21
+#define PIC_HI 0xA0
+#define PIC_MASK_HI 0xA1
+
+/* GPIO pins */
+#define GPIO_CCLK 0x800
+#define GPIO_DSCLK 0x400
+#define GPIO_E2CLK 0x200
+#define GPIO_IOLOAD 0x100
+#define GPIO_RED_LED 0x080
+#define GPIO_WDTIMER 0x040
+#define GPIO_DATA 0x020
+#define GPIO_IOCLK 0x010
+#define GPIO_DONE 0x008
+#define GPIO_FAN 0x004
+#define GPIO_GREEN_LED 0x002
+#define GPIO_RESET 0x001
+
+/* CPLD pins */
+#define CPLD_DS_ENABLE 8
+#define CPLD_7111_DISABLE 4
+#define CPLD_UNMUTE 2
+#define CPLD_FLASH_WR_ENABLE 1
+
+#ifndef __ASSEMBLY__
+extern raw_spinlock_t nw_gpio_lock;
+extern void nw_gpio_modify_op(unsigned int mask, unsigned int set);
+extern void nw_gpio_modify_io(unsigned int mask, unsigned int in);
+extern unsigned int nw_gpio_read(void);
+extern void nw_cpld_modify(unsigned int mask, unsigned int set);
+#endif
+
+#endif
diff --git a/arch/arm/mach-footbridge/include/mach/io.h b/arch/arm/mach-footbridge/include/mach/io.h
new file mode 100644
index 00000000000..aba46388cc0
--- /dev/null
+++ b/arch/arm/mach-footbridge/include/mach/io.h
@@ -0,0 +1,23 @@
+/*
+ * arch/arm/mach-footbridge/include/mach/io.h
+ *
+ * Copyright (C) 1997-1999 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Modifications:
+ * 06-12-1997 RMK Created.
+ * 07-04-1999 RMK Major cleanup
+ */
+#ifndef __ASM_ARM_ARCH_IO_H
+#define __ASM_ARM_ARCH_IO_H
+
+/*
+ * Translation of various i/o addresses to host addresses for !CONFIG_MMU
+ */
+#define PCIO_BASE 0x7c000000
+#define __io(a) ((void __iomem *)(PCIO_BASE + (a)))
+
+#endif
diff --git a/arch/arm/mach-footbridge/include/mach/irqs.h b/arch/arm/mach-footbridge/include/mach/irqs.h
new file mode 100644
index 00000000000..61c714c4920
--- /dev/null
+++ b/arch/arm/mach-footbridge/include/mach/irqs.h
@@ -0,0 +1,96 @@
+/*
+ * arch/arm/mach-footbridge/include/mach/irqs.h
+ *
+ * Copyright (C) 1998 Russell King
+ * Copyright (C) 1998 Phil Blundell
+ *
+ * Changelog:
+ * 20-Jan-1998 RMK Started merge of EBSA286, CATS and NetWinder
+ * 01-Feb-1999 PJB ISA IRQs start at 0 not 16
+ */
+#include <asm/mach-types.h>
+
+#define NR_IRQS 36
+#define NR_DC21285_IRQS 16
+
+#define _ISA_IRQ(x) (0 + (x))
+#define _ISA_INR(x) ((x) - 0)
+#define _DC21285_IRQ(x) (16 + (x))
+#define _DC21285_INR(x) ((x) - 16)
+
+/*
+ * This is a list of all interrupts that the 21285
+ * can generate and we handle.
+ */
+#define IRQ_CONRX _DC21285_IRQ(0)
+#define IRQ_CONTX _DC21285_IRQ(1)
+#define IRQ_TIMER1 _DC21285_IRQ(2)
+#define IRQ_TIMER2 _DC21285_IRQ(3)
+#define IRQ_TIMER3 _DC21285_IRQ(4)
+#define IRQ_IN0 _DC21285_IRQ(5)
+#define IRQ_IN1 _DC21285_IRQ(6)
+#define IRQ_IN2 _DC21285_IRQ(7)
+#define IRQ_IN3 _DC21285_IRQ(8)
+#define IRQ_DOORBELLHOST _DC21285_IRQ(9)
+#define IRQ_DMA1 _DC21285_IRQ(10)
+#define IRQ_DMA2 _DC21285_IRQ(11)
+#define IRQ_PCI _DC21285_IRQ(12)
+#define IRQ_SDRAMPARITY _DC21285_IRQ(13)
+#define IRQ_I2OINPOST _DC21285_IRQ(14)
+#define IRQ_PCI_ABORT _DC21285_IRQ(15)
+#define IRQ_PCI_SERR _DC21285_IRQ(16)
+#define IRQ_DISCARD_TIMER _DC21285_IRQ(17)
+#define IRQ_PCI_DPERR _DC21285_IRQ(18)
+#define IRQ_PCI_PERR _DC21285_IRQ(19)
+
+#define IRQ_ISA_TIMER _ISA_IRQ(0)
+#define IRQ_ISA_KEYBOARD _ISA_IRQ(1)
+#define IRQ_ISA_CASCADE _ISA_IRQ(2)
+#define IRQ_ISA_UART2 _ISA_IRQ(3)
+#define IRQ_ISA_UART _ISA_IRQ(4)
+#define IRQ_ISA_FLOPPY _ISA_IRQ(6)
+#define IRQ_ISA_PRINTER _ISA_IRQ(7)
+#define IRQ_ISA_RTC_ALARM _ISA_IRQ(8)
+#define IRQ_ISA_2 _ISA_IRQ(9)
+#define IRQ_ISA_PS2MOUSE _ISA_IRQ(12)
+#define IRQ_ISA_HARDDISK1 _ISA_IRQ(14)
+#define IRQ_ISA_HARDDISK2 _ISA_IRQ(15)
+
+#define IRQ_MASK_UART_RX (1 << 2)
+#define IRQ_MASK_UART_TX (1 << 3)
+#define IRQ_MASK_TIMER1 (1 << 4)
+#define IRQ_MASK_TIMER2 (1 << 5)
+#define IRQ_MASK_TIMER3 (1 << 6)
+#define IRQ_MASK_IN0 (1 << 8)
+#define IRQ_MASK_IN1 (1 << 9)
+#define IRQ_MASK_IN2 (1 << 10)
+#define IRQ_MASK_IN3 (1 << 11)
+#define IRQ_MASK_DOORBELLHOST (1 << 15)
+#define IRQ_MASK_DMA1 (1 << 16)
+#define IRQ_MASK_DMA2 (1 << 17)
+#define IRQ_MASK_PCI (1 << 18)
+#define IRQ_MASK_SDRAMPARITY (1 << 24)
+#define IRQ_MASK_I2OINPOST (1 << 25)
+#define IRQ_MASK_PCI_ABORT ((1 << 29) | (1 << 30))
+#define IRQ_MASK_PCI_SERR (1 << 23)
+#define IRQ_MASK_DISCARD_TIMER (1 << 27)
+#define IRQ_MASK_PCI_DPERR (1 << 28)
+#define IRQ_MASK_PCI_PERR (1 << 31)
+
+/*
+ * Netwinder interrupt allocations
+ */
+#define IRQ_NETWINDER_ETHER10 IRQ_IN0
+#define IRQ_NETWINDER_ETHER100 IRQ_IN1
+#define IRQ_NETWINDER_VIDCOMP IRQ_IN2
+#define IRQ_NETWINDER_PS2MOUSE _ISA_IRQ(5)
+#define IRQ_NETWINDER_IR _ISA_IRQ(6)
+#define IRQ_NETWINDER_BUTTON _ISA_IRQ(10)
+#define IRQ_NETWINDER_VGA _ISA_IRQ(11)
+#define IRQ_NETWINDER_SOUND _ISA_IRQ(12)
+
+#define I8042_KBD_IRQ IRQ_ISA_KEYBOARD
+#define I8042_AUX_IRQ (machine_is_netwinder() ? IRQ_NETWINDER_PS2MOUSE : IRQ_ISA_PS2MOUSE)
+#define IRQ_FLOPPYDISK IRQ_ISA_FLOPPY
+
+#define irq_canonicalize(_i) (((_i) == IRQ_ISA_CASCADE) ? IRQ_ISA_2 : _i)
diff --git a/arch/arm/mach-footbridge/include/mach/isa-dma.h b/arch/arm/mach-footbridge/include/mach/isa-dma.h
new file mode 100644
index 00000000000..5bd4a0d338a
--- /dev/null
+++ b/arch/arm/mach-footbridge/include/mach/isa-dma.h
@@ -0,0 +1,25 @@
+/*
+ * arch/arm/mach-footbridge/include/mach/isa-dma.h
+ *
+ * Architecture DMA routines
+ *
+ * Copyright (C) 1998,1999 Russell King
+ * Copyright (C) 1998,1999 Philip Blundell
+ */
+#ifndef __ASM_ARCH_DMA_H
+#define __ASM_ARCH_DMA_H
+
+/*
+ * The 21285 has two internal DMA channels; we call these 8 and 9.
+ * On CATS hardware we have an additional eight ISA dma channels
+ * numbered 0..7.
+ */
+#define _ISA_DMA(x) (0+(x))
+#define _DC21285_DMA(x) (8+(x))
+
+#define MAX_DMA_CHANNELS 10
+
+#define DMA_FLOPPY _ISA_DMA(2)
+#define DMA_ISA_CASCADE _ISA_DMA(4)
+
+#endif /* _ASM_ARCH_DMA_H */
diff --git a/arch/arm/mach-footbridge/include/mach/memory.h b/arch/arm/mach-footbridge/include/mach/memory.h
new file mode 100644
index 00000000000..5c6df377f96
--- /dev/null
+++ b/arch/arm/mach-footbridge/include/mach/memory.h
@@ -0,0 +1,69 @@
+/*
+ * arch/arm/mach-footbridge/include/mach/memory.h
+ *
+ * Copyright (C) 1996-1999 Russell King.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Changelog:
+ * 20-Oct-1996 RMK Created
+ * 31-Dec-1997 RMK Fixed definitions to reduce warnings.
+ * 17-May-1998 DAG Added __virt_to_bus and __bus_to_virt functions.
+ * 21-Nov-1998 RMK Changed __virt_to_bus and __bus_to_virt to macros.
+ * 21-Mar-1999 RMK Added PAGE_OFFSET for co285 architecture.
+ * Renamed to memory.h
+ * Moved PAGE_OFFSET and TASK_SIZE here
+ */
+#ifndef __ASM_ARCH_MEMORY_H
+#define __ASM_ARCH_MEMORY_H
+
+
+#if defined(CONFIG_FOOTBRIDGE_ADDIN)
+/*
+ * If we may be using add-in footbridge mode, then we must
+ * use the out-of-line translation that makes use of the
+ * PCI BAR
+ */
+#ifndef __ASSEMBLY__
+extern unsigned long __virt_to_bus(unsigned long);
+extern unsigned long __bus_to_virt(unsigned long);
+extern unsigned long __pfn_to_bus(unsigned long);
+extern unsigned long __bus_to_pfn(unsigned long);
+#endif
+#define __virt_to_bus __virt_to_bus
+#define __bus_to_virt __bus_to_virt
+
+#elif defined(CONFIG_FOOTBRIDGE_HOST)
+
+/*
+ * The footbridge is programmed to expose the system RAM at 0xe0000000.
+ * The requirement is that the RAM isn't placed at bus address 0, which
+ * would clash with VGA cards.
+ */
+#define BUS_OFFSET 0xe0000000
+#define __virt_to_bus(x) ((x) + (BUS_OFFSET - PAGE_OFFSET))
+#define __bus_to_virt(x) ((x) - (BUS_OFFSET - PAGE_OFFSET))
+#define __pfn_to_bus(x) (__pfn_to_phys(x) + (BUS_OFFSET - PHYS_OFFSET))
+#define __bus_to_pfn(x) __phys_to_pfn((x) - (BUS_OFFSET - PHYS_OFFSET))
+
+#else
+
+#error "Undefined footbridge mode"
+
+#endif
+
+/*
+ * Cache flushing area.
+ */
+#define FLUSH_BASE 0xf9000000
+
+/*
+ * Physical DRAM offset.
+ */
+#define PLAT_PHYS_OFFSET UL(0x00000000)
+
+#define FLUSH_BASE_PHYS 0x50000000
+
+#endif
diff --git a/arch/arm/mach-footbridge/include/mach/uncompress.h b/arch/arm/mach-footbridge/include/mach/uncompress.h
new file mode 100644
index 00000000000..a69398c05a5
--- /dev/null
+++ b/arch/arm/mach-footbridge/include/mach/uncompress.h
@@ -0,0 +1,37 @@
+/*
+ * arch/arm/mach-footbridge/include/mach/uncompress.h
+ *
+ * Copyright (C) 1996-1999 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <asm/mach-types.h>
+
+/*
+ * Note! This could cause problems on the NetWinder
+ */
+#define DC21285_BASE ((volatile unsigned int *)0x42000160)
+#define SER0_BASE ((volatile unsigned char *)0x7c0003f8)
+
+static inline void putc(char c)
+{
+ if (machine_is_netwinder()) {
+ while ((SER0_BASE[5] & 0x60) != 0x60)
+ barrier();
+ SER0_BASE[0] = c;
+ } else {
+ while (DC21285_BASE[6] & 8);
+ DC21285_BASE[0] = c;
+ }
+}
+
+static inline void flush(void)
+{
+}
+
+/*
+ * nothing to do
+ */
+#define arch_decomp_setup()
diff --git a/arch/arm/mach-footbridge/isa-irq.c b/arch/arm/mach-footbridge/isa-irq.c
index 79443ffc891..c3a0abbc904 100644
--- a/arch/arm/mach-footbridge/isa-irq.c
+++ b/arch/arm/mach-footbridge/isa-irq.c
@@ -18,70 +18,73 @@
#include <linux/interrupt.h>
#include <linux/list.h>
#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/spinlock.h>
#include <asm/mach/irq.h>
-#include <asm/hardware.h>
+#include <mach/hardware.h>
#include <asm/hardware/dec21285.h>
#include <asm/irq.h>
-#include <asm/io.h>
#include <asm/mach-types.h>
-static void isa_mask_pic_lo_irq(unsigned int irq)
+#include "common.h"
+
+static void isa_mask_pic_lo_irq(struct irq_data *d)
{
- unsigned int mask = 1 << (irq & 7);
+ unsigned int mask = 1 << (d->irq & 7);
outb(inb(PIC_MASK_LO) | mask, PIC_MASK_LO);
}
-static void isa_ack_pic_lo_irq(unsigned int irq)
+static void isa_ack_pic_lo_irq(struct irq_data *d)
{
- unsigned int mask = 1 << (irq & 7);
+ unsigned int mask = 1 << (d->irq & 7);
outb(inb(PIC_MASK_LO) | mask, PIC_MASK_LO);
outb(0x20, PIC_LO);
}
-static void isa_unmask_pic_lo_irq(unsigned int irq)
+static void isa_unmask_pic_lo_irq(struct irq_data *d)
{
- unsigned int mask = 1 << (irq & 7);
+ unsigned int mask = 1 << (d->irq & 7);
outb(inb(PIC_MASK_LO) & ~mask, PIC_MASK_LO);
}
static struct irq_chip isa_lo_chip = {
- .ack = isa_ack_pic_lo_irq,
- .mask = isa_mask_pic_lo_irq,
- .unmask = isa_unmask_pic_lo_irq,
+ .irq_ack = isa_ack_pic_lo_irq,
+ .irq_mask = isa_mask_pic_lo_irq,
+ .irq_unmask = isa_unmask_pic_lo_irq,
};
-static void isa_mask_pic_hi_irq(unsigned int irq)
+static void isa_mask_pic_hi_irq(struct irq_data *d)
{
- unsigned int mask = 1 << (irq & 7);
+ unsigned int mask = 1 << (d->irq & 7);
outb(inb(PIC_MASK_HI) | mask, PIC_MASK_HI);
}
-static void isa_ack_pic_hi_irq(unsigned int irq)
+static void isa_ack_pic_hi_irq(struct irq_data *d)
{
- unsigned int mask = 1 << (irq & 7);
+ unsigned int mask = 1 << (d->irq & 7);
outb(inb(PIC_MASK_HI) | mask, PIC_MASK_HI);
outb(0x62, PIC_LO);
outb(0x20, PIC_HI);
}
-static void isa_unmask_pic_hi_irq(unsigned int irq)
+static void isa_unmask_pic_hi_irq(struct irq_data *d)
{
- unsigned int mask = 1 << (irq & 7);
+ unsigned int mask = 1 << (d->irq & 7);
outb(inb(PIC_MASK_HI) & ~mask, PIC_MASK_HI);
}
static struct irq_chip isa_hi_chip = {
- .ack = isa_ack_pic_hi_irq,
- .mask = isa_mask_pic_hi_irq,
- .unmask = isa_unmask_pic_hi_irq,
+ .irq_ack = isa_ack_pic_hi_irq,
+ .irq_mask = isa_mask_pic_hi_irq,
+ .irq_unmask = isa_unmask_pic_hi_irq,
};
static void
@@ -94,8 +97,7 @@ isa_irq_handler(unsigned int irq, struct irq_desc *desc)
return;
}
- desc = irq_desc + isa_irq;
- desc_handle_irq(isa_irq, desc);
+ generic_handle_irq(isa_irq);
}
static struct irqaction irq_cascade = {
@@ -149,14 +151,14 @@ void __init isa_init_irq(unsigned int host_irq)
if (host_irq != (unsigned int)-1) {
for (irq = _ISA_IRQ(0); irq < _ISA_IRQ(8); irq++) {
- set_irq_chip(irq, &isa_lo_chip);
- set_irq_handler(irq, handle_level_irq);
+ irq_set_chip_and_handler(irq, &isa_lo_chip,
+ handle_level_irq);
set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
}
for (irq = _ISA_IRQ(8); irq < _ISA_IRQ(16); irq++) {
- set_irq_chip(irq, &isa_hi_chip);
- set_irq_handler(irq, handle_level_irq);
+ irq_set_chip_and_handler(irq, &isa_hi_chip,
+ handle_level_irq);
set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
}
@@ -164,7 +166,7 @@ void __init isa_init_irq(unsigned int host_irq)
request_resource(&ioport_resource, &pic2_resource);
setup_irq(IRQ_ISA_CASCADE, &irq_cascade);
- set_irq_chained_handler(host_irq, isa_irq_handler);
+ irq_set_chained_handler(host_irq, isa_irq_handler);
/*
* On the NetWinder, don't automatically
diff --git a/arch/arm/mach-footbridge/isa-rtc.c b/arch/arm/mach-footbridge/isa-rtc.c
new file mode 100644
index 00000000000..07fde4051f7
--- /dev/null
+++ b/arch/arm/mach-footbridge/isa-rtc.c
@@ -0,0 +1,57 @@
+/*
+ * arch/arm/mach-footbridge/isa-rtc.c
+ *
+ * Copyright (C) 1998 Russell King.
+ * Copyright (C) 1998 Phil Blundell
+ *
+ * CATS has a real-time clock, though the evaluation board doesn't.
+ *
+ * Changelog:
+ * 21-Mar-1998 RMK Created
+ * 27-Aug-1998 PJB CATS support
+ * 28-Dec-1998 APH Made leds optional
+ * 20-Jan-1999 RMK Started merge of EBSA285, CATS and NetWinder
+ * 16-Mar-1999 RMK More support for EBSA285-like machines with RTCs in
+ */
+
+#define RTC_PORT(x) (0x70+(x))
+#define RTC_ALWAYS_BCD 0
+
+#include <linux/init.h>
+#include <linux/mc146818rtc.h>
+#include <linux/bcd.h>
+#include <linux/io.h>
+
+#include "common.h"
+
+void __init isa_rtc_init(void)
+{
+ int reg_d, reg_b;
+
+ /*
+ * Probe for the RTC.
+ */
+ reg_d = CMOS_READ(RTC_REG_D);
+
+ /*
+ * make sure the divider is set
+ */
+ CMOS_WRITE(RTC_REF_CLCK_32KHZ, RTC_REG_A);
+
+ /*
+ * Set control reg B
+ * (24 hour mode, update enabled)
+ */
+ reg_b = CMOS_READ(RTC_REG_B) & 0x7f;
+ reg_b |= 2;
+ CMOS_WRITE(reg_b, RTC_REG_B);
+
+ if ((CMOS_READ(RTC_REG_A) & 0x7f) == RTC_REF_CLCK_32KHZ &&
+ CMOS_READ(RTC_REG_B) == reg_b) {
+ /*
+ * We have a RTC. Check the battery
+ */
+ if ((reg_d & 0x80) == 0)
+ printk(KERN_WARNING "RTC: *** warning: CMOS battery bad\n");
+ }
+}
diff --git a/arch/arm/mach-footbridge/isa-timer.c b/arch/arm/mach-footbridge/isa-timer.c
index a764e01d357..b73f52e196b 100644
--- a/arch/arm/mach-footbridge/isa-timer.c
+++ b/arch/arm/mach-footbridge/isa-timer.c
@@ -4,90 +4,37 @@
* Copyright (C) 1998 Russell King.
* Copyright (C) 1998 Phil Blundell
*/
+#include <linux/clockchips.h>
+#include <linux/i8253.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
+#include <linux/spinlock.h>
+#include <linux/timex.h>
-#include <asm/io.h>
#include <asm/irq.h>
-
#include <asm/mach/time.h>
#include "common.h"
-/*
- * ISA timer tick support
- */
-#define mSEC_10_from_14 ((14318180 + 100) / 200)
-
-static unsigned long isa_gettimeoffset(void)
-{
- int count;
-
- static int count_p = (mSEC_10_from_14/6); /* for the first call after boot */
- static unsigned long jiffies_p = 0;
-
- /*
- * cache volatile jiffies temporarily; we have IRQs turned off.
- */
- unsigned long jiffies_t;
-
- /* timer count may underflow right here */
- outb_p(0x00, 0x43); /* latch the count ASAP */
-
- count = inb_p(0x40); /* read the latched count */
-
- /*
- * We do this guaranteed double memory access instead of a _p
- * postfix in the previous port access. Wheee, hackady hack
- */
- jiffies_t = jiffies;
-
- count |= inb_p(0x40) << 8;
-
- /* Detect timer underflows. If we haven't had a timer tick since
- the last time we were called, and time is apparently going
- backwards, the counter must have wrapped during this routine. */
- if ((jiffies_t == jiffies_p) && (count > count_p))
- count -= (mSEC_10_from_14/6);
- else
- jiffies_p = jiffies_t;
-
- count_p = count;
-
- count = (((mSEC_10_from_14/6)-1) - count) * (tick_nsec / 1000);
- count = (count + (mSEC_10_from_14/6)/2) / (mSEC_10_from_14/6);
-
- return count;
-}
-
-static irqreturn_t
-isa_timer_interrupt(int irq, void *dev_id)
+static irqreturn_t pit_timer_interrupt(int irq, void *dev_id)
{
- timer_tick();
+ struct clock_event_device *ce = dev_id;
+ ce->event_handler(ce);
return IRQ_HANDLED;
}
-static struct irqaction isa_timer_irq = {
- .name = "ISA timer tick",
- .handler = isa_timer_interrupt,
- .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+static struct irqaction pit_timer_irq = {
+ .name = "pit",
+ .handler = pit_timer_interrupt,
+ .flags = IRQF_TIMER | IRQF_IRQPOLL,
+ .dev_id = &i8253_clockevent,
};
-static void __init isa_timer_init(void)
+void __init isa_timer_init(void)
{
- isa_rtc_init();
-
- /* enable PIT timer */
- /* set for periodic (4) and LSB/MSB write (0x30) */
- outb(0x34, 0x43);
- outb((mSEC_10_from_14/6) & 0xFF, 0x40);
- outb((mSEC_10_from_14/6) >> 8, 0x40);
+ clocksource_i8253_init();
- setup_irq(IRQ_ISA_TIMER, &isa_timer_irq);
+ setup_irq(i8253_clockevent.irq, &pit_timer_irq);
+ clockevent_i8253_init(false);
}
-
-struct sys_timer isa_timer = {
- .init = isa_timer_init,
- .offset = isa_gettimeoffset,
-};
diff --git a/arch/arm/mach-footbridge/isa.c b/arch/arm/mach-footbridge/isa.c
index 725a219d0ed..4d9276c27d6 100644
--- a/arch/arm/mach-footbridge/isa.c
+++ b/arch/arm/mach-footbridge/isa.c
@@ -11,6 +11,9 @@
#include <linux/serial_8250.h>
#include <asm/irq.h>
+#include <asm/hardware/dec21285.h>
+
+#include "common.h"
static struct resource rtc_resources[] = {
[0] = {
@@ -77,11 +80,18 @@ static struct platform_device serial_device = {
static int __init footbridge_isa_init(void)
{
- int err;
+ int err = 0;
- err = platform_device_register(&rtc_device);
- if (err)
- printk(KERN_ERR "Unable to register RTC device: %d\n", err);
+ if (!footbridge_cfn_mode())
+ return 0;
+
+ /* Personal server doesn't have RTC */
+ if (!machine_is_personal_server()) {
+ isa_rtc_init();
+ err = platform_device_register(&rtc_device);
+ if (err)
+ printk(KERN_ERR "Unable to register RTC device: %d\n", err);
+ }
err = platform_device_register(&serial_device);
if (err)
printk(KERN_ERR "Unable to register serial device: %d\n", err);
diff --git a/arch/arm/mach-footbridge/netwinder-hw.c b/arch/arm/mach-footbridge/netwinder-hw.c
index a1f381c64a3..cdee08c6d23 100644
--- a/arch/arm/mach-footbridge/netwinder-hw.c
+++ b/arch/arm/mach-footbridge/netwinder-hw.c
@@ -10,12 +10,15 @@
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <linux/leds.h>
#include <asm/hardware/dec21285.h>
-#include <asm/io.h>
-#include <asm/leds.h>
#include <asm/mach-types.h>
#include <asm/setup.h>
+#include <asm/system_misc.h>
#include <asm/mach/arch.h>
@@ -25,13 +28,6 @@
#define GP1_IO_BASE 0x338
#define GP2_IO_BASE 0x33a
-
-#ifdef CONFIG_LEDS
-#define DEFAULT_LEDS 0
-#else
-#define DEFAULT_LEDS GPIO_GREEN_LED
-#endif
-
/*
* Winbond WB83977F accessibility stuff
*/
@@ -67,13 +63,14 @@ static inline void wb977_ww(int reg, int val)
/*
* This is a lock for accessing ports GP1_IO_BASE and GP2_IO_BASE
*/
-DEFINE_SPINLOCK(gpio_lock);
+DEFINE_RAW_SPINLOCK(nw_gpio_lock);
+EXPORT_SYMBOL(nw_gpio_lock);
static unsigned int current_gpio_op;
static unsigned int current_gpio_io;
static unsigned int current_cpld;
-void gpio_modify_op(int mask, int set)
+void nw_gpio_modify_op(unsigned int mask, unsigned int set)
{
unsigned int new_gpio, changed;
@@ -86,6 +83,7 @@ void gpio_modify_op(int mask, int set)
if (changed & 0xff00)
outb(new_gpio >> 8, GP2_IO_BASE);
}
+EXPORT_SYMBOL(nw_gpio_modify_op);
static inline void __gpio_modify_io(int mask, int in)
{
@@ -118,7 +116,7 @@ static inline void __gpio_modify_io(int mask, int in)
}
}
-void gpio_modify_io(int mask, int in)
+void nw_gpio_modify_io(unsigned int mask, unsigned int in)
{
/* Open up the SuperIO chip */
wb977_open();
@@ -128,11 +126,13 @@ void gpio_modify_io(int mask, int in)
/* Close up the EFER gate */
wb977_close();
}
+EXPORT_SYMBOL(nw_gpio_modify_io);
-int gpio_read(void)
+unsigned int nw_gpio_read(void)
{
return inb(GP1_IO_BASE) | inb(GP2_IO_BASE) << 8;
}
+EXPORT_SYMBOL(nw_gpio_read);
/*
* Initialise the Winbond W83977F global registers
@@ -322,9 +322,9 @@ static inline void wb977_init_gpio(void)
/*
* Set Group1/Group2 outputs
*/
- spin_lock_irqsave(&gpio_lock, flags);
- gpio_modify_op(-1, GPIO_RED_LED | GPIO_FAN);
- spin_unlock_irqrestore(&gpio_lock, flags);
+ raw_spin_lock_irqsave(&nw_gpio_lock, flags);
+ nw_gpio_modify_op(-1, GPIO_RED_LED | GPIO_FAN);
+ raw_spin_unlock_irqrestore(&nw_gpio_lock, flags);
}
/*
@@ -359,34 +359,35 @@ static void __init wb977_init(void)
wb977_close();
}
-void cpld_modify(int mask, int set)
+void nw_cpld_modify(unsigned int mask, unsigned int set)
{
int msk;
current_cpld = (current_cpld & ~mask) | set;
- gpio_modify_io(GPIO_DATA | GPIO_IOCLK | GPIO_IOLOAD, 0);
- gpio_modify_op(GPIO_IOLOAD, 0);
+ nw_gpio_modify_io(GPIO_DATA | GPIO_IOCLK | GPIO_IOLOAD, 0);
+ nw_gpio_modify_op(GPIO_IOLOAD, 0);
for (msk = 8; msk; msk >>= 1) {
int bit = current_cpld & msk;
- gpio_modify_op(GPIO_DATA | GPIO_IOCLK, bit ? GPIO_DATA : 0);
- gpio_modify_op(GPIO_IOCLK, GPIO_IOCLK);
+ nw_gpio_modify_op(GPIO_DATA | GPIO_IOCLK, bit ? GPIO_DATA : 0);
+ nw_gpio_modify_op(GPIO_IOCLK, GPIO_IOCLK);
}
- gpio_modify_op(GPIO_IOCLK|GPIO_DATA, 0);
- gpio_modify_op(GPIO_IOLOAD|GPIO_DSCLK, GPIO_IOLOAD|GPIO_DSCLK);
- gpio_modify_op(GPIO_IOLOAD, 0);
+ nw_gpio_modify_op(GPIO_IOCLK|GPIO_DATA, 0);
+ nw_gpio_modify_op(GPIO_IOLOAD|GPIO_DSCLK, GPIO_IOLOAD|GPIO_DSCLK);
+ nw_gpio_modify_op(GPIO_IOLOAD, 0);
}
+EXPORT_SYMBOL(nw_cpld_modify);
static void __init cpld_init(void)
{
unsigned long flags;
- spin_lock_irqsave(&gpio_lock, flags);
- cpld_modify(-1, CPLD_UNMUTE | CPLD_7111_DISABLE);
- spin_unlock_irqrestore(&gpio_lock, flags);
+ raw_spin_lock_irqsave(&nw_gpio_lock, flags);
+ nw_cpld_modify(-1, CPLD_UNMUTE | CPLD_7111_DISABLE);
+ raw_spin_unlock_irqrestore(&nw_gpio_lock, flags);
}
static unsigned char rwa_unlock[] __initdata =
@@ -596,12 +597,6 @@ static void __init rwa010_init(void)
rwa010_soundblaster_reset();
}
-EXPORT_SYMBOL(gpio_lock);
-EXPORT_SYMBOL(gpio_modify_op);
-EXPORT_SYMBOL(gpio_modify_io);
-EXPORT_SYMBOL(cpld_modify);
-EXPORT_SYMBOL(gpio_read);
-
/*
* Initialise any other hardware after we've got the PCI bus
* initialised. We may need the PCI bus to talk to this other
@@ -610,15 +605,9 @@ EXPORT_SYMBOL(gpio_read);
static int __init nw_hw_init(void)
{
if (machine_is_netwinder()) {
- unsigned long flags;
-
wb977_init();
cpld_init();
rwa010_init();
-
- spin_lock_irqsave(&gpio_lock, flags);
- gpio_modify_op(GPIO_RED_LED|GPIO_GREEN_LED, DEFAULT_LEDS);
- spin_unlock_irqrestore(&gpio_lock, flags);
}
return 0;
}
@@ -631,8 +620,7 @@ __initcall(nw_hw_init);
* the parameter page.
*/
static void __init
-fixup_netwinder(struct machine_desc *desc, struct tag *tags,
- char **cmdline, struct meminfo *mi)
+fixup_netwinder(struct tag *tags, char **cmdline)
{
#ifdef CONFIG_ISAPNP
extern int isapnp_disable;
@@ -646,11 +634,131 @@ fixup_netwinder(struct machine_desc *desc, struct tag *tags,
#endif
}
+static void netwinder_restart(enum reboot_mode mode, const char *cmd)
+{
+ if (mode == REBOOT_SOFT) {
+ /* Jump into the ROM */
+ soft_restart(0x41000000);
+ } else {
+ local_irq_disable();
+ local_fiq_disable();
+
+ /* open up the SuperIO chip */
+ outb(0x87, 0x370);
+ outb(0x87, 0x370);
+
+ /* aux function group 1 (logical device 7) */
+ outb(0x07, 0x370);
+ outb(0x07, 0x371);
+
+ /* set GP16 for WD-TIMER output */
+ outb(0xe6, 0x370);
+ outb(0x00, 0x371);
+
+ /* set a RED LED and toggle WD_TIMER for rebooting */
+ outb(0xc4, 0x338);
+ }
+}
+
+/* LEDs */
+#if defined(CONFIG_NEW_LEDS) && defined(CONFIG_LEDS_CLASS)
+struct netwinder_led {
+ struct led_classdev cdev;
+ u8 mask;
+};
+
+/*
+ * The triggers lines up below will only be used if the
+ * LED triggers are compiled in.
+ */
+static const struct {
+ const char *name;
+ const char *trigger;
+} netwinder_leds[] = {
+ { "netwinder:green", "heartbeat", },
+ { "netwinder:red", "cpu0", },
+};
+
+/*
+ * The LED control in Netwinder is reversed:
+ * - setting bit means turn off LED
+ * - clearing bit means turn on LED
+ */
+static void netwinder_led_set(struct led_classdev *cdev,
+ enum led_brightness b)
+{
+ struct netwinder_led *led = container_of(cdev,
+ struct netwinder_led, cdev);
+ unsigned long flags;
+ u32 reg;
+
+ raw_spin_lock_irqsave(&nw_gpio_lock, flags);
+ reg = nw_gpio_read();
+ if (b != LED_OFF)
+ reg &= ~led->mask;
+ else
+ reg |= led->mask;
+ nw_gpio_modify_op(led->mask, reg);
+ raw_spin_unlock_irqrestore(&nw_gpio_lock, flags);
+}
+
+static enum led_brightness netwinder_led_get(struct led_classdev *cdev)
+{
+ struct netwinder_led *led = container_of(cdev,
+ struct netwinder_led, cdev);
+ unsigned long flags;
+ u32 reg;
+
+ raw_spin_lock_irqsave(&nw_gpio_lock, flags);
+ reg = nw_gpio_read();
+ raw_spin_unlock_irqrestore(&nw_gpio_lock, flags);
+
+ return (reg & led->mask) ? LED_OFF : LED_FULL;
+}
+
+static int __init netwinder_leds_init(void)
+{
+ int i;
+
+ if (!machine_is_netwinder())
+ return -ENODEV;
+
+ for (i = 0; i < ARRAY_SIZE(netwinder_leds); i++) {
+ struct netwinder_led *led;
+
+ led = kzalloc(sizeof(*led), GFP_KERNEL);
+ if (!led)
+ break;
+
+ led->cdev.name = netwinder_leds[i].name;
+ led->cdev.brightness_set = netwinder_led_set;
+ led->cdev.brightness_get = netwinder_led_get;
+ led->cdev.default_trigger = netwinder_leds[i].trigger;
+
+ if (i == 0)
+ led->mask = GPIO_GREEN_LED;
+ else
+ led->mask = GPIO_RED_LED;
+
+ if (led_classdev_register(NULL, &led->cdev) < 0) {
+ kfree(led);
+ break;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * Since we may have triggers on any subsystem, defer registration
+ * until after subsystem_init.
+ */
+fs_initcall(netwinder_leds_init);
+#endif
+
MACHINE_START(NETWINDER, "Rebel-NetWinder")
/* Maintainer: Russell King/Rebel.com */
- .phys_io = DC21285_ARMCSR_BASE,
- .io_pg_offst = ((0xfe000000) >> 18) & 0xfffc,
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.video_start = 0x000a0000,
.video_end = 0x000bffff,
.reserve_lp0 = 1,
@@ -658,5 +766,6 @@ MACHINE_START(NETWINDER, "Rebel-NetWinder")
.fixup = fixup_netwinder,
.map_io = footbridge_map_io,
.init_irq = footbridge_init_irq,
- .timer = &isa_timer,
+ .init_time = isa_timer_init,
+ .restart = netwinder_restart,
MACHINE_END
diff --git a/arch/arm/mach-footbridge/netwinder-leds.c b/arch/arm/mach-footbridge/netwinder-leds.c
deleted file mode 100644
index 8e9cac5a213..00000000000
--- a/arch/arm/mach-footbridge/netwinder-leds.c
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * linux/arch/arm/mach-footbridge/netwinder-leds.c
- *
- * Copyright (C) 1998-1999 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * NetWinder LED control routines.
- *
- * The Netwinder uses the leds as follows:
- * - Green - toggles state every 50 timer interrupts
- * - Red - On if the system is not idle
- *
- * Changelog:
- * 02-05-1999 RMK Various cleanups
- */
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/spinlock.h>
-
-#include <asm/hardware.h>
-#include <asm/leds.h>
-#include <asm/mach-types.h>
-#include <asm/system.h>
-
-#define LED_STATE_ENABLED 1
-#define LED_STATE_CLAIMED 2
-static char led_state;
-static char hw_led_state;
-
-static DEFINE_SPINLOCK(leds_lock);
-extern spinlock_t gpio_lock;
-
-static void netwinder_leds_event(led_event_t evt)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&leds_lock, flags);
-
- switch (evt) {
- case led_start:
- led_state |= LED_STATE_ENABLED;
- hw_led_state = GPIO_GREEN_LED;
- break;
-
- case led_stop:
- led_state &= ~LED_STATE_ENABLED;
- break;
-
- case led_claim:
- led_state |= LED_STATE_CLAIMED;
- hw_led_state = 0;
- break;
-
- case led_release:
- led_state &= ~LED_STATE_CLAIMED;
- hw_led_state = 0;
- break;
-
-#ifdef CONFIG_LEDS_TIMER
- case led_timer:
- if (!(led_state & LED_STATE_CLAIMED))
- hw_led_state ^= GPIO_GREEN_LED;
- break;
-#endif
-
-#ifdef CONFIG_LEDS_CPU
- case led_idle_start:
- if (!(led_state & LED_STATE_CLAIMED))
- hw_led_state &= ~GPIO_RED_LED;
- break;
-
- case led_idle_end:
- if (!(led_state & LED_STATE_CLAIMED))
- hw_led_state |= GPIO_RED_LED;
- break;
-#endif
-
- case led_halted:
- if (!(led_state & LED_STATE_CLAIMED))
- hw_led_state |= GPIO_RED_LED;
- break;
-
- case led_green_on:
- if (led_state & LED_STATE_CLAIMED)
- hw_led_state |= GPIO_GREEN_LED;
- break;
-
- case led_green_off:
- if (led_state & LED_STATE_CLAIMED)
- hw_led_state &= ~GPIO_GREEN_LED;
- break;
-
- case led_amber_on:
- if (led_state & LED_STATE_CLAIMED)
- hw_led_state |= GPIO_GREEN_LED | GPIO_RED_LED;
- break;
-
- case led_amber_off:
- if (led_state & LED_STATE_CLAIMED)
- hw_led_state &= ~(GPIO_GREEN_LED | GPIO_RED_LED);
- break;
-
- case led_red_on:
- if (led_state & LED_STATE_CLAIMED)
- hw_led_state |= GPIO_RED_LED;
- break;
-
- case led_red_off:
- if (led_state & LED_STATE_CLAIMED)
- hw_led_state &= ~GPIO_RED_LED;
- break;
-
- default:
- break;
- }
-
- spin_unlock_irqrestore(&leds_lock, flags);
-
- if (led_state & LED_STATE_ENABLED) {
- spin_lock_irqsave(&gpio_lock, flags);
- gpio_modify_op(GPIO_RED_LED | GPIO_GREEN_LED, hw_led_state);
- spin_unlock_irqrestore(&gpio_lock, flags);
- }
-}
-
-static int __init leds_init(void)
-{
- if (machine_is_netwinder())
- leds_event = netwinder_leds_event;
-
- leds_event(led_start);
-
- return 0;
-}
-
-__initcall(leds_init);
diff --git a/arch/arm/mach-footbridge/netwinder-pci.c b/arch/arm/mach-footbridge/netwinder-pci.c
index e263d6d54a0..0fba5134e4f 100644
--- a/arch/arm/mach-footbridge/netwinder-pci.c
+++ b/arch/arm/mach-footbridge/netwinder-pci.c
@@ -17,7 +17,7 @@
* We now use the slot ID instead of the device identifiers to select
* which interrupt is routed where.
*/
-static int __init netwinder_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+static int __init netwinder_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
switch (slot) {
case 0: /* host bridge */
@@ -43,11 +43,10 @@ static int __init netwinder_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
}
static struct hw_pci netwinder_pci __initdata = {
- .swizzle = pci_std_swizzle,
.map_irq = netwinder_map_irq,
.nr_controllers = 1,
+ .ops = &dc21285_ops,
.setup = dc21285_setup,
- .scan = dc21285_scan_bus,
.preinit = dc21285_preinit,
.postinit = dc21285_postinit,
};
diff --git a/arch/arm/mach-footbridge/personal-pci.c b/arch/arm/mach-footbridge/personal-pci.c
index d5fca95afda..5c9ee54613b 100644
--- a/arch/arm/mach-footbridge/personal-pci.c
+++ b/arch/arm/mach-footbridge/personal-pci.c
@@ -18,7 +18,8 @@ static int irqmap_personal_server[] __initdata = {
IRQ_DOORBELLHOST, IRQ_DMA1, IRQ_DMA2, IRQ_PCI
};
-static int __init personal_server_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+static int __init personal_server_map_irq(const struct pci_dev *dev, u8 slot,
+ u8 pin)
{
unsigned char line;
@@ -40,8 +41,8 @@ static int __init personal_server_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
static struct hw_pci personal_server_pci __initdata = {
.map_irq = personal_server_map_irq,
.nr_controllers = 1,
+ .ops = &dc21285_ops,
.setup = dc21285_setup,
- .scan = dc21285_scan_bus,
.preinit = dc21285_preinit,
.postinit = dc21285_postinit,
};
diff --git a/arch/arm/mach-footbridge/personal.c b/arch/arm/mach-footbridge/personal.c
index c4f843fc099..7bdeabdcd4d 100644
--- a/arch/arm/mach-footbridge/personal.c
+++ b/arch/arm/mach-footbridge/personal.c
@@ -4,6 +4,7 @@
* Personal server (Skiff) machine fixup
*/
#include <linux/init.h>
+#include <linux/spinlock.h>
#include <asm/hardware/dec21285.h>
#include <asm/mach-types.h>
@@ -14,11 +15,10 @@
MACHINE_START(PERSONAL_SERVER, "Compaq-PersonalServer")
/* Maintainer: Jamey Hicks / George France */
- .phys_io = DC21285_ARMCSR_BASE,
- .io_pg_offst = ((0xfe000000) >> 18) & 0xfffc,
- .boot_params = 0x00000100,
+ .atag_offset = 0x100,
.map_io = footbridge_map_io,
.init_irq = footbridge_init_irq,
- .timer = &footbridge_timer,
+ .init_time = footbridge_timer_init,
+ .restart = footbridge_restart,
MACHINE_END
diff --git a/arch/arm/mach-footbridge/time.c b/arch/arm/mach-footbridge/time.c
deleted file mode 100644
index d5cfcda385d..00000000000
--- a/arch/arm/mach-footbridge/time.c
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * linux/include/asm-arm/arch-ebsa285/time.h
- *
- * Copyright (C) 1998 Russell King.
- * Copyright (C) 1998 Phil Blundell
- *
- * CATS has a real-time clock, though the evaluation board doesn't.
- *
- * Changelog:
- * 21-Mar-1998 RMK Created
- * 27-Aug-1998 PJB CATS support
- * 28-Dec-1998 APH Made leds optional
- * 20-Jan-1999 RMK Started merge of EBSA285, CATS and NetWinder
- * 16-Mar-1999 RMK More support for EBSA285-like machines with RTCs in
- */
-
-#define RTC_PORT(x) (rtc_base+(x))
-#define RTC_ALWAYS_BCD 0
-
-#include <linux/timex.h>
-#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/mc146818rtc.h>
-#include <linux/bcd.h>
-
-#include <asm/hardware.h>
-#include <asm/io.h>
-
-#include <asm/mach/time.h>
-#include "common.h"
-
-static int rtc_base;
-
-static unsigned long __init get_isa_cmos_time(void)
-{
- unsigned int year, mon, day, hour, min, sec;
-
- // check to see if the RTC makes sense.....
- if ((CMOS_READ(RTC_VALID) & RTC_VRT) == 0)
- return mktime(1970, 1, 1, 0, 0, 0);
-
- do {
- sec = CMOS_READ(RTC_SECONDS);
- min = CMOS_READ(RTC_MINUTES);
- hour = CMOS_READ(RTC_HOURS);
- day = CMOS_READ(RTC_DAY_OF_MONTH);
- mon = CMOS_READ(RTC_MONTH);
- year = CMOS_READ(RTC_YEAR);
- } while (sec != CMOS_READ(RTC_SECONDS));
-
- if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
- BCD_TO_BIN(sec);
- BCD_TO_BIN(min);
- BCD_TO_BIN(hour);
- BCD_TO_BIN(day);
- BCD_TO_BIN(mon);
- BCD_TO_BIN(year);
- }
- if ((year += 1900) < 1970)
- year += 100;
- return mktime(year, mon, day, hour, min, sec);
-}
-
-static int set_isa_cmos_time(void)
-{
- int retval = 0;
- int real_seconds, real_minutes, cmos_minutes;
- unsigned char save_control, save_freq_select;
- unsigned long nowtime = xtime.tv_sec;
-
- save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */
- CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
-
- save_freq_select = CMOS_READ(RTC_FREQ_SELECT); /* stop and reset prescaler */
- CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
-
- cmos_minutes = CMOS_READ(RTC_MINUTES);
- if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
- BCD_TO_BIN(cmos_minutes);
-
- /*
- * since we're only adjusting minutes and seconds,
- * don't interfere with hour overflow. This avoids
- * messing with unknown time zones but requires your
- * RTC not to be off by more than 15 minutes
- */
- real_seconds = nowtime % 60;
- real_minutes = nowtime / 60;
- if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1)
- real_minutes += 30; /* correct for half hour time zone */
- real_minutes %= 60;
-
- if (abs(real_minutes - cmos_minutes) < 30) {
- if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
- BIN_TO_BCD(real_seconds);
- BIN_TO_BCD(real_minutes);
- }
- CMOS_WRITE(real_seconds,RTC_SECONDS);
- CMOS_WRITE(real_minutes,RTC_MINUTES);
- } else
- retval = -1;
-
- /* The following flags have to be released exactly in this order,
- * otherwise the DS12887 (popular MC146818A clone with integrated
- * battery and quartz) will not reset the oscillator and will not
- * update precisely 500 ms later. You won't find this mentioned in
- * the Dallas Semiconductor data sheets, but who believes data
- * sheets anyway ... -- Markus Kuhn
- */
- CMOS_WRITE(save_control, RTC_CONTROL);
- CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
-
- return retval;
-}
-
-void __init isa_rtc_init(void)
-{
- if (machine_is_personal_server())
- /*
- * Add-in 21285s shouldn't access the RTC
- */
- rtc_base = 0;
- else
- rtc_base = 0x70;
-
- if (rtc_base) {
- int reg_d, reg_b;
-
- /*
- * Probe for the RTC.
- */
- reg_d = CMOS_READ(RTC_REG_D);
-
- /*
- * make sure the divider is set
- */
- CMOS_WRITE(RTC_REF_CLCK_32KHZ, RTC_REG_A);
-
- /*
- * Set control reg B
- * (24 hour mode, update enabled)
- */
- reg_b = CMOS_READ(RTC_REG_B) & 0x7f;
- reg_b |= 2;
- CMOS_WRITE(reg_b, RTC_REG_B);
-
- if ((CMOS_READ(RTC_REG_A) & 0x7f) == RTC_REF_CLCK_32KHZ &&
- CMOS_READ(RTC_REG_B) == reg_b) {
- struct timespec tv;
-
- /*
- * We have a RTC. Check the battery
- */
- if ((reg_d & 0x80) == 0)
- printk(KERN_WARNING "RTC: *** warning: CMOS battery bad\n");
-
- tv.tv_nsec = 0;
- tv.tv_sec = get_isa_cmos_time();
- do_settimeofday(&tv);
- set_rtc = set_isa_cmos_time;
- } else
- rtc_base = 0;
- }
-}