Commit c3823c47 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/hskinnemoen/avr32-2.6

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/hskinnemoen/avr32-2.6: (25 commits)
  avr32: Add hardware power-down function call
  avr32: add include/asm-avr32/serial.h
  avr32: don't offer PARPORT_PC
  avr32: don't offer CONFIG_GEN_RTC
  avr32: don't offer CONFIG_RTC
  add include/asm-avr32/xor.h
  avr32: Remove two unused #defines from mm/init.c
  avr32: Implement set_rate(), set_parent() and mode() for pll1
  avr32: Generic clockevents support
  avr32: Move sleep code into mach-at32ap
  avr32: Use constants from sysreg.h in asm.h
  avr32: Delete mostly unused header asm/intc.h
  avr32: start clocksource cleanup
  avr32: pass i2c board info through at32_add_device_twi
  avr32: cleanup - use _AC macro to define PAGE_SIZE
  Generate raw keyboard codes for AVR32 architecture
  atmel_usba_udc: Add support for AT91CAP9 UDPHS
  atmel_usba_udc: Add missing kfree() in usba_udc_remove()
  atmel_usba_udc: move endpoint declarations into platform data.
  atmel_usba_udc: Kill GPIO_PIN_NONE
  ...
parents 5dfeaef8 ed3fa7c9
......@@ -47,6 +47,9 @@ config RWSEM_GENERIC_SPINLOCK
config GENERIC_TIME
def_bool y
config GENERIC_CLOCKEVENTS
def_bool y
config RWSEM_XCHGADD_ALGORITHM
def_bool n
......@@ -70,6 +73,8 @@ source "init/Kconfig"
menu "System Type and features"
source "kernel/time/Kconfig"
config SUBARCH_AVR32B
bool
config MMU
......
......@@ -741,26 +741,6 @@ irq_level\level:
.section .irq.text,"ax",@progbits
.global cpu_idle_sleep
cpu_idle_sleep:
mask_interrupts
get_thread_info r8
ld.w r9, r8[TI_flags]
bld r9, TIF_NEED_RESCHED
brcs cpu_idle_enable_int_and_exit
sbr r9, TIF_CPU_GOING_TO_SLEEP
st.w r8[TI_flags], r9
unmask_interrupts
sleep 0
cpu_idle_skip_sleep:
mask_interrupts
ld.w r9, r8[TI_flags]
cbr r9, TIF_CPU_GOING_TO_SLEEP
st.w r8[TI_flags], r9
cpu_idle_enable_int_and_exit:
unmask_interrupts
retal r12
.global irq_level0
.global irq_level1
.global irq_level2
......
......@@ -18,11 +18,11 @@
#include <asm/sysreg.h>
#include <asm/ocd.h>
#include <asm/arch/pm.h>
void (*pm_power_off)(void) = NULL;
EXPORT_SYMBOL(pm_power_off);
extern void cpu_idle_sleep(void);
/*
* This file handles the architecture-dependent parts of process handling..
*/
......@@ -54,6 +54,8 @@ void machine_halt(void)
void machine_power_off(void)
{
if (pm_power_off)
pm_power_off();
}
void machine_restart(char *cmd)
......
/*
* 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/clockchips.h>
#include <linux/time.h>
#include <linux/module.h>
#include <linux/interrupt.h>
......@@ -27,207 +23,133 @@
#include <asm/io.h>
#include <asm/sections.h>
/* how many counter cycles in a jiffy? */
static u32 cycles_per_jiffy;
#include <asm/arch/pm.h>
/* the count value for the next timer interrupt */
static u32 expirelo;
cycle_t __weak read_cycle_count(void)
static cycle_t read_cycle_count(void)
{
return (cycle_t)sysreg_read(COUNT);
}
struct clocksource __weak clocksource_avr32 = {
.name = "avr32",
.rating = 350,
/*
* The architectural cycle count registers are a fine clocksource unless
* the system idle loop use sleep states like "idle": the CPU cycles
* measured by COUNT (and COMPARE) don't happen during sleep states.
* Their duration also changes if cpufreq changes the CPU clock rate.
* So we rate the clocksource using COUNT as very low quality.
*/
static struct clocksource counter = {
.name = "avr32_counter",
.rating = 50,
.read = read_cycle_count,
.mask = CLOCKSOURCE_MASK(32),
.shift = 16,
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
};
irqreturn_t __weak timer_interrupt(int irq, void *dev_id);
struct irqaction timer_irqaction = {
.handler = timer_interrupt,
.flags = IRQF_DISABLED,
.name = "timer",
};
/*
* By default we provide the null RTC ops
*/
static unsigned long null_rtc_get_time(void)
static irqreturn_t timer_interrupt(int irq, void *dev_id)
{
return mktime(2007, 1, 1, 0, 0, 0);
}
static int null_rtc_set_time(unsigned long sec)
{
return 0;
}
struct clock_event_device *evdev = dev_id;
static unsigned long (*rtc_get_time)(void) = null_rtc_get_time;
static int (*rtc_set_time)(unsigned long) = null_rtc_set_time;
static void avr32_timer_ack(void)
{
u32 count;
/* Ack this timer interrupt and set the next one */
expirelo += cycles_per_jiffy;
/* setting COMPARE to 0 stops the COUNT-COMPARE */
if (expirelo == 0) {
sysreg_write(COMPARE, expirelo + 1);
} else {
sysreg_write(COMPARE, expirelo);
}
/*
* Disable the interrupt until the clockevent subsystem
* reprograms it.
*/
sysreg_write(COMPARE, 0);
/* Check to see if we have missed any timer interrupts */
count = sysreg_read(COUNT);
if ((count - expirelo) < 0x7fffffff) {
expirelo = count + cycles_per_jiffy;
sysreg_write(COMPARE, expirelo);
}
evdev->event_handler(evdev);
return IRQ_HANDLED;
}
int __weak avr32_hpt_init(void)
{
int ret;
unsigned long mult, shift, count_hz;
count_hz = clk_get_rate(boot_cpu_data.clk);
shift = clocksource_avr32.shift;
mult = clocksource_hz2mult(count_hz, shift);
clocksource_avr32.mult = mult;
{
u64 tmp;
tmp = TICK_NSEC;
tmp <<= shift;
tmp += mult / 2;
do_div(tmp, mult);
cycles_per_jiffy = tmp;
}
static struct irqaction timer_irqaction = {
.handler = timer_interrupt,
.flags = IRQF_TIMER | IRQF_DISABLED,
.name = "avr32_comparator",
};
ret = setup_irq(0, &timer_irqaction);
if (ret) {
pr_debug("timer: could not request IRQ 0: %d\n", ret);
return -ENODEV;
}
static int comparator_next_event(unsigned long delta,
struct clock_event_device *evdev)
{
unsigned long flags;
printk(KERN_INFO "timer: AT32AP COUNT-COMPARE at irq 0, "
"%lu.%03lu MHz\n",
((count_hz + 500) / 1000) / 1000,
((count_hz + 500) / 1000) % 1000);
raw_local_irq_save(flags);
return 0;
}
/* The time to read COUNT then update COMPARE must be less
* than the min_delta_ns value for this clockevent source.
*/
sysreg_write(COMPARE, (sysreg_read(COUNT) + delta) ? : 1);
/*
* Taken from MIPS c0_hpt_timer_init().
*
* The reason COUNT is written twice is probably to make sure we don't get any
* timer interrupts while we are messing with the counter.
*/
int __weak avr32_hpt_start(void)
{
u32 count = sysreg_read(COUNT);
expirelo = (count / cycles_per_jiffy + 1) * cycles_per_jiffy;
sysreg_write(COUNT, expirelo - cycles_per_jiffy);
sysreg_write(COMPARE, expirelo);
sysreg_write(COUNT, count);
raw_local_irq_restore(flags);
return 0;
}
/*
* local_timer_interrupt() does profiling and process accounting on a
* per-CPU basis.
*
* In UP mode, it is invoked from the (global) timer_interrupt.
*/
void local_timer_interrupt(int irq, void *dev_id)
static void comparator_mode(enum clock_event_mode mode,
struct clock_event_device *evdev)
{
if (current->pid)
profile_tick(CPU_PROFILING);
update_process_times(user_mode(get_irq_regs()));
switch (mode) {
case CLOCK_EVT_MODE_ONESHOT:
pr_debug("%s: start\n", evdev->name);
/* FALLTHROUGH */
case CLOCK_EVT_MODE_RESUME:
cpu_disable_idle_sleep();
break;
case CLOCK_EVT_MODE_UNUSED:
case CLOCK_EVT_MODE_SHUTDOWN:
sysreg_write(COMPARE, 0);
pr_debug("%s: stop\n", evdev->name);
cpu_enable_idle_sleep();
break;
default:
BUG();
}
}
irqreturn_t __weak timer_interrupt(int irq, void *dev_id)
{
/* 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;
}
static struct clock_event_device comparator = {
.name = "avr32_comparator",
.features = CLOCK_EVT_FEAT_ONESHOT,
.shift = 16,
.rating = 50,
.cpumask = CPU_MASK_CPU0,
.set_next_event = comparator_next_event,
.set_mode = comparator_mode,
};
void __init time_init(void)
{
unsigned long counter_hz;
int ret;
/*
* Make sure we don't get any COMPARE interrupts before we can
* handle them.
*/
sysreg_write(COMPARE, 0);
xtime.tv_sec = rtc_get_time();
xtime.tv_sec = mktime(2007, 1, 1, 0, 0, 0);
xtime.tv_nsec = 0;
set_normalized_timespec(&wall_to_monotonic,
-xtime.tv_sec, -xtime.tv_nsec);
ret = avr32_hpt_init();
if (ret) {
pr_debug("timer: failed setup: %d\n", ret);
return;
}
/* figure rate for counter */
counter_hz = clk_get_rate(boot_cpu_data.clk);
counter.mult = clocksource_hz2mult(counter_hz, counter.shift);
ret = clocksource_register(&clocksource_avr32);
ret = clocksource_register(&counter);
if (ret)
pr_debug("timer: could not register clocksource: %d\n", ret);
ret = avr32_hpt_start();
if (ret) {
pr_debug("timer: failed starting: %d\n", ret);
return;
}
}
/* setup COMPARE clockevent */
comparator.mult = div_sc(counter_hz, NSEC_PER_SEC, comparator.shift);
comparator.max_delta_ns = clockevent_delta2ns((u32)~0, &comparator);
comparator.min_delta_ns = clockevent_delta2ns(50, &comparator) + 1;
static struct sysdev_class timer_class = {
.name = "timer",
};
sysreg_write(COMPARE, 0);
timer_irqaction.dev_id = &comparator;
static struct sys_device timer_device = {
.id = 0,
.cls = &timer_class,
};
ret = setup_irq(0, &timer_irqaction);
if (ret)
pr_debug("timer: could not request IRQ 0: %d\n", ret);
else {
clockevents_register_device(&comparator);
static int __init init_timer_sysfs(void)
{
int err = sysdev_class_register(&timer_class);
if (!err)
err = sysdev_register(&timer_device);
return err;
pr_info("%s: irq 0, %lu.%03lu MHz\n", comparator.name,
((counter_hz + 500) / 1000) / 1000,
((counter_hz + 500) / 1000) % 1000);
}
}
device_initcall(init_timer_sysfs);
obj-y += at32ap.o clock.o intc.o extint.o pio.o hsmc.o
obj-$(CONFIG_CPU_AT32AP700X) += at32ap700x.o
obj-$(CONFIG_CPU_AT32AP700X) += time-tc.o
obj-$(CONFIG_CPU_AT32AP700X) += at32ap700x.o pm-at32ap700x.o
obj-$(CONFIG_CPU_FREQ_AT32AP) += cpufreq.o
......@@ -6,11 +6,13 @@
* published by the Free Software Foundation.
*/
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/spi/spi.h>
#include <linux/usb/atmel_usba_udc.h>
#include <asm/io.h>
#include <asm/irq.h>
......@@ -98,6 +100,9 @@ unsigned long at32ap7000_osc_rates[3] = {
[2] = 12000000,
};
static struct clk osc0;
static struct clk osc1;
static unsigned long osc_get_rate(struct clk *clk)
{
return at32ap7000_osc_rates[clk->index];
......@@ -107,9 +112,6 @@ static unsigned long pll_get_rate(struct clk *clk, unsigned long control)
{
unsigned long div, mul, rate;
if (!(control & PM_BIT(PLLEN)))
return 0;
div = PM_BFEXT(PLLDIV, control) + 1;
mul = PM_BFEXT(PLLMUL, control) + 1;
......@@ -120,6 +122,71 @@ static unsigned long pll_get_rate(struct clk *clk, unsigned long control)
return rate;
}
static long pll_set_rate(struct clk *clk, unsigned long rate,
u32 *pll_ctrl)
{
unsigned long mul;
unsigned long mul_best_fit = 0;
unsigned long div;
unsigned long div_min;
unsigned long div_max;
unsigned long div_best_fit = 0;
unsigned long base;
unsigned long pll_in;
unsigned long actual = 0;
unsigned long rate_error;
unsigned long rate_error_prev = ~0UL;
u32 ctrl;
/* Rate must be between 80 MHz and 200 Mhz. */
if (rate < 80000000UL || rate > 200000000UL)
return -EINVAL;
ctrl = PM_BF(PLLOPT, 4);
base = clk->parent->get_rate(clk->parent);
/* PLL input frequency must be between 6 MHz and 32 MHz. */
div_min = DIV_ROUND_UP(base, 32000000UL);
div_max = base / 6000000UL;
if (div_max < div_min)
return -EINVAL;
for (div = div_min; div <= div_max; div++) {
pll_in = (base + div / 2) / div;
mul = (rate + pll_in / 2) / pll_in;
if (mul == 0)
continue;
actual = pll_in * mul;
rate_error = abs(actual - rate);
if (rate_error < rate_error_prev) {
mul_best_fit = mul;
div_best_fit = div;
rate_error_prev = rate_error;
}
if (rate_error == 0)
break;
}
if (div_best_fit == 0)
return -EINVAL;
ctrl |= PM_BF(PLLMUL, mul_best_fit - 1);
ctrl |= PM_BF(PLLDIV, div_best_fit - 1);
ctrl |= PM_BF(PLLCOUNT, 16);
if (clk->parent == &osc1)
ctrl |= PM_BIT(PLLOSC);
*pll_ctrl = ctrl;
return actual;
}
static unsigned long pll0_get_rate(struct clk *clk)
{
u32 control;
......@@ -129,6 +196,41 @@ static unsigned long pll0_get_rate(struct clk *clk)
return pll_get_rate(clk, control);
}
static void pll1_mode(struct clk *clk, int enabled)
{
unsigned long timeout;
u32 status;
u32 ctrl;
ctrl = pm_readl(PLL1);
if (enabled) {
if (!PM_BFEXT(PLLMUL, ctrl) && !PM_BFEXT(PLLDIV, ctrl)) {
pr_debug("clk %s: failed to enable, rate not set\n",
clk->name);
return;
}
ctrl |= PM_BIT(PLLEN);
pm_writel(PLL1, ctrl);
/* Wait for PLL lock. */
for (timeout = 10000; timeout; timeout--) {
status = pm_readl(ISR);
if (status & PM_BIT(LOCK1))
break;
udelay(10);
}
if (!(status & PM_BIT(LOCK1)))
printk(KERN_ERR "clk %s: timeout waiting for lock\n",
clk->name);
} else {
ctrl &= ~PM_BIT(PLLEN);
pm_writel(PLL1, ctrl);
}
}
static unsigned long pll1_get_rate(struct clk *clk)
{
u32 control;
......@@ -138,6 +240,49 @@ static unsigned long pll1_get_rate(struct clk *clk)
return pll_get_rate(clk, control);
}
static long pll1_set_rate(struct clk *clk, unsigned long rate, int apply)
{
u32 ctrl = 0;
unsigned long actual_rate;
actual_rate = pll_set_rate(clk, rate, &ctrl);
if (apply) {
if (actual_rate != rate)
return -EINVAL;
if (clk->users > 0)
return -EBUSY;
pr_debug(KERN_INFO "clk %s: new rate %lu (actual rate %lu)\n",
clk->name, rate, actual_rate);
pm_writel(PLL1, ctrl);
}
return actual_rate;
}
static int pll1_set_parent(struct clk *clk, struct clk *parent)
{
u32 ctrl;
if (clk->users > 0)
return -EBUSY;
ctrl = pm_readl(PLL1);
WARN_ON(ctrl & PM_BIT(PLLEN));
if (parent == &osc0)
ctrl &= ~PM_BIT(PLLOSC);
else if (parent == &osc1)
ctrl |= PM_BIT(PLLOSC);
else
return -EINVAL;
pm_writel(PLL1, ctrl);
clk->parent = parent;
return 0;
}
/*
* The AT32AP7000 has five primary clock sources: One 32kHz
* oscillator, two crystal oscillators and two PLLs.
......@@ -166,7 +311,10 @@ static struct clk pll0 = {
};
static struct clk pll1 = {
.name = "pll1",
.mode = pll1_mode,
.get_rate = pll1_get_rate,
.set_rate = pll1_set_rate,
.set_parent = pll1_set_parent,
.parent = &osc0,
};
......@@ -605,19 +753,32 @@ static inline void set_ebi_sfr_bits(u32 mask)
}
/* --------------------------------------------------------------------
* System Timer/Counter (TC)
* Timer/Counter (TC)
* -------------------------------------------------------------------- */
static struct resource at32_systc0_resource[] = {
static struct resource at32_tcb0_resource[] = {
PBMEM(0xfff00c00),
IRQ(22),
};
struct platform_device at32_systc0_device = {
.name = "systc",
static struct platform_device at32_tcb0_device = {
.name = "atmel_tcb",
.id = 0,
.resource = at32_systc0_resource,
.num_resources = ARRAY_SIZE(at32_systc0_resource),
.resource = at32_tcb0_resource,
.num_resources = ARRAY_SIZE(at32_tcb0_resource),
};
DEV_CLK(pclk, at32_systc0, pbb, 3);
DEV_CLK(t0_clk, at32_tcb0, pbb, 3);
static struct resource at32_tcb1_resource[] = {
PBMEM(0xfff01000),
IRQ(23),
};
static struct platform_device at32_tcb1_device = {
.name = "atmel_tcb",
.id = 1,
.resource = at32_tcb1_resource,
.num_resources = ARRAY_SIZE(at32_tcb1_resource),
};
DEV_CLK(t0_clk, at32_tcb1, pbb, 4);
/* --------------------------------------------------------------------
* PIO
......@@ -669,7 +830,8 @@ void __init at32_add_system_devices(void)
platform_device_register(&pdc_device);
platform_device_register(&dmaca0_device);
platform_device_register(&at32_systc0_device);
platform_device_register(&at32_tcb0_device);
platform_device_register(&at32_tcb1_device);
platform_device_register(&pio0_device);
platform_device_register(&pio1_device);
......@@ -989,7 +1151,9 @@ static struct clk atmel_twi0_pclk = {
.index = 2,
};
struct platform_device *__init at32_add_device_twi(unsigned int id)
struct platform_device *__init at32_add_device_twi(unsigned int id,
struct i2c_board_info *b,
unsigned int n)
{
struct platform_device *pdev;
......@@ -1009,6 +1173,9 @@ struct platform_device *__init at32_add_device_twi(unsigned int id)
atmel_twi0_pclk.dev = &pdev->dev;
if (b)
i2c_register_board_info(id, b, n);
platform_device_add(pdev);
return pdev;
......@@ -1351,9 +1518,39 @@ static struct clk usba0_hclk = {
.index = 6,
};
#define EP(nam, idx, maxpkt, maxbk, dma, isoc) \
[idx] = { \
.name = nam, \
.index = idx, \
.fifo_size = maxpkt, \
.nr_banks = maxbk, \
.can_dma = dma, \
.can_isoc = isoc, \
}
static struct usba_ep_data at32_usba_ep[] __initdata = {
EP("ep0", 0, 64, 1, 0, 0),
EP("ep1", 1, 512, 2, 1, 1),
EP("ep2", 2, 512, 2, 1, 1),
EP("ep3-int", 3, 64, 3, 1, 0),
EP("ep4-int", 4, 64, 3, 1, 0),
EP("ep5", 5, 1024, 3, 1, 1),
EP("ep6", 6, 1024, 3, 1, 1),
};
#undef EP
struct platform_device *__init
at32_add_device_usba(unsigned int id, struct usba_platform_data *data)
{
/*
* pdata doesn't have room for any endpoints, so we need to
* append room for the ones we need right after it.
*/
struct {
struct usba_platform_data pdata;
struct usba_ep_data ep[7];
} usba_data;
struct platform_device *pdev;
if (id != 0)
......@@ -1367,13 +1564,20 @@ at32_add_device_usba(unsigned int id, struct usba_platform_data *data)
ARRAY_SIZE(usba0_resource)))
goto out_free_pdev;
if (data) {
if (platform_device_add_data(pdev, data, sizeof(*data)))
goto out_free_pdev;
if (data)
usba_data.pdata.vbus_pin = data->vbus_pin;
else
usba_data.pdata.vbus_pin = -EINVAL;
data = &usba_data.pdata;
data->num_ep = ARRAY_SIZE(at32_usba_ep);
memcpy(data->ep, at32_usba_ep, sizeof(at32_usba_ep));
if (data->vbus_pin != GPIO_PIN_NONE)
at32_select_gpio(data->vbus_pin, 0);
}
if (platform_device_add_data(pdev, data, sizeof(usba_data)))
goto out_free_pdev;
if (data->vbus_pin >= 0)
at32_select_gpio(data->vbus_pin, 0);
usba0_pclk.dev = &pdev->dev;
usba0_hclk.dev = &pdev->dev;
......@@ -1694,7 +1898,8 @@ struct clk *at32_clock_list[] = {
&pio2_mck,
&pio3_mck,
&pio4_mck,
&at32_systc0_pclk,
&at32_tcb0_t0_clk,
&at32_tcb1_t0_clk,
&atmel_usart0_usart,
&atmel_usart1_usart,
&atmel_usart2_usart,
......
......@@ -13,7 +13,6 @@
#include <linux/irq.h>
#include <linux/platform_device.h>
#include <asm/intc.h>
#include <asm/io.h>
#include "intc.h"
......
/*
* Low-level Power Management code.
*
* Copyright (C) 2008 Atmel Corporation
*
* 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/asm.h>
#include <asm/asm-offsets.h>
#include <asm/thread_info.h>
#include <asm/arch/pm.h>
.section .bss, "wa", @nobits
.global disable_idle_sleep
.type disable_idle_sleep, @object
disable_idle_sleep:
.int 4
.size disable_idle_sleep, . - disable_idle_sleep
/* Keep this close to the irq handlers */
.section .irq.text, "ax", @progbits
/*
* void cpu_enter_idle(void)
*
* Put the CPU into "idle" mode, in which it will consume
* significantly less power.
*
* If an interrupt comes along in the window between
* unmask_interrupts and the sleep instruction below, the
* interrupt code will adjust the return address so that we
* never execute the sleep instruction. This is required
* because the AP7000 doesn't unmask interrupts when entering
* sleep modes; later CPUs may not need this workaround.
*/
.global cpu_enter_idle
.type cpu_enter_idle, @function
cpu_enter_idle:
mask_interrupts
get_thread_info r8
ld.w r9, r8[TI_flags]
bld r9, TIF_NEED_RESCHED
brcs .Lret_from_sleep
sbr r9, TIF_CPU_GOING_TO_SLEEP
st.w r8[TI_flags], r9
unmask_interrupts
sleep CPU_SLEEP_IDLE
.size cpu_idle_sleep, . - cpu_idle_sleep
/*
* Common return path for PM functions that don't run from
* SRAM.
*/
.global cpu_idle_skip_sleep
.type cpu_idle_skip_sleep, @function
cpu_idle_skip_sleep:
mask_interrupts
ld.w r9, r8[TI_flags]
cbr r9, TIF_CPU_GOING_TO_SLEEP
st.w r8[TI_flags], r9
.Lret_from_sleep:
unmask_interrupts
retal r12
.size cpu_idle_skip_sleep, . - cpu_idle_skip_sleep
/*
* 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 = ARRAY_SIZE(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;
}
......@@ -34,9 +34,6 @@ struct page *empty_zero_page;
*/
unsigned long mmu_context_cache = NO_CONTEXT;
#define START_PFN (NODE_DATA(0)->bdata->node_boot_start >> PAGE_SHIFT)
#define MAX_LOW_PFN (NODE_DATA(0)->bdata->node_low_pfn)
void show_mem(void)
{
int total = 0, reserved = 0, cached = 0;
......
......@@ -16,7 +16,6 @@
#include <linux/sched.h>
#include <linux/types.h>
#include <asm/intc.h>
#include <asm/sysreg.h>
#include <asm/system.h>
......
......@@ -706,7 +706,7 @@ config NVRAM
config RTC
tristate "Enhanced Real Time Clock Support"
depends on !PPC && !PARISC && !IA64 && !M68K && !SPARC && !FRV && !ARM && !SUPERH && !S390
depends on !PPC && !PARISC && !IA64 && !M68K && !SPARC && !FRV && !ARM && !SUPERH && !S390 && !AVR32
---help---
If you say Y here and create a character special file /dev/rtc with
major number 10 and minor number 135 using mknod ("man mknod"), you
......@@ -776,7 +776,7 @@ config SGI_IP27_RTC
config GEN_RTC
tristate "Generic /dev/rtc emulation"
depends on RTC!=y && !IA64 && !ARM && !M32R && !MIPS && !SPARC && !FRV && !S390 && !SUPERH
depends on RTC!=y && !IA64 && !ARM && !M32R && !MIPS && !SPARC && !FRV && !S390 && !SUPERH && !AVR32
---help---
If you say Y here and create a character special file /dev/rtc with
major number 10 and minor number 135 using mknod ("man mknod"), you
......
......@@ -1033,7 +1033,8 @@ DECLARE_TASKLET_DISABLED(keyboard_tasklet, kbd_bh, 0);
#if defined(CONFIG_X86) || defined(CONFIG_IA64) || defined(CONFIG_ALPHA) ||\
defined(CONFIG_MIPS) || defined(CONFIG_PPC) || defined(CONFIG_SPARC) ||\
defined(CONFIG_PARISC) || defined(CONFIG_SUPERH) ||\
(defined(CONFIG_ARM) && defined(CONFIG_KEYBOARD_ATKBD) && !defined(CONFIG_ARCH_RPC))
(defined(CONFIG_ARM) && defined(CONFIG_KEYBOARD_ATKBD) && !defined(CONFIG_ARCH_RPC)) ||\
defined(CONFIG_AVR32)
#define HW_RAW(dev) (test_bit(EV_MSC, dev->evbit) && test_bit(MSC_RAW, dev->mscbit) &&\
((dev)->id.bustype == BUS_I8042) && ((dev)->id.vendor == 0x0001) && ((dev)->id.product == 0x0001))
......
obj-$(CONFIG_ATMEL_TCB_CLKSRC) += tcb_clksrc.o
obj-$(CONFIG_X86_CYCLONE_TIMER) += cyclone.o
obj-$(CONFIG_X86_PM_TIMER) += acpi_pm.o
obj-$(CONFIG_SCx200HR_TIMER) += scx200_hrt.o
#include <linux/init.h>
#include <linux/clocksource.h>
#include <linux/clockchips.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/ioport.h>
#include <linux/io.h>
#include <linux/platform_device.h>
#include <linux/atmel_tc.h>
/*
* We're configured to use a specific TC block, one that's not hooked
* up to external hardware, to provide a time solution:
*
* - Two channels combine to create a free-running 32 bit counter
* with a base rate of 5+ MHz, packaged as a clocksource (with
* resolution better than 200 nsec).
*
* - The third channel may be used to provide a 16-bit clockevent
* source, used in either periodic or oneshot mode. This runs
* at 32 KiHZ, and can handle delays of up to two seconds.
*
* A boot clocksource and clockevent source are also currently needed,
* unless the relevant platforms (ARM/AT91, AVR32/AT32) are changed so
* this code can be used when init_timers() is called, well before most
* devices are set up. (Some low end AT91 parts, which can run uClinux,
* have only the timers in one TC block... they currently don't support
* the tclib code, because of that initialization issue.)
*
* REVISIT behavior during system suspend states... we should disable
* all clocks and save the power. Easily done for clockevent devices,
* but clocksources won't necessarily get the needed notifications.
* For deeper system sleep states, this will be mandatory...
*/
static void __iomem *tcaddr;
static cycle_t tc_get_cycles(void)
{
unsigned long flags;
u32 lower, upper;
raw_local_irq_save(flags);
do {
upper = __raw_readl(tcaddr + ATMEL_TC_REG(1, CV));
lower = __raw_readl(tcaddr + ATMEL_TC_REG(0, CV));
} while (upper != __raw_readl(tcaddr + ATMEL_TC_REG(1, CV)));
raw_local_irq_restore(flags);
return (upper << 16) | lower;
}
static struct clocksource clksrc = {
.name = "tcb_clksrc",
.rating = 200,
.read = tc_get_cycles,
.mask = CLOCKSOURCE_MASK(32),
.shift = 18,
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
};
#ifdef CONFIG_GENERIC_CLOCKEVENTS
struct tc_clkevt_device {
struct clock_event_device clkevt;
struct clk *clk;
void __iomem *regs;
};
static struct tc_clkevt_device *to_tc_clkevt(struct clock_event_device *clkevt)
{
return container_of(clkevt, struct tc_clkevt_device, clkevt);
}
/* For now, we always use the 32K clock ... this optimizes for NO_HZ,
* because using one of the divided clocks would usually mean the
* tick rate can never be less than several dozen Hz (vs 0.5 Hz).
*
* A divided clock could be good for high resolution timers, since
* 30.5 usec resolution can seem "low".
*/
static u32 timer_clock;
static void tc_mode(enum clock_event_mode m, struct clock_event_device *d)
{
struct tc_clkevt_device *tcd = to_tc_clkevt(d);
void __iomem *regs = tcd->regs;
if (tcd->clkevt.mode == CLOCK_EVT_MODE_PERIODIC
|| tcd->clkevt.mode == CLOCK_EVT_MODE_ONESHOT) {
__raw_writel(0xff, regs + ATMEL_TC_REG(2, IDR));
__raw_writel(ATMEL_TC_CLKDIS, regs + ATMEL_TC_REG(2, CCR));
clk_disable(tcd->clk);
}
switch (m) {
/* By not making the gentime core emulate periodic mode on top
* of oneshot, we get lower overhead and improved accuracy.
*/
case CLOCK_EVT_MODE_PERIODIC:
clk_enable(tcd->clk);
/* slow clock, count up to RC, then irq and restart */
__raw_writel(timer_clock
| ATMEL_TC_WAVE | ATMEL_TC_WAVESEL_UP_AUTO,
regs + ATMEL_TC_REG(2, CMR));
__raw_writel((32768 + HZ/2) / HZ, tcaddr + ATMEL_TC_REG(2, RC));
/* Enable clock and interrupts on RC compare */
__raw_writel(ATMEL_TC_CPCS, regs + ATMEL_TC_REG(2, IER));
/* go go gadget! */
__raw_writel(ATMEL_TC_CLKEN | ATMEL_TC_SWTRG,
regs + ATMEL_TC_REG(2, CCR));
break;
case CLOCK_EVT_MODE_ONESHOT:
clk_enable(tcd->clk);
/* slow clock, count up to RC, then irq and stop */
__raw_writel(timer_clock | ATMEL_TC_CPCSTOP
| ATMEL_TC_WAVE | ATMEL_TC_WAVESEL_UP_AUTO,
regs + ATMEL_TC_REG(2, CMR));
__raw_writel(ATMEL_TC_CPCS, regs + ATMEL_TC_REG(2, IER));
/* set_next_event() configures and starts the timer */
break;
default:
break;
}
}
static int tc_next_event(unsigned long delta, struct clock_event_device *d)
{
__raw_writel(delta, tcaddr + ATMEL_TC_REG(2, RC));
/* go go gadget! */
__raw_writel(ATMEL_TC_CLKEN | ATMEL_TC_SWTRG,
tcaddr + ATMEL_TC_REG(2, CCR));
return 0;
}
static struct tc_clkevt_device clkevt = {
.clkevt = {
.name = "tc_clkevt",
.features = CLOCK_EVT_FEAT_PERIODIC
| CLOCK_EVT_FEAT_ONESHOT,
.shift = 32,
/* Should be lower than at91rm9200's system timer */
.rating = 125,
.cpumask = CPU_MASK_CPU0,
.set_next_event = tc_next_event,
.set_mode = tc_mode,
},
};
static irqreturn_t ch2_irq(int irq, void *handle)
{
struct tc_clkevt_device *dev = handle;
unsigned int sr;
sr = __raw_readl(dev->regs + ATMEL_TC_REG(2, SR));
if (sr & ATMEL_TC_CPCS) {
dev->clkevt.event_handler(&dev->clkevt);
return IRQ_HANDLED;
}
return IRQ_NONE;
}
static struct irqaction tc_irqaction = {
.name = "tc_clkevt",
.flags = IRQF_TIMER | IRQF_DISABLED,
.handler = ch2_irq,
};
static void __init setup_clkevents(struct atmel_tc *tc, int clk32k_divisor_idx)
{
struct clk *t2_clk = tc->clk[2];
int irq = tc->irq[2];
clkevt.regs = tc->regs;
clkevt.clk = t2_clk;
tc_irqaction.dev_id = &clkevt;
timer_clock = clk32k_divisor_idx;
clkevt.clkevt.mult = div_sc(32768, NSEC_PER_SEC, clkevt.clkevt.shift);
clkevt.clkevt.max_delta_ns
= clockevent_delta2ns(0xffff, &clkevt.clkevt);
clkevt.clkevt.min_delta_ns = clockevent_delta2ns(1, &clkevt.clkevt) + 1;
setup_irq(irq, &tc_irqaction);
clockevents_register_device(&clkevt.clkevt);
}
#else /* !CONFIG_GENERIC_CLOCKEVENTS */
static void __init setup_clkevents(struct atmel_tc *tc, int clk32k_divisor_idx)
{
/* NOTHING */
}
#endif
static int __init tcb_clksrc_init(void)
{
static char bootinfo[] __initdata
= KERN_DEBUG "%s: tc%d at %d.%03d MHz\n";
struct platform_device *pdev;
struct atmel_tc *tc;
struct clk *t0_clk;
u32 rate, divided_rate = 0;
int best_divisor_idx = -1;
int clk32k_divisor_idx = -1;
int i;
tc = atmel_tc_alloc(CONFIG_ATMEL_TCB_CLKSRC_BLOCK, clksrc.name);
if (!tc) {
pr_debug("can't alloc TC for clocksource\n");
return -ENODEV;
}
tcaddr = tc->regs;
pdev = tc->pdev;
t0_clk = tc->clk[0];
clk_enable(t0_clk);
/* How fast will we be counting? Pick something over 5 MHz. */
rate = (u32) clk_get_rate(t0_clk);
for (i = 0; i < 5; i++) {
unsigned divisor = atmel_tc_divisors[i];
unsigned tmp;
/* remember 32 KiHz clock for later */
if (!divisor) {
clk32k_divisor_idx = i;
continue;
}
tmp = rate / divisor;
pr_debug("TC: %u / %-3u [%d] --> %u\n", rate, divisor, i, tmp);
if (best_divisor_idx > 0) {
if (tmp < 5 * 1000 * 1000)
continue;
}
divided_rate = tmp;
best_divisor_idx = i;
}
clksrc.mult = clocksource_hz2mult(divided_rate, clksrc.shift);
printk(bootinfo, clksrc.name, CONFIG_ATMEL_TCB_CLKSRC_BLOCK,
divided_rate / 1000000,
((divided_rate + 500000) % 1000000) / 1000);
/* tclib will give us three clocks no matter what the
* underlying platform supports.
*/
clk_enable(tc->clk[1]);
/* channel 0: waveform mode, input mclk/8, clock TIOA0 on overflow */
__raw_writel(best_divisor_idx /* likely divide-by-8 */
| ATMEL_TC_WAVE
| ATMEL_TC_WAVESEL_UP /* free-run */
| ATMEL_TC_ACPA_SET /* TIOA0 rises at 0 */
| ATMEL_TC_ACPC_CLEAR, /* (duty cycle 50%) */
tcaddr + ATMEL_TC_REG(0, CMR));
__raw_writel(0x0000, tcaddr + ATMEL_TC_REG(0, RA));
__raw_writel(0x8000, tcaddr + ATMEL_TC_REG(0, RC));
__raw_writel(0xff, tcaddr + ATMEL_TC_REG(0, IDR)); /* no irqs */
__raw_writel(ATMEL_TC_CLKEN, tcaddr + ATMEL_TC_REG(0, CCR));
/* channel 1: waveform mode, input TIOA0 */
__raw_writel(ATMEL_TC_XC1 /* input: TIOA0 */
| ATMEL_TC_WAVE
| ATMEL_TC_WAVESEL_UP, /* free-run */
tcaddr + ATMEL_TC_REG(1, CMR));
__raw_writel(0xff, tcaddr + ATMEL_TC_REG(1, IDR)); /* no irqs */
__raw_writel(ATMEL_TC_CLKEN, tcaddr + ATMEL_TC_REG(1, CCR));
/* chain channel 0 to channel 1, then reset all the timers */
__raw_writel(ATMEL_TC_TC1XC1S_TIOA0, tcaddr + ATMEL_TC_BMR);
__raw_writel(ATMEL_TC_SYNC, tcaddr + ATMEL_TC_BCR);
/* and away we go! */
clocksource_register(&clksrc);
/* channel 2: periodic and oneshot timer support */
setup_clkevents(tc, clk32k_divisor_idx);
return 0;
}
arch_initcall(tcb_clksrc_init);
......@@ -22,6 +22,39 @@ config ATMEL_PWM
purposes including software controlled power-efficent backlights
on LCD displays, motor control, and waveform generation.
config ATMEL_TCLIB
bool "Atmel AT32/AT91 Timer/Counter Library"
depends on (AVR32 || ARCH_AT91)
help
Select this if you want a library to allocate the Timer/Counter
blocks found on many Atmel processors. This facilitates using
these blocks by different drivers despite processor differences.
config ATMEL_TCB_CLKSRC
bool "TC Block Clocksource"
depends on ATMEL_TCLIB && GENERIC_TIME
default y
help
Select this to get a high precision clocksource based on a
TC block with a 5+ MHz base clock rate. Two timer channels
are combined to make a single 32-bit timer.
When GENERIC_CLOCKEVENTS is defined, the third timer channel
may be used as a clock event device supporting oneshot mode
(delays of up to two seconds) based on the 32 KiHz clock.
config ATMEL_TCB_CLKSRC_BLOCK
int
depends on ATMEL_TCB_CLKSRC
prompt "TC Block" if ARCH_AT91RM9200 || ARCH_AT91SAM9260 || CPU_AT32AP700X
default 0
range 0 1
help
Some chips provide more than one TC block, so you have the
choice of which one to use for the clock framework. The other
TC can be used for other purposes, such as PWM generation and
interval timing.
config IBM_ASM
tristate "Device driver for IBM RSA service processor"
depends on X86 && PCI && INPUT && EXPERIMENTAL
......
......@@ -10,6 +10,7 @@ obj-$(CONFIG_ACER_WMI) += acer-wmi.o
obj-$(CONFIG_ASUS_LAPTOP) += asus-laptop.o
obj-$(CONFIG_ATMEL_PWM) += atmel_pwm.o
obj-$(CONFIG_ATMEL_SSC) += atmel-ssc.o
obj-$(CONFIG_ATMEL_TCLIB) += atmel_tclib.o
obj-$(CONFIG_TC1100_WMI) += tc1100-wmi.o
obj-$(CONFIG_LKDTM) += lkdtm.o
obj-$(CONFIG_TIFM_CORE) += tifm_core.o
......
#include <linux/atmel_tc.h>
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/ioport.h>
#include <linux/kernel.h>
#include <linux/platform_device.h>
/* Number of bytes to reserve for the iomem resource */
#define ATMEL_TC_IOMEM_SIZE 256
/*
* This is a thin library to solve the problem of how to portably allocate
* one of the TC blocks. For simplicity, it doesn't currently expect to
* share individual timers between different drivers.
*/
#if defined(CONFIG_AVR32)
/* AVR32 has these divide PBB */
const u8 atmel_tc_divisors[5] = { 0, 4, 8, 16, 32, };
EXPORT_SYMBOL(atmel_tc_divisors);
#elif defined(CONFIG_ARCH_AT91)
/* AT91 has these divide MCK */
const u8 atmel_tc_divisors[5] = { 2, 8, 32, 128, 0, };
EXPORT_SYMBOL(atmel_tc_divisors);
#endif
static DEFINE_SPINLOCK(tc_list_lock);
static LIST_HEAD(tc_list);
/**
* atmel_tc_alloc - allocate a specified TC block
* @block: which block to allocate
* @name: name to be associated with the iomem resource
*
* Caller allocates a block. If it is available, a pointer to a
* pre-initialized struct atmel_tc is returned. The caller can access
* the registers directly through the "regs" field.
*/
struct atmel_tc *atmel_tc_alloc(unsigned block, const char *name)
{
struct atmel_tc *tc;
struct platform_device *pdev = NULL;
struct resource *r;
spin_lock(&tc_list_lock);
list_for_each_entry(tc, &tc_list, node) {
if (tc->pdev->id == block) {
pdev = tc->pdev;
break;
}
}
if (!pdev || tc->iomem)
goto fail;
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
r = request_mem_region(r->start, ATMEL_TC_IOMEM_SIZE, name);
if (!r)
goto fail;
tc->regs = ioremap(r->start, ATMEL_TC_IOMEM_SIZE);
if (!tc->regs)
goto fail_ioremap;
tc->iomem = r;
out:
spin_unlock(&tc_list_lock);
return tc;
fail_ioremap:
release_resource(r);
fail:
tc = NULL;
goto out;
}
EXPORT_SYMBOL_GPL(atmel_tc_alloc);
/**
* atmel_tc_free - release a specified TC block
* @tc: Timer/counter block that was returned by atmel_tc_alloc()
*
* This reverses the effect of atmel_tc_alloc(), unmapping the I/O
* registers, invalidating the resource returned by that routine and
* making the TC available to other drivers.
*/
void atmel_tc_free(struct atmel_tc *tc)
{
spin_lock(&tc_list_lock);
if (tc->regs) {
iounmap(tc->regs);
release_resource(tc->iomem);
tc->regs = NULL;
tc->iomem = NULL;
}
spin_unlock(&tc_list_lock);
}
EXPORT_SYMBOL_GPL(atmel_tc_free);
static int __init tc_probe(struct platform_device *pdev)
{
struct atmel_tc *tc;
struct clk *clk;
int irq;
if (!platform_get_resource(pdev, IORESOURCE_MEM, 0))
return -EINVAL;
irq = platform_get_irq(pdev, 0);
if (irq < 0)
return -EINVAL;
tc = kzalloc(sizeof(struct atmel_tc), GFP_KERNEL);
if (!tc)
return -ENOMEM;
tc->pdev = pdev;
clk = clk_get(&pdev->dev, "t0_clk");
if (IS_ERR(clk)) {
kfree(tc);
return -EINVAL;
}
tc->clk[0] = clk;
tc->clk[1] = clk_get(&pdev->dev, "t1_clk");
if (IS_ERR(tc->clk[1]))
tc->clk[1] = clk;
tc->clk[2] = clk_get(&pdev->dev, "t2_clk");
if (IS_ERR(tc->clk[2]))
tc->clk[2] = clk;
tc->irq[0] = irq;
tc->irq[1] = platform_get_irq(pdev, 1);
if (tc->irq[1] < 0)
tc->irq[1] = irq;
tc->irq[2] = platform_get_irq(pdev, 2);
if (tc->irq[2] < 0)
tc->irq[2] = irq;
spin_lock(&tc_list_lock);
list_add_tail(&tc->node, &tc_list);
spin_unlock(&tc_list_lock);
return 0;
}
static struct platform_driver tc_driver = {
.driver.name = "atmel_tcb",
};
static int __init tc_init(void)
{
return platform_driver_probe(&tc_driver, tc_probe);
}
arch_initcall(tc_init);
......@@ -36,7 +36,7 @@ if PARPORT
config PARPORT_PC
tristate "PC-style hardware"
depends on (!SPARC64 || PCI) && !SPARC32 && !M32R && !FRV && \
(!M68K || ISA) && !MN10300
(!M68K || ISA) && !MN10300 && !AVR32
---help---
You should say Y here if you have a PC-style parallel port. All
IBM PC compatible computers and some Alphas have PC-style
......
......@@ -118,10 +118,10 @@ config USB_AMD5536UDC
config USB_GADGET_ATMEL_USBA
boolean "Atmel USBA"
select USB_GADGET_DUALSPEED
depends on AVR32
depends on AVR32 || ARCH_AT91CAP9
help
USBA is the integrated high-speed USB Device controller on
the AT32AP700x processors from Atmel.
the AT32AP700x and AT91CAP9 processors from Atmel.
config USB_ATMEL_USBA
tristate
......
This diff is collapsed.
......@@ -41,6 +41,15 @@
#define USBA_EN_USBA (1 << 8)
#define USBA_DETACH (1 << 9)
#define USBA_REMOTE_WAKE_UP (1 << 10)
#define USBA_PULLD_DIS (1 << 11)
#if defined(CONFIG_AVR32)
#define USBA_ENABLE_MASK USBA_EN_USBA
#define USBA_DISABLE_MASK 0
#elif defined(CONFIG_ARCH_AT91)
#define USBA_ENABLE_MASK (USBA_EN_USBA | USBA_PULLD_DIS)
#define USBA_DISABLE_MASK USBA_DETACH
#endif /* CONFIG_ARCH_AT91 */
/* Bitfields in FNUM */
#define USBA_MICRO_FRAME_NUM_OFFSET 0
......
......@@ -38,9 +38,7 @@ struct platform_device *
at32_add_device_lcdc(unsigned int id, struct atmel_lcdfb_info *data,
unsigned long fbmem_start, unsigned long fbmem_len);
struct usba_platform_data {
int vbus_pin;
};
struct usba_platform_data;
struct platform_device *
at32_add_device_usba(unsigned int id, struct usba_platform_data *data);
......@@ -68,7 +66,10 @@ struct platform_device *at32_add_device_pwm(u32 mask);
struct platform_device *
at32_add_device_ssc(unsigned int id, unsigned int flags);
struct platform_device *at32_add_device_twi(unsigned int id);
struct i2c_board_info;
struct platform_device *at32_add_device_twi(unsigned int id,
struct i2c_board_info *b,
unsigned int n);
struct platform_device *at32_add_device_mci(unsigned int id);
struct platform_device *at32_add_device_ac97c(unsigned int id);
struct platform_device *at32_add_device_abdac(unsigned int id);
......
/*
* AVR32 AP Power Management.
*
* Copyright (C) 2008 Atmel Corporation
*
* 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.
*/
#ifndef __ASM_AVR32_ARCH_PM_H
#define __ASM_AVR32_ARCH_PM_H
/* Possible arguments to the "sleep" instruction */
#define CPU_SLEEP_IDLE 0
#define CPU_SLEEP_FROZEN 1
#define CPU_SLEEP_STANDBY 2
#define CPU_SLEEP_STOP 3
#define CPU_SLEEP_STATIC 5
#ifndef __ASSEMBLY__
extern void cpu_enter_idle(void);
extern bool disable_idle_sleep;
static inline void cpu_disable_idle_sleep(void)
{
disable_idle_sleep = true;
}
static inline void cpu_enable_idle_sleep(void)
{
disable_idle_sleep = false;
}
static inline void cpu_idle_sleep(void)
{
/*
* If we're using the COUNT and COMPARE registers for
* timekeeping, we can't use the IDLE state.
*/
if (disable_idle_sleep)
cpu_relax();
else
cpu_enter_idle();
}
#endif
#endif /* __ASM_AVR32_ARCH_PM_H */
/*
* Copyright (C) 2007 Atmel Corporation
*
* 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.
*/
#ifndef _ASM_AVR32_ARCH_AT32AP_TIME_H
#define _ASM_AVR32_ARCH_AT32AP_TIME_H
#include <linux/platform_device.h>
extern struct irqaction timer_irqaction;
extern struct platform_device at32_systc0_device;
extern void local_timer_interrupt(int irq, void *dev_id);
#define TIMER_BCR 0x000000c0
#define TIMER_BCR_SYNC 0
#define TIMER_BMR 0x000000c4
#define TIMER_BMR_TC0XC0S 0
#define TIMER_BMR_TC1XC1S 2
#define TIMER_BMR_TC2XC2S 4
#define TIMER_CCR 0x00000000
#define TIMER_CCR_CLKDIS 1
#define TIMER_CCR_CLKEN 0
#define TIMER_CCR_SWTRG 2
#define TIMER_CMR 0x00000004
#define TIMER_CMR_ABETRG 10
#define TIMER_CMR_ACPA 16
#define TIMER_CMR_ACPC 18
#define TIMER_CMR_AEEVT 20
#define TIMER_CMR_ASWTRG 22
#define TIMER_CMR_BCPB 24
#define TIMER_CMR_BCPC 26
#define TIMER_CMR_BEEVT 28
#define TIMER_CMR_BSWTRG 30
#define TIMER_CMR_BURST 4
#define TIMER_CMR_CLKI 3
#define TIMER_CMR_CPCDIS 7
#define TIMER_CMR_CPCSTOP 6
#define TIMER_CMR_CPCTRG 14
#define TIMER_CMR_EEVT 10
#define TIMER_CMR_EEVTEDG 8
#define TIMER_CMR_ENETRG 12
#define TIMER_CMR_ETRGEDG 8
#define TIMER_CMR_LDBDIS 7
#define TIMER_CMR_LDBSTOP 6
#define TIMER_CMR_LDRA 16
#define TIMER_CMR_LDRB 18
#define TIMER_CMR_TCCLKS 0
#define TIMER_CMR_WAVE 15
#define TIMER_CMR_WAVSEL 13
#define TIMER_CV 0x00000010
#define TIMER_CV_CV 0
#define TIMER_IDR 0x00000028
#define TIMER_IDR_COVFS 0
#define TIMER_IDR_CPAS 2
#define TIMER_IDR_CPBS 3
#define TIMER_IDR_CPCS 4
#define TIMER_IDR_ETRGS 7
#define TIMER_IDR_LDRAS 5
#define TIMER_IDR_LDRBS 6
#define TIMER_IDR_LOVRS 1
#define TIMER_IER 0x00000024
#define TIMER_IER_COVFS 0
#define TIMER_IER_CPAS 2
#define TIMER_IER_CPBS 3
#define TIMER_IER_CPCS 4
#define TIMER_IER_ETRGS 7
#define TIMER_IER_LDRAS 5
#define TIMER_IER_LDRBS 6
#define TIMER_IER_LOVRS 1
#define TIMER_IMR 0x0000002c
#define TIMER_IMR_COVFS 0
#define TIMER_IMR_CPAS 2
#define TIMER_IMR_CPBS 3
#define TIMER_IMR_CPCS 4
#define TIMER_IMR_ETRGS 7
#define TIMER_IMR_LDRAS 5
#define TIMER_IMR_LDRBS 6
#define TIMER_IMR_LOVRS 1
#define TIMER_RA 0x00000014
#define TIMER_RA_RA 0
#define TIMER_RB 0x00000018
#define TIMER_RB_RB 0
#define TIMER_RC 0x0000001c
#define TIMER_RC_RC 0
#define TIMER_SR 0x00000020
#define TIMER_SR_CLKSTA 16
#define TIMER_SR_COVFS 0
#define TIMER_SR_CPAS 2
#define TIMER_SR_CPBS 3
#define TIMER_SR_CPCS 4
#define TIMER_SR_ETRGS 7
#define TIMER_SR_LDRAS 5
#define TIMER_SR_LDRBS 6
#define TIMER_SR_LOVRS 1
#define TIMER_SR_MTIOA 17
#define TIMER_SR_MTIOB 18
/* Bit manipulation macros */
#define TIMER_BIT(name) (1 << TIMER_##name)
#define TIMER_BF(name,value) ((value) << TIMER_##name)
/* Register access macros */
#define timer_read(port,instance,reg) \
__raw_readl(port + (0x40 * instance) + TIMER_##reg)
#define timer_write(port,instance,reg,value) \
__raw_writel((value), port + (0x40 * instance) + TIMER_##reg)
#endif /* _ASM_AVR32_ARCH_AT32AP_TIME_H */
......@@ -12,10 +12,10 @@
#include <asm/asm-offsets.h>
#include <asm/thread_info.h>
#define mask_interrupts ssrf SR_GM_BIT
#define mask_exceptions ssrf SR_EM_BIT
#define unmask_interrupts csrf SR_GM_BIT
#define unmask_exceptions csrf SR_EM_BIT
#define mask_interrupts ssrf SYSREG_GM_OFFSET
#define mask_exceptions ssrf SYSREG_EM_OFFSET
#define unmask_interrupts csrf SYSREG_GM_OFFSET
#define unmask_exceptions csrf SYSREG_EM_OFFSET
#ifdef CONFIG_FRAME_POINTER
.macro save_fp
......
#ifndef __ASM_AVR32_INTC_H
#define __ASM_AVR32_INTC_H
#include <linux/sysdev.h>
#include <linux/interrupt.h>
struct irq_controller;
struct irqaction;
struct pt_regs;
struct platform_device;
/* Information about the internal interrupt controller */
struct intc_device {
/* ioremapped address of configuration block */
void __iomem *regs;
/* the physical device */
struct platform_device *pdev;
/* Number of interrupt lines per group. */
unsigned int irqs_per_group;
/* The highest group ID + 1 */
unsigned int nr_groups;
/*
* Bitfield indicating which groups are actually in use. The
* size of the array is
* ceil(group_max / (8 * sizeof(unsigned int))).
*/
unsigned int group_mask[];
};
struct irq_controller_class {
/*
* A short name identifying this kind of controller.
*/
const char *typename;
/*
* Handle the IRQ. Must do any necessary acking and masking.
*/
irqreturn_t (*handle)(int irq, void *dev_id, struct pt_regs *regs);
/*
* Register a new IRQ handler.
*/
int (*setup)(struct irq_controller *ctrl, unsigned int irq,
struct irqaction *action);
/*
* Unregister a IRQ handler.
*/
void (*free)(struct irq_controller *ctrl, unsigned int irq,
void *dev_id);
/*
* Mask the IRQ in the interrupt controller.
*/
void (*mask)(struct irq_controller *ctrl, unsigned int irq);
/*
* Unmask the IRQ in the interrupt controller.
*/
void (*unmask)(struct irq_controller *ctrl, unsigned int irq);
/*
* Set the type of the IRQ. See below for possible types.
* Return -EINVAL if a given type is not supported
*/
int (*set_type)(struct irq_controller *ctrl, unsigned int irq,
unsigned int type);
/*
* Return the IRQ type currently set
*/
unsigned int (*get_type)(struct irq_controller *ctrl, unsigned int irq);
};
struct irq_controller {
struct irq_controller_class *class;
unsigned int irq_group;
unsigned int first_irq;
unsigned int nr_irqs;
struct list_head list;
};
struct intc_group_desc {
struct irq_controller *ctrl;
irqreturn_t (*handle)(int, void *, struct pt_regs *);
unsigned long flags;
void *dev_id;
const char *devname;
};
/*
* The internal interrupt controller. Defined in board/part-specific
* devices.c.
* TODO: Should probably be defined per-cpu.
*/
extern struct intc_device intc;
extern int request_internal_irq(unsigned int irq,
irqreturn_t (*handler)(int, void *, struct pt_regs *),
unsigned long irqflags,
const char *devname, void *dev_id);
extern void free_internal_irq(unsigned int irq);
/* Only used by time_init() */
extern int setup_internal_irq(unsigned int irq, struct intc_group_desc *desc);
/*
* Set interrupt priority for a given group. `group' can be found by
* using irq_to_group(irq). Priority can be from 0 (lowest) to 3
* (highest). Higher-priority interrupts will preempt lower-priority
* interrupts (unless interrupts are masked globally).
*
* This function does not check for conflicts within a group.
*/
extern int intc_set_priority(unsigned int group,
unsigned int priority);
/*
* Returns a bitmask of pending interrupts in a group.
*/
extern unsigned long intc_get_pending(unsigned int group);
/*
* Register a new external interrupt controller. Returns the first
* external IRQ number that is assigned to the new controller.
*/
extern int intc_register_controller(struct irq_controller *ctrl);
#endif /* __ASM_AVR32_INTC_H */
......@@ -14,6 +14,11 @@
#ifndef __ASSEMBLER__
int nmi_enable(void);
void nmi_disable(void);
/*
* Returns a bitmask of pending interrupts in a group.
*/
extern unsigned long intc_get_pending(unsigned int group);
#endif
#endif /* __ASM_AVR32_IOCTLS_H */
......@@ -8,13 +8,11 @@
#ifndef __ASM_AVR32_PAGE_H
#define __ASM_AVR32_PAGE_H
#include <linux/const.h>
/* PAGE_SHIFT determines the page size */
#define PAGE_SHIFT 12
#ifdef __ASSEMBLY__
#define PAGE_SIZE (1 << PAGE_SHIFT)
#else
#define PAGE_SIZE (1UL << PAGE_SHIFT)
#endif
#define PAGE_SIZE (_AC(1, UL) << PAGE_SHIFT)
#define PAGE_MASK (~(PAGE_SIZE-1))
#define PTE_MASK PAGE_MASK
......
#ifndef _ASM_SERIAL_H
#define _ASM_SERIAL_H
/*
* This assumes you have a 1.8432 MHz clock for your UART.
*
* It'd be nice if someone built a serial card with a 24.576 MHz
* clock, since the 16550A is capable of handling a top speed of 1.5
* megabits/second; but this requires the faster clock.
*/
#define BASE_BAUD (1843200 / 16)
#endif /* _ASM_SERIAL_H */
#ifndef _ASM_XOR_H
#define _ASM_XOR_H
#include <asm-generic/xor.h>
#endif
This diff is collapsed.
/*
* Platform data definitions for Atmel USBA gadget driver.
*/
#ifndef __LINUX_USB_USBA_H
#define __LINUX_USB_USBA_H
struct usba_ep_data {
char *name;
int index;
int fifo_size;
int nr_banks;
int can_dma;
int can_isoc;
};
struct usba_platform_data {
int vbus_pin;
int num_ep;
struct usba_ep_data ep[0];
};
#endif /* __LINUX_USB_USBA_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment