Commit 5bae7ac9 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:
  [AVR32] Initialize phy_mask for both macb devices
  [AVR32] Fix atomic_add_unless() and atomic_sub_unless()
  [AVR32] Correct misspelled CONFIG_BLK_DEV_INITRD variable.
  [AVR32] Fix build error in parse_tag_rdimg()
  [AVR32] Don't wire up macb0 unless SW6 is in default position
  [AVR32] Wire up SSC platform device 0 as TX on ATSTK1000 board
  [AVR32] Add Atmel SSC driver platform device to AT32AP architecture
  [AVR32] Remove optimization of unaligned word loads
  [AVR32] Make STK1000 mux settings configurable
  [AVR32] CPU frequency scaling for AT32AP
  [AVR32] Split SM device into PM, RTC, WDT and EIC
  [AVR32] faster avr32 unaligned access
parents 97405fe2 587ca761
...@@ -113,6 +113,10 @@ config BOARD_ATNGW100 ...@@ -113,6 +113,10 @@ config BOARD_ATNGW100
bool "ATNGW100 Network Gateway" bool "ATNGW100 Network Gateway"
endchoice endchoice
if BOARD_ATSTK1000
source "arch/avr32/boards/atstk1000/Kconfig"
endif
choice choice
prompt "Boot loader type" prompt "Boot loader type"
default LOADER_U_BOOT default LOADER_U_BOOT
...@@ -185,6 +189,27 @@ config CMDLINE ...@@ -185,6 +189,27 @@ config CMDLINE
endmenu endmenu
menu "Power managment options"
menu "CPU Frequency scaling"
source "drivers/cpufreq/Kconfig"
config CPU_FREQ_AT32AP
bool "CPU frequency driver for AT32AP"
depends on CPU_FREQ && PLATFORM_AT32AP
default n
help
This enables the CPU frequency driver for AT32AP processors.
For details, take a look in <file:Documentation/cpu-freq>.
If in doubt, say N.
endmenu
endmenu
menu "Bus options" menu "Bus options"
config PCI config PCI
......
# STK1000 customization
if BOARD_ATSTK1002
config BOARD_ATSTK1002_CUSTOM
bool "Non-default STK-1002 jumper settings"
help
You will normally leave the jumpers on the CPU card at their
default settings. If you need to use certain peripherals,
you will need to change some of those jumpers.
if BOARD_ATSTK1002_CUSTOM
config BOARD_ATSTK1002_SW1_CUSTOM
bool "SW1: use SSC1 (not SPI0)"
help
This also prevents using the external DAC as an audio interface,
and means you can't initialize the on-board QVGA display.
config BOARD_ATSTK1002_SW2_CUSTOM
bool "SW2: use IRDA or TIMER0 (not UART-A, MMC/SD, and PS2-A)"
help
If you change this you'll want an updated boot loader putting
the console on UART-C not UART-A.
config BOARD_ATSTK1002_SW3_CUSTOM
bool "SW3: use TIMER1 (not SSC0 and GCLK)"
help
This also prevents using the external DAC as an audio interface.
config BOARD_ATSTK1002_SW4_CUSTOM
bool "SW4: use ISI/Camera (not GPIOs, SPI1, and PS2-B)"
help
To use the camera interface you'll need a custom card (on the
PCI-format connector) connect a video sensor.
config BOARD_ATSTK1002_SW5_CUSTOM
bool "SW5: use MACB1 (not LCDC)"
config BOARD_ATSTK1002_SW6_CUSTOM
bool "SW6: more GPIOs (not MACB0)"
endif # custom
config BOARD_ATSTK1002_SPI1
bool "Configure SPI1 controller"
depends on !BOARD_ATSTK1002_SW4_CUSTOM
help
All the signals for the second SPI controller are available on
GPIO lines and accessed through the J1 jumper block. Say "y"
here to configure that SPI controller.
endif # stk 1002
...@@ -27,15 +27,27 @@ ...@@ -27,15 +27,27 @@
#include "atstk1000.h" #include "atstk1000.h"
#define SW2_DEFAULT /* MMCI and UART_A available */
struct eth_addr { struct eth_addr {
u8 addr[6]; u8 addr[6];
}; };
static struct eth_addr __initdata hw_addr[2]; static struct eth_addr __initdata hw_addr[2];
static struct eth_platform_data __initdata eth_data[2]; static struct eth_platform_data __initdata eth_data[2] = {
{
/*
* The MDIO pullups on STK1000 are a bit too weak for
* the autodetection to work properly, so we have to
* mask out everything but the correct address.
*/
.phy_mask = ~(1U << 16),
},
{
.phy_mask = ~(1U << 17),
},
};
#ifndef CONFIG_BOARD_ATSTK1002_SW1_CUSTOM
static struct spi_board_info spi0_board_info[] __initdata = { static struct spi_board_info spi0_board_info[] __initdata = {
{ {
/* QVGA display */ /* QVGA display */
...@@ -45,6 +57,13 @@ static struct spi_board_info spi0_board_info[] __initdata = { ...@@ -45,6 +57,13 @@ static struct spi_board_info spi0_board_info[] __initdata = {
.mode = SPI_MODE_3, .mode = SPI_MODE_3,
}, },
}; };
#endif
#ifdef CONFIG_BOARD_ATSTK1002_SPI1
static struct spi_board_info spi1_board_info[] __initdata = { {
/* patch in custom entries here */
} };
#endif
/* /*
* The next two functions should go away as the boot loader is * The next two functions should go away as the boot loader is
...@@ -103,10 +122,10 @@ static void __init set_hw_addr(struct platform_device *pdev) ...@@ -103,10 +122,10 @@ static void __init set_hw_addr(struct platform_device *pdev)
void __init setup_board(void) void __init setup_board(void)
{ {
#ifdef SW2_DEFAULT #ifdef CONFIG_BOARD_ATSTK1002_SW2_CUSTOM
at32_map_usart(1, 0); /* USART 1/A: /dev/ttyS0, DB9 */
#else
at32_map_usart(0, 1); /* USART 0/B: /dev/ttyS1, IRDA */ at32_map_usart(0, 1); /* USART 0/B: /dev/ttyS1, IRDA */
#else
at32_map_usart(1, 0); /* USART 1/A: /dev/ttyS0, DB9 */
#endif #endif
/* USART 2/unused: expansion connector */ /* USART 2/unused: expansion connector */
at32_map_usart(3, 2); /* USART 3/C: /dev/ttyS2, DB9 */ at32_map_usart(3, 2); /* USART 3/C: /dev/ttyS2, DB9 */
...@@ -140,18 +159,31 @@ static int __init atstk1002_init(void) ...@@ -140,18 +159,31 @@ static int __init atstk1002_init(void)
at32_add_system_devices(); at32_add_system_devices();
#ifdef SW2_DEFAULT #ifdef CONFIG_BOARD_ATSTK1002_SW2_CUSTOM
at32_add_device_usart(0);
#else
at32_add_device_usart(1); at32_add_device_usart(1);
#else
at32_add_device_usart(0);
#endif #endif
at32_add_device_usart(2); at32_add_device_usart(2);
#ifndef CONFIG_BOARD_ATSTK1002_SW6_CUSTOM
set_hw_addr(at32_add_device_eth(0, &eth_data[0])); set_hw_addr(at32_add_device_eth(0, &eth_data[0]));
#endif
#ifndef CONFIG_BOARD_ATSTK1002_SW1_CUSTOM
at32_add_device_spi(0, spi0_board_info, ARRAY_SIZE(spi0_board_info)); at32_add_device_spi(0, spi0_board_info, ARRAY_SIZE(spi0_board_info));
#endif
#ifdef CONFIG_BOARD_ATSTK1002_SPI1
at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info));
#endif
#ifdef CONFIG_BOARD_ATSTK1002_SW5_CUSTOM
set_hw_addr(at32_add_device_eth(1, &eth_data[1]));
#else
at32_add_device_lcdc(0, &atstk1000_lcdc_data, at32_add_device_lcdc(0, &atstk1000_lcdc_data,
fbmem_start, fbmem_size); fbmem_start, fbmem_size);
#endif
#ifndef CONFIG_BOARD_ATSTK1002_SW3_CUSTOM
at32_add_device_ssc(0, ATMEL_SSC_TX);
#endif
return 0; return 0;
} }
......
...@@ -313,7 +313,7 @@ __tagtable(ATAG_MEM, parse_tag_mem); ...@@ -313,7 +313,7 @@ __tagtable(ATAG_MEM, parse_tag_mem);
static int __init parse_tag_rdimg(struct tag *tag) static int __init parse_tag_rdimg(struct tag *tag)
{ {
#ifdef CONFIG_INITRD #ifdef CONFIG_BLK_DEV_INITRD
struct tag_mem_range *mem = &tag->u.mem_range; struct tag_mem_range *mem = &tag->u.mem_range;
int ret; int ret;
...@@ -323,7 +323,7 @@ static int __init parse_tag_rdimg(struct tag *tag) ...@@ -323,7 +323,7 @@ static int __init parse_tag_rdimg(struct tag *tag)
return 0; return 0;
} }
ret = add_reserved_region(mem->start, mem->start + mem->size - 1, ret = add_reserved_region(mem->addr, mem->addr + mem->size - 1,
"initrd"); "initrd");
if (ret) { if (ret) {
printk(KERN_WARNING printk(KERN_WARNING
......
obj-y += at32ap.o clock.o intc.o extint.o pio.o hsmc.o obj-y += at32ap.o clock.o intc.o extint.o pio.o hsmc.o
obj-$(CONFIG_CPU_AT32AP7000) += at32ap7000.o obj-$(CONFIG_CPU_AT32AP7000) += at32ap7000.o
obj-$(CONFIG_CPU_AT32AP7000) += time-tc.o obj-$(CONFIG_CPU_AT32AP7000) += time-tc.o
obj-$(CONFIG_CPU_FREQ_AT32AP) += cpufreq.o
...@@ -11,41 +11,10 @@ ...@@ -11,41 +11,10 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <asm/io.h>
#include <asm/arch/init.h> #include <asm/arch/init.h>
#include <asm/arch/sm.h>
struct at32_sm system_manager;
static int __init at32_sm_init(void)
{
struct resource *regs;
struct at32_sm *sm = &system_manager;
int ret = -ENXIO;
regs = platform_get_resource(&at32_sm_device, IORESOURCE_MEM, 0);
if (!regs)
goto fail;
spin_lock_init(&sm->lock);
sm->pdev = &at32_sm_device;
ret = -ENOMEM;
sm->regs = ioremap(regs->start, regs->end - regs->start + 1);
if (!sm->regs)
goto fail;
return 0;
fail:
printk(KERN_ERR "Failed to initialize System Manager: %d\n", ret);
return ret;
}
void __init setup_platform(void) void __init setup_platform(void)
{ {
at32_sm_init();
at32_clock_init(); at32_clock_init();
at32_portmux_init(); at32_portmux_init();
} }
......
This diff is collapsed.
/*
* 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.
*/
/*#define DEBUG*/
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/init.h>
#include <linux/cpufreq.h>
#include <linux/io.h>
#include <linux/clk.h>
#include <linux/err.h>
#include <asm/system.h>
static struct clk *cpuclk;
static int at32_verify_speed(struct cpufreq_policy *policy)
{
if (policy->cpu != 0)
return -EINVAL;
cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
policy->cpuinfo.max_freq);
return 0;
}
static unsigned int at32_get_speed(unsigned int cpu)
{
/* No SMP support */
if (cpu)
return 0;
return (unsigned int)((clk_get_rate(cpuclk) + 500) / 1000);
}
static int at32_set_target(struct cpufreq_policy *policy,
unsigned int target_freq,
unsigned int relation)
{
struct cpufreq_freqs freqs;
long freq;
/* Convert target_freq from kHz to Hz */
freq = clk_round_rate(cpuclk, target_freq * 1000);
/* Check if policy->min <= new_freq <= policy->max */
if(freq < (policy->min * 1000) || freq > (policy->max * 1000))
return -EINVAL;
pr_debug("cpufreq: requested frequency %u Hz\n", target_freq * 1000);
freqs.old = at32_get_speed(0);
freqs.new = (freq + 500) / 1000;
freqs.cpu = 0;
freqs.flags = 0;
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
clk_set_rate(cpuclk, freq);
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
pr_debug("cpufreq: set frequency %lu Hz\n", freq);
return 0;
}
static int __init at32_cpufreq_driver_init(struct cpufreq_policy *policy)
{
if (policy->cpu != 0)
return -EINVAL;
cpuclk = clk_get(NULL, "cpu");
if (IS_ERR(cpuclk)) {
pr_debug("cpufreq: could not get CPU clk\n");
return PTR_ERR(cpuclk);
}
policy->cpuinfo.min_freq = (clk_round_rate(cpuclk, 1) + 500) / 1000;
policy->cpuinfo.max_freq = (clk_round_rate(cpuclk, ~0UL) + 500) / 1000;
policy->cpuinfo.transition_latency = 0;
policy->cur = at32_get_speed(0);
policy->min = policy->cpuinfo.min_freq;
policy->max = policy->cpuinfo.max_freq;
policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
printk("cpufreq: AT32AP CPU frequency driver\n");
return 0;
}
static struct cpufreq_driver at32_driver = {
.name = "at32ap",
.owner = THIS_MODULE,
.init = at32_cpufreq_driver_init,
.verify = at32_verify_speed,
.target = at32_set_target,
.get = at32_get_speed,
.flags = CPUFREQ_STICKY,
};
static int __init at32_cpufreq_init(void)
{
return cpufreq_register_driver(&at32_driver);
}
arch_initcall(at32_cpufreq_init);
...@@ -17,42 +17,83 @@ ...@@ -17,42 +17,83 @@
#include <asm/io.h> #include <asm/io.h>
#include <asm/arch/sm.h> /* EIC register offsets */
#define EIC_IER 0x0000
#include "sm.h" #define EIC_IDR 0x0004
#define EIC_IMR 0x0008
#define EIC_ISR 0x000c
#define EIC_ICR 0x0010
#define EIC_MODE 0x0014
#define EIC_EDGE 0x0018
#define EIC_LEVEL 0x001c
#define EIC_TEST 0x0020
#define EIC_NMIC 0x0024
/* Bitfields in TEST */
#define EIC_TESTEN_OFFSET 31
#define EIC_TESTEN_SIZE 1
/* Bitfields in NMIC */
#define EIC_EN_OFFSET 0
#define EIC_EN_SIZE 1
/* Bit manipulation macros */
#define EIC_BIT(name) \
(1 << EIC_##name##_OFFSET)
#define EIC_BF(name,value) \
(((value) & ((1 << EIC_##name##_SIZE) - 1)) \
<< EIC_##name##_OFFSET)
#define EIC_BFEXT(name,value) \
(((value) >> EIC_##name##_OFFSET) \
& ((1 << EIC_##name##_SIZE) - 1))
#define EIC_BFINS(name,value,old) \
(((old) & ~(((1 << EIC_##name##_SIZE) - 1) \
<< EIC_##name##_OFFSET)) \
| EIC_BF(name,value))
/* Register access macros */
#define eic_readl(port,reg) \
__raw_readl((port)->regs + EIC_##reg)
#define eic_writel(port,reg,value) \
__raw_writel((value), (port)->regs + EIC_##reg)
struct eic {
void __iomem *regs;
struct irq_chip *chip;
unsigned int first_irq;
};
static void eim_ack_irq(unsigned int irq) static void eic_ack_irq(unsigned int irq)
{ {
struct at32_sm *sm = get_irq_chip_data(irq); struct eic *eic = get_irq_chip_data(irq);
sm_writel(sm, EIM_ICR, 1 << (irq - sm->eim_first_irq)); eic_writel(eic, ICR, 1 << (irq - eic->first_irq));
} }
static void eim_mask_irq(unsigned int irq) static void eic_mask_irq(unsigned int irq)
{ {
struct at32_sm *sm = get_irq_chip_data(irq); struct eic *eic = get_irq_chip_data(irq);
sm_writel(sm, EIM_IDR, 1 << (irq - sm->eim_first_irq)); eic_writel(eic, IDR, 1 << (irq - eic->first_irq));
} }
static void eim_mask_ack_irq(unsigned int irq) static void eic_mask_ack_irq(unsigned int irq)
{ {
struct at32_sm *sm = get_irq_chip_data(irq); struct eic *eic = get_irq_chip_data(irq);
sm_writel(sm, EIM_ICR, 1 << (irq - sm->eim_first_irq)); eic_writel(eic, ICR, 1 << (irq - eic->first_irq));
sm_writel(sm, EIM_IDR, 1 << (irq - sm->eim_first_irq)); eic_writel(eic, IDR, 1 << (irq - eic->first_irq));
} }
static void eim_unmask_irq(unsigned int irq) static void eic_unmask_irq(unsigned int irq)
{ {
struct at32_sm *sm = get_irq_chip_data(irq); struct eic *eic = get_irq_chip_data(irq);
sm_writel(sm, EIM_IER, 1 << (irq - sm->eim_first_irq)); eic_writel(eic, IER, 1 << (irq - eic->first_irq));
} }
static int eim_set_irq_type(unsigned int irq, unsigned int flow_type) static int eic_set_irq_type(unsigned int irq, unsigned int flow_type)
{ {
struct at32_sm *sm = get_irq_chip_data(irq); struct eic *eic = get_irq_chip_data(irq);
struct irq_desc *desc; struct irq_desc *desc;
unsigned int i = irq - sm->eim_first_irq; unsigned int i = irq - eic->first_irq;
u32 mode, edge, level; u32 mode, edge, level;
unsigned long flags;
int ret = 0; int ret = 0;
flow_type &= IRQ_TYPE_SENSE_MASK; flow_type &= IRQ_TYPE_SENSE_MASK;
...@@ -60,11 +101,10 @@ static int eim_set_irq_type(unsigned int irq, unsigned int flow_type) ...@@ -60,11 +101,10 @@ static int eim_set_irq_type(unsigned int irq, unsigned int flow_type)
flow_type = IRQ_TYPE_LEVEL_LOW; flow_type = IRQ_TYPE_LEVEL_LOW;
desc = &irq_desc[irq]; desc = &irq_desc[irq];
spin_lock_irqsave(&sm->lock, flags);
mode = sm_readl(sm, EIM_MODE); mode = eic_readl(eic, MODE);
edge = sm_readl(sm, EIM_EDGE); edge = eic_readl(eic, EDGE);
level = sm_readl(sm, EIM_LEVEL); level = eic_readl(eic, LEVEL);
switch (flow_type) { switch (flow_type) {
case IRQ_TYPE_LEVEL_LOW: case IRQ_TYPE_LEVEL_LOW:
...@@ -89,9 +129,9 @@ static int eim_set_irq_type(unsigned int irq, unsigned int flow_type) ...@@ -89,9 +129,9 @@ static int eim_set_irq_type(unsigned int irq, unsigned int flow_type)
} }
if (ret == 0) { if (ret == 0) {
sm_writel(sm, EIM_MODE, mode); eic_writel(eic, MODE, mode);
sm_writel(sm, EIM_EDGE, edge); eic_writel(eic, EDGE, edge);
sm_writel(sm, EIM_LEVEL, level); eic_writel(eic, LEVEL, level);
if (flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) if (flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
flow_type |= IRQ_LEVEL; flow_type |= IRQ_LEVEL;
...@@ -99,35 +139,33 @@ static int eim_set_irq_type(unsigned int irq, unsigned int flow_type) ...@@ -99,35 +139,33 @@ static int eim_set_irq_type(unsigned int irq, unsigned int flow_type)
desc->status |= flow_type; desc->status |= flow_type;
} }
spin_unlock_irqrestore(&sm->lock, flags);
return ret; return ret;
} }
struct irq_chip eim_chip = { struct irq_chip eic_chip = {
.name = "eim", .name = "eic",
.ack = eim_ack_irq, .ack = eic_ack_irq,
.mask = eim_mask_irq, .mask = eic_mask_irq,
.mask_ack = eim_mask_ack_irq, .mask_ack = eic_mask_ack_irq,
.unmask = eim_unmask_irq, .unmask = eic_unmask_irq,
.set_type = eim_set_irq_type, .set_type = eic_set_irq_type,
}; };
static void demux_eim_irq(unsigned int irq, struct irq_desc *desc) static void demux_eic_irq(unsigned int irq, struct irq_desc *desc)
{ {
struct at32_sm *sm = desc->handler_data; struct eic *eic = desc->handler_data;
struct irq_desc *ext_desc; struct irq_desc *ext_desc;
unsigned long status, pending; unsigned long status, pending;
unsigned int i, ext_irq; unsigned int i, ext_irq;
status = sm_readl(sm, EIM_ISR); status = eic_readl(eic, ISR);
pending = status & sm_readl(sm, EIM_IMR); pending = status & eic_readl(eic, IMR);
while (pending) { while (pending) {
i = fls(pending) - 1; i = fls(pending) - 1;
pending &= ~(1 << i); pending &= ~(1 << i);
ext_irq = i + sm->eim_first_irq; ext_irq = i + eic->first_irq;
ext_desc = irq_desc + ext_irq; ext_desc = irq_desc + ext_irq;
if (ext_desc->status & IRQ_LEVEL) if (ext_desc->status & IRQ_LEVEL)
handle_level_irq(ext_irq, ext_desc); handle_level_irq(ext_irq, ext_desc);
...@@ -136,51 +174,85 @@ static void demux_eim_irq(unsigned int irq, struct irq_desc *desc) ...@@ -136,51 +174,85 @@ static void demux_eim_irq(unsigned int irq, struct irq_desc *desc)
} }
} }
static int __init eim_init(void) static int __init eic_probe(struct platform_device *pdev)
{ {
struct at32_sm *sm = &system_manager; struct eic *eic;
struct resource *regs;
unsigned int i; unsigned int i;
unsigned int nr_irqs; unsigned int nr_irqs;
unsigned int int_irq; unsigned int int_irq;
int ret;
u32 pattern; u32 pattern;
/* regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
* The EIM is really the same module as SM, so register int_irq = platform_get_irq(pdev, 0);
* mapping, etc. has been taken care of already. if (!regs || !int_irq) {
*/ dev_dbg(&pdev->dev, "missing regs and/or irq resource\n");
return -ENXIO;
}
ret = -ENOMEM;
eic = kzalloc(sizeof(struct eic), GFP_KERNEL);
if (!eic) {
dev_dbg(&pdev->dev, "no memory for eic structure\n");
goto err_kzalloc;
}
eic->first_irq = EIM_IRQ_BASE + 32 * pdev->id;
eic->regs = ioremap(regs->start, regs->end - regs->start + 1);
if (!eic->regs) {
dev_dbg(&pdev->dev, "failed to map regs\n");
goto err_ioremap;
}
/* /*
* Find out how many interrupt lines that are actually * Find out how many interrupt lines that are actually
* implemented in hardware. * implemented in hardware.
*/ */
sm_writel(sm, EIM_IDR, ~0UL); eic_writel(eic, IDR, ~0UL);
sm_writel(sm, EIM_MODE, ~0UL); eic_writel(eic, MODE, ~0UL);
pattern = sm_readl(sm, EIM_MODE); pattern = eic_readl(eic, MODE);
nr_irqs = fls(pattern); nr_irqs = fls(pattern);
/* Trigger on falling edge unless overridden by driver */ /* Trigger on falling edge unless overridden by driver */
sm_writel(sm, EIM_MODE, 0UL); eic_writel(eic, MODE, 0UL);
sm_writel(sm, EIM_EDGE, 0UL); eic_writel(eic, EDGE, 0UL);
sm->eim_chip = &eim_chip; eic->chip = &eic_chip;
for (i = 0; i < nr_irqs; i++) { for (i = 0; i < nr_irqs; i++) {
/* NOTE the handler we set here is ignored by the demux */ /* NOTE the handler we set here is ignored by the demux */
set_irq_chip_and_handler(sm->eim_first_irq + i, &eim_chip, set_irq_chip_and_handler(eic->first_irq + i, &eic_chip,
handle_level_irq); handle_level_irq);
set_irq_chip_data(sm->eim_first_irq + i, sm); set_irq_chip_data(eic->first_irq + i, eic);
} }
int_irq = platform_get_irq_byname(sm->pdev, "eim"); set_irq_chained_handler(int_irq, demux_eic_irq);
set_irq_data(int_irq, eic);
set_irq_chained_handler(int_irq, demux_eim_irq);
set_irq_data(int_irq, sm);
printk("EIM: External Interrupt Module at 0x%p, IRQ %u\n", dev_info(&pdev->dev,
sm->regs, int_irq); "External Interrupt Controller at 0x%p, IRQ %u\n",
printk("EIM: Handling %u external IRQs, starting with IRQ %u\n", eic->regs, int_irq);
nr_irqs, sm->eim_first_irq); dev_info(&pdev->dev,
"Handling %u external IRQs, starting with IRQ %u\n",
nr_irqs, eic->first_irq);
return 0; return 0;
err_ioremap:
kfree(eic);
err_kzalloc:
return ret;
}
static struct platform_driver eic_driver = {
.driver = {
.name = "at32_eic",
},
};
static int __init eic_init(void)
{
return platform_driver_probe(&eic_driver, eic_probe);
} }
arch_initcall(eim_init); arch_initcall(eic_init);
/*
* Register definitions for the Power Manager (PM)
*/
#ifndef __ARCH_AVR32_MACH_AT32AP_PM_H__
#define __ARCH_AVR32_MACH_AT32AP_PM_H__
/* PM register offsets */
#define PM_MCCTRL 0x0000
#define PM_CKSEL 0x0004
#define PM_CPU_MASK 0x0008
#define PM_HSB_MASK 0x000c
#define PM_PBA_MASK 0x0010
#define PM_PBB_MASK 0x0014
#define PM_PLL0 0x0020
#define PM_PLL1 0x0024
#define PM_IER 0x0040
#define PM_IDR 0x0044
#define PM_IMR 0x0048
#define PM_ISR 0x004c
#define PM_ICR 0x0050
#define PM_GCCTRL(x) (0x0060 + 4 * (x))
#define PM_RCAUSE 0x00c0
/* Bitfields in CKSEL */
#define PM_CPUSEL_OFFSET 0
#define PM_CPUSEL_SIZE 3
#define PM_CPUDIV_OFFSET 7
#define PM_CPUDIV_SIZE 1
#define PM_HSBSEL_OFFSET 8
#define PM_HSBSEL_SIZE 3
#define PM_HSBDIV_OFFSET 15
#define PM_HSBDIV_SIZE 1
#define PM_PBASEL_OFFSET 16
#define PM_PBASEL_SIZE 3
#define PM_PBADIV_OFFSET 23
#define PM_PBADIV_SIZE 1
#define PM_PBBSEL_OFFSET 24
#define PM_PBBSEL_SIZE 3
#define PM_PBBDIV_OFFSET 31
#define PM_PBBDIV_SIZE 1
/* Bitfields in PLL0 */
#define PM_PLLEN_OFFSET 0
#define PM_PLLEN_SIZE 1
#define PM_PLLOSC_OFFSET 1
#define PM_PLLOSC_SIZE 1
#define PM_PLLOPT_OFFSET 2
#define PM_PLLOPT_SIZE 3
#define PM_PLLDIV_OFFSET 8
#define PM_PLLDIV_SIZE 8
#define PM_PLLMUL_OFFSET 16
#define PM_PLLMUL_SIZE 8
#define PM_PLLCOUNT_OFFSET 24
#define PM_PLLCOUNT_SIZE 6
#define PM_PLLTEST_OFFSET 31
#define PM_PLLTEST_SIZE 1
/* Bitfields in ICR */
#define PM_LOCK0_OFFSET 0
#define PM_LOCK0_SIZE 1
#define PM_LOCK1_OFFSET 1
#define PM_LOCK1_SIZE 1
#define PM_WAKE_OFFSET 2
#define PM_WAKE_SIZE 1
#define PM_CKRDY_OFFSET 5
#define PM_CKRDY_SIZE 1
#define PM_MSKRDY_OFFSET 6
#define PM_MSKRDY_SIZE 1
/* Bitfields in GCCTRL0 */
#define PM_OSCSEL_OFFSET 0
#define PM_OSCSEL_SIZE 1
#define PM_PLLSEL_OFFSET 1
#define PM_PLLSEL_SIZE 1
#define PM_CEN_OFFSET 2
#define PM_CEN_SIZE 1
#define PM_DIVEN_OFFSET 4
#define PM_DIVEN_SIZE 1
#define PM_DIV_OFFSET 8
#define PM_DIV_SIZE 8
/* Bitfields in RCAUSE */
#define PM_POR_OFFSET 0
#define PM_POR_SIZE 1
#define PM_EXT_OFFSET 2
#define PM_EXT_SIZE 1
#define PM_WDT_OFFSET 3
#define PM_WDT_SIZE 1
#define PM_NTAE_OFFSET 4
#define PM_NTAE_SIZE 1
/* Bit manipulation macros */
#define PM_BIT(name) \
(1 << PM_##name##_OFFSET)
#define PM_BF(name,value) \
(((value) & ((1 << PM_##name##_SIZE) - 1)) \
<< PM_##name##_OFFSET)
#define PM_BFEXT(name,value) \
(((value) >> PM_##name##_OFFSET) \
& ((1 << PM_##name##_SIZE) - 1))
#define PM_BFINS(name,value,old)\
(((old) & ~(((1 << PM_##name##_SIZE) - 1) \
<< PM_##name##_OFFSET)) \
| PM_BF(name,value))
/* Register access macros */
#define pm_readl(reg) \
__raw_readl((void __iomem *)AT32_PM_BASE + PM_##reg)
#define pm_writel(reg,value) \
__raw_writel((value), (void __iomem *)AT32_PM_BASE + PM_##reg)
#endif /* __ARCH_AVR32_MACH_AT32AP_PM_H__ */
/*
* Register definitions for SM
*
* System Manager
*/
#ifndef __ASM_AVR32_SM_H__
#define __ASM_AVR32_SM_H__
/* SM register offsets */
#define SM_PM_MCCTRL 0x0000
#define SM_PM_CKSEL 0x0004
#define SM_PM_CPU_MASK 0x0008
#define SM_PM_HSB_MASK 0x000c
#define SM_PM_PBA_MASK 0x0010
#define SM_PM_PBB_MASK 0x0014
#define SM_PM_PLL0 0x0020
#define SM_PM_PLL1 0x0024
#define SM_PM_VCTRL 0x0030
#define SM_PM_VMREF 0x0034
#define SM_PM_VMV 0x0038
#define SM_PM_IER 0x0040
#define SM_PM_IDR 0x0044
#define SM_PM_IMR 0x0048
#define SM_PM_ISR 0x004c
#define SM_PM_ICR 0x0050
#define SM_PM_GCCTRL 0x0060
#define SM_RTC_CTRL 0x0080
#define SM_RTC_VAL 0x0084
#define SM_RTC_TOP 0x0088
#define SM_RTC_IER 0x0090
#define SM_RTC_IDR 0x0094
#define SM_RTC_IMR 0x0098
#define SM_RTC_ISR 0x009c
#define SM_RTC_ICR 0x00a0
#define SM_WDT_CTRL 0x00b0
#define SM_WDT_CLR 0x00b4
#define SM_WDT_EXT 0x00b8
#define SM_RC_RCAUSE 0x00c0
#define SM_EIM_IER 0x0100
#define SM_EIM_IDR 0x0104
#define SM_EIM_IMR 0x0108
#define SM_EIM_ISR 0x010c
#define SM_EIM_ICR 0x0110
#define SM_EIM_MODE 0x0114
#define SM_EIM_EDGE 0x0118
#define SM_EIM_LEVEL 0x011c
#define SM_EIM_TEST 0x0120
#define SM_EIM_NMIC 0x0124
/* Bitfields in PM_MCCTRL */
/* Bitfields in PM_CKSEL */
#define SM_CPUSEL_OFFSET 0
#define SM_CPUSEL_SIZE 3
#define SM_CPUDIV_OFFSET 7
#define SM_CPUDIV_SIZE 1
#define SM_HSBSEL_OFFSET 8
#define SM_HSBSEL_SIZE 3
#define SM_HSBDIV_OFFSET 15
#define SM_HSBDIV_SIZE 1
#define SM_PBASEL_OFFSET 16
#define SM_PBASEL_SIZE 3
#define SM_PBADIV_OFFSET 23
#define SM_PBADIV_SIZE 1
#define SM_PBBSEL_OFFSET 24
#define SM_PBBSEL_SIZE 3
#define SM_PBBDIV_OFFSET 31
#define SM_PBBDIV_SIZE 1
/* Bitfields in PM_CPU_MASK */
/* Bitfields in PM_HSB_MASK */
/* Bitfields in PM_PBA_MASK */
/* Bitfields in PM_PBB_MASK */
/* Bitfields in PM_PLL0 */
#define SM_PLLEN_OFFSET 0
#define SM_PLLEN_SIZE 1
#define SM_PLLOSC_OFFSET 1
#define SM_PLLOSC_SIZE 1
#define SM_PLLOPT_OFFSET 2
#define SM_PLLOPT_SIZE 3
#define SM_PLLDIV_OFFSET 8
#define SM_PLLDIV_SIZE 8
#define SM_PLLMUL_OFFSET 16
#define SM_PLLMUL_SIZE 8
#define SM_PLLCOUNT_OFFSET 24
#define SM_PLLCOUNT_SIZE 6
#define SM_PLLTEST_OFFSET 31
#define SM_PLLTEST_SIZE 1
/* Bitfields in PM_PLL1 */
/* Bitfields in PM_VCTRL */
#define SM_VAUTO_OFFSET 0
#define SM_VAUTO_SIZE 1
#define SM_PM_VCTRL_VAL_OFFSET 8
#define SM_PM_VCTRL_VAL_SIZE 7
/* Bitfields in PM_VMREF */
#define SM_REFSEL_OFFSET 0
#define SM_REFSEL_SIZE 4
/* Bitfields in PM_VMV */
#define SM_PM_VMV_VAL_OFFSET 0
#define SM_PM_VMV_VAL_SIZE 8
/* Bitfields in PM_IER */
/* Bitfields in PM_IDR */
/* Bitfields in PM_IMR */
/* Bitfields in PM_ISR */
/* Bitfields in PM_ICR */
#define SM_LOCK0_OFFSET 0
#define SM_LOCK0_SIZE 1
#define SM_LOCK1_OFFSET 1
#define SM_LOCK1_SIZE 1
#define SM_WAKE_OFFSET 2
#define SM_WAKE_SIZE 1
#define SM_VOK_OFFSET 3
#define SM_VOK_SIZE 1
#define SM_VMRDY_OFFSET 4
#define SM_VMRDY_SIZE 1
#define SM_CKRDY_OFFSET 5
#define SM_CKRDY_SIZE 1
/* Bitfields in PM_GCCTRL */
#define SM_OSCSEL_OFFSET 0
#define SM_OSCSEL_SIZE 1
#define SM_PLLSEL_OFFSET 1
#define SM_PLLSEL_SIZE 1
#define SM_CEN_OFFSET 2
#define SM_CEN_SIZE 1
#define SM_CPC_OFFSET 3
#define SM_CPC_SIZE 1
#define SM_DIVEN_OFFSET 4
#define SM_DIVEN_SIZE 1
#define SM_DIV_OFFSET 8
#define SM_DIV_SIZE 8
/* Bitfields in RTC_CTRL */
#define SM_PCLR_OFFSET 1
#define SM_PCLR_SIZE 1
#define SM_TOPEN_OFFSET 2
#define SM_TOPEN_SIZE 1
#define SM_CLKEN_OFFSET 3
#define SM_CLKEN_SIZE 1
#define SM_PSEL_OFFSET 8
#define SM_PSEL_SIZE 16
/* Bitfields in RTC_VAL */
#define SM_RTC_VAL_VAL_OFFSET 0
#define SM_RTC_VAL_VAL_SIZE 31
/* Bitfields in RTC_TOP */
#define SM_RTC_TOP_VAL_OFFSET 0
#define SM_RTC_TOP_VAL_SIZE 32
/* Bitfields in RTC_IER */
/* Bitfields in RTC_IDR */
/* Bitfields in RTC_IMR */
/* Bitfields in RTC_ISR */
/* Bitfields in RTC_ICR */
#define SM_TOPI_OFFSET 0
#define SM_TOPI_SIZE 1
/* Bitfields in WDT_CTRL */
#define SM_KEY_OFFSET 24
#define SM_KEY_SIZE 8
/* Bitfields in WDT_CLR */
/* Bitfields in WDT_EXT */
/* Bitfields in RC_RCAUSE */
#define SM_POR_OFFSET 0
#define SM_POR_SIZE 1
#define SM_BOD_OFFSET 1
#define SM_BOD_SIZE 1
#define SM_EXT_OFFSET 2
#define SM_EXT_SIZE 1
#define SM_WDT_OFFSET 3
#define SM_WDT_SIZE 1
#define SM_NTAE_OFFSET 4
#define SM_NTAE_SIZE 1
#define SM_SERP_OFFSET 5
#define SM_SERP_SIZE 1
/* Bitfields in EIM_IER */
/* Bitfields in EIM_IDR */
/* Bitfields in EIM_IMR */
/* Bitfields in EIM_ISR */
/* Bitfields in EIM_ICR */
/* Bitfields in EIM_MODE */
/* Bitfields in EIM_EDGE */
#define SM_INT0_OFFSET 0
#define SM_INT0_SIZE 1
#define SM_INT1_OFFSET 1
#define SM_INT1_SIZE 1
#define SM_INT2_OFFSET 2
#define SM_INT2_SIZE 1
#define SM_INT3_OFFSET 3
#define SM_INT3_SIZE 1
/* Bitfields in EIM_LEVEL */
/* Bitfields in EIM_TEST */
#define SM_TESTEN_OFFSET 31
#define SM_TESTEN_SIZE 1
/* Bitfields in EIM_NMIC */
#define SM_EN_OFFSET 0
#define SM_EN_SIZE 1
/* Bit manipulation macros */
#define SM_BIT(name) (1 << SM_##name##_OFFSET)
#define SM_BF(name,value) (((value) & ((1 << SM_##name##_SIZE) - 1)) << SM_##name##_OFFSET)
#define SM_BFEXT(name,value) (((value) >> SM_##name##_OFFSET) & ((1 << SM_##name##_SIZE) - 1))
#define SM_BFINS(name,value,old) (((old) & ~(((1 << SM_##name##_SIZE) - 1) << SM_##name##_OFFSET)) | SM_BF(name,value))
/* Register access macros */
#define sm_readl(port,reg) \
__raw_readl((port)->regs + SM_##reg)
#define sm_writel(port,reg,value) \
__raw_writel((value), (port)->regs + SM_##reg)
#endif /* __ASM_AVR32_SM_H__ */
...@@ -36,4 +36,18 @@ struct platform_device * ...@@ -36,4 +36,18 @@ struct platform_device *
at32_add_device_lcdc(unsigned int id, struct atmel_lcdfb_info *data, at32_add_device_lcdc(unsigned int id, struct atmel_lcdfb_info *data,
unsigned long fbmem_start, unsigned long fbmem_len); unsigned long fbmem_start, unsigned long fbmem_len);
/* depending on what's hooked up, not all SSC pins will be used */
#define ATMEL_SSC_TK 0x01
#define ATMEL_SSC_TF 0x02
#define ATMEL_SSC_TD 0x04
#define ATMEL_SSC_TX (ATMEL_SSC_TK | ATMEL_SSC_TF | ATMEL_SSC_TD)
#define ATMEL_SSC_RK 0x10
#define ATMEL_SSC_RF 0x20
#define ATMEL_SSC_RD 0x40
#define ATMEL_SSC_RX (ATMEL_SSC_RK | ATMEL_SSC_RF | ATMEL_SSC_RD)
struct platform_device *
at32_add_device_ssc(unsigned int id, unsigned int flags);
#endif /* __ASM_ARCH_BOARD_H */ #endif /* __ASM_ARCH_BOARD_H */
/*
* AT32 System Manager interface.
*
* Copyright (C) 2006 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_AT32_SM_H__
#define __ASM_AVR32_AT32_SM_H__
struct irq_chip;
struct platform_device;
struct at32_sm {
spinlock_t lock;
void __iomem *regs;
struct irq_chip *eim_chip;
unsigned int eim_first_irq;
struct platform_device *pdev;
};
extern struct platform_device at32_sm_device;
extern struct at32_sm system_manager;
#endif /* __ASM_AVR32_AT32_SM_H__ */
...@@ -101,7 +101,7 @@ static inline int atomic_sub_unless(atomic_t *v, int a, int u) ...@@ -101,7 +101,7 @@ static inline int atomic_sub_unless(atomic_t *v, int a, int u)
" mov %1, 1\n" " mov %1, 1\n"
"1:" "1:"
: "=&r"(tmp), "=&r"(result), "=o"(v->counter) : "=&r"(tmp), "=&r"(result), "=o"(v->counter)
: "m"(v->counter), "rKs21"(a), "rKs21"(u) : "m"(v->counter), "rKs21"(a), "rKs21"(u), "1"(result)
: "cc", "memory"); : "cc", "memory");
return result; return result;
...@@ -137,7 +137,7 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u) ...@@ -137,7 +137,7 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u)
" mov %1, 1\n" " mov %1, 1\n"
"1:" "1:"
: "=&r"(tmp), "=&r"(result), "=o"(v->counter) : "=&r"(tmp), "=&r"(result), "=o"(v->counter)
: "m"(v->counter), "r"(a), "ir"(u) : "m"(v->counter), "r"(a), "ir"(u), "1"(result)
: "cc", "memory"); : "cc", "memory");
} }
......
...@@ -7,19 +7,10 @@ ...@@ -7,19 +7,10 @@
* words, but halfwords must be halfword-aligned, and doublewords must * words, but halfwords must be halfword-aligned, and doublewords must
* be word-aligned. * be word-aligned.
* *
* TODO: Make all this CPU-specific and optimize. * However, swapped word loads must be word-aligned so we can't
* optimize word loads in general.
*/ */
#include <linux/string.h> #include <asm-generic/unaligned.h>
/* Use memmove here, so gcc does not insert a __builtin_memcpy. */
#define get_unaligned(ptr) \
({ __typeof__(*(ptr)) __tmp; memmove(&__tmp, (ptr), sizeof(*(ptr))); __tmp; })
#define put_unaligned(val, ptr) \
({ __typeof__(*(ptr)) __tmp = (val); \
memmove((ptr), &__tmp, sizeof(*(ptr))); \
(void)0; })
#endif /* __ASM_AVR32_UNALIGNED_H */ #endif /* __ASM_AVR32_UNALIGNED_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