]> git.hungrycats.org Git - linux/commitdiff
[ARM] Add Integrator/CP platform support.
authorRussell King <rmk@flint.arm.linux.org.uk>
Fri, 6 Feb 2004 17:36:13 +0000 (17:36 +0000)
committerRussell King <rmk@flint.arm.linux.org.uk>
Fri, 6 Feb 2004 17:36:13 +0000 (17:36 +0000)
This cset adds platform support for the ARM Integrator/CP platform.

arch/arm/mach-integrator/Kconfig
arch/arm/mach-integrator/Makefile
arch/arm/mach-integrator/cpu.c
arch/arm/mach-integrator/integrator_cp.c [new file with mode: 0644]
arch/arm/mach-integrator/leds.c
include/asm-arm/arch-integrator/irqs.h
include/asm-arm/arch-integrator/time.h

index dac0ad80773e7663e37e760f52dcc2758e82de8c..47f67a206c6cf20068de36b1a294f68b548717a6 100644 (file)
@@ -7,6 +7,15 @@ config ARCH_INTEGRATOR_AP
          Include support for the ARM(R) Integrator/AP and
          Integrator/PP2 platforms.
 
+config ARCH_INTEGRATOR_CP
+       bool "Support Integrator/CP platform"
+       select ARCH_CINTEGRATOR
+       help
+         Include support for the ARM(R) Integrator CP platform.
+
+config ARCH_CINTEGRATOR
+       bool
+
 config INTEGRATOR_IMPD1
        tristate "Include support for Integrator/IM-PD1"
        depends on ARCH_INTEGRATOR_AP
index 6e2f5a2217eaf6c2c02a54d10382bf2886a66d0f..34726a4da39d4ac36252d5293c556276886399c3 100644 (file)
@@ -6,6 +6,7 @@
 
 obj-y                                  := core.o lm.o time.o
 obj-$(CONFIG_ARCH_INTEGRATOR_AP)       += integrator_ap.o
+obj-$(CONFIG_ARCH_INTEGRATOR_CP)       += integrator_cp.o
 
 obj-$(CONFIG_LEDS)                     += leds.o
 obj-$(CONFIG_PCI)                      += pci_v3.o pci.o
index a33722ede48a9b40b7a6a6b3223c63e903c008b7..f2c1567a4d8b67348523451fc022f7b7b7ade93a 100644 (file)
@@ -22,6 +22,7 @@
 
 #include <asm/hardware.h>
 #include <asm/io.h>
+#include <asm/mach-types.h>
 #include <asm/hardware/icst525.h>
 
 static struct cpufreq_driver integrator_driver;
@@ -98,7 +99,12 @@ static int integrator_set_target(struct cpufreq_policy *policy,
 
        /* get current setting */
        cm_osc = __raw_readl(CM_OSC);
-       vco.s = (cm_osc >> 8) & 7;
+
+       if (machine_is_integrator()) {
+               vco.s = (cm_osc >> 8) & 7;
+       } else if (machine_is_cintegrator()) {
+               vco.s = 1;
+       }
        vco.v = cm_osc & 255;
        vco.r = 22;
        freqs.old = icst525_khz(&cclk_params, vco);
@@ -107,7 +113,7 @@ static int integrator_set_target(struct cpufreq_policy *policy,
         * larger freq in case of CPUFREQ_RELATION_L.
         */
        if (relation == CPUFREQ_RELATION_L)
-               target_freq += 1999;
+               target_freq += 999;
        if (target_freq > policy->max)
                target_freq = policy->max;
        vco = icst525_khz_to_vco(&cclk_params, target_freq);
@@ -123,8 +129,14 @@ static int integrator_set_target(struct cpufreq_policy *policy,
        cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
 
        cm_osc = __raw_readl(CM_OSC);
-       cm_osc &= 0xfffff800;
-       cm_osc |= vco.v | vco.s << 8;
+
+       if (machine_is_integrator()) {
+               cm_osc &= 0xfffff800;
+               cm_osc |= vco.s << 8;
+       } else if (machine_is_cintegrator()) {
+               cm_osc &= 0xffffff00;
+       }
+       cm_osc |= vco.v;
 
        __raw_writel(0xa05f, CM_LOCK);
        __raw_writel(cm_osc, CM_OSC);
@@ -144,7 +156,7 @@ static int integrator_cpufreq_init(struct cpufreq_policy *policy)
 {
        unsigned long cpus_allowed;
        unsigned int cpu = policy->cpu;
-       u_int cm_osc, cm_stat, mem_freq_khz;
+       u_int cm_osc;
        struct icst525_vco vco;
 
        cpus_allowed = current->cpus_allowed;
@@ -153,18 +165,13 @@ static int integrator_cpufreq_init(struct cpufreq_policy *policy)
        BUG_ON(cpu != smp_processor_id());
 
        /* detect memory etc. */
-       cm_stat = __raw_readl(CM_STAT);
        cm_osc = __raw_readl(CM_OSC);
-       vco.s = (cm_osc >> 20) & 7;
-       vco.v = (cm_osc >> 12) & 255;
-       vco.r = 22;
-       mem_freq_khz = icst525_khz(&lclk_params, vco) / 2;
 
-       printk(KERN_INFO "CPU%d: Module id: %d\n", cpu, cm_stat & 255);
-       printk(KERN_INFO "CPU%d: Memory clock = %d.%03d MHz\n",
-              cpu, mem_freq_khz / 1000, mem_freq_khz % 1000);
-
-       vco.s = (cm_osc >> 8) & 7;
+       if (machine_is_integrator()) {
+               vco.s = (cm_osc >> 8) & 7;
+       } else if (machine_is_cintegrator()) {
+               vco.s = 1;
+       }
        vco.v = cm_osc & 255;
        vco.r = 22;
 
diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c
new file mode 100644 (file)
index 0000000..7519410
--- /dev/null
@@ -0,0 +1,367 @@
+/*
+ *  linux/arch/arm/mach-integrator/integrator_cp.c
+ *
+ *  Copyright (C) 2003 Deep Blue Solutions Ltd
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License.
+ */
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/sysdev.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/hardware/amba.h>
+#include <asm/hardware/amba_kmi.h>
+
+#include <asm/arch/lm.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/flash.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/mmc.h>
+#include <asm/mach/map.h>
+
+#define INTCP_PA_MMC_BASE              0x1c000000
+#define INTCP_PA_AACI_BASE             0x1d000000
+
+#define INTCP_PA_FLASH_BASE            0x24000000
+#define INTCP_FLASH_SIZE               SZ_32M
+
+#define INTCP_VA_CIC_BASE              0xf1000040
+#define INTCP_VA_PIC_BASE              0xf1400000
+#define INTCP_VA_SIC_BASE              0xfca00000
+
+#define INTCP_PA_ETH_BASE              0xc8000000
+#define INTCP_ETH_SIZE                 0x10
+
+#define INTCP_VA_CTRL_BASE             0xfcb00000
+#define INTCP_FLASHPROG                        0x04
+#define CINTEGRATOR_FLASHPROG_FLVPPEN  (1 << 0)
+#define CINTEGRATOR_FLASHPROG_FLWREN   (1 << 1)
+
+/*
+ * Logical      Physical
+ * f1000000    10000000        Core module registers
+ * f1100000    11000000        System controller registers
+ * f1200000    12000000        EBI registers
+ * f1300000    13000000        Counter/Timer
+ * f1400000    14000000        Interrupt controller
+ * f1600000    16000000        UART 0
+ * f1700000    17000000        UART 1
+ * f1a00000    1a000000        Debug LEDs
+ * f1b00000    1b000000        GPIO
+ */
+
+static struct map_desc intcp_io_desc[] __initdata = {
+ { IO_ADDRESS(INTEGRATOR_HDR_BASE),   INTEGRATOR_HDR_BASE,   SZ_4K,  MT_DEVICE },
+ { IO_ADDRESS(INTEGRATOR_SC_BASE),    INTEGRATOR_SC_BASE,    SZ_4K,  MT_DEVICE },
+ { IO_ADDRESS(INTEGRATOR_EBI_BASE),   INTEGRATOR_EBI_BASE,   SZ_4K,  MT_DEVICE },
+ { IO_ADDRESS(INTEGRATOR_CT_BASE),    INTEGRATOR_CT_BASE,    SZ_4K,  MT_DEVICE },
+ { IO_ADDRESS(INTEGRATOR_IC_BASE),    INTEGRATOR_IC_BASE,    SZ_4K,  MT_DEVICE },
+ { IO_ADDRESS(INTEGRATOR_UART0_BASE), INTEGRATOR_UART0_BASE, SZ_4K,  MT_DEVICE },
+ { IO_ADDRESS(INTEGRATOR_UART1_BASE), INTEGRATOR_UART1_BASE, SZ_4K,  MT_DEVICE },
+ { IO_ADDRESS(INTEGRATOR_DBG_BASE),   INTEGRATOR_DBG_BASE,   SZ_4K,  MT_DEVICE },
+ { IO_ADDRESS(INTEGRATOR_GPIO_BASE),  INTEGRATOR_GPIO_BASE,  SZ_4K,  MT_DEVICE },
+ { 0xfc900000, 0xc9000000, SZ_4K, MT_DEVICE },
+ { 0xfca00000, 0xca000000, SZ_4K, MT_DEVICE },
+ { 0xfcb00000, 0xcb000000, SZ_4K, MT_DEVICE },
+};
+
+static void __init intcp_map_io(void)
+{
+       iotable_init(intcp_io_desc, ARRAY_SIZE(intcp_io_desc));
+}
+
+#define cic_writel     __raw_writel
+#define cic_readl      __raw_readl
+#define pic_writel     __raw_writel
+#define pic_readl      __raw_readl
+#define sic_writel     __raw_writel
+#define sic_readl      __raw_readl
+
+static void cic_mask_irq(unsigned int irq)
+{
+       irq -= IRQ_CIC_START;
+       cic_writel(1 << irq, INTCP_VA_CIC_BASE + IRQ_ENABLE_CLEAR);
+}
+
+static void cic_unmask_irq(unsigned int irq)
+{
+       irq -= IRQ_CIC_START;
+       cic_writel(1 << irq, INTCP_VA_CIC_BASE + IRQ_ENABLE_SET);
+}
+
+static struct irqchip cic_chip = {
+       .ack    = cic_mask_irq,
+       .mask   = cic_mask_irq,
+       .unmask = cic_unmask_irq,
+};
+
+static void pic_mask_irq(unsigned int irq)
+{
+       irq -= IRQ_PIC_START;
+       pic_writel(1 << irq, INTCP_VA_PIC_BASE + IRQ_ENABLE_CLEAR);
+}
+
+static void pic_unmask_irq(unsigned int irq)
+{
+       irq -= IRQ_PIC_START;
+       pic_writel(1 << irq, INTCP_VA_PIC_BASE + IRQ_ENABLE_SET);
+}
+
+static struct irqchip pic_chip = {
+       .ack    = pic_mask_irq,
+       .mask   = pic_mask_irq,
+       .unmask = pic_unmask_irq,
+};
+
+static void sic_mask_irq(unsigned int irq)
+{
+       irq -= IRQ_SIC_START;
+       sic_writel(1 << irq, INTCP_VA_SIC_BASE + IRQ_ENABLE_CLEAR);
+}
+
+static void sic_unmask_irq(unsigned int irq)
+{
+       irq -= IRQ_SIC_START;
+       sic_writel(1 << irq, INTCP_VA_SIC_BASE + IRQ_ENABLE_SET);
+}
+
+static struct irqchip sic_chip = {
+       .ack    = sic_mask_irq,
+       .mask   = sic_mask_irq,
+       .unmask = sic_unmask_irq,
+};
+
+static void
+sic_handle_irq(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
+{
+       unsigned long status = sic_readl(INTCP_VA_SIC_BASE + IRQ_STATUS);
+
+       if (status == 0) {
+               do_bad_IRQ(irq, desc, regs);
+               return;
+       }
+
+       do {
+               irq = ffs(status) - 1;
+               status &= ~(1 << irq);
+
+               irq += IRQ_SIC_START;
+
+               desc = irq_desc + irq;
+               desc->handle(irq, desc, regs);
+       } while (status);
+}
+
+static void __init intcp_init_irq(void)
+{
+       unsigned int i;
+
+       /*
+        * Disable all interrupt sources
+        */
+       pic_writel(0xffffffff, INTCP_VA_PIC_BASE + IRQ_ENABLE_CLEAR);
+       pic_writel(0xffffffff, INTCP_VA_PIC_BASE + FIQ_ENABLE_CLEAR);
+
+       for (i = IRQ_PIC_START; i <= IRQ_PIC_END; i++) {
+               if (i == 11)
+                       i = 22;
+               if (i == IRQ_CP_CPPLDINT)
+                       i++;
+               if (i == 29)
+                       break;
+               set_irq_chip(i, &pic_chip);
+               set_irq_handler(i, do_level_IRQ);
+               set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
+       }
+
+       cic_writel(0xffffffff, INTCP_VA_CIC_BASE + IRQ_ENABLE_CLEAR);
+       cic_writel(0xffffffff, INTCP_VA_CIC_BASE + FIQ_ENABLE_CLEAR);
+
+       for (i = IRQ_CIC_START; i <= IRQ_CIC_END; i++) {
+               set_irq_chip(i, &cic_chip);
+               set_irq_handler(i, do_level_IRQ);
+               set_irq_flags(i, IRQF_VALID);
+       }
+
+       sic_writel(0x00000fff, INTCP_VA_SIC_BASE + IRQ_ENABLE_CLEAR);
+       sic_writel(0x00000fff, INTCP_VA_SIC_BASE + FIQ_ENABLE_CLEAR);
+
+       for (i = IRQ_SIC_START; i <= IRQ_SIC_END; i++) {
+               set_irq_chip(i, &sic_chip);
+               set_irq_handler(i, do_level_IRQ);
+               set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
+       }
+
+       set_irq_handler(IRQ_CP_CPPLDINT, sic_handle_irq);
+       pic_unmask_irq(IRQ_CP_CPPLDINT);
+}
+
+/*
+ * Flash handling.
+ */
+static int intcp_flash_init(void)
+{
+       u32 val;
+
+       val = readl(INTCP_VA_CTRL_BASE + INTCP_FLASHPROG);
+       val |= CINTEGRATOR_FLASHPROG_FLWREN;
+       writel(val, INTCP_VA_CTRL_BASE + INTCP_FLASHPROG);
+
+       return 0;
+}
+
+static void intcp_flash_exit(void)
+{
+       u32 val;
+
+       val = readl(INTCP_VA_CTRL_BASE + INTCP_FLASHPROG);
+       val &= ~(CINTEGRATOR_FLASHPROG_FLVPPEN|CINTEGRATOR_FLASHPROG_FLWREN);
+       writel(val, INTCP_VA_CTRL_BASE + INTCP_FLASHPROG);
+}
+
+static void intcp_flash_set_vpp(int on)
+{
+       u32 val;
+
+       val = readl(INTCP_VA_CTRL_BASE + INTCP_FLASHPROG);
+       if (on)
+               val |= CINTEGRATOR_FLASHPROG_FLVPPEN;
+       else
+               val &= ~CINTEGRATOR_FLASHPROG_FLVPPEN;
+       writel(val, INTCP_VA_CTRL_BASE + INTCP_FLASHPROG);
+}
+
+static struct flash_platform_data intcp_flash_data = {
+       .map_name       = "cfi_probe",
+       .width          = 4,
+       .init           = intcp_flash_init,
+       .exit           = intcp_flash_exit,
+       .set_vpp        = intcp_flash_set_vpp,
+};
+
+static struct resource intcp_flash_resource = {
+       .start          = INTCP_PA_FLASH_BASE,
+       .end            = INTCP_PA_FLASH_BASE + INTCP_FLASH_SIZE - 1,
+       .flags          = IORESOURCE_MEM,
+};
+
+static struct platform_device intcp_flash_device = {
+       .name           = "armflash",
+       .id             = 0,
+       .dev            = {
+               .platform_data  = &intcp_flash_data,
+       },
+       .num_resources  = 1,
+       .resource       = &intcp_flash_resource,
+};
+
+static struct resource smc91x_resources[] = {
+       [0] = {
+               .start  = INTCP_PA_ETH_BASE,
+               .end    = INTCP_PA_ETH_BASE + INTCP_ETH_SIZE - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = IRQ_CP_ETHINT,
+               .end    = IRQ_CP_ETHINT,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device smc91x_device = {
+       .name           = "smc91x",
+       .id             = 0,
+       .num_resources  = ARRAY_SIZE(smc91x_resources),
+       .resource       = smc91x_resources,
+};
+
+static struct platform_device *intcp_devs[] __initdata = {
+       &intcp_flash_device,
+       &smc91x_device,
+};
+
+/*
+ * It seems that the card insertion interrupt remains active after
+ * we've acknowledged it.  We therefore ignore the interrupt, and
+ * rely on reading it from the SIC.  This also means that we must
+ * clear the latched interrupt.
+ */
+static unsigned int mmc_status(struct device *dev)
+{
+       unsigned int status = readl(0xfca00004);
+       writel(8, 0xfcb00008);
+
+       return status & 8;
+}
+
+static struct mmc_platform_data mmc_data = {
+       .mclk           = 33000000,
+       .ocr_mask       = MMC_VDD_32_33|MMC_VDD_33_34,
+       .status         = mmc_status,
+};
+
+static struct amba_device mmc_device = {
+       .dev            = {
+               .bus_id = "mb:1c",
+               .platform_data = &mmc_data,
+       },
+       .res            = {
+               .start  = INTCP_PA_MMC_BASE,
+               .end    = INTCP_PA_MMC_BASE + SZ_4K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       .irq            = { IRQ_CP_MMCIINT0, IRQ_CP_MMCIINT1 },
+       .periphid       = 0,
+};
+
+static struct amba_device aaci_device = {
+       .dev            = {
+               .bus_id = "mb:1d",
+       },
+       .res            = {
+               .start  = INTCP_PA_AACI_BASE,
+               .end    = INTCP_PA_AACI_BASE + SZ_4K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       .irq            = { IRQ_CP_AACIINT, NO_IRQ },
+       .periphid       = 0,
+};
+
+static struct amba_device *amba_devs[] __initdata = {
+       &mmc_device,
+       &aaci_device,
+};
+
+static void __init intcp_init(void)
+{
+       int i;
+
+       platform_add_devices(intcp_devs, ARRAY_SIZE(intcp_devs));
+
+       for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
+               struct amba_device *d = amba_devs[i];
+               amba_device_register(d, &iomem_resource);
+       }
+}
+
+MACHINE_START(CINTEGRATOR, "ARM-IntegratorCP")
+       MAINTAINER("ARM Ltd/Deep Blue Solutions Ltd")
+       BOOT_MEM(0x00000000, 0x16000000, 0xf1600000)
+       BOOT_PARAMS(0x00000100)
+       MAPIO(intcp_map_io)
+       INITIRQ(intcp_init_irq)
+       INIT_MACHINE(intcp_init)
+MACHINE_END
index b86a5b0f6f83f89c347043edf7dbd51d09042e94..9d182b77b31269e8e18aa40b9b95fc8fe1a36b31 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  linux/arch/arm/mach-integrator/leds.c
  *
- *  Integrator LED control routines
+ *  Integrator/AP and Integrator/CP LED control routines
  *
  *  Copyright (C) 1999 ARM Limited
  *  Copyright (C) 2000 Deep Blue Solutions Ltd
@@ -79,7 +79,7 @@ static void integrator_leds_event(led_event_t ledevt)
 
 static int __init leds_init(void)
 {
-       if (machine_is_integrator())
+       if (machine_is_integrator() || machine_is_cintegrator())
                leds_event = integrator_leds_event;
 
        return 0;
index a36789ad20f8afbbda46061e6820ddbf573cd9bc..ba7b3afee4453685a4e38e6faacc799716c38ca1 100644 (file)
 #define IRQ_AP_CPINT1                  19
 #define IRQ_AP_LBUSTIMEOUT             20
 #define IRQ_AP_APCINT                  21
+#define IRQ_CP_CLCDCINT                        22
+#define IRQ_CP_MMCIINT0                        23
+#define IRQ_CP_MMCIINT1                        24
+#define IRQ_CP_AACIINT                 25
+#define IRQ_CP_CPPLDINT                        26
+#define IRQ_CP_ETHINT                  27
+#define IRQ_CP_TSPENINT                        28
 #define IRQ_PIC_END                    31
 
 #define IRQ_CIC_START                  32
 #define IRQ_CM_COMMTX                  34
 #define IRQ_CIC_END                    34
 
+/*
+ * IntegratorCP only
+ */
+#define IRQ_SIC_START                  35
+#define IRQ_SIC_CP_SOFTINT             35
+#define IRQ_SIC_CP_RI0                 36
+#define IRQ_SIC_CP_RI1                 37
+#define IRQ_SIC_CP_CARDIN              38
+#define IRQ_SIC_CP_LMINT0              39
+#define IRQ_SIC_CP_LMINT1              40
+#define IRQ_SIC_CP_LMINT2              41
+#define IRQ_SIC_CP_LMINT3              42
+#define IRQ_SIC_CP_LMINT4              43
+#define IRQ_SIC_CP_LMINT5              44
+#define IRQ_SIC_CP_LMINT6              45
+#define IRQ_SIC_CP_LMINT7              46
+#define IRQ_SIC_END                    46
+
 #define NR_IRQS                         47
 
index e361e947f1519afdf6c0da673de111954c8956ea..2ecbfa7f12597f1c0619c23756a6add30eb3405e 100644 (file)
@@ -17,6 +17,7 @@
  */
 #include <asm/system.h>
 #include <asm/leds.h>
+#include <asm/mach-types.h>
 
 /*
  * Where is the timer (VA)?
  */
 #define TIMER_INTERVAL (TICKS_PER_uSEC * mSEC_10)
 #if TIMER_INTERVAL >= 0x100000
-#define TIMER_RELOAD   (TIMER_INTERVAL >> 8)           /* Divide by 256 */
-#define TIMER_CTRL     0x88                            /* Enable, Clock / 256 */
 #define TICKS2USECS(x) (256 * (x) / TICKS_PER_uSEC)
 #elif TIMER_INTERVAL >= 0x10000
-#define TIMER_RELOAD   (TIMER_INTERVAL >> 4)           /* Divide by 16 */
-#define TIMER_CTRL     0x84                            /* Enable, Clock / 16 */
 #define TICKS2USECS(x) (16 * (x) / TICKS_PER_uSEC)
 #else
-#define TIMER_RELOAD   (TIMER_INTERVAL)
-#define TIMER_CTRL     0x80                            /* Enable */
 #define TICKS2USECS(x) ((x) / TICKS_PER_uSEC)
 #endif
 
+#define TIMER_CTRL_IE  (1 << 5)                        /* Interrupt Enable */
+
 /*
  * What does it look like?
  */
@@ -56,6 +53,8 @@ typedef struct TimerStruct {
 
 extern unsigned long (*gettimeoffset)(void);
 
+static unsigned long timer_reload;
+
 /*
  * Returns number of ms since last clock interrupt.  Note that interrupts
  * will have been disabled by do_gettimeoffset()
@@ -81,13 +80,13 @@ static unsigned long integrator_gettimeoffset(void)
        /*
         * Number of ticks since last interrupt.
         */
-       ticks1 = TIMER_RELOAD - ticks2;
+       ticks1 = timer_reload - ticks2;
 
        /*
         * Interrupt pending?  If so, we've reloaded once already.
         */
        if (status & (1 << IRQ_TIMERINT1))
-               ticks1 += TIMER_RELOAD;
+               ticks1 += timer_reload;
 
        /*
         * Convert the ticks to usecs
@@ -121,8 +120,21 @@ void __init time_init(void)
        volatile TimerStruct_t *timer0 = (volatile TimerStruct_t *)TIMER0_VA_BASE;
        volatile TimerStruct_t *timer1 = (volatile TimerStruct_t *)TIMER1_VA_BASE;
        volatile TimerStruct_t *timer2 = (volatile TimerStruct_t *)TIMER2_VA_BASE;
-
-       timer_irq.handler = integrator_timer_interrupt;
+       unsigned int timer_ctrl = 0x80 | 0x40;  /* periodic */
+
+       if (machine_is_integrator()) {
+               timer_reload = 1000000 * TICKS_PER_uSEC / HZ;
+       } else if (machine_is_cintegrator()) {
+               timer_reload = 1000000 / HZ;
+               timer_ctrl |= TIMER_CTRL_IE;
+       }
+       if (timer_reload > 0x100000) {
+               timer_reload >>= 8;
+               timer_ctrl |= 0x08; /* /256 */
+       } else if (timer_reload > 0x010000) {
+               timer_reload >>= 4;
+               timer_ctrl |= 0x04; /* /16 */
+       }
 
        /*
         * Initialise to a known state (all timers off)
@@ -131,12 +143,14 @@ void __init time_init(void)
        timer1->TimerControl = 0;
        timer2->TimerControl = 0;
 
-       timer1->TimerLoad    = TIMER_RELOAD;
-       timer1->TimerControl = TIMER_CTRL | 0x40;       /* periodic */
+       timer1->TimerLoad    = timer_reload;
+       timer1->TimerValue   = timer_reload;
+       timer1->TimerControl = timer_ctrl;
 
        /* 
         * Make irqs happen for the system timer
         */
+       timer_irq.handler = integrator_timer_interrupt;
        setup_irq(IRQ_TIMERINT1, &timer_irq);
        gettimeoffset = integrator_gettimeoffset;
 }