summaryrefslogtreecommitdiffstats
path: root/arch/avr32/mach-at32ap
diff options
context:
space:
mode:
Diffstat (limited to 'arch/avr32/mach-at32ap')
-rw-r--r--arch/avr32/mach-at32ap/Kconfig31
-rw-r--r--arch/avr32/mach-at32ap/Makefile1
-rw-r--r--arch/avr32/mach-at32ap/at32ap7000.c70
-rw-r--r--arch/avr32/mach-at32ap/clock.c2
-rw-r--r--arch/avr32/mach-at32ap/hmatrix.h182
-rw-r--r--arch/avr32/mach-at32ap/hsmc.c23
-rw-r--r--arch/avr32/mach-at32ap/time-tc.c218
7 files changed, 525 insertions, 2 deletions
diff --git a/arch/avr32/mach-at32ap/Kconfig b/arch/avr32/mach-at32ap/Kconfig
new file mode 100644
index 00000000000..eb307838457
--- /dev/null
+++ b/arch/avr32/mach-at32ap/Kconfig
@@ -0,0 +1,31 @@
+if PLATFORM_AT32AP
+
+menu "Atmel AVR32 AP options"
+
+choice
+ prompt "AT32AP7000 static memory bus width"
+ depends on CPU_AT32AP7000
+ default AP7000_16_BIT_SMC
+ help
+ Define the width of the AP7000 external static memory interface.
+ This is used to determine how to mangle the address and/or data
+ when doing little-endian port access.
+
+ The current code can only support a single external memory bus
+ width for all chip selects, excluding the flash (which is using
+ raw access and is thus not affected by any of this.)
+
+config AP7000_32_BIT_SMC
+ bool "32 bit"
+
+config AP7000_16_BIT_SMC
+ bool "16 bit"
+
+config AP7000_8_BIT_SMC
+ bool "8 bit"
+
+endchoice
+
+endmenu
+
+endif # PLATFORM_AT32AP
diff --git a/arch/avr32/mach-at32ap/Makefile b/arch/avr32/mach-at32ap/Makefile
index b21bea9af8b..f1d395724ac 100644
--- a/arch/avr32/mach-at32ap/Makefile
+++ b/arch/avr32/mach-at32ap/Makefile
@@ -1,2 +1,3 @@
obj-y += at32ap.o clock.o intc.o extint.o pio.o hsmc.o
obj-$(CONFIG_CPU_AT32AP7000) += at32ap7000.o
+obj-$(CONFIG_CPU_AT32AP7000) += time-tc.o
diff --git a/arch/avr32/mach-at32ap/at32ap7000.c b/arch/avr32/mach-at32ap/at32ap7000.c
index 472703f90c2..56db45b99a0 100644
--- a/arch/avr32/mach-at32ap/at32ap7000.c
+++ b/arch/avr32/mach-at32ap/at32ap7000.c
@@ -18,6 +18,7 @@
#include <asm/arch/sm.h>
#include "clock.h"
+#include "hmatrix.h"
#include "pio.h"
#include "sm.h"
@@ -416,7 +417,15 @@ struct platform_device at32_sm_device = {
.resource = sm_resource,
.num_resources = ARRAY_SIZE(sm_resource),
};
-DEV_CLK(pclk, at32_sm, pbb, 0);
+static struct clk at32_sm_pclk = {
+ .name = "pclk",
+ .dev = &at32_sm_device.dev,
+ .parent = &pbb_clk,
+ .mode = pbb_clk_mode,
+ .get_rate = pbb_clk_get_rate,
+ .users = 1,
+ .index = 0,
+};
static struct resource intc0_resource[] = {
PBMEM(0xfff00400),
@@ -442,6 +451,7 @@ static struct clk hramc_clk = {
.mode = hsb_clk_mode,
.get_rate = hsb_clk_get_rate,
.users = 1,
+ .index = 3,
};
static struct resource smc0_resource[] = {
@@ -467,6 +477,57 @@ static struct clk pico_clk = {
};
/* --------------------------------------------------------------------
+ * HMATRIX
+ * -------------------------------------------------------------------- */
+
+static struct clk hmatrix_clk = {
+ .name = "hmatrix_clk",
+ .parent = &pbb_clk,
+ .mode = pbb_clk_mode,
+ .get_rate = pbb_clk_get_rate,
+ .index = 2,
+ .users = 1,
+};
+#define HMATRIX_BASE ((void __iomem *)0xfff00800)
+
+#define hmatrix_readl(reg) \
+ __raw_readl((HMATRIX_BASE) + HMATRIX_##reg)
+#define hmatrix_writel(reg,value) \
+ __raw_writel((value), (HMATRIX_BASE) + HMATRIX_##reg)
+
+/*
+ * Set bits in the HMATRIX Special Function Register (SFR) used by the
+ * External Bus Interface (EBI). This can be used to enable special
+ * features like CompactFlash support, NAND Flash support, etc. on
+ * certain chipselects.
+ */
+static inline void set_ebi_sfr_bits(u32 mask)
+{
+ u32 sfr;
+
+ clk_enable(&hmatrix_clk);
+ sfr = hmatrix_readl(SFR4);
+ sfr |= mask;
+ hmatrix_writel(SFR4, sfr);
+ clk_disable(&hmatrix_clk);
+}
+
+/* --------------------------------------------------------------------
+ * System Timer/Counter (TC)
+ * -------------------------------------------------------------------- */
+static struct resource at32_systc0_resource[] = {
+ PBMEM(0xfff00c00),
+ IRQ(22),
+};
+struct platform_device at32_systc0_device = {
+ .name = "systc",
+ .id = 0,
+ .resource = at32_systc0_resource,
+ .num_resources = ARRAY_SIZE(at32_systc0_resource),
+};
+DEV_CLK(pclk, at32_systc0, pbb, 3);
+
+/* --------------------------------------------------------------------
* PIO
* -------------------------------------------------------------------- */
@@ -514,6 +575,8 @@ void __init at32_add_system_devices(void)
platform_device_register(&smc0_device);
platform_device_register(&pdc_device);
+ platform_device_register(&at32_systc0_device);
+
platform_device_register(&pio0_device);
platform_device_register(&pio1_device);
platform_device_register(&pio2_device);
@@ -950,6 +1013,7 @@ struct clk *at32_clock_list[] = {
&pbb_clk,
&at32_sm_pclk,
&at32_intc0_pclk,
+ &hmatrix_clk,
&ebi_clk,
&hramc_clk,
&smc0_pclk,
@@ -962,6 +1026,7 @@ struct clk *at32_clock_list[] = {
&pio2_mck,
&pio3_mck,
&pio4_mck,
+ &at32_systc0_pclk,
&atmel_usart0_usart,
&atmel_usart1_usart,
&atmel_usart2_usart,
@@ -1024,6 +1089,9 @@ void __init at32_clock_init(void)
for (i = 0; i < ARRAY_SIZE(at32_clock_list); i++) {
struct clk *clk = at32_clock_list[i];
+ if (clk->users == 0)
+ continue;
+
if (clk->mode == &cpu_clk_mode)
cpu_mask |= 1 << clk->index;
else if (clk->mode == &hsb_clk_mode)
diff --git a/arch/avr32/mach-at32ap/clock.c b/arch/avr32/mach-at32ap/clock.c
index 00c435452d7..0f8c89c9f83 100644
--- a/arch/avr32/mach-at32ap/clock.c
+++ b/arch/avr32/mach-at32ap/clock.c
@@ -18,7 +18,7 @@
#include "clock.h"
-static spinlock_t clk_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(clk_lock);
struct clk *clk_get(struct device *dev, const char *id)
{
diff --git a/arch/avr32/mach-at32ap/hmatrix.h b/arch/avr32/mach-at32ap/hmatrix.h
new file mode 100644
index 00000000000..d10bfb60d68
--- /dev/null
+++ b/arch/avr32/mach-at32ap/hmatrix.h
@@ -0,0 +1,182 @@
+/*
+ * Register definitions for High-Speed Bus Matrix
+ */
+#ifndef __HMATRIX_H
+#define __HMATRIX_H
+
+/* HMATRIX register offsets */
+#define HMATRIX_MCFG0 0x0000
+#define HMATRIX_MCFG1 0x0004
+#define HMATRIX_MCFG2 0x0008
+#define HMATRIX_MCFG3 0x000c
+#define HMATRIX_MCFG4 0x0010
+#define HMATRIX_MCFG5 0x0014
+#define HMATRIX_MCFG6 0x0018
+#define HMATRIX_MCFG7 0x001c
+#define HMATRIX_MCFG8 0x0020
+#define HMATRIX_MCFG9 0x0024
+#define HMATRIX_MCFG10 0x0028
+#define HMATRIX_MCFG11 0x002c
+#define HMATRIX_MCFG12 0x0030
+#define HMATRIX_MCFG13 0x0034
+#define HMATRIX_MCFG14 0x0038
+#define HMATRIX_MCFG15 0x003c
+#define HMATRIX_SCFG0 0x0040
+#define HMATRIX_SCFG1 0x0044
+#define HMATRIX_SCFG2 0x0048
+#define HMATRIX_SCFG3 0x004c
+#define HMATRIX_SCFG4 0x0050
+#define HMATRIX_SCFG5 0x0054
+#define HMATRIX_SCFG6 0x0058
+#define HMATRIX_SCFG7 0x005c
+#define HMATRIX_SCFG8 0x0060
+#define HMATRIX_SCFG9 0x0064
+#define HMATRIX_SCFG10 0x0068
+#define HMATRIX_SCFG11 0x006c
+#define HMATRIX_SCFG12 0x0070
+#define HMATRIX_SCFG13 0x0074
+#define HMATRIX_SCFG14 0x0078
+#define HMATRIX_SCFG15 0x007c
+#define HMATRIX_PRAS0 0x0080
+#define HMATRIX_PRBS0 0x0084
+#define HMATRIX_PRAS1 0x0088
+#define HMATRIX_PRBS1 0x008c
+#define HMATRIX_PRAS2 0x0090
+#define HMATRIX_PRBS2 0x0094
+#define HMATRIX_PRAS3 0x0098
+#define HMATRIX_PRBS3 0x009c
+#define HMATRIX_PRAS4 0x00a0
+#define HMATRIX_PRBS4 0x00a4
+#define HMATRIX_PRAS5 0x00a8
+#define HMATRIX_PRBS5 0x00ac
+#define HMATRIX_PRAS6 0x00b0
+#define HMATRIX_PRBS6 0x00b4
+#define HMATRIX_PRAS7 0x00b8
+#define HMATRIX_PRBS7 0x00bc
+#define HMATRIX_PRAS8 0x00c0
+#define HMATRIX_PRBS8 0x00c4
+#define HMATRIX_PRAS9 0x00c8
+#define HMATRIX_PRBS9 0x00cc
+#define HMATRIX_PRAS10 0x00d0
+#define HMATRIX_PRBS10 0x00d4
+#define HMATRIX_PRAS11 0x00d8
+#define HMATRIX_PRBS11 0x00dc
+#define HMATRIX_PRAS12 0x00e0
+#define HMATRIX_PRBS12 0x00e4
+#define HMATRIX_PRAS13 0x00e8
+#define HMATRIX_PRBS13 0x00ec
+#define HMATRIX_PRAS14 0x00f0
+#define HMATRIX_PRBS14 0x00f4
+#define HMATRIX_PRAS15 0x00f8
+#define HMATRIX_PRBS15 0x00fc
+#define HMATRIX_MRCR 0x0100
+#define HMATRIX_SFR0 0x0110
+#define HMATRIX_SFR1 0x0114
+#define HMATRIX_SFR2 0x0118
+#define HMATRIX_SFR3 0x011c
+#define HMATRIX_SFR4 0x0120
+#define HMATRIX_SFR5 0x0124
+#define HMATRIX_SFR6 0x0128
+#define HMATRIX_SFR7 0x012c
+#define HMATRIX_SFR8 0x0130
+#define HMATRIX_SFR9 0x0134
+#define HMATRIX_SFR10 0x0138
+#define HMATRIX_SFR11 0x013c
+#define HMATRIX_SFR12 0x0140
+#define HMATRIX_SFR13 0x0144
+#define HMATRIX_SFR14 0x0148
+#define HMATRIX_SFR15 0x014c
+
+/* Bitfields in MCFGx */
+#define HMATRIX_ULBT_OFFSET 0
+#define HMATRIX_ULBT_SIZE 3
+
+/* Bitfields in SCFGx */
+#define HMATRIX_SLOT_CYCLE_OFFSET 0
+#define HMATRIX_SLOT_CYCLE_SIZE 8
+#define HMATRIX_DEFMSTR_TYPE_OFFSET 16
+#define HMATRIX_DEFMSTR_TYPE_SIZE 2
+#define HMATRIX_FIXED_DEFMSTR_OFFSET 18
+#define HMATRIX_FIXED_DEFMSTR_SIZE 4
+#define HMATRIX_ARBT_OFFSET 24
+#define HMATRIX_ARBT_SIZE 2
+
+/* Bitfields in PRASx */
+#define HMATRIX_M0PR_OFFSET 0
+#define HMATRIX_M0PR_SIZE 4
+#define HMATRIX_M1PR_OFFSET 4
+#define HMATRIX_M1PR_SIZE 4
+#define HMATRIX_M2PR_OFFSET 8
+#define HMATRIX_M2PR_SIZE 4
+#define HMATRIX_M3PR_OFFSET 12
+#define HMATRIX_M3PR_SIZE 4
+#define HMATRIX_M4PR_OFFSET 16
+#define HMATRIX_M4PR_SIZE 4
+#define HMATRIX_M5PR_OFFSET 20
+#define HMATRIX_M5PR_SIZE 4
+#define HMATRIX_M6PR_OFFSET 24
+#define HMATRIX_M6PR_SIZE 4
+#define HMATRIX_M7PR_OFFSET 28
+#define HMATRIX_M7PR_SIZE 4
+
+/* Bitfields in PRBSx */
+#define HMATRIX_M8PR_OFFSET 0
+#define HMATRIX_M8PR_SIZE 4
+#define HMATRIX_M9PR_OFFSET 4
+#define HMATRIX_M9PR_SIZE 4
+#define HMATRIX_M10PR_OFFSET 8
+#define HMATRIX_M10PR_SIZE 4
+#define HMATRIX_M11PR_OFFSET 12
+#define HMATRIX_M11PR_SIZE 4
+#define HMATRIX_M12PR_OFFSET 16
+#define HMATRIX_M12PR_SIZE 4
+#define HMATRIX_M13PR_OFFSET 20
+#define HMATRIX_M13PR_SIZE 4
+#define HMATRIX_M14PR_OFFSET 24
+#define HMATRIX_M14PR_SIZE 4
+#define HMATRIX_M15PR_OFFSET 28
+#define HMATRIX_M15PR_SIZE 4
+
+/* Bitfields in SFR4 */
+#define HMATRIX_CS1A_OFFSET 1
+#define HMATRIX_CS1A_SIZE 1
+#define HMATRIX_CS3A_OFFSET 3
+#define HMATRIX_CS3A_SIZE 1
+#define HMATRIX_CS4A_OFFSET 4
+#define HMATRIX_CS4A_SIZE 1
+#define HMATRIX_CS5A_OFFSET 5
+#define HMATRIX_CS5A_SIZE 1
+#define HMATRIX_DBPUC_OFFSET 8
+#define HMATRIX_DBPUC_SIZE 1
+
+/* Constants for ULBT */
+#define HMATRIX_ULBT_INFINITE 0
+#define HMATRIX_ULBT_SINGLE 1
+#define HMATRIX_ULBT_FOUR_BEAT 2
+#define HMATRIX_ULBT_EIGHT_BEAT 3
+#define HMATRIX_ULBT_SIXTEEN_BEAT 4
+
+/* Constants for DEFMSTR_TYPE */
+#define HMATRIX_DEFMSTR_TYPE_NO_DEFAULT 0
+#define HMATRIX_DEFMSTR_TYPE_LAST_DEFAULT 1
+#define HMATRIX_DEFMSTR_TYPE_FIXED_DEFAULT 2
+
+/* Constants for ARBT */
+#define HMATRIX_ARBT_ROUND_ROBIN 0
+#define HMATRIX_ARBT_FIXED_PRIORITY 1
+
+/* Bit manipulation macros */
+#define HMATRIX_BIT(name) \
+ (1 << HMATRIX_##name##_OFFSET)
+#define HMATRIX_BF(name,value) \
+ (((value) & ((1 << HMATRIX_##name##_SIZE) - 1)) \
+ << HMATRIX_##name##_OFFSET)
+#define HMATRIX_BFEXT(name,value) \
+ (((value) >> HMATRIX_##name##_OFFSET) \
+ & ((1 << HMATRIX_##name##_SIZE) - 1))
+#define HMATRIX_BFINS(name,value,old) \
+ (((old) & ~(((1 << HMATRIX_##name##_SIZE) - 1) \
+ << HMATRIX_##name##_OFFSET)) \
+ | HMATRIX_BF(name,value))
+
+#endif /* __HMATRIX_H */
diff --git a/arch/avr32/mach-at32ap/hsmc.c b/arch/avr32/mach-at32ap/hsmc.c
index 7691721928a..5e22a750632 100644
--- a/arch/avr32/mach-at32ap/hsmc.c
+++ b/arch/avr32/mach-at32ap/hsmc.c
@@ -75,12 +75,35 @@ int smc_set_configuration(int cs, const struct smc_config *config)
return -EINVAL;
}
+ switch (config->nwait_mode) {
+ case 0:
+ mode |= HSMC_BF(EXNW_MODE, HSMC_EXNW_MODE_DISABLED);
+ break;
+ case 1:
+ mode |= HSMC_BF(EXNW_MODE, HSMC_EXNW_MODE_RESERVED);
+ break;
+ case 2:
+ mode |= HSMC_BF(EXNW_MODE, HSMC_EXNW_MODE_FROZEN);
+ break;
+ case 3:
+ mode |= HSMC_BF(EXNW_MODE, HSMC_EXNW_MODE_READY);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (config->tdf_cycles) {
+ mode |= HSMC_BF(TDF_CYCLES, config->tdf_cycles);
+ }
+
if (config->nrd_controlled)
mode |= HSMC_BIT(READ_MODE);
if (config->nwe_controlled)
mode |= HSMC_BIT(WRITE_MODE);
if (config->byte_write)
mode |= HSMC_BIT(BAT);
+ if (config->tdf_mode)
+ mode |= HSMC_BIT(TDF_MODE);
pr_debug("smc cs%d: setup/%08x pulse/%08x cycle/%08x mode/%08x\n",
cs, setup, pulse, cycle, mode);
diff --git a/arch/avr32/mach-at32ap/time-tc.c b/arch/avr32/mach-at32ap/time-tc.c
new file mode 100644
index 00000000000..e3070bdd4bb
--- /dev/null
+++ b/arch/avr32/mach-at32ap/time-tc.c
@@ -0,0 +1,218 @@
+/*
+ * Copyright (C) 2004-2007 Atmel Corporation
+ *
+ * Based on MIPS implementation arch/mips/kernel/time.c
+ * Copyright 2001 MontaVista Software Inc.
+ *
+ * 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 <linux/clk.h>
+#include <linux/clocksource.h>
+#include <linux/time.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/kernel_stat.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/profile.h>
+#include <linux/sysdev.h>
+#include <linux/err.h>
+
+#include <asm/div64.h>
+#include <asm/sysreg.h>
+#include <asm/io.h>
+#include <asm/sections.h>
+
+#include <asm/arch/time.h>
+
+/* how many counter cycles in a jiffy? */
+static u32 cycles_per_jiffy;
+
+/* the count value for the next timer interrupt */
+static u32 expirelo;
+
+/* the I/O registers of the TC module */
+static void __iomem *ioregs;
+
+cycle_t read_cycle_count(void)
+{
+ return (cycle_t)timer_read(ioregs, 0, CV);
+}
+
+struct clocksource clocksource_avr32 = {
+ .name = "avr32",
+ .rating = 342,
+ .read = read_cycle_count,
+ .mask = CLOCKSOURCE_MASK(16),
+ .shift = 16,
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static void avr32_timer_ack(void)
+{
+ u16 count = expirelo;
+
+ /* Ack this timer interrupt and set the next one, use a u16
+ * variable so it will wrap around correctly */
+ count += cycles_per_jiffy;
+ expirelo = count;
+ timer_write(ioregs, 0, RC, expirelo);
+
+ /* Check to see if we have missed any timer interrupts */
+ count = timer_read(ioregs, 0, CV);
+ if ((count - expirelo) < 0x7fff) {
+ expirelo = count + cycles_per_jiffy;
+ timer_write(ioregs, 0, RC, expirelo);
+ }
+}
+
+u32 avr32_hpt_read(void)
+{
+ return timer_read(ioregs, 0, CV);
+}
+
+static int avr32_timer_calc_div_and_set_jiffies(struct clk *pclk)
+{
+ unsigned int cycles_max = (clocksource_avr32.mask + 1) / 2;
+ unsigned int divs[] = { 4, 8, 16, 32 };
+ int divs_size = sizeof(divs) / sizeof(*divs);
+ int i = 0;
+ unsigned long count_hz;
+ unsigned long shift;
+ unsigned long mult;
+ int clock_div = -1;
+ u64 tmp;
+
+ shift = clocksource_avr32.shift;
+
+ do {
+ count_hz = clk_get_rate(pclk) / divs[i];
+ mult = clocksource_hz2mult(count_hz, shift);
+ clocksource_avr32.mult = mult;
+
+ tmp = TICK_NSEC;
+ tmp <<= shift;
+ tmp += mult / 2;
+ do_div(tmp, mult);
+
+ cycles_per_jiffy = tmp;
+ } while (cycles_per_jiffy > cycles_max && ++i < divs_size);
+
+ clock_div = i + 1;
+
+ if (clock_div > divs_size) {
+ pr_debug("timer: could not calculate clock divider\n");
+ return -EFAULT;
+ }
+
+ /* Set the clock divider */
+ timer_write(ioregs, 0, CMR, TIMER_BF(CMR_TCCLKS, clock_div));
+
+ return 0;
+}
+
+int avr32_hpt_init(unsigned int count)
+{
+ struct resource *regs;
+ struct clk *pclk;
+ int irq = -1;
+ int ret = 0;
+
+ ret = -ENXIO;
+
+ irq = platform_get_irq(&at32_systc0_device, 0);
+ if (irq < 0) {
+ pr_debug("timer: could not get irq\n");
+ goto out_error;
+ }
+
+ pclk = clk_get(&at32_systc0_device.dev, "pclk");
+ if (IS_ERR(pclk)) {
+ pr_debug("timer: could not get clk: %ld\n", PTR_ERR(pclk));
+ goto out_error;
+ }
+ clk_enable(pclk);
+
+ regs = platform_get_resource(&at32_systc0_device, IORESOURCE_MEM, 0);
+ if (!regs) {
+ pr_debug("timer: could not get resource\n");
+ goto out_error_clk;
+ }
+
+ ioregs = ioremap(regs->start, regs->end - regs->start + 1);
+ if (!ioregs) {
+ pr_debug("timer: could not get ioregs\n");
+ goto out_error_clk;
+ }
+
+ ret = avr32_timer_calc_div_and_set_jiffies(pclk);
+ if (ret)
+ goto out_error_io;
+
+ ret = setup_irq(irq, &timer_irqaction);
+ if (ret) {
+ pr_debug("timer: could not request irq %d: %d\n",
+ irq, ret);
+ goto out_error_io;
+ }
+
+ expirelo = (timer_read(ioregs, 0, CV) / cycles_per_jiffy + 1)
+ * cycles_per_jiffy;
+
+ /* Enable clock and interrupts on RC compare */
+ timer_write(ioregs, 0, CCR, TIMER_BIT(CCR_CLKEN));
+ timer_write(ioregs, 0, IER, TIMER_BIT(IER_CPCS));
+ /* Set cycles to first interrupt */
+ timer_write(ioregs, 0, RC, expirelo);
+
+ printk(KERN_INFO "timer: AT32AP system timer/counter at 0x%p irq %d\n",
+ ioregs, irq);
+
+ return 0;
+
+out_error_io:
+ iounmap(ioregs);
+out_error_clk:
+ clk_put(pclk);
+out_error:
+ return ret;
+}
+
+int avr32_hpt_start(void)
+{
+ timer_write(ioregs, 0, CCR, TIMER_BIT(CCR_SWTRG));
+ return 0;
+}
+
+irqreturn_t timer_interrupt(int irq, void *dev_id)
+{
+ unsigned int sr = timer_read(ioregs, 0, SR);
+
+ if (sr & TIMER_BIT(SR_CPCS)) {
+ /* ack timer interrupt and try to set next interrupt */
+ avr32_timer_ack();
+
+ /*
+ * Call the generic timer interrupt handler
+ */
+ write_seqlock(&xtime_lock);
+ do_timer(1);
+ write_sequnlock(&xtime_lock);
+
+ /*
+ * In UP mode, we call local_timer_interrupt() to do profiling
+ * and process accounting.
+ *
+ * SMP is not supported yet.
+ */
+ local_timer_interrupt(irq, dev_id);
+
+ return IRQ_HANDLED;
+ }
+
+ return IRQ_NONE;
+}