mirror of
https://github.com/AetherDroid/android_kernel_samsung_on5xelte.git
synced 2025-09-09 01:28:05 -04:00
Fixed MTP to work with TWRP
This commit is contained in:
commit
f6dfaef42e
50820 changed files with 20846062 additions and 0 deletions
31
arch/avr32/mach-at32ap/Kconfig
Normal file
31
arch/avr32/mach-at32ap/Kconfig
Normal file
|
@ -0,0 +1,31 @@
|
|||
if PLATFORM_AT32AP
|
||||
|
||||
menu "Atmel AVR32 AP options"
|
||||
|
||||
choice
|
||||
prompt "AT32AP700x static memory bus width"
|
||||
depends on CPU_AT32AP700X
|
||||
default AP700X_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 AP700X_32_BIT_SMC
|
||||
bool "32 bit"
|
||||
|
||||
config AP700X_16_BIT_SMC
|
||||
bool "16 bit"
|
||||
|
||||
config AP700X_8_BIT_SMC
|
||||
bool "8 bit"
|
||||
|
||||
endchoice
|
||||
|
||||
endmenu
|
||||
|
||||
endif # PLATFORM_AT32AP
|
8
arch/avr32/mach-at32ap/Makefile
Normal file
8
arch/avr32/mach-at32ap/Makefile
Normal file
|
@ -0,0 +1,8 @@
|
|||
obj-y += pdc.o clock.o intc.o extint.o pio.o hsmc.o
|
||||
obj-y += hmatrix.o
|
||||
obj-$(CONFIG_CPU_AT32AP700X) += at32ap700x.o pm-at32ap700x.o
|
||||
obj-$(CONFIG_PM) += pm.o
|
||||
|
||||
ifeq ($(CONFIG_PM_DEBUG),y)
|
||||
CFLAGS_pm.o += -DDEBUG
|
||||
endif
|
2360
arch/avr32/mach-at32ap/at32ap700x.c
Normal file
2360
arch/avr32/mach-at32ap/at32ap700x.c
Normal file
File diff suppressed because it is too large
Load diff
307
arch/avr32/mach-at32ap/clock.c
Normal file
307
arch/avr32/mach-at32ap/clock.c
Normal file
|
@ -0,0 +1,307 @@
|
|||
/*
|
||||
* Clock management for AT32AP CPUs
|
||||
*
|
||||
* Copyright (C) 2006 Atmel Corporation
|
||||
*
|
||||
* Based on arch/arm/mach-at91/clock.c
|
||||
* Copyright (C) 2005 David Brownell
|
||||
* Copyright (C) 2005 Ivan Kokshaysky
|
||||
*
|
||||
* 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/err.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/list.h>
|
||||
|
||||
#include <mach/chip.h>
|
||||
|
||||
#include "clock.h"
|
||||
|
||||
/* at32 clock list */
|
||||
static LIST_HEAD(at32_clock_list);
|
||||
|
||||
static DEFINE_SPINLOCK(clk_lock);
|
||||
static DEFINE_SPINLOCK(clk_list_lock);
|
||||
|
||||
void at32_clk_register(struct clk *clk)
|
||||
{
|
||||
spin_lock(&clk_list_lock);
|
||||
/* add the new item to the end of the list */
|
||||
list_add_tail(&clk->list, &at32_clock_list);
|
||||
spin_unlock(&clk_list_lock);
|
||||
}
|
||||
|
||||
static struct clk *__clk_get(struct device *dev, const char *id)
|
||||
{
|
||||
struct clk *clk;
|
||||
|
||||
list_for_each_entry(clk, &at32_clock_list, list) {
|
||||
if (clk->dev == dev && strcmp(id, clk->name) == 0) {
|
||||
return clk;
|
||||
}
|
||||
}
|
||||
|
||||
return ERR_PTR(-ENOENT);
|
||||
}
|
||||
|
||||
struct clk *clk_get(struct device *dev, const char *id)
|
||||
{
|
||||
struct clk *clk;
|
||||
|
||||
spin_lock(&clk_list_lock);
|
||||
clk = __clk_get(dev, id);
|
||||
spin_unlock(&clk_list_lock);
|
||||
|
||||
return clk;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(clk_get);
|
||||
|
||||
void clk_put(struct clk *clk)
|
||||
{
|
||||
/* clocks are static for now, we can't free them */
|
||||
}
|
||||
EXPORT_SYMBOL(clk_put);
|
||||
|
||||
static void __clk_enable(struct clk *clk)
|
||||
{
|
||||
if (clk->parent)
|
||||
__clk_enable(clk->parent);
|
||||
if (clk->users++ == 0 && clk->mode)
|
||||
clk->mode(clk, 1);
|
||||
}
|
||||
|
||||
int clk_enable(struct clk *clk)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&clk_lock, flags);
|
||||
__clk_enable(clk);
|
||||
spin_unlock_irqrestore(&clk_lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(clk_enable);
|
||||
|
||||
static void __clk_disable(struct clk *clk)
|
||||
{
|
||||
if (clk->users == 0) {
|
||||
printk(KERN_ERR "%s: mismatched disable\n", clk->name);
|
||||
WARN_ON(1);
|
||||
return;
|
||||
}
|
||||
|
||||
if (--clk->users == 0 && clk->mode)
|
||||
clk->mode(clk, 0);
|
||||
if (clk->parent)
|
||||
__clk_disable(clk->parent);
|
||||
}
|
||||
|
||||
void clk_disable(struct clk *clk)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&clk_lock, flags);
|
||||
__clk_disable(clk);
|
||||
spin_unlock_irqrestore(&clk_lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL(clk_disable);
|
||||
|
||||
unsigned long clk_get_rate(struct clk *clk)
|
||||
{
|
||||
unsigned long flags;
|
||||
unsigned long rate;
|
||||
|
||||
spin_lock_irqsave(&clk_lock, flags);
|
||||
rate = clk->get_rate(clk);
|
||||
spin_unlock_irqrestore(&clk_lock, flags);
|
||||
|
||||
return rate;
|
||||
}
|
||||
EXPORT_SYMBOL(clk_get_rate);
|
||||
|
||||
long clk_round_rate(struct clk *clk, unsigned long rate)
|
||||
{
|
||||
unsigned long flags, actual_rate;
|
||||
|
||||
if (!clk->set_rate)
|
||||
return -ENOSYS;
|
||||
|
||||
spin_lock_irqsave(&clk_lock, flags);
|
||||
actual_rate = clk->set_rate(clk, rate, 0);
|
||||
spin_unlock_irqrestore(&clk_lock, flags);
|
||||
|
||||
return actual_rate;
|
||||
}
|
||||
EXPORT_SYMBOL(clk_round_rate);
|
||||
|
||||
int clk_set_rate(struct clk *clk, unsigned long rate)
|
||||
{
|
||||
unsigned long flags;
|
||||
long ret;
|
||||
|
||||
if (!clk->set_rate)
|
||||
return -ENOSYS;
|
||||
|
||||
spin_lock_irqsave(&clk_lock, flags);
|
||||
ret = clk->set_rate(clk, rate, 1);
|
||||
spin_unlock_irqrestore(&clk_lock, flags);
|
||||
|
||||
return (ret < 0) ? ret : 0;
|
||||
}
|
||||
EXPORT_SYMBOL(clk_set_rate);
|
||||
|
||||
int clk_set_parent(struct clk *clk, struct clk *parent)
|
||||
{
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
if (!clk->set_parent)
|
||||
return -ENOSYS;
|
||||
|
||||
spin_lock_irqsave(&clk_lock, flags);
|
||||
ret = clk->set_parent(clk, parent);
|
||||
spin_unlock_irqrestore(&clk_lock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(clk_set_parent);
|
||||
|
||||
struct clk *clk_get_parent(struct clk *clk)
|
||||
{
|
||||
return clk->parent;
|
||||
}
|
||||
EXPORT_SYMBOL(clk_get_parent);
|
||||
|
||||
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
|
||||
/* /sys/kernel/debug/at32ap_clk */
|
||||
|
||||
#include <linux/io.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include "pm.h"
|
||||
|
||||
|
||||
#define NEST_DELTA 2
|
||||
#define NEST_MAX 6
|
||||
|
||||
struct clkinf {
|
||||
struct seq_file *s;
|
||||
unsigned nest;
|
||||
};
|
||||
|
||||
static void
|
||||
dump_clock(struct clk *parent, struct clkinf *r)
|
||||
{
|
||||
unsigned nest = r->nest;
|
||||
char buf[16 + NEST_MAX];
|
||||
struct clk *clk;
|
||||
unsigned i;
|
||||
|
||||
/* skip clocks coupled to devices that aren't registered */
|
||||
if (parent->dev && !dev_name(parent->dev) && !parent->users)
|
||||
return;
|
||||
|
||||
/* <nest spaces> name <pad to end> */
|
||||
memset(buf, ' ', sizeof(buf) - 1);
|
||||
buf[sizeof(buf) - 1] = 0;
|
||||
i = strlen(parent->name);
|
||||
memcpy(buf + nest, parent->name,
|
||||
min(i, (unsigned)(sizeof(buf) - 1 - nest)));
|
||||
|
||||
seq_printf(r->s, "%s%c users=%2d %-3s %9ld Hz",
|
||||
buf, parent->set_parent ? '*' : ' ',
|
||||
parent->users,
|
||||
parent->users ? "on" : "off", /* NOTE: not-paranoid!! */
|
||||
clk_get_rate(parent));
|
||||
if (parent->dev)
|
||||
seq_printf(r->s, ", for %s", dev_name(parent->dev));
|
||||
seq_printf(r->s, "\n");
|
||||
|
||||
/* cost of this scan is small, but not linear... */
|
||||
r->nest = nest + NEST_DELTA;
|
||||
|
||||
list_for_each_entry(clk, &at32_clock_list, list) {
|
||||
if (clk->parent == parent)
|
||||
dump_clock(clk, r);
|
||||
}
|
||||
r->nest = nest;
|
||||
}
|
||||
|
||||
static int clk_show(struct seq_file *s, void *unused)
|
||||
{
|
||||
struct clkinf r;
|
||||
int i;
|
||||
struct clk *clk;
|
||||
|
||||
/* show all the power manager registers */
|
||||
seq_printf(s, "MCCTRL = %8x\n", pm_readl(MCCTRL));
|
||||
seq_printf(s, "CKSEL = %8x\n", pm_readl(CKSEL));
|
||||
seq_printf(s, "CPUMASK = %8x\n", pm_readl(CPU_MASK));
|
||||
seq_printf(s, "HSBMASK = %8x\n", pm_readl(HSB_MASK));
|
||||
seq_printf(s, "PBAMASK = %8x\n", pm_readl(PBA_MASK));
|
||||
seq_printf(s, "PBBMASK = %8x\n", pm_readl(PBB_MASK));
|
||||
seq_printf(s, "PLL0 = %8x\n", pm_readl(PLL0));
|
||||
seq_printf(s, "PLL1 = %8x\n", pm_readl(PLL1));
|
||||
seq_printf(s, "IMR = %8x\n", pm_readl(IMR));
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (i == 5)
|
||||
continue;
|
||||
seq_printf(s, "GCCTRL%d = %8x\n", i, pm_readl(GCCTRL(i)));
|
||||
}
|
||||
|
||||
seq_printf(s, "\n");
|
||||
|
||||
r.s = s;
|
||||
r.nest = 0;
|
||||
/* protected from changes on the list while dumping */
|
||||
spin_lock(&clk_list_lock);
|
||||
|
||||
/* show clock tree as derived from the three oscillators */
|
||||
clk = __clk_get(NULL, "osc32k");
|
||||
dump_clock(clk, &r);
|
||||
clk_put(clk);
|
||||
|
||||
clk = __clk_get(NULL, "osc0");
|
||||
dump_clock(clk, &r);
|
||||
clk_put(clk);
|
||||
|
||||
clk = __clk_get(NULL, "osc1");
|
||||
dump_clock(clk, &r);
|
||||
clk_put(clk);
|
||||
|
||||
spin_unlock(&clk_list_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int clk_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, clk_show, NULL);
|
||||
}
|
||||
|
||||
static const struct file_operations clk_operations = {
|
||||
.open = clk_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
|
||||
static int __init clk_debugfs_init(void)
|
||||
{
|
||||
(void) debugfs_create_file("at32ap_clk", S_IFREG | S_IRUGO,
|
||||
NULL, NULL, &clk_operations);
|
||||
|
||||
return 0;
|
||||
}
|
||||
postcore_initcall(clk_debugfs_init);
|
||||
|
||||
#endif
|
35
arch/avr32/mach-at32ap/clock.h
Normal file
35
arch/avr32/mach-at32ap/clock.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Clock management for AT32AP CPUs
|
||||
*
|
||||
* Copyright (C) 2006 Atmel Corporation
|
||||
*
|
||||
* Based on arch/arm/mach-at91/clock.c
|
||||
* Copyright (C) 2005 David Brownell
|
||||
* Copyright (C) 2005 Ivan Kokshaysky
|
||||
*
|
||||
* 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/list.h>
|
||||
|
||||
|
||||
void at32_clk_register(struct clk *clk);
|
||||
|
||||
struct clk {
|
||||
struct list_head list; /* linking element */
|
||||
const char *name; /* Clock name/function */
|
||||
struct device *dev; /* Device the clock is used by */
|
||||
struct clk *parent; /* Parent clock, if any */
|
||||
void (*mode)(struct clk *clk, int enabled);
|
||||
unsigned long (*get_rate)(struct clk *clk);
|
||||
long (*set_rate)(struct clk *clk, unsigned long rate,
|
||||
int apply);
|
||||
int (*set_parent)(struct clk *clk, struct clk *parent);
|
||||
u16 users; /* Enabled if non-zero */
|
||||
u16 index; /* Sibling index */
|
||||
};
|
||||
|
||||
unsigned long pba_clk_get_rate(struct clk *clk);
|
||||
void pba_clk_mode(struct clk *clk, int enabled);
|
272
arch/avr32/mach-at32ap/extint.c
Normal file
272
arch/avr32/mach-at32ap/extint.c
Normal file
|
@ -0,0 +1,272 @@
|
|||
/*
|
||||
* External interrupt handling for AT32AP CPUs
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <linux/errno.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/random.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
|
||||
/* EIC register offsets */
|
||||
#define EIC_IER 0x0000
|
||||
#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_NMIC 0x0024
|
||||
|
||||
/* Bitfields in NMIC */
|
||||
#define EIC_NMIC_ENABLE (1 << 0)
|
||||
|
||||
/* 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 struct eic *nmi_eic;
|
||||
static bool nmi_enabled;
|
||||
|
||||
static void eic_ack_irq(struct irq_data *d)
|
||||
{
|
||||
struct eic *eic = irq_data_get_irq_chip_data(d);
|
||||
eic_writel(eic, ICR, 1 << (d->irq - eic->first_irq));
|
||||
}
|
||||
|
||||
static void eic_mask_irq(struct irq_data *d)
|
||||
{
|
||||
struct eic *eic = irq_data_get_irq_chip_data(d);
|
||||
eic_writel(eic, IDR, 1 << (d->irq - eic->first_irq));
|
||||
}
|
||||
|
||||
static void eic_mask_ack_irq(struct irq_data *d)
|
||||
{
|
||||
struct eic *eic = irq_data_get_irq_chip_data(d);
|
||||
eic_writel(eic, ICR, 1 << (d->irq - eic->first_irq));
|
||||
eic_writel(eic, IDR, 1 << (d->irq - eic->first_irq));
|
||||
}
|
||||
|
||||
static void eic_unmask_irq(struct irq_data *d)
|
||||
{
|
||||
struct eic *eic = irq_data_get_irq_chip_data(d);
|
||||
eic_writel(eic, IER, 1 << (d->irq - eic->first_irq));
|
||||
}
|
||||
|
||||
static int eic_set_irq_type(struct irq_data *d, unsigned int flow_type)
|
||||
{
|
||||
struct eic *eic = irq_data_get_irq_chip_data(d);
|
||||
unsigned int irq = d->irq;
|
||||
unsigned int i = irq - eic->first_irq;
|
||||
u32 mode, edge, level;
|
||||
|
||||
flow_type &= IRQ_TYPE_SENSE_MASK;
|
||||
if (flow_type == IRQ_TYPE_NONE)
|
||||
flow_type = IRQ_TYPE_LEVEL_LOW;
|
||||
|
||||
mode = eic_readl(eic, MODE);
|
||||
edge = eic_readl(eic, EDGE);
|
||||
level = eic_readl(eic, LEVEL);
|
||||
|
||||
switch (flow_type) {
|
||||
case IRQ_TYPE_LEVEL_LOW:
|
||||
mode |= 1 << i;
|
||||
level &= ~(1 << i);
|
||||
break;
|
||||
case IRQ_TYPE_LEVEL_HIGH:
|
||||
mode |= 1 << i;
|
||||
level |= 1 << i;
|
||||
break;
|
||||
case IRQ_TYPE_EDGE_RISING:
|
||||
mode &= ~(1 << i);
|
||||
edge |= 1 << i;
|
||||
break;
|
||||
case IRQ_TYPE_EDGE_FALLING:
|
||||
mode &= ~(1 << i);
|
||||
edge &= ~(1 << i);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
eic_writel(eic, MODE, mode);
|
||||
eic_writel(eic, EDGE, edge);
|
||||
eic_writel(eic, LEVEL, level);
|
||||
|
||||
irqd_set_trigger_type(d, flow_type);
|
||||
if (flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
|
||||
__irq_set_handler_locked(irq, handle_level_irq);
|
||||
else
|
||||
__irq_set_handler_locked(irq, handle_edge_irq);
|
||||
|
||||
return IRQ_SET_MASK_OK_NOCOPY;
|
||||
}
|
||||
|
||||
static struct irq_chip eic_chip = {
|
||||
.name = "eic",
|
||||
.irq_ack = eic_ack_irq,
|
||||
.irq_mask = eic_mask_irq,
|
||||
.irq_mask_ack = eic_mask_ack_irq,
|
||||
.irq_unmask = eic_unmask_irq,
|
||||
.irq_set_type = eic_set_irq_type,
|
||||
};
|
||||
|
||||
static void demux_eic_irq(unsigned int irq, struct irq_desc *desc)
|
||||
{
|
||||
struct eic *eic = irq_desc_get_handler_data(desc);
|
||||
unsigned long status, pending;
|
||||
unsigned int i;
|
||||
|
||||
status = eic_readl(eic, ISR);
|
||||
pending = status & eic_readl(eic, IMR);
|
||||
|
||||
while (pending) {
|
||||
i = fls(pending) - 1;
|
||||
pending &= ~(1 << i);
|
||||
|
||||
generic_handle_irq(i + eic->first_irq);
|
||||
}
|
||||
}
|
||||
|
||||
int nmi_enable(void)
|
||||
{
|
||||
nmi_enabled = true;
|
||||
|
||||
if (nmi_eic)
|
||||
eic_writel(nmi_eic, NMIC, EIC_NMIC_ENABLE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void nmi_disable(void)
|
||||
{
|
||||
if (nmi_eic)
|
||||
eic_writel(nmi_eic, NMIC, 0);
|
||||
|
||||
nmi_enabled = false;
|
||||
}
|
||||
|
||||
static int __init eic_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct eic *eic;
|
||||
struct resource *regs;
|
||||
unsigned int i;
|
||||
unsigned int nr_of_irqs;
|
||||
unsigned int int_irq;
|
||||
int ret;
|
||||
u32 pattern;
|
||||
|
||||
regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
int_irq = platform_get_irq(pdev, 0);
|
||||
if (!regs || (int)int_irq <= 0) {
|
||||
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, resource_size(regs));
|
||||
if (!eic->regs) {
|
||||
dev_dbg(&pdev->dev, "failed to map regs\n");
|
||||
goto err_ioremap;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find out how many interrupt lines that are actually
|
||||
* implemented in hardware.
|
||||
*/
|
||||
eic_writel(eic, IDR, ~0UL);
|
||||
eic_writel(eic, MODE, ~0UL);
|
||||
pattern = eic_readl(eic, MODE);
|
||||
nr_of_irqs = fls(pattern);
|
||||
|
||||
/* Trigger on low level unless overridden by driver */
|
||||
eic_writel(eic, EDGE, 0UL);
|
||||
eic_writel(eic, LEVEL, 0UL);
|
||||
|
||||
eic->chip = &eic_chip;
|
||||
|
||||
for (i = 0; i < nr_of_irqs; i++) {
|
||||
irq_set_chip_and_handler(eic->first_irq + i, &eic_chip,
|
||||
handle_level_irq);
|
||||
irq_set_chip_data(eic->first_irq + i, eic);
|
||||
}
|
||||
|
||||
irq_set_chained_handler(int_irq, demux_eic_irq);
|
||||
irq_set_handler_data(int_irq, eic);
|
||||
|
||||
if (pdev->id == 0) {
|
||||
nmi_eic = eic;
|
||||
if (nmi_enabled)
|
||||
/*
|
||||
* Someone tried to enable NMI before we were
|
||||
* ready. Do it now.
|
||||
*/
|
||||
nmi_enable();
|
||||
}
|
||||
|
||||
dev_info(&pdev->dev,
|
||||
"External Interrupt Controller at 0x%p, IRQ %u\n",
|
||||
eic->regs, int_irq);
|
||||
dev_info(&pdev->dev,
|
||||
"Handling %u external IRQs, starting with IRQ %u\n",
|
||||
nr_of_irqs, eic->first_irq);
|
||||
|
||||
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(eic_init);
|
88
arch/avr32/mach-at32ap/hmatrix.c
Normal file
88
arch/avr32/mach-at32ap/hmatrix.c
Normal file
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* High-Speed Bus Matrix helper functions
|
||||
*
|
||||
* 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 <linux/clk.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#include <mach/chip.h>
|
||||
#include <mach/hmatrix.h>
|
||||
|
||||
static inline void __hmatrix_write_reg(unsigned long offset, u32 value)
|
||||
{
|
||||
__raw_writel(value, (void __iomem __force *)(HMATRIX_BASE + offset));
|
||||
}
|
||||
|
||||
static inline u32 __hmatrix_read_reg(unsigned long offset)
|
||||
{
|
||||
return __raw_readl((void __iomem __force *)(HMATRIX_BASE + offset));
|
||||
}
|
||||
|
||||
/**
|
||||
* hmatrix_write_reg - write HMATRIX configuration register
|
||||
* @offset: register offset
|
||||
* @value: value to be written to the register at @offset
|
||||
*/
|
||||
void hmatrix_write_reg(unsigned long offset, u32 value)
|
||||
{
|
||||
clk_enable(&at32_hmatrix_clk);
|
||||
__hmatrix_write_reg(offset, value);
|
||||
__hmatrix_read_reg(offset);
|
||||
clk_disable(&at32_hmatrix_clk);
|
||||
}
|
||||
|
||||
/**
|
||||
* hmatrix_read_reg - read HMATRIX configuration register
|
||||
* @offset: register offset
|
||||
*
|
||||
* Returns the value of the register at @offset.
|
||||
*/
|
||||
u32 hmatrix_read_reg(unsigned long offset)
|
||||
{
|
||||
u32 value;
|
||||
|
||||
clk_enable(&at32_hmatrix_clk);
|
||||
value = __hmatrix_read_reg(offset);
|
||||
clk_disable(&at32_hmatrix_clk);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* hmatrix_sfr_set_bits - set bits in a slave's Special Function Register
|
||||
* @slave_id: operate on the SFR belonging to this slave
|
||||
* @mask: mask of bits to be set in the SFR
|
||||
*/
|
||||
void hmatrix_sfr_set_bits(unsigned int slave_id, u32 mask)
|
||||
{
|
||||
u32 value;
|
||||
|
||||
clk_enable(&at32_hmatrix_clk);
|
||||
value = __hmatrix_read_reg(HMATRIX_SFR(slave_id));
|
||||
value |= mask;
|
||||
__hmatrix_write_reg(HMATRIX_SFR(slave_id), value);
|
||||
__hmatrix_read_reg(HMATRIX_SFR(slave_id));
|
||||
clk_disable(&at32_hmatrix_clk);
|
||||
}
|
||||
|
||||
/**
|
||||
* hmatrix_sfr_set_bits - clear bits in a slave's Special Function Register
|
||||
* @slave_id: operate on the SFR belonging to this slave
|
||||
* @mask: mask of bits to be cleared in the SFR
|
||||
*/
|
||||
void hmatrix_sfr_clear_bits(unsigned int slave_id, u32 mask)
|
||||
{
|
||||
u32 value;
|
||||
|
||||
clk_enable(&at32_hmatrix_clk);
|
||||
value = __hmatrix_read_reg(HMATRIX_SFR(slave_id));
|
||||
value &= ~mask;
|
||||
__hmatrix_write_reg(HMATRIX_SFR(slave_id), value);
|
||||
__hmatrix_read_reg(HMATRIX_SFR(slave_id));
|
||||
clk_disable(&at32_hmatrix_clk);
|
||||
}
|
282
arch/avr32/mach-at32ap/hsmc.c
Normal file
282
arch/avr32/mach-at32ap/hsmc.c
Normal file
|
@ -0,0 +1,282 @@
|
|||
/*
|
||||
* Static Memory Controller for AT32 chips
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#include <linux/clk.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <mach/smc.h>
|
||||
|
||||
#include "hsmc.h"
|
||||
|
||||
#define NR_CHIP_SELECTS 6
|
||||
|
||||
struct hsmc {
|
||||
void __iomem *regs;
|
||||
struct clk *pclk;
|
||||
struct clk *mck;
|
||||
};
|
||||
|
||||
static struct hsmc *hsmc;
|
||||
|
||||
void smc_set_timing(struct smc_config *config,
|
||||
const struct smc_timing *timing)
|
||||
{
|
||||
int recover;
|
||||
int cycle;
|
||||
|
||||
unsigned long mul;
|
||||
|
||||
/* Reset all SMC timings */
|
||||
config->ncs_read_setup = 0;
|
||||
config->nrd_setup = 0;
|
||||
config->ncs_write_setup = 0;
|
||||
config->nwe_setup = 0;
|
||||
config->ncs_read_pulse = 0;
|
||||
config->nrd_pulse = 0;
|
||||
config->ncs_write_pulse = 0;
|
||||
config->nwe_pulse = 0;
|
||||
config->read_cycle = 0;
|
||||
config->write_cycle = 0;
|
||||
|
||||
/*
|
||||
* cycles = x / T = x * f
|
||||
* = ((x * 1000000000) * ((f * 65536) / 1000000000)) / 65536
|
||||
* = ((x * 1000000000) * (((f / 10000) * 65536) / 100000)) / 65536
|
||||
*/
|
||||
mul = (clk_get_rate(hsmc->mck) / 10000) << 16;
|
||||
mul /= 100000;
|
||||
|
||||
#define ns2cyc(x) ((((x) * mul) + 65535) >> 16)
|
||||
|
||||
if (timing->ncs_read_setup > 0)
|
||||
config->ncs_read_setup = ns2cyc(timing->ncs_read_setup);
|
||||
|
||||
if (timing->nrd_setup > 0)
|
||||
config->nrd_setup = ns2cyc(timing->nrd_setup);
|
||||
|
||||
if (timing->ncs_write_setup > 0)
|
||||
config->ncs_write_setup = ns2cyc(timing->ncs_write_setup);
|
||||
|
||||
if (timing->nwe_setup > 0)
|
||||
config->nwe_setup = ns2cyc(timing->nwe_setup);
|
||||
|
||||
if (timing->ncs_read_pulse > 0)
|
||||
config->ncs_read_pulse = ns2cyc(timing->ncs_read_pulse);
|
||||
|
||||
if (timing->nrd_pulse > 0)
|
||||
config->nrd_pulse = ns2cyc(timing->nrd_pulse);
|
||||
|
||||
if (timing->ncs_write_pulse > 0)
|
||||
config->ncs_write_pulse = ns2cyc(timing->ncs_write_pulse);
|
||||
|
||||
if (timing->nwe_pulse > 0)
|
||||
config->nwe_pulse = ns2cyc(timing->nwe_pulse);
|
||||
|
||||
if (timing->read_cycle > 0)
|
||||
config->read_cycle = ns2cyc(timing->read_cycle);
|
||||
|
||||
if (timing->write_cycle > 0)
|
||||
config->write_cycle = ns2cyc(timing->write_cycle);
|
||||
|
||||
/* Extend read cycle in needed */
|
||||
if (timing->ncs_read_recover > 0)
|
||||
recover = ns2cyc(timing->ncs_read_recover);
|
||||
else
|
||||
recover = 1;
|
||||
|
||||
cycle = config->ncs_read_setup + config->ncs_read_pulse + recover;
|
||||
|
||||
if (config->read_cycle < cycle)
|
||||
config->read_cycle = cycle;
|
||||
|
||||
/* Extend read cycle in needed */
|
||||
if (timing->nrd_recover > 0)
|
||||
recover = ns2cyc(timing->nrd_recover);
|
||||
else
|
||||
recover = 1;
|
||||
|
||||
cycle = config->nrd_setup + config->nrd_pulse + recover;
|
||||
|
||||
if (config->read_cycle < cycle)
|
||||
config->read_cycle = cycle;
|
||||
|
||||
/* Extend write cycle in needed */
|
||||
if (timing->ncs_write_recover > 0)
|
||||
recover = ns2cyc(timing->ncs_write_recover);
|
||||
else
|
||||
recover = 1;
|
||||
|
||||
cycle = config->ncs_write_setup + config->ncs_write_pulse + recover;
|
||||
|
||||
if (config->write_cycle < cycle)
|
||||
config->write_cycle = cycle;
|
||||
|
||||
/* Extend write cycle in needed */
|
||||
if (timing->nwe_recover > 0)
|
||||
recover = ns2cyc(timing->nwe_recover);
|
||||
else
|
||||
recover = 1;
|
||||
|
||||
cycle = config->nwe_setup + config->nwe_pulse + recover;
|
||||
|
||||
if (config->write_cycle < cycle)
|
||||
config->write_cycle = cycle;
|
||||
}
|
||||
EXPORT_SYMBOL(smc_set_timing);
|
||||
|
||||
int smc_set_configuration(int cs, const struct smc_config *config)
|
||||
{
|
||||
unsigned long offset;
|
||||
u32 setup, pulse, cycle, mode;
|
||||
|
||||
if (!hsmc)
|
||||
return -ENODEV;
|
||||
if (cs >= NR_CHIP_SELECTS)
|
||||
return -EINVAL;
|
||||
|
||||
setup = (HSMC_BF(NWE_SETUP, config->nwe_setup)
|
||||
| HSMC_BF(NCS_WR_SETUP, config->ncs_write_setup)
|
||||
| HSMC_BF(NRD_SETUP, config->nrd_setup)
|
||||
| HSMC_BF(NCS_RD_SETUP, config->ncs_read_setup));
|
||||
pulse = (HSMC_BF(NWE_PULSE, config->nwe_pulse)
|
||||
| HSMC_BF(NCS_WR_PULSE, config->ncs_write_pulse)
|
||||
| HSMC_BF(NRD_PULSE, config->nrd_pulse)
|
||||
| HSMC_BF(NCS_RD_PULSE, config->ncs_read_pulse));
|
||||
cycle = (HSMC_BF(NWE_CYCLE, config->write_cycle)
|
||||
| HSMC_BF(NRD_CYCLE, config->read_cycle));
|
||||
|
||||
switch (config->bus_width) {
|
||||
case 1:
|
||||
mode = HSMC_BF(DBW, HSMC_DBW_8_BITS);
|
||||
break;
|
||||
case 2:
|
||||
mode = HSMC_BF(DBW, HSMC_DBW_16_BITS);
|
||||
break;
|
||||
case 4:
|
||||
mode = HSMC_BF(DBW, HSMC_DBW_32_BITS);
|
||||
break;
|
||||
default:
|
||||
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);
|
||||
|
||||
offset = cs * 0x10;
|
||||
hsmc_writel(hsmc, SETUP0 + offset, setup);
|
||||
hsmc_writel(hsmc, PULSE0 + offset, pulse);
|
||||
hsmc_writel(hsmc, CYCLE0 + offset, cycle);
|
||||
hsmc_writel(hsmc, MODE0 + offset, mode);
|
||||
hsmc_readl(hsmc, MODE0); /* I/O barrier */
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(smc_set_configuration);
|
||||
|
||||
static int hsmc_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct resource *regs;
|
||||
struct clk *pclk, *mck;
|
||||
int ret;
|
||||
|
||||
if (hsmc)
|
||||
return -EBUSY;
|
||||
|
||||
regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!regs)
|
||||
return -ENXIO;
|
||||
pclk = clk_get(&pdev->dev, "pclk");
|
||||
if (IS_ERR(pclk))
|
||||
return PTR_ERR(pclk);
|
||||
mck = clk_get(&pdev->dev, "mck");
|
||||
if (IS_ERR(mck)) {
|
||||
ret = PTR_ERR(mck);
|
||||
goto out_put_pclk;
|
||||
}
|
||||
|
||||
ret = -ENOMEM;
|
||||
hsmc = kzalloc(sizeof(struct hsmc), GFP_KERNEL);
|
||||
if (!hsmc)
|
||||
goto out_put_clocks;
|
||||
|
||||
clk_enable(pclk);
|
||||
clk_enable(mck);
|
||||
|
||||
hsmc->pclk = pclk;
|
||||
hsmc->mck = mck;
|
||||
hsmc->regs = ioremap(regs->start, resource_size(regs));
|
||||
if (!hsmc->regs)
|
||||
goto out_disable_clocks;
|
||||
|
||||
dev_info(&pdev->dev, "Atmel Static Memory Controller at 0x%08lx\n",
|
||||
(unsigned long)regs->start);
|
||||
|
||||
platform_set_drvdata(pdev, hsmc);
|
||||
|
||||
return 0;
|
||||
|
||||
out_disable_clocks:
|
||||
clk_disable(mck);
|
||||
clk_disable(pclk);
|
||||
kfree(hsmc);
|
||||
out_put_clocks:
|
||||
clk_put(mck);
|
||||
out_put_pclk:
|
||||
clk_put(pclk);
|
||||
hsmc = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct platform_driver hsmc_driver = {
|
||||
.probe = hsmc_probe,
|
||||
.driver = {
|
||||
.name = "smc",
|
||||
},
|
||||
};
|
||||
|
||||
static int __init hsmc_init(void)
|
||||
{
|
||||
return platform_driver_register(&hsmc_driver);
|
||||
}
|
||||
core_initcall(hsmc_init);
|
127
arch/avr32/mach-at32ap/hsmc.h
Normal file
127
arch/avr32/mach-at32ap/hsmc.h
Normal file
|
@ -0,0 +1,127 @@
|
|||
/*
|
||||
* Register definitions for Atmel Static Memory Controller (SMC)
|
||||
*
|
||||
* 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_HSMC_H__
|
||||
#define __ASM_AVR32_HSMC_H__
|
||||
|
||||
/* HSMC register offsets */
|
||||
#define HSMC_SETUP0 0x0000
|
||||
#define HSMC_PULSE0 0x0004
|
||||
#define HSMC_CYCLE0 0x0008
|
||||
#define HSMC_MODE0 0x000c
|
||||
#define HSMC_SETUP1 0x0010
|
||||
#define HSMC_PULSE1 0x0014
|
||||
#define HSMC_CYCLE1 0x0018
|
||||
#define HSMC_MODE1 0x001c
|
||||
#define HSMC_SETUP2 0x0020
|
||||
#define HSMC_PULSE2 0x0024
|
||||
#define HSMC_CYCLE2 0x0028
|
||||
#define HSMC_MODE2 0x002c
|
||||
#define HSMC_SETUP3 0x0030
|
||||
#define HSMC_PULSE3 0x0034
|
||||
#define HSMC_CYCLE3 0x0038
|
||||
#define HSMC_MODE3 0x003c
|
||||
#define HSMC_SETUP4 0x0040
|
||||
#define HSMC_PULSE4 0x0044
|
||||
#define HSMC_CYCLE4 0x0048
|
||||
#define HSMC_MODE4 0x004c
|
||||
#define HSMC_SETUP5 0x0050
|
||||
#define HSMC_PULSE5 0x0054
|
||||
#define HSMC_CYCLE5 0x0058
|
||||
#define HSMC_MODE5 0x005c
|
||||
|
||||
/* Bitfields in SETUP0 */
|
||||
#define HSMC_NWE_SETUP_OFFSET 0
|
||||
#define HSMC_NWE_SETUP_SIZE 6
|
||||
#define HSMC_NCS_WR_SETUP_OFFSET 8
|
||||
#define HSMC_NCS_WR_SETUP_SIZE 6
|
||||
#define HSMC_NRD_SETUP_OFFSET 16
|
||||
#define HSMC_NRD_SETUP_SIZE 6
|
||||
#define HSMC_NCS_RD_SETUP_OFFSET 24
|
||||
#define HSMC_NCS_RD_SETUP_SIZE 6
|
||||
|
||||
/* Bitfields in PULSE0 */
|
||||
#define HSMC_NWE_PULSE_OFFSET 0
|
||||
#define HSMC_NWE_PULSE_SIZE 7
|
||||
#define HSMC_NCS_WR_PULSE_OFFSET 8
|
||||
#define HSMC_NCS_WR_PULSE_SIZE 7
|
||||
#define HSMC_NRD_PULSE_OFFSET 16
|
||||
#define HSMC_NRD_PULSE_SIZE 7
|
||||
#define HSMC_NCS_RD_PULSE_OFFSET 24
|
||||
#define HSMC_NCS_RD_PULSE_SIZE 7
|
||||
|
||||
/* Bitfields in CYCLE0 */
|
||||
#define HSMC_NWE_CYCLE_OFFSET 0
|
||||
#define HSMC_NWE_CYCLE_SIZE 9
|
||||
#define HSMC_NRD_CYCLE_OFFSET 16
|
||||
#define HSMC_NRD_CYCLE_SIZE 9
|
||||
|
||||
/* Bitfields in MODE0 */
|
||||
#define HSMC_READ_MODE_OFFSET 0
|
||||
#define HSMC_READ_MODE_SIZE 1
|
||||
#define HSMC_WRITE_MODE_OFFSET 1
|
||||
#define HSMC_WRITE_MODE_SIZE 1
|
||||
#define HSMC_EXNW_MODE_OFFSET 4
|
||||
#define HSMC_EXNW_MODE_SIZE 2
|
||||
#define HSMC_BAT_OFFSET 8
|
||||
#define HSMC_BAT_SIZE 1
|
||||
#define HSMC_DBW_OFFSET 12
|
||||
#define HSMC_DBW_SIZE 2
|
||||
#define HSMC_TDF_CYCLES_OFFSET 16
|
||||
#define HSMC_TDF_CYCLES_SIZE 4
|
||||
#define HSMC_TDF_MODE_OFFSET 20
|
||||
#define HSMC_TDF_MODE_SIZE 1
|
||||
#define HSMC_PMEN_OFFSET 24
|
||||
#define HSMC_PMEN_SIZE 1
|
||||
#define HSMC_PS_OFFSET 28
|
||||
#define HSMC_PS_SIZE 2
|
||||
|
||||
/* Constants for READ_MODE */
|
||||
#define HSMC_READ_MODE_NCS_CONTROLLED 0
|
||||
#define HSMC_READ_MODE_NRD_CONTROLLED 1
|
||||
|
||||
/* Constants for WRITE_MODE */
|
||||
#define HSMC_WRITE_MODE_NCS_CONTROLLED 0
|
||||
#define HSMC_WRITE_MODE_NWE_CONTROLLED 1
|
||||
|
||||
/* Constants for EXNW_MODE */
|
||||
#define HSMC_EXNW_MODE_DISABLED 0
|
||||
#define HSMC_EXNW_MODE_RESERVED 1
|
||||
#define HSMC_EXNW_MODE_FROZEN 2
|
||||
#define HSMC_EXNW_MODE_READY 3
|
||||
|
||||
/* Constants for BAT */
|
||||
#define HSMC_BAT_BYTE_SELECT 0
|
||||
#define HSMC_BAT_BYTE_WRITE 1
|
||||
|
||||
/* Constants for DBW */
|
||||
#define HSMC_DBW_8_BITS 0
|
||||
#define HSMC_DBW_16_BITS 1
|
||||
#define HSMC_DBW_32_BITS 2
|
||||
|
||||
/* Bit manipulation macros */
|
||||
#define HSMC_BIT(name) \
|
||||
(1 << HSMC_##name##_OFFSET)
|
||||
#define HSMC_BF(name,value) \
|
||||
(((value) & ((1 << HSMC_##name##_SIZE) - 1)) \
|
||||
<< HSMC_##name##_OFFSET)
|
||||
#define HSMC_BFEXT(name,value) \
|
||||
(((value) >> HSMC_##name##_OFFSET) \
|
||||
& ((1 << HSMC_##name##_SIZE) - 1))
|
||||
#define HSMC_BFINS(name,value,old) \
|
||||
(((old) & ~(((1 << HSMC_##name##_SIZE) - 1) \
|
||||
<< HSMC_##name##_OFFSET)) | HSMC_BF(name,value))
|
||||
|
||||
/* Register access macros */
|
||||
#define hsmc_readl(port,reg) \
|
||||
__raw_readl((port)->regs + HSMC_##reg)
|
||||
#define hsmc_writel(port,reg,value) \
|
||||
__raw_writel((value), (port)->regs + HSMC_##reg)
|
||||
|
||||
#endif /* __ASM_AVR32_HSMC_H__ */
|
245
arch/avr32/mach-at32ap/include/mach/at32ap700x.h
Normal file
245
arch/avr32/mach-at32ap/include/mach/at32ap700x.h
Normal file
|
@ -0,0 +1,245 @@
|
|||
/*
|
||||
* Pin definitions for AT32AP7000.
|
||||
*
|
||||
* 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_ARCH_AT32AP700X_H__
|
||||
#define __ASM_ARCH_AT32AP700X_H__
|
||||
|
||||
#define GPIO_PERIPH_A 0
|
||||
#define GPIO_PERIPH_B 1
|
||||
|
||||
/*
|
||||
* Pin numbers identifying specific GPIO pins on the chip. They can
|
||||
* also be converted to IRQ numbers by passing them through
|
||||
* gpio_to_irq().
|
||||
*/
|
||||
#define GPIO_PIOA_BASE (0)
|
||||
#define GPIO_PIOB_BASE (GPIO_PIOA_BASE + 32)
|
||||
#define GPIO_PIOC_BASE (GPIO_PIOB_BASE + 32)
|
||||
#define GPIO_PIOD_BASE (GPIO_PIOC_BASE + 32)
|
||||
#define GPIO_PIOE_BASE (GPIO_PIOD_BASE + 32)
|
||||
|
||||
#define GPIO_PIN_PA(N) (GPIO_PIOA_BASE + (N))
|
||||
#define GPIO_PIN_PB(N) (GPIO_PIOB_BASE + (N))
|
||||
#define GPIO_PIN_PC(N) (GPIO_PIOC_BASE + (N))
|
||||
#define GPIO_PIN_PD(N) (GPIO_PIOD_BASE + (N))
|
||||
#define GPIO_PIN_PE(N) (GPIO_PIOE_BASE + (N))
|
||||
|
||||
|
||||
/*
|
||||
* DMAC peripheral hardware handshaking interfaces, used with dw_dmac
|
||||
*/
|
||||
#define DMAC_MCI_RX 0
|
||||
#define DMAC_MCI_TX 1
|
||||
#define DMAC_DAC_TX 2
|
||||
#define DMAC_AC97_A_RX 3
|
||||
#define DMAC_AC97_A_TX 4
|
||||
#define DMAC_AC97_B_RX 5
|
||||
#define DMAC_AC97_B_TX 6
|
||||
#define DMAC_DMAREQ_0 7
|
||||
#define DMAC_DMAREQ_1 8
|
||||
#define DMAC_DMAREQ_2 9
|
||||
#define DMAC_DMAREQ_3 10
|
||||
|
||||
/* HSB master IDs */
|
||||
#define HMATRIX_MASTER_CPU_DCACHE 0
|
||||
#define HMATRIX_MASTER_CPU_ICACHE 1
|
||||
#define HMATRIX_MASTER_PDC 2
|
||||
#define HMATRIX_MASTER_ISI 3
|
||||
#define HMATRIX_MASTER_USBA 4
|
||||
#define HMATRIX_MASTER_LCDC 5
|
||||
#define HMATRIX_MASTER_MACB0 6
|
||||
#define HMATRIX_MASTER_MACB1 7
|
||||
#define HMATRIX_MASTER_DMACA_M0 8
|
||||
#define HMATRIX_MASTER_DMACA_M1 9
|
||||
|
||||
/* HSB slave IDs */
|
||||
#define HMATRIX_SLAVE_SRAM0 0
|
||||
#define HMATRIX_SLAVE_SRAM1 1
|
||||
#define HMATRIX_SLAVE_PBA 2
|
||||
#define HMATRIX_SLAVE_PBB 3
|
||||
#define HMATRIX_SLAVE_EBI 4
|
||||
#define HMATRIX_SLAVE_USBA 5
|
||||
#define HMATRIX_SLAVE_LCDC 6
|
||||
#define HMATRIX_SLAVE_DMACA 7
|
||||
|
||||
/* Bits in HMATRIX SFR4 (EBI) */
|
||||
#define HMATRIX_EBI_SDRAM_ENABLE (1 << 1)
|
||||
#define HMATRIX_EBI_NAND_ENABLE (1 << 3)
|
||||
#define HMATRIX_EBI_CF0_ENABLE (1 << 4)
|
||||
#define HMATRIX_EBI_CF1_ENABLE (1 << 5)
|
||||
#define HMATRIX_EBI_PULLUP_DISABLE (1 << 8)
|
||||
|
||||
/*
|
||||
* Base addresses of controllers that may be accessed early by
|
||||
* platform code.
|
||||
*/
|
||||
#define PM_BASE 0xfff00000
|
||||
#define HMATRIX_BASE 0xfff00800
|
||||
#define SDRAMC_BASE 0xfff03800
|
||||
|
||||
/* LCDC on port C */
|
||||
#define ATMEL_LCDC_PC_CC (1ULL << 19)
|
||||
#define ATMEL_LCDC_PC_HSYNC (1ULL << 20)
|
||||
#define ATMEL_LCDC_PC_PCLK (1ULL << 21)
|
||||
#define ATMEL_LCDC_PC_VSYNC (1ULL << 22)
|
||||
#define ATMEL_LCDC_PC_DVAL (1ULL << 23)
|
||||
#define ATMEL_LCDC_PC_MODE (1ULL << 24)
|
||||
#define ATMEL_LCDC_PC_PWR (1ULL << 25)
|
||||
#define ATMEL_LCDC_PC_DATA0 (1ULL << 26)
|
||||
#define ATMEL_LCDC_PC_DATA1 (1ULL << 27)
|
||||
#define ATMEL_LCDC_PC_DATA2 (1ULL << 28)
|
||||
#define ATMEL_LCDC_PC_DATA3 (1ULL << 29)
|
||||
#define ATMEL_LCDC_PC_DATA4 (1ULL << 30)
|
||||
#define ATMEL_LCDC_PC_DATA5 (1ULL << 31)
|
||||
|
||||
/* LCDC on port D */
|
||||
#define ATMEL_LCDC_PD_DATA6 (1ULL << 0)
|
||||
#define ATMEL_LCDC_PD_DATA7 (1ULL << 1)
|
||||
#define ATMEL_LCDC_PD_DATA8 (1ULL << 2)
|
||||
#define ATMEL_LCDC_PD_DATA9 (1ULL << 3)
|
||||
#define ATMEL_LCDC_PD_DATA10 (1ULL << 4)
|
||||
#define ATMEL_LCDC_PD_DATA11 (1ULL << 5)
|
||||
#define ATMEL_LCDC_PD_DATA12 (1ULL << 6)
|
||||
#define ATMEL_LCDC_PD_DATA13 (1ULL << 7)
|
||||
#define ATMEL_LCDC_PD_DATA14 (1ULL << 8)
|
||||
#define ATMEL_LCDC_PD_DATA15 (1ULL << 9)
|
||||
#define ATMEL_LCDC_PD_DATA16 (1ULL << 10)
|
||||
#define ATMEL_LCDC_PD_DATA17 (1ULL << 11)
|
||||
#define ATMEL_LCDC_PD_DATA18 (1ULL << 12)
|
||||
#define ATMEL_LCDC_PD_DATA19 (1ULL << 13)
|
||||
#define ATMEL_LCDC_PD_DATA20 (1ULL << 14)
|
||||
#define ATMEL_LCDC_PD_DATA21 (1ULL << 15)
|
||||
#define ATMEL_LCDC_PD_DATA22 (1ULL << 16)
|
||||
#define ATMEL_LCDC_PD_DATA23 (1ULL << 17)
|
||||
|
||||
/* LCDC on port E */
|
||||
#define ATMEL_LCDC_PE_CC (1ULL << (32 + 0))
|
||||
#define ATMEL_LCDC_PE_DVAL (1ULL << (32 + 1))
|
||||
#define ATMEL_LCDC_PE_MODE (1ULL << (32 + 2))
|
||||
#define ATMEL_LCDC_PE_DATA0 (1ULL << (32 + 3))
|
||||
#define ATMEL_LCDC_PE_DATA1 (1ULL << (32 + 4))
|
||||
#define ATMEL_LCDC_PE_DATA2 (1ULL << (32 + 5))
|
||||
#define ATMEL_LCDC_PE_DATA3 (1ULL << (32 + 6))
|
||||
#define ATMEL_LCDC_PE_DATA4 (1ULL << (32 + 7))
|
||||
#define ATMEL_LCDC_PE_DATA8 (1ULL << (32 + 8))
|
||||
#define ATMEL_LCDC_PE_DATA9 (1ULL << (32 + 9))
|
||||
#define ATMEL_LCDC_PE_DATA10 (1ULL << (32 + 10))
|
||||
#define ATMEL_LCDC_PE_DATA11 (1ULL << (32 + 11))
|
||||
#define ATMEL_LCDC_PE_DATA12 (1ULL << (32 + 12))
|
||||
#define ATMEL_LCDC_PE_DATA16 (1ULL << (32 + 13))
|
||||
#define ATMEL_LCDC_PE_DATA17 (1ULL << (32 + 14))
|
||||
#define ATMEL_LCDC_PE_DATA18 (1ULL << (32 + 15))
|
||||
#define ATMEL_LCDC_PE_DATA19 (1ULL << (32 + 16))
|
||||
#define ATMEL_LCDC_PE_DATA20 (1ULL << (32 + 17))
|
||||
#define ATMEL_LCDC_PE_DATA21 (1ULL << (32 + 18))
|
||||
|
||||
|
||||
#define ATMEL_LCDC(PORT, PIN) (ATMEL_LCDC_##PORT##_##PIN)
|
||||
|
||||
|
||||
#define ATMEL_LCDC_PRI_24B_DATA ( \
|
||||
ATMEL_LCDC(PC, DATA0) | ATMEL_LCDC(PC, DATA1) | \
|
||||
ATMEL_LCDC(PC, DATA2) | ATMEL_LCDC(PC, DATA3) | \
|
||||
ATMEL_LCDC(PC, DATA4) | ATMEL_LCDC(PC, DATA5) | \
|
||||
ATMEL_LCDC(PD, DATA6) | ATMEL_LCDC(PD, DATA7) | \
|
||||
ATMEL_LCDC(PD, DATA8) | ATMEL_LCDC(PD, DATA9) | \
|
||||
ATMEL_LCDC(PD, DATA10) | ATMEL_LCDC(PD, DATA11) | \
|
||||
ATMEL_LCDC(PD, DATA12) | ATMEL_LCDC(PD, DATA13) | \
|
||||
ATMEL_LCDC(PD, DATA14) | ATMEL_LCDC(PD, DATA15) | \
|
||||
ATMEL_LCDC(PD, DATA16) | ATMEL_LCDC(PD, DATA17) | \
|
||||
ATMEL_LCDC(PD, DATA18) | ATMEL_LCDC(PD, DATA19) | \
|
||||
ATMEL_LCDC(PD, DATA20) | ATMEL_LCDC(PD, DATA21) | \
|
||||
ATMEL_LCDC(PD, DATA22) | ATMEL_LCDC(PD, DATA23))
|
||||
|
||||
#define ATMEL_LCDC_ALT_24B_DATA ( \
|
||||
ATMEL_LCDC(PE, DATA0) | ATMEL_LCDC(PE, DATA1) | \
|
||||
ATMEL_LCDC(PE, DATA2) | ATMEL_LCDC(PE, DATA3) | \
|
||||
ATMEL_LCDC(PE, DATA4) | ATMEL_LCDC(PC, DATA5) | \
|
||||
ATMEL_LCDC(PD, DATA6) | ATMEL_LCDC(PD, DATA7) | \
|
||||
ATMEL_LCDC(PE, DATA8) | ATMEL_LCDC(PE, DATA9) | \
|
||||
ATMEL_LCDC(PE, DATA10) | ATMEL_LCDC(PE, DATA11) | \
|
||||
ATMEL_LCDC(PE, DATA12) | ATMEL_LCDC(PD, DATA13) | \
|
||||
ATMEL_LCDC(PD, DATA14) | ATMEL_LCDC(PD, DATA15) | \
|
||||
ATMEL_LCDC(PE, DATA16) | ATMEL_LCDC(PE, DATA17) | \
|
||||
ATMEL_LCDC(PE, DATA18) | ATMEL_LCDC(PE, DATA19) | \
|
||||
ATMEL_LCDC(PE, DATA20) | ATMEL_LCDC(PE, DATA21) | \
|
||||
ATMEL_LCDC(PD, DATA22) | ATMEL_LCDC(PD, DATA23))
|
||||
|
||||
#define ATMEL_LCDC_PRI_18B_DATA ( \
|
||||
ATMEL_LCDC(PC, DATA2) | ATMEL_LCDC(PC, DATA3) | \
|
||||
ATMEL_LCDC(PC, DATA4) | ATMEL_LCDC(PC, DATA5) | \
|
||||
ATMEL_LCDC(PD, DATA6) | ATMEL_LCDC(PD, DATA7) | \
|
||||
ATMEL_LCDC(PD, DATA10) | ATMEL_LCDC(PD, DATA11) | \
|
||||
ATMEL_LCDC(PD, DATA12) | ATMEL_LCDC(PD, DATA13) | \
|
||||
ATMEL_LCDC(PD, DATA14) | ATMEL_LCDC(PD, DATA15) | \
|
||||
ATMEL_LCDC(PD, DATA18) | ATMEL_LCDC(PD, DATA19) | \
|
||||
ATMEL_LCDC(PD, DATA20) | ATMEL_LCDC(PD, DATA21) | \
|
||||
ATMEL_LCDC(PD, DATA22) | ATMEL_LCDC(PD, DATA23))
|
||||
|
||||
#define ATMEL_LCDC_ALT_18B_DATA ( \
|
||||
ATMEL_LCDC(PE, DATA2) | ATMEL_LCDC(PE, DATA3) | \
|
||||
ATMEL_LCDC(PE, DATA4) | ATMEL_LCDC(PC, DATA5) | \
|
||||
ATMEL_LCDC(PD, DATA6) | ATMEL_LCDC(PD, DATA7) | \
|
||||
ATMEL_LCDC(PE, DATA10) | ATMEL_LCDC(PE, DATA11) | \
|
||||
ATMEL_LCDC(PE, DATA12) | ATMEL_LCDC(PD, DATA13) | \
|
||||
ATMEL_LCDC(PD, DATA14) | ATMEL_LCDC(PD, DATA15) | \
|
||||
ATMEL_LCDC(PE, DATA18) | ATMEL_LCDC(PE, DATA19) | \
|
||||
ATMEL_LCDC(PE, DATA20) | ATMEL_LCDC(PE, DATA21) | \
|
||||
ATMEL_LCDC(PD, DATA22) | ATMEL_LCDC(PD, DATA23))
|
||||
|
||||
#define ATMEL_LCDC_PRI_15B_DATA ( \
|
||||
ATMEL_LCDC(PC, DATA3) | ATMEL_LCDC(PC, DATA4) | \
|
||||
ATMEL_LCDC(PC, DATA5) | ATMEL_LCDC(PD, DATA6) | \
|
||||
ATMEL_LCDC(PD, DATA7) | \
|
||||
ATMEL_LCDC(PD, DATA11) | ATMEL_LCDC(PD, DATA12) | \
|
||||
ATMEL_LCDC(PD, DATA13) | ATMEL_LCDC(PD, DATA14) | \
|
||||
ATMEL_LCDC(PD, DATA15) | \
|
||||
ATMEL_LCDC(PD, DATA19) | ATMEL_LCDC(PD, DATA20) | \
|
||||
ATMEL_LCDC(PD, DATA21) | ATMEL_LCDC(PD, DATA22) | \
|
||||
ATMEL_LCDC(PD, DATA23))
|
||||
|
||||
#define ATMEL_LCDC_ALT_15B_DATA ( \
|
||||
ATMEL_LCDC(PE, DATA3) | ATMEL_LCDC(PE, DATA4) | \
|
||||
ATMEL_LCDC(PC, DATA5) | ATMEL_LCDC(PD, DATA6) | \
|
||||
ATMEL_LCDC(PD, DATA7) | \
|
||||
ATMEL_LCDC(PE, DATA11) | ATMEL_LCDC(PE, DATA12) | \
|
||||
ATMEL_LCDC(PD, DATA13) | ATMEL_LCDC(PD, DATA14) | \
|
||||
ATMEL_LCDC(PD, DATA15) | \
|
||||
ATMEL_LCDC(PE, DATA19) | ATMEL_LCDC(PE, DATA20) | \
|
||||
ATMEL_LCDC(PE, DATA21) | ATMEL_LCDC(PD, DATA22) | \
|
||||
ATMEL_LCDC(PD, DATA23))
|
||||
|
||||
#define ATMEL_LCDC_PRI_CONTROL ( \
|
||||
ATMEL_LCDC(PC, CC) | ATMEL_LCDC(PC, DVAL) | \
|
||||
ATMEL_LCDC(PC, MODE) | ATMEL_LCDC(PC, PWR))
|
||||
|
||||
#define ATMEL_LCDC_ALT_CONTROL ( \
|
||||
ATMEL_LCDC(PE, CC) | ATMEL_LCDC(PE, DVAL) | \
|
||||
ATMEL_LCDC(PE, MODE) | ATMEL_LCDC(PC, PWR))
|
||||
|
||||
#define ATMEL_LCDC_CONTROL ( \
|
||||
ATMEL_LCDC(PC, HSYNC) | ATMEL_LCDC(PC, VSYNC) | \
|
||||
ATMEL_LCDC(PC, PCLK))
|
||||
|
||||
#define ATMEL_LCDC_PRI_24BIT (ATMEL_LCDC_CONTROL | ATMEL_LCDC_PRI_24B_DATA)
|
||||
|
||||
#define ATMEL_LCDC_ALT_24BIT (ATMEL_LCDC_CONTROL | ATMEL_LCDC_ALT_24B_DATA)
|
||||
|
||||
#define ATMEL_LCDC_PRI_18BIT (ATMEL_LCDC_CONTROL | ATMEL_LCDC_PRI_18B_DATA)
|
||||
|
||||
#define ATMEL_LCDC_ALT_18BIT (ATMEL_LCDC_CONTROL | ATMEL_LCDC_ALT_18B_DATA)
|
||||
|
||||
#define ATMEL_LCDC_PRI_15BIT (ATMEL_LCDC_CONTROL | ATMEL_LCDC_PRI_15B_DATA)
|
||||
|
||||
#define ATMEL_LCDC_ALT_15BIT (ATMEL_LCDC_CONTROL | ATMEL_LCDC_ALT_15B_DATA)
|
||||
|
||||
/* Bitmask for all EBI data (D16..D31) pins on port E */
|
||||
#define ATMEL_EBI_PE_DATA_ALL (0x0000FFFF)
|
||||
|
||||
#endif /* __ASM_ARCH_AT32AP700X_H__ */
|
17
arch/avr32/mach-at32ap/include/mach/atmel-mci.h
Normal file
17
arch/avr32/mach-at32ap/include/mach/atmel-mci.h
Normal file
|
@ -0,0 +1,17 @@
|
|||
#ifndef __MACH_ATMEL_MCI_H
|
||||
#define __MACH_ATMEL_MCI_H
|
||||
|
||||
#include <linux/platform_data/dma-dw.h>
|
||||
|
||||
/**
|
||||
* struct mci_dma_data - DMA data for MCI interface
|
||||
*/
|
||||
struct mci_dma_data {
|
||||
struct dw_dma_slave sdata;
|
||||
};
|
||||
|
||||
/* accessor macros */
|
||||
#define slave_data_ptr(s) (&(s)->sdata)
|
||||
#define find_slave_dev(s) ((s)->sdata.dma_dev)
|
||||
|
||||
#endif /* __MACH_ATMEL_MCI_H */
|
115
arch/avr32/mach-at32ap/include/mach/board.h
Normal file
115
arch/avr32/mach-at32ap/include/mach/board.h
Normal file
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
* Platform data definitions.
|
||||
*/
|
||||
#ifndef __ASM_ARCH_BOARD_H
|
||||
#define __ASM_ARCH_BOARD_H
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/serial.h>
|
||||
#include <linux/platform_data/macb.h>
|
||||
#include <linux/platform_data/atmel.h>
|
||||
|
||||
#define GPIO_PIN_NONE (-1)
|
||||
|
||||
/*
|
||||
* Clock rates for various on-board oscillators. The number of entries
|
||||
* in this array is chip-dependent.
|
||||
*/
|
||||
extern unsigned long at32_board_osc_rates[];
|
||||
|
||||
/*
|
||||
* This used to add essential system devices, but this is now done
|
||||
* automatically. Please don't use it in new board code.
|
||||
*/
|
||||
static inline void __deprecated at32_add_system_devices(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
extern struct platform_device *atmel_default_console_device;
|
||||
|
||||
/* Flags for selecting USART extra pins */
|
||||
#define ATMEL_USART_RTS 0x01
|
||||
#define ATMEL_USART_CTS 0x02
|
||||
#define ATMEL_USART_CLK 0x04
|
||||
|
||||
void at32_map_usart(unsigned int hw_id, unsigned int line, int flags);
|
||||
struct platform_device *at32_add_device_usart(unsigned int id);
|
||||
|
||||
struct platform_device *
|
||||
at32_add_device_eth(unsigned int id, struct macb_platform_data *data);
|
||||
|
||||
struct spi_board_info;
|
||||
struct platform_device *
|
||||
at32_add_device_spi(unsigned int id, struct spi_board_info *b, unsigned int n);
|
||||
void at32_spi_setup_slaves(unsigned int bus_num, struct spi_board_info *b, unsigned int n);
|
||||
|
||||
struct atmel_lcdfb_pdata;
|
||||
struct platform_device *
|
||||
at32_add_device_lcdc(unsigned int id, struct atmel_lcdfb_pdata *data,
|
||||
unsigned long fbmem_start, unsigned long fbmem_len,
|
||||
u64 pin_mask);
|
||||
|
||||
struct usba_platform_data;
|
||||
struct platform_device *
|
||||
at32_add_device_usba(unsigned int id, struct usba_platform_data *data);
|
||||
|
||||
struct ide_platform_data {
|
||||
u8 cs;
|
||||
};
|
||||
struct platform_device *
|
||||
at32_add_device_ide(unsigned int id, unsigned int extint,
|
||||
struct ide_platform_data *data);
|
||||
|
||||
/* mask says which PWM channels to mux */
|
||||
struct platform_device *at32_add_device_pwm(u32 mask);
|
||||
|
||||
/* 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);
|
||||
|
||||
struct i2c_board_info;
|
||||
struct platform_device *at32_add_device_twi(unsigned int id,
|
||||
struct i2c_board_info *b,
|
||||
unsigned int n);
|
||||
|
||||
struct mci_platform_data;
|
||||
struct platform_device *
|
||||
at32_add_device_mci(unsigned int id, struct mci_platform_data *data);
|
||||
|
||||
struct ac97c_platform_data;
|
||||
struct platform_device *
|
||||
at32_add_device_ac97c(unsigned int id, struct ac97c_platform_data *data,
|
||||
unsigned int flags);
|
||||
|
||||
struct atmel_abdac_pdata;
|
||||
struct platform_device *
|
||||
at32_add_device_abdac(unsigned int id, struct atmel_abdac_pdata *data);
|
||||
|
||||
struct platform_device *at32_add_device_psif(unsigned int id);
|
||||
|
||||
struct cf_platform_data {
|
||||
int detect_pin;
|
||||
int reset_pin;
|
||||
int vcc_pin;
|
||||
int ready_pin;
|
||||
u8 cs;
|
||||
};
|
||||
struct platform_device *
|
||||
at32_add_device_cf(unsigned int id, unsigned int extint,
|
||||
struct cf_platform_data *data);
|
||||
|
||||
struct platform_device *
|
||||
at32_add_device_nand(unsigned int id, struct atmel_nand_data *data);
|
||||
|
||||
#endif /* __ASM_ARCH_BOARD_H */
|
19
arch/avr32/mach-at32ap/include/mach/chip.h
Normal file
19
arch/avr32/mach-at32ap/include/mach/chip.h
Normal file
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* AVR32 chip-specific definitions
|
||||
*
|
||||
* 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_CHIP_H__
|
||||
#define __ASM_AVR32_ARCH_CHIP_H__
|
||||
|
||||
#if defined(CONFIG_CPU_AT32AP700X)
|
||||
# include <mach/at32ap700x.h>
|
||||
#else
|
||||
# error Unknown chip type selected
|
||||
#endif
|
||||
|
||||
#endif /* __ASM_AVR32_ARCH_CHIP_H__ */
|
47
arch/avr32/mach-at32ap/include/mach/cpu.h
Normal file
47
arch/avr32/mach-at32ap/include/mach/cpu.h
Normal file
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* AVR32 and (fake) AT91 CPU identification
|
||||
*
|
||||
* 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_ARCH_CPU_H
|
||||
#define __ASM_ARCH_CPU_H
|
||||
|
||||
/*
|
||||
* Only AT32AP7000 is defined for now. We can identify the specific
|
||||
* chip at runtime, but I'm not sure if it's really worth it.
|
||||
*/
|
||||
#ifdef CONFIG_CPU_AT32AP700X
|
||||
# define cpu_is_at32ap7000() (1)
|
||||
#else
|
||||
# define cpu_is_at32ap7000() (0)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Since this is AVR32, we will never run on any AT91 CPU. But these
|
||||
* definitions may reduce clutter in common drivers.
|
||||
*/
|
||||
#define cpu_is_at91rm9200() (0)
|
||||
#define cpu_is_at91sam9xe() (0)
|
||||
#define cpu_is_at91sam9260() (0)
|
||||
#define cpu_is_at91sam9261() (0)
|
||||
#define cpu_is_at91sam9263() (0)
|
||||
#define cpu_is_at91sam9rl() (0)
|
||||
#define cpu_is_at91sam9g10() (0)
|
||||
#define cpu_is_at91sam9g20() (0)
|
||||
#define cpu_is_at91sam9g45() (0)
|
||||
#define cpu_is_at91sam9g45es() (0)
|
||||
#define cpu_is_at91sam9m10() (0)
|
||||
#define cpu_is_at91sam9g46() (0)
|
||||
#define cpu_is_at91sam9m11() (0)
|
||||
#define cpu_is_at91sam9x5() (0)
|
||||
#define cpu_is_at91sam9g15() (0)
|
||||
#define cpu_is_at91sam9g35() (0)
|
||||
#define cpu_is_at91sam9x35() (0)
|
||||
#define cpu_is_at91sam9g25() (0)
|
||||
#define cpu_is_at91sam9x25() (0)
|
||||
|
||||
#endif /* __ASM_ARCH_CPU_H */
|
45
arch/avr32/mach-at32ap/include/mach/gpio.h
Normal file
45
arch/avr32/mach-at32ap/include/mach/gpio.h
Normal file
|
@ -0,0 +1,45 @@
|
|||
#ifndef __ASM_AVR32_ARCH_GPIO_H
|
||||
#define __ASM_AVR32_ARCH_GPIO_H
|
||||
|
||||
#include <linux/compiler.h>
|
||||
#include <asm/irq.h>
|
||||
|
||||
|
||||
/* Some GPIO chips can manage IRQs; some can't. The exact numbers can
|
||||
* be changed if needed, but for the moment they're not configurable.
|
||||
*/
|
||||
#define ARCH_NR_GPIOS (NR_GPIO_IRQS + 2 * 32)
|
||||
|
||||
|
||||
/* Arch-neutral GPIO API, supporting both "native" and external GPIOs. */
|
||||
#include <asm-generic/gpio.h>
|
||||
|
||||
static inline int gpio_get_value(unsigned int gpio)
|
||||
{
|
||||
return __gpio_get_value(gpio);
|
||||
}
|
||||
|
||||
static inline void gpio_set_value(unsigned int gpio, int value)
|
||||
{
|
||||
__gpio_set_value(gpio, value);
|
||||
}
|
||||
|
||||
static inline int gpio_cansleep(unsigned int gpio)
|
||||
{
|
||||
return __gpio_cansleep(gpio);
|
||||
}
|
||||
|
||||
|
||||
static inline int gpio_to_irq(unsigned int gpio)
|
||||
{
|
||||
if (gpio < NR_GPIO_IRQS)
|
||||
return gpio + GPIO_IRQ_BASE;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline int irq_to_gpio(unsigned int irq)
|
||||
{
|
||||
return irq - GPIO_IRQ_BASE;
|
||||
}
|
||||
|
||||
#endif /* __ASM_AVR32_ARCH_GPIO_H */
|
55
arch/avr32/mach-at32ap/include/mach/hmatrix.h
Normal file
55
arch/avr32/mach-at32ap/include/mach/hmatrix.h
Normal file
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* High-Speed Bus Matrix configuration registers
|
||||
*
|
||||
* 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 __HMATRIX_H
|
||||
#define __HMATRIX_H
|
||||
|
||||
extern struct clk at32_hmatrix_clk;
|
||||
|
||||
void hmatrix_write_reg(unsigned long offset, u32 value);
|
||||
u32 hmatrix_read_reg(unsigned long offset);
|
||||
|
||||
void hmatrix_sfr_set_bits(unsigned int slave_id, u32 mask);
|
||||
void hmatrix_sfr_clear_bits(unsigned int slave_id, u32 mask);
|
||||
|
||||
/* Master Configuration register */
|
||||
#define HMATRIX_MCFG(m) (0x0000 + 4 * (m))
|
||||
/* Undefined length burst limit */
|
||||
# define HMATRIX_MCFG_ULBT_INFINITE 0 /* Infinite length */
|
||||
# define HMATRIX_MCFG_ULBT_SINGLE 1 /* Single Access */
|
||||
# define HMATRIX_MCFG_ULBT_FOUR_BEAT 2 /* Four beat */
|
||||
# define HMATRIX_MCFG_ULBT_EIGHT_BEAT 3 /* Eight beat */
|
||||
# define HMATRIX_MCFG_ULBT_SIXTEEN_BEAT 4 /* Sixteen beat */
|
||||
|
||||
/* Slave Configuration register */
|
||||
#define HMATRIX_SCFG(s) (0x0040 + 4 * (s))
|
||||
# define HMATRIX_SCFG_SLOT_CYCLE(x) ((x) << 0) /* Max burst cycles */
|
||||
# define HMATRIX_SCFG_DEFMSTR_NONE ( 0 << 16) /* No default master */
|
||||
# define HMATRIX_SCFG_DEFMSTR_LAST ( 1 << 16) /* Last def master */
|
||||
# define HMATRIX_SCFG_DEFMSTR_FIXED ( 2 << 16) /* Fixed def master */
|
||||
# define HMATRIX_SCFG_FIXED_DEFMSTR(m) ((m) << 18) /* Fixed master ID */
|
||||
# define HMATRIX_SCFG_ARBT_ROUND_ROBIN ( 0 << 24) /* RR arbitration */
|
||||
# define HMATRIX_SCFG_ARBT_FIXED_PRIO ( 1 << 24) /* Fixed priority */
|
||||
|
||||
/* Slave Priority register A (master 0..7) */
|
||||
#define HMATRIX_PRAS(s) (0x0080 + 8 * (s))
|
||||
# define HMATRIX_PRAS_PRIO(m, p) ((p) << ((m) * 4))
|
||||
|
||||
/* Slave Priority register A (master 8..15) */
|
||||
#define HMATRIX_PRBS(s) (0x0084 + 8 * (s))
|
||||
# define HMATRIX_PRBS_PRIO(m, p) ((p) << (((m) - 8) * 4))
|
||||
|
||||
/* Master Remap Control Register */
|
||||
#define HMATRIX_MRCR 0x0100
|
||||
# define HMATRIX_MRCR_REMAP(m) ( 1 << (m)) /* Remap master m */
|
||||
|
||||
/* Special Function Register. Bit definitions are chip-specific */
|
||||
#define HMATRIX_SFR(s) (0x0110 + 4 * (s))
|
||||
|
||||
#endif /* __HMATRIX_H */
|
18
arch/avr32/mach-at32ap/include/mach/init.h
Normal file
18
arch/avr32/mach-at32ap/include/mach/init.h
Normal file
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
* AT32AP platform initialization calls.
|
||||
*
|
||||
* 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_AT32AP_INIT_H__
|
||||
#define __ASM_AVR32_AT32AP_INIT_H__
|
||||
|
||||
void setup_platform(void);
|
||||
void setup_board(void);
|
||||
|
||||
void at32_setup_serial_console(unsigned int usart_id);
|
||||
|
||||
#endif /* __ASM_AVR32_AT32AP_INIT_H__ */
|
38
arch/avr32/mach-at32ap/include/mach/io.h
Normal file
38
arch/avr32/mach-at32ap/include/mach/io.h
Normal file
|
@ -0,0 +1,38 @@
|
|||
#ifndef __ASM_AVR32_ARCH_AT32AP_IO_H
|
||||
#define __ASM_AVR32_ARCH_AT32AP_IO_H
|
||||
|
||||
#include <linux/swab.h>
|
||||
|
||||
#if defined(CONFIG_AP700X_32_BIT_SMC)
|
||||
# define __swizzle_addr_b(addr) (addr ^ 3UL)
|
||||
# define __swizzle_addr_w(addr) (addr ^ 2UL)
|
||||
# define __swizzle_addr_l(addr) (addr)
|
||||
# define ioswabb(a, x) (x)
|
||||
# define ioswabw(a, x) (x)
|
||||
# define ioswabl(a, x) (x)
|
||||
# define __mem_ioswabb(a, x) (x)
|
||||
# define __mem_ioswabw(a, x) swab16(x)
|
||||
# define __mem_ioswabl(a, x) swab32(x)
|
||||
#elif defined(CONFIG_AP700X_16_BIT_SMC)
|
||||
# define __swizzle_addr_b(addr) (addr ^ 1UL)
|
||||
# define __swizzle_addr_w(addr) (addr)
|
||||
# define __swizzle_addr_l(addr) (addr)
|
||||
# define ioswabb(a, x) (x)
|
||||
# define ioswabw(a, x) (x)
|
||||
# define ioswabl(a, x) swahw32(x)
|
||||
# define __mem_ioswabb(a, x) (x)
|
||||
# define __mem_ioswabw(a, x) swab16(x)
|
||||
# define __mem_ioswabl(a, x) swahb32(x)
|
||||
#else
|
||||
# define __swizzle_addr_b(addr) (addr)
|
||||
# define __swizzle_addr_w(addr) (addr)
|
||||
# define __swizzle_addr_l(addr) (addr)
|
||||
# define ioswabb(a, x) (x)
|
||||
# define ioswabw(a, x) swab16(x)
|
||||
# define ioswabl(a, x) swab32(x)
|
||||
# define __mem_ioswabb(a, x) (x)
|
||||
# define __mem_ioswabw(a, x) (x)
|
||||
# define __mem_ioswabl(a, x) (x)
|
||||
#endif
|
||||
|
||||
#endif /* __ASM_AVR32_ARCH_AT32AP_IO_H */
|
14
arch/avr32/mach-at32ap/include/mach/irq.h
Normal file
14
arch/avr32/mach-at32ap/include/mach/irq.h
Normal file
|
@ -0,0 +1,14 @@
|
|||
#ifndef __ASM_AVR32_ARCH_IRQ_H
|
||||
#define __ASM_AVR32_ARCH_IRQ_H
|
||||
|
||||
#define EIM_IRQ_BASE NR_INTERNAL_IRQS
|
||||
#define NR_EIM_IRQS 32
|
||||
#define AT32_EXTINT(n) (EIM_IRQ_BASE + (n))
|
||||
|
||||
#define GPIO_IRQ_BASE (EIM_IRQ_BASE + NR_EIM_IRQS)
|
||||
#define NR_GPIO_CTLR (5 /*internal*/ + 1 /*external*/)
|
||||
#define NR_GPIO_IRQS (NR_GPIO_CTLR * 32)
|
||||
|
||||
#define NR_IRQS (GPIO_IRQ_BASE + NR_GPIO_IRQS)
|
||||
|
||||
#endif /* __ASM_AVR32_ARCH_IRQ_H */
|
27
arch/avr32/mach-at32ap/include/mach/pm.h
Normal file
27
arch/avr32/mach-at32ap/include/mach/pm.h
Normal file
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* 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 void cpu_enter_standby(unsigned long sdramc_base);
|
||||
|
||||
void intc_set_suspend_handler(unsigned long offset);
|
||||
#endif
|
||||
|
||||
#endif /* __ASM_AVR32_ARCH_PM_H */
|
30
arch/avr32/mach-at32ap/include/mach/portmux.h
Normal file
30
arch/avr32/mach-at32ap/include/mach/portmux.h
Normal file
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* AT32 portmux 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_ARCH_PORTMUX_H__
|
||||
#define __ASM_ARCH_PORTMUX_H__
|
||||
|
||||
/*
|
||||
* Set up pin multiplexing, called from board init only.
|
||||
*
|
||||
* The following flags determine the initial state of the pin.
|
||||
*/
|
||||
#define AT32_GPIOF_PULLUP 0x00000001 /* (not-OUT) Enable pull-up */
|
||||
#define AT32_GPIOF_OUTPUT 0x00000002 /* (OUT) Enable output driver */
|
||||
#define AT32_GPIOF_HIGH 0x00000004 /* (OUT) Set output high */
|
||||
#define AT32_GPIOF_DEGLITCH 0x00000008 /* (IN) Filter glitches */
|
||||
#define AT32_GPIOF_MULTIDRV 0x00000010 /* Enable multidriver option */
|
||||
|
||||
void at32_select_periph(unsigned int port, unsigned int pin,
|
||||
unsigned int periph, unsigned long flags);
|
||||
void at32_select_gpio(unsigned int pin, unsigned long flags);
|
||||
void at32_deselect_pin(unsigned int pin);
|
||||
void at32_reserve_pin(unsigned int port, u32 pin_mask);
|
||||
|
||||
#endif /* __ASM_ARCH_PORTMUX_H__ */
|
113
arch/avr32/mach-at32ap/include/mach/smc.h
Normal file
113
arch/avr32/mach-at32ap/include/mach/smc.h
Normal file
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
* Static Memory Controller for AT32 chips
|
||||
*
|
||||
* Copyright (C) 2006 Atmel Corporation
|
||||
*
|
||||
* Inspired by the OMAP2 General-Purpose Memory Controller interface
|
||||
*
|
||||
* 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 __ARCH_AT32AP_SMC_H
|
||||
#define __ARCH_AT32AP_SMC_H
|
||||
|
||||
/*
|
||||
* All timing parameters are in nanoseconds.
|
||||
*/
|
||||
struct smc_timing {
|
||||
/* Delay from address valid to assertion of given strobe */
|
||||
int ncs_read_setup;
|
||||
int nrd_setup;
|
||||
int ncs_write_setup;
|
||||
int nwe_setup;
|
||||
|
||||
/* Pulse length of given strobe */
|
||||
int ncs_read_pulse;
|
||||
int nrd_pulse;
|
||||
int ncs_write_pulse;
|
||||
int nwe_pulse;
|
||||
|
||||
/* Total cycle length of given operation */
|
||||
int read_cycle;
|
||||
int write_cycle;
|
||||
|
||||
/* Minimal recovery times, will extend cycle if needed */
|
||||
int ncs_read_recover;
|
||||
int nrd_recover;
|
||||
int ncs_write_recover;
|
||||
int nwe_recover;
|
||||
};
|
||||
|
||||
/*
|
||||
* All timing parameters are in clock cycles.
|
||||
*/
|
||||
struct smc_config {
|
||||
|
||||
/* Delay from address valid to assertion of given strobe */
|
||||
u8 ncs_read_setup;
|
||||
u8 nrd_setup;
|
||||
u8 ncs_write_setup;
|
||||
u8 nwe_setup;
|
||||
|
||||
/* Pulse length of given strobe */
|
||||
u8 ncs_read_pulse;
|
||||
u8 nrd_pulse;
|
||||
u8 ncs_write_pulse;
|
||||
u8 nwe_pulse;
|
||||
|
||||
/* Total cycle length of given operation */
|
||||
u8 read_cycle;
|
||||
u8 write_cycle;
|
||||
|
||||
/* Bus width in bytes */
|
||||
u8 bus_width;
|
||||
|
||||
/*
|
||||
* 0: Data is sampled on rising edge of NCS
|
||||
* 1: Data is sampled on rising edge of NRD
|
||||
*/
|
||||
unsigned int nrd_controlled:1;
|
||||
|
||||
/*
|
||||
* 0: Data is driven on falling edge of NCS
|
||||
* 1: Data is driven on falling edge of NWR
|
||||
*/
|
||||
unsigned int nwe_controlled:1;
|
||||
|
||||
/*
|
||||
* 0: NWAIT is disabled
|
||||
* 1: Reserved
|
||||
* 2: NWAIT is frozen mode
|
||||
* 3: NWAIT in ready mode
|
||||
*/
|
||||
unsigned int nwait_mode:2;
|
||||
|
||||
/*
|
||||
* 0: Byte select access type
|
||||
* 1: Byte write access type
|
||||
*/
|
||||
unsigned int byte_write:1;
|
||||
|
||||
/*
|
||||
* Number of clock cycles before data is released after
|
||||
* the rising edge of the read controlling signal
|
||||
*
|
||||
* Total cycles from SMC is tdf_cycles + 1
|
||||
*/
|
||||
unsigned int tdf_cycles:4;
|
||||
|
||||
/*
|
||||
* 0: TDF optimization disabled
|
||||
* 1: TDF optimization enabled
|
||||
*/
|
||||
unsigned int tdf_mode:1;
|
||||
};
|
||||
|
||||
extern void smc_set_timing(struct smc_config *config,
|
||||
const struct smc_timing *timing);
|
||||
|
||||
extern int smc_set_configuration(int cs, const struct smc_config *config);
|
||||
extern struct smc_config *smc_get_configuration(int cs);
|
||||
|
||||
#endif /* __ARCH_AT32AP_SMC_H */
|
30
arch/avr32/mach-at32ap/include/mach/sram.h
Normal file
30
arch/avr32/mach-at32ap/include/mach/sram.h
Normal file
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Simple SRAM allocator
|
||||
*
|
||||
* 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_SRAM_H
|
||||
#define __ASM_AVR32_ARCH_SRAM_H
|
||||
|
||||
#include <linux/genalloc.h>
|
||||
|
||||
extern struct gen_pool *sram_pool;
|
||||
|
||||
static inline unsigned long sram_alloc(size_t len)
|
||||
{
|
||||
if (!sram_pool)
|
||||
return 0UL;
|
||||
|
||||
return gen_pool_alloc(sram_pool, len);
|
||||
}
|
||||
|
||||
static inline void sram_free(unsigned long addr, size_t len)
|
||||
{
|
||||
return gen_pool_free(sram_pool, addr, len);
|
||||
}
|
||||
|
||||
#endif /* __ASM_AVR32_ARCH_SRAM_H */
|
200
arch/avr32/mach-at32ap/intc.c
Normal file
200
arch/avr32/mach-at32ap/intc.c
Normal file
|
@ -0,0 +1,200 @@
|
|||
/*
|
||||
* Copyright (C) 2006, 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 <linux/clk.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/syscore_ops.h>
|
||||
#include <linux/export.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
|
||||
#include "intc.h"
|
||||
|
||||
struct intc {
|
||||
void __iomem *regs;
|
||||
struct irq_chip chip;
|
||||
#ifdef CONFIG_PM
|
||||
unsigned long suspend_ipr;
|
||||
unsigned long saved_ipr[64];
|
||||
#endif
|
||||
};
|
||||
|
||||
extern struct platform_device at32_intc0_device;
|
||||
|
||||
/*
|
||||
* TODO: We may be able to implement mask/unmask by setting IxM flags
|
||||
* in the status register.
|
||||
*/
|
||||
static void intc_mask_irq(struct irq_data *d)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static void intc_unmask_irq(struct irq_data *d)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static struct intc intc0 = {
|
||||
.chip = {
|
||||
.name = "intc",
|
||||
.irq_mask = intc_mask_irq,
|
||||
.irq_unmask = intc_unmask_irq,
|
||||
},
|
||||
};
|
||||
|
||||
/*
|
||||
* All interrupts go via intc at some point.
|
||||
*/
|
||||
asmlinkage void do_IRQ(int level, struct pt_regs *regs)
|
||||
{
|
||||
struct pt_regs *old_regs;
|
||||
unsigned int irq;
|
||||
unsigned long status_reg;
|
||||
|
||||
local_irq_disable();
|
||||
|
||||
old_regs = set_irq_regs(regs);
|
||||
|
||||
irq_enter();
|
||||
|
||||
irq = intc_readl(&intc0, INTCAUSE0 - 4 * level);
|
||||
generic_handle_irq(irq);
|
||||
|
||||
/*
|
||||
* Clear all interrupt level masks so that we may handle
|
||||
* interrupts during softirq processing. If this is a nested
|
||||
* interrupt, interrupts must stay globally disabled until we
|
||||
* return.
|
||||
*/
|
||||
status_reg = sysreg_read(SR);
|
||||
status_reg &= ~(SYSREG_BIT(I0M) | SYSREG_BIT(I1M)
|
||||
| SYSREG_BIT(I2M) | SYSREG_BIT(I3M));
|
||||
sysreg_write(SR, status_reg);
|
||||
|
||||
irq_exit();
|
||||
|
||||
set_irq_regs(old_regs);
|
||||
}
|
||||
|
||||
void __init init_IRQ(void)
|
||||
{
|
||||
extern void _evba(void);
|
||||
extern void irq_level0(void);
|
||||
struct resource *regs;
|
||||
struct clk *pclk;
|
||||
unsigned int i;
|
||||
u32 offset, readback;
|
||||
|
||||
regs = platform_get_resource(&at32_intc0_device, IORESOURCE_MEM, 0);
|
||||
if (!regs) {
|
||||
printk(KERN_EMERG "intc: no mmio resource defined\n");
|
||||
goto fail;
|
||||
}
|
||||
pclk = clk_get(&at32_intc0_device.dev, "pclk");
|
||||
if (IS_ERR(pclk)) {
|
||||
printk(KERN_EMERG "intc: no clock defined\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
clk_enable(pclk);
|
||||
|
||||
intc0.regs = ioremap(regs->start, resource_size(regs));
|
||||
if (!intc0.regs) {
|
||||
printk(KERN_EMERG "intc: failed to map registers (0x%08lx)\n",
|
||||
(unsigned long)regs->start);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize all interrupts to level 0 (lowest priority). The
|
||||
* priority level may be changed by calling
|
||||
* irq_set_priority().
|
||||
*
|
||||
*/
|
||||
offset = (unsigned long)&irq_level0 - (unsigned long)&_evba;
|
||||
for (i = 0; i < NR_INTERNAL_IRQS; i++) {
|
||||
intc_writel(&intc0, INTPR0 + 4 * i, offset);
|
||||
readback = intc_readl(&intc0, INTPR0 + 4 * i);
|
||||
if (readback == offset)
|
||||
irq_set_chip_and_handler(i, &intc0.chip,
|
||||
handle_simple_irq);
|
||||
}
|
||||
|
||||
/* Unmask all interrupt levels */
|
||||
sysreg_write(SR, (sysreg_read(SR)
|
||||
& ~(SR_I3M | SR_I2M | SR_I1M | SR_I0M)));
|
||||
|
||||
return;
|
||||
|
||||
fail:
|
||||
panic("Interrupt controller initialization failed!\n");
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
void intc_set_suspend_handler(unsigned long offset)
|
||||
{
|
||||
intc0.suspend_ipr = offset;
|
||||
}
|
||||
|
||||
static int intc_suspend(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (unlikely(!irqs_disabled())) {
|
||||
pr_err("intc_suspend: called with interrupts enabled\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (unlikely(!intc0.suspend_ipr)) {
|
||||
pr_err("intc_suspend: suspend_ipr not initialized\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = 0; i < 64; i++) {
|
||||
intc0.saved_ipr[i] = intc_readl(&intc0, INTPR0 + 4 * i);
|
||||
intc_writel(&intc0, INTPR0 + 4 * i, intc0.suspend_ipr);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void intc_resume(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 64; i++)
|
||||
intc_writel(&intc0, INTPR0 + 4 * i, intc0.saved_ipr[i]);
|
||||
}
|
||||
#else
|
||||
#define intc_suspend NULL
|
||||
#define intc_resume NULL
|
||||
#endif
|
||||
|
||||
static struct syscore_ops intc_syscore_ops = {
|
||||
.suspend = intc_suspend,
|
||||
.resume = intc_resume,
|
||||
};
|
||||
|
||||
static int __init intc_init_syscore(void)
|
||||
{
|
||||
register_syscore_ops(&intc_syscore_ops);
|
||||
|
||||
return 0;
|
||||
}
|
||||
device_initcall(intc_init_syscore);
|
||||
|
||||
unsigned long intc_get_pending(unsigned int group)
|
||||
{
|
||||
return intc_readl(&intc0, INTREQ0 + 4 * group);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(intc_get_pending);
|
329
arch/avr32/mach-at32ap/intc.h
Normal file
329
arch/avr32/mach-at32ap/intc.h
Normal file
|
@ -0,0 +1,329 @@
|
|||
/*
|
||||
* Automatically generated by gen-header.xsl
|
||||
*/
|
||||
#ifndef __ASM_AVR32_PERIHP_INTC_H__
|
||||
#define __ASM_AVR32_PERIHP_INTC_H__
|
||||
|
||||
#define INTC_NUM_INT_GRPS 33
|
||||
|
||||
#define INTC_INTPR0 0x0
|
||||
# define INTC_INTPR0_INTLEV_OFFSET 30
|
||||
# define INTC_INTPR0_INTLEV_SIZE 2
|
||||
# define INTC_INTPR0_OFFSET_OFFSET 0
|
||||
# define INTC_INTPR0_OFFSET_SIZE 24
|
||||
#define INTC_INTREQ0 0x100
|
||||
# define INTC_INTREQ0_IREQUEST0_OFFSET 0
|
||||
# define INTC_INTREQ0_IREQUEST0_SIZE 1
|
||||
# define INTC_INTREQ0_IREQUEST1_OFFSET 1
|
||||
# define INTC_INTREQ0_IREQUEST1_SIZE 1
|
||||
#define INTC_INTPR1 0x4
|
||||
# define INTC_INTPR1_INTLEV_OFFSET 30
|
||||
# define INTC_INTPR1_INTLEV_SIZE 2
|
||||
# define INTC_INTPR1_OFFSET_OFFSET 0
|
||||
# define INTC_INTPR1_OFFSET_SIZE 24
|
||||
#define INTC_INTREQ1 0x104
|
||||
# define INTC_INTREQ1_IREQUEST32_OFFSET 0
|
||||
# define INTC_INTREQ1_IREQUEST32_SIZE 1
|
||||
# define INTC_INTREQ1_IREQUEST33_OFFSET 1
|
||||
# define INTC_INTREQ1_IREQUEST33_SIZE 1
|
||||
# define INTC_INTREQ1_IREQUEST34_OFFSET 2
|
||||
# define INTC_INTREQ1_IREQUEST34_SIZE 1
|
||||
# define INTC_INTREQ1_IREQUEST35_OFFSET 3
|
||||
# define INTC_INTREQ1_IREQUEST35_SIZE 1
|
||||
# define INTC_INTREQ1_IREQUEST36_OFFSET 4
|
||||
# define INTC_INTREQ1_IREQUEST36_SIZE 1
|
||||
# define INTC_INTREQ1_IREQUEST37_OFFSET 5
|
||||
# define INTC_INTREQ1_IREQUEST37_SIZE 1
|
||||
#define INTC_INTPR2 0x8
|
||||
# define INTC_INTPR2_INTLEV_OFFSET 30
|
||||
# define INTC_INTPR2_INTLEV_SIZE 2
|
||||
# define INTC_INTPR2_OFFSET_OFFSET 0
|
||||
# define INTC_INTPR2_OFFSET_SIZE 24
|
||||
#define INTC_INTREQ2 0x108
|
||||
# define INTC_INTREQ2_IREQUEST64_OFFSET 0
|
||||
# define INTC_INTREQ2_IREQUEST64_SIZE 1
|
||||
# define INTC_INTREQ2_IREQUEST65_OFFSET 1
|
||||
# define INTC_INTREQ2_IREQUEST65_SIZE 1
|
||||
# define INTC_INTREQ2_IREQUEST66_OFFSET 2
|
||||
# define INTC_INTREQ2_IREQUEST66_SIZE 1
|
||||
# define INTC_INTREQ2_IREQUEST67_OFFSET 3
|
||||
# define INTC_INTREQ2_IREQUEST67_SIZE 1
|
||||
# define INTC_INTREQ2_IREQUEST68_OFFSET 4
|
||||
# define INTC_INTREQ2_IREQUEST68_SIZE 1
|
||||
#define INTC_INTPR3 0xc
|
||||
# define INTC_INTPR3_INTLEV_OFFSET 30
|
||||
# define INTC_INTPR3_INTLEV_SIZE 2
|
||||
# define INTC_INTPR3_OFFSET_OFFSET 0
|
||||
# define INTC_INTPR3_OFFSET_SIZE 24
|
||||
#define INTC_INTREQ3 0x10c
|
||||
# define INTC_INTREQ3_IREQUEST96_OFFSET 0
|
||||
# define INTC_INTREQ3_IREQUEST96_SIZE 1
|
||||
#define INTC_INTPR4 0x10
|
||||
# define INTC_INTPR4_INTLEV_OFFSET 30
|
||||
# define INTC_INTPR4_INTLEV_SIZE 2
|
||||
# define INTC_INTPR4_OFFSET_OFFSET 0
|
||||
# define INTC_INTPR4_OFFSET_SIZE 24
|
||||
#define INTC_INTREQ4 0x110
|
||||
# define INTC_INTREQ4_IREQUEST128_OFFSET 0
|
||||
# define INTC_INTREQ4_IREQUEST128_SIZE 1
|
||||
#define INTC_INTPR5 0x14
|
||||
# define INTC_INTPR5_INTLEV_OFFSET 30
|
||||
# define INTC_INTPR5_INTLEV_SIZE 2
|
||||
# define INTC_INTPR5_OFFSET_OFFSET 0
|
||||
# define INTC_INTPR5_OFFSET_SIZE 24
|
||||
#define INTC_INTREQ5 0x114
|
||||
# define INTC_INTREQ5_IREQUEST160_OFFSET 0
|
||||
# define INTC_INTREQ5_IREQUEST160_SIZE 1
|
||||
#define INTC_INTPR6 0x18
|
||||
# define INTC_INTPR6_INTLEV_OFFSET 30
|
||||
# define INTC_INTPR6_INTLEV_SIZE 2
|
||||
# define INTC_INTPR6_OFFSET_OFFSET 0
|
||||
# define INTC_INTPR6_OFFSET_SIZE 24
|
||||
#define INTC_INTREQ6 0x118
|
||||
# define INTC_INTREQ6_IREQUEST192_OFFSET 0
|
||||
# define INTC_INTREQ6_IREQUEST192_SIZE 1
|
||||
#define INTC_INTPR7 0x1c
|
||||
# define INTC_INTPR7_INTLEV_OFFSET 30
|
||||
# define INTC_INTPR7_INTLEV_SIZE 2
|
||||
# define INTC_INTPR7_OFFSET_OFFSET 0
|
||||
# define INTC_INTPR7_OFFSET_SIZE 24
|
||||
#define INTC_INTREQ7 0x11c
|
||||
# define INTC_INTREQ7_IREQUEST224_OFFSET 0
|
||||
# define INTC_INTREQ7_IREQUEST224_SIZE 1
|
||||
#define INTC_INTPR8 0x20
|
||||
# define INTC_INTPR8_INTLEV_OFFSET 30
|
||||
# define INTC_INTPR8_INTLEV_SIZE 2
|
||||
# define INTC_INTPR8_OFFSET_OFFSET 0
|
||||
# define INTC_INTPR8_OFFSET_SIZE 24
|
||||
#define INTC_INTREQ8 0x120
|
||||
# define INTC_INTREQ8_IREQUEST256_OFFSET 0
|
||||
# define INTC_INTREQ8_IREQUEST256_SIZE 1
|
||||
#define INTC_INTPR9 0x24
|
||||
# define INTC_INTPR9_INTLEV_OFFSET 30
|
||||
# define INTC_INTPR9_INTLEV_SIZE 2
|
||||
# define INTC_INTPR9_OFFSET_OFFSET 0
|
||||
# define INTC_INTPR9_OFFSET_SIZE 24
|
||||
#define INTC_INTREQ9 0x124
|
||||
# define INTC_INTREQ9_IREQUEST288_OFFSET 0
|
||||
# define INTC_INTREQ9_IREQUEST288_SIZE 1
|
||||
#define INTC_INTPR10 0x28
|
||||
# define INTC_INTPR10_INTLEV_OFFSET 30
|
||||
# define INTC_INTPR10_INTLEV_SIZE 2
|
||||
# define INTC_INTPR10_OFFSET_OFFSET 0
|
||||
# define INTC_INTPR10_OFFSET_SIZE 24
|
||||
#define INTC_INTREQ10 0x128
|
||||
# define INTC_INTREQ10_IREQUEST320_OFFSET 0
|
||||
# define INTC_INTREQ10_IREQUEST320_SIZE 1
|
||||
#define INTC_INTPR11 0x2c
|
||||
# define INTC_INTPR11_INTLEV_OFFSET 30
|
||||
# define INTC_INTPR11_INTLEV_SIZE 2
|
||||
# define INTC_INTPR11_OFFSET_OFFSET 0
|
||||
# define INTC_INTPR11_OFFSET_SIZE 24
|
||||
#define INTC_INTREQ11 0x12c
|
||||
# define INTC_INTREQ11_IREQUEST352_OFFSET 0
|
||||
# define INTC_INTREQ11_IREQUEST352_SIZE 1
|
||||
#define INTC_INTPR12 0x30
|
||||
# define INTC_INTPR12_INTLEV_OFFSET 30
|
||||
# define INTC_INTPR12_INTLEV_SIZE 2
|
||||
# define INTC_INTPR12_OFFSET_OFFSET 0
|
||||
# define INTC_INTPR12_OFFSET_SIZE 24
|
||||
#define INTC_INTREQ12 0x130
|
||||
# define INTC_INTREQ12_IREQUEST384_OFFSET 0
|
||||
# define INTC_INTREQ12_IREQUEST384_SIZE 1
|
||||
#define INTC_INTPR13 0x34
|
||||
# define INTC_INTPR13_INTLEV_OFFSET 30
|
||||
# define INTC_INTPR13_INTLEV_SIZE 2
|
||||
# define INTC_INTPR13_OFFSET_OFFSET 0
|
||||
# define INTC_INTPR13_OFFSET_SIZE 24
|
||||
#define INTC_INTREQ13 0x134
|
||||
# define INTC_INTREQ13_IREQUEST416_OFFSET 0
|
||||
# define INTC_INTREQ13_IREQUEST416_SIZE 1
|
||||
#define INTC_INTPR14 0x38
|
||||
# define INTC_INTPR14_INTLEV_OFFSET 30
|
||||
# define INTC_INTPR14_INTLEV_SIZE 2
|
||||
# define INTC_INTPR14_OFFSET_OFFSET 0
|
||||
# define INTC_INTPR14_OFFSET_SIZE 24
|
||||
#define INTC_INTREQ14 0x138
|
||||
# define INTC_INTREQ14_IREQUEST448_OFFSET 0
|
||||
# define INTC_INTREQ14_IREQUEST448_SIZE 1
|
||||
#define INTC_INTPR15 0x3c
|
||||
# define INTC_INTPR15_INTLEV_OFFSET 30
|
||||
# define INTC_INTPR15_INTLEV_SIZE 2
|
||||
# define INTC_INTPR15_OFFSET_OFFSET 0
|
||||
# define INTC_INTPR15_OFFSET_SIZE 24
|
||||
#define INTC_INTREQ15 0x13c
|
||||
# define INTC_INTREQ15_IREQUEST480_OFFSET 0
|
||||
# define INTC_INTREQ15_IREQUEST480_SIZE 1
|
||||
#define INTC_INTPR16 0x40
|
||||
# define INTC_INTPR16_INTLEV_OFFSET 30
|
||||
# define INTC_INTPR16_INTLEV_SIZE 2
|
||||
# define INTC_INTPR16_OFFSET_OFFSET 0
|
||||
# define INTC_INTPR16_OFFSET_SIZE 24
|
||||
#define INTC_INTREQ16 0x140
|
||||
# define INTC_INTREQ16_IREQUEST512_OFFSET 0
|
||||
# define INTC_INTREQ16_IREQUEST512_SIZE 1
|
||||
#define INTC_INTPR17 0x44
|
||||
# define INTC_INTPR17_INTLEV_OFFSET 30
|
||||
# define INTC_INTPR17_INTLEV_SIZE 2
|
||||
# define INTC_INTPR17_OFFSET_OFFSET 0
|
||||
# define INTC_INTPR17_OFFSET_SIZE 24
|
||||
#define INTC_INTREQ17 0x144
|
||||
# define INTC_INTREQ17_IREQUEST544_OFFSET 0
|
||||
# define INTC_INTREQ17_IREQUEST544_SIZE 1
|
||||
#define INTC_INTPR18 0x48
|
||||
# define INTC_INTPR18_INTLEV_OFFSET 30
|
||||
# define INTC_INTPR18_INTLEV_SIZE 2
|
||||
# define INTC_INTPR18_OFFSET_OFFSET 0
|
||||
# define INTC_INTPR18_OFFSET_SIZE 24
|
||||
#define INTC_INTREQ18 0x148
|
||||
# define INTC_INTREQ18_IREQUEST576_OFFSET 0
|
||||
# define INTC_INTREQ18_IREQUEST576_SIZE 1
|
||||
#define INTC_INTPR19 0x4c
|
||||
# define INTC_INTPR19_INTLEV_OFFSET 30
|
||||
# define INTC_INTPR19_INTLEV_SIZE 2
|
||||
# define INTC_INTPR19_OFFSET_OFFSET 0
|
||||
# define INTC_INTPR19_OFFSET_SIZE 24
|
||||
#define INTC_INTREQ19 0x14c
|
||||
# define INTC_INTREQ19_IREQUEST608_OFFSET 0
|
||||
# define INTC_INTREQ19_IREQUEST608_SIZE 1
|
||||
# define INTC_INTREQ19_IREQUEST609_OFFSET 1
|
||||
# define INTC_INTREQ19_IREQUEST609_SIZE 1
|
||||
# define INTC_INTREQ19_IREQUEST610_OFFSET 2
|
||||
# define INTC_INTREQ19_IREQUEST610_SIZE 1
|
||||
# define INTC_INTREQ19_IREQUEST611_OFFSET 3
|
||||
# define INTC_INTREQ19_IREQUEST611_SIZE 1
|
||||
#define INTC_INTPR20 0x50
|
||||
# define INTC_INTPR20_INTLEV_OFFSET 30
|
||||
# define INTC_INTPR20_INTLEV_SIZE 2
|
||||
# define INTC_INTPR20_OFFSET_OFFSET 0
|
||||
# define INTC_INTPR20_OFFSET_SIZE 24
|
||||
#define INTC_INTREQ20 0x150
|
||||
# define INTC_INTREQ20_IREQUEST640_OFFSET 0
|
||||
# define INTC_INTREQ20_IREQUEST640_SIZE 1
|
||||
#define INTC_INTPR21 0x54
|
||||
# define INTC_INTPR21_INTLEV_OFFSET 30
|
||||
# define INTC_INTPR21_INTLEV_SIZE 2
|
||||
# define INTC_INTPR21_OFFSET_OFFSET 0
|
||||
# define INTC_INTPR21_OFFSET_SIZE 24
|
||||
#define INTC_INTREQ21 0x154
|
||||
# define INTC_INTREQ21_IREQUEST672_OFFSET 0
|
||||
# define INTC_INTREQ21_IREQUEST672_SIZE 1
|
||||
#define INTC_INTPR22 0x58
|
||||
# define INTC_INTPR22_INTLEV_OFFSET 30
|
||||
# define INTC_INTPR22_INTLEV_SIZE 2
|
||||
# define INTC_INTPR22_OFFSET_OFFSET 0
|
||||
# define INTC_INTPR22_OFFSET_SIZE 24
|
||||
#define INTC_INTREQ22 0x158
|
||||
# define INTC_INTREQ22_IREQUEST704_OFFSET 0
|
||||
# define INTC_INTREQ22_IREQUEST704_SIZE 1
|
||||
# define INTC_INTREQ22_IREQUEST705_OFFSET 1
|
||||
# define INTC_INTREQ22_IREQUEST705_SIZE 1
|
||||
# define INTC_INTREQ22_IREQUEST706_OFFSET 2
|
||||
# define INTC_INTREQ22_IREQUEST706_SIZE 1
|
||||
#define INTC_INTPR23 0x5c
|
||||
# define INTC_INTPR23_INTLEV_OFFSET 30
|
||||
# define INTC_INTPR23_INTLEV_SIZE 2
|
||||
# define INTC_INTPR23_OFFSET_OFFSET 0
|
||||
# define INTC_INTPR23_OFFSET_SIZE 24
|
||||
#define INTC_INTREQ23 0x15c
|
||||
# define INTC_INTREQ23_IREQUEST736_OFFSET 0
|
||||
# define INTC_INTREQ23_IREQUEST736_SIZE 1
|
||||
# define INTC_INTREQ23_IREQUEST737_OFFSET 1
|
||||
# define INTC_INTREQ23_IREQUEST737_SIZE 1
|
||||
# define INTC_INTREQ23_IREQUEST738_OFFSET 2
|
||||
# define INTC_INTREQ23_IREQUEST738_SIZE 1
|
||||
#define INTC_INTPR24 0x60
|
||||
# define INTC_INTPR24_INTLEV_OFFSET 30
|
||||
# define INTC_INTPR24_INTLEV_SIZE 2
|
||||
# define INTC_INTPR24_OFFSET_OFFSET 0
|
||||
# define INTC_INTPR24_OFFSET_SIZE 24
|
||||
#define INTC_INTREQ24 0x160
|
||||
# define INTC_INTREQ24_IREQUEST768_OFFSET 0
|
||||
# define INTC_INTREQ24_IREQUEST768_SIZE 1
|
||||
#define INTC_INTPR25 0x64
|
||||
# define INTC_INTPR25_INTLEV_OFFSET 30
|
||||
# define INTC_INTPR25_INTLEV_SIZE 2
|
||||
# define INTC_INTPR25_OFFSET_OFFSET 0
|
||||
# define INTC_INTPR25_OFFSET_SIZE 24
|
||||
#define INTC_INTREQ25 0x164
|
||||
# define INTC_INTREQ25_IREQUEST800_OFFSET 0
|
||||
# define INTC_INTREQ25_IREQUEST800_SIZE 1
|
||||
#define INTC_INTPR26 0x68
|
||||
# define INTC_INTPR26_INTLEV_OFFSET 30
|
||||
# define INTC_INTPR26_INTLEV_SIZE 2
|
||||
# define INTC_INTPR26_OFFSET_OFFSET 0
|
||||
# define INTC_INTPR26_OFFSET_SIZE 24
|
||||
#define INTC_INTREQ26 0x168
|
||||
# define INTC_INTREQ26_IREQUEST832_OFFSET 0
|
||||
# define INTC_INTREQ26_IREQUEST832_SIZE 1
|
||||
#define INTC_INTPR27 0x6c
|
||||
# define INTC_INTPR27_INTLEV_OFFSET 30
|
||||
# define INTC_INTPR27_INTLEV_SIZE 2
|
||||
# define INTC_INTPR27_OFFSET_OFFSET 0
|
||||
# define INTC_INTPR27_OFFSET_SIZE 24
|
||||
#define INTC_INTREQ27 0x16c
|
||||
# define INTC_INTREQ27_IREQUEST864_OFFSET 0
|
||||
# define INTC_INTREQ27_IREQUEST864_SIZE 1
|
||||
#define INTC_INTPR28 0x70
|
||||
# define INTC_INTPR28_INTLEV_OFFSET 30
|
||||
# define INTC_INTPR28_INTLEV_SIZE 2
|
||||
# define INTC_INTPR28_OFFSET_OFFSET 0
|
||||
# define INTC_INTPR28_OFFSET_SIZE 24
|
||||
#define INTC_INTREQ28 0x170
|
||||
# define INTC_INTREQ28_IREQUEST896_OFFSET 0
|
||||
# define INTC_INTREQ28_IREQUEST896_SIZE 1
|
||||
#define INTC_INTPR29 0x74
|
||||
# define INTC_INTPR29_INTLEV_OFFSET 30
|
||||
# define INTC_INTPR29_INTLEV_SIZE 2
|
||||
# define INTC_INTPR29_OFFSET_OFFSET 0
|
||||
# define INTC_INTPR29_OFFSET_SIZE 24
|
||||
#define INTC_INTREQ29 0x174
|
||||
# define INTC_INTREQ29_IREQUEST928_OFFSET 0
|
||||
# define INTC_INTREQ29_IREQUEST928_SIZE 1
|
||||
#define INTC_INTPR30 0x78
|
||||
# define INTC_INTPR30_INTLEV_OFFSET 30
|
||||
# define INTC_INTPR30_INTLEV_SIZE 2
|
||||
# define INTC_INTPR30_OFFSET_OFFSET 0
|
||||
# define INTC_INTPR30_OFFSET_SIZE 24
|
||||
#define INTC_INTREQ30 0x178
|
||||
# define INTC_INTREQ30_IREQUEST960_OFFSET 0
|
||||
# define INTC_INTREQ30_IREQUEST960_SIZE 1
|
||||
#define INTC_INTPR31 0x7c
|
||||
# define INTC_INTPR31_INTLEV_OFFSET 30
|
||||
# define INTC_INTPR31_INTLEV_SIZE 2
|
||||
# define INTC_INTPR31_OFFSET_OFFSET 0
|
||||
# define INTC_INTPR31_OFFSET_SIZE 24
|
||||
#define INTC_INTREQ31 0x17c
|
||||
# define INTC_INTREQ31_IREQUEST992_OFFSET 0
|
||||
# define INTC_INTREQ31_IREQUEST992_SIZE 1
|
||||
#define INTC_INTPR32 0x80
|
||||
# define INTC_INTPR32_INTLEV_OFFSET 30
|
||||
# define INTC_INTPR32_INTLEV_SIZE 2
|
||||
# define INTC_INTPR32_OFFSET_OFFSET 0
|
||||
# define INTC_INTPR32_OFFSET_SIZE 24
|
||||
#define INTC_INTREQ32 0x180
|
||||
# define INTC_INTREQ32_IREQUEST1024_OFFSET 0
|
||||
# define INTC_INTREQ32_IREQUEST1024_SIZE 1
|
||||
#define INTC_INTCAUSE0 0x20c
|
||||
# define INTC_INTCAUSE0_CAUSEGRP_OFFSET 0
|
||||
# define INTC_INTCAUSE0_CAUSEGRP_SIZE 6
|
||||
#define INTC_INTCAUSE1 0x208
|
||||
# define INTC_INTCAUSE1_CAUSEGRP_OFFSET 0
|
||||
# define INTC_INTCAUSE1_CAUSEGRP_SIZE 6
|
||||
#define INTC_INTCAUSE2 0x204
|
||||
# define INTC_INTCAUSE2_CAUSEGRP_OFFSET 0
|
||||
# define INTC_INTCAUSE2_CAUSEGRP_SIZE 6
|
||||
#define INTC_INTCAUSE3 0x200
|
||||
# define INTC_INTCAUSE3_CAUSEGRP_OFFSET 0
|
||||
# define INTC_INTCAUSE3_CAUSEGRP_SIZE 6
|
||||
|
||||
#define INTC_BIT(name) (1 << INTC_##name##_OFFSET)
|
||||
#define INTC_MKBF(name, value) (((value) & ((1 << INTC_##name##_SIZE) - 1)) << INTC_##name##_OFFSET)
|
||||
#define INTC_GETBF(name, value) (((value) >> INTC_##name##_OFFSET) & ((1 << INTC_##name##_SIZE) - 1))
|
||||
|
||||
#define intc_readl(port,reg) \
|
||||
__raw_readl((port)->regs + INTC_##reg)
|
||||
#define intc_writel(port,reg,value) \
|
||||
__raw_writel((value), (port)->regs + INTC_##reg)
|
||||
|
||||
#endif /* __ASM_AVR32_PERIHP_INTC_H__ */
|
47
arch/avr32/mach-at32ap/pdc.c
Normal file
47
arch/avr32/mach-at32ap/pdc.c
Normal file
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
static int __init pdc_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct clk *pclk, *hclk;
|
||||
|
||||
pclk = clk_get(&pdev->dev, "pclk");
|
||||
if (IS_ERR(pclk)) {
|
||||
dev_err(&pdev->dev, "no pclk defined\n");
|
||||
return PTR_ERR(pclk);
|
||||
}
|
||||
hclk = clk_get(&pdev->dev, "hclk");
|
||||
if (IS_ERR(hclk)) {
|
||||
dev_err(&pdev->dev, "no hclk defined\n");
|
||||
clk_put(pclk);
|
||||
return PTR_ERR(hclk);
|
||||
}
|
||||
|
||||
clk_enable(pclk);
|
||||
clk_enable(hclk);
|
||||
|
||||
dev_info(&pdev->dev, "Atmel Peripheral DMA Controller enabled\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver pdc_driver = {
|
||||
.driver = {
|
||||
.name = "pdc",
|
||||
},
|
||||
};
|
||||
|
||||
static int __init pdc_init(void)
|
||||
{
|
||||
return platform_driver_probe(&pdc_driver, pdc_probe);
|
||||
}
|
||||
arch_initcall(pdc_init);
|
470
arch/avr32/mach-at32ap/pio.c
Normal file
470
arch/avr32/mach-at32ap/pio.c
Normal file
|
@ -0,0 +1,470 @@
|
|||
/*
|
||||
* Atmel PIO2 Port Multiplexer support
|
||||
*
|
||||
* Copyright (C) 2004-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.
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/irq.h>
|
||||
|
||||
#include <asm/gpio.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#include <mach/portmux.h>
|
||||
|
||||
#include "pio.h"
|
||||
|
||||
#define MAX_NR_PIO_DEVICES 8
|
||||
|
||||
struct pio_device {
|
||||
struct gpio_chip chip;
|
||||
void __iomem *regs;
|
||||
const struct platform_device *pdev;
|
||||
struct clk *clk;
|
||||
u32 pinmux_mask;
|
||||
char name[8];
|
||||
};
|
||||
|
||||
static struct pio_device pio_dev[MAX_NR_PIO_DEVICES];
|
||||
|
||||
static struct pio_device *gpio_to_pio(unsigned int gpio)
|
||||
{
|
||||
struct pio_device *pio;
|
||||
unsigned int index;
|
||||
|
||||
index = gpio >> 5;
|
||||
if (index >= MAX_NR_PIO_DEVICES)
|
||||
return NULL;
|
||||
pio = &pio_dev[index];
|
||||
if (!pio->regs)
|
||||
return NULL;
|
||||
|
||||
return pio;
|
||||
}
|
||||
|
||||
/* Pin multiplexing API */
|
||||
static DEFINE_SPINLOCK(pio_lock);
|
||||
|
||||
void __init at32_select_periph(unsigned int port, u32 pin_mask,
|
||||
unsigned int periph, unsigned long flags)
|
||||
{
|
||||
struct pio_device *pio;
|
||||
|
||||
/* assign and verify pio */
|
||||
pio = gpio_to_pio(port);
|
||||
if (unlikely(!pio)) {
|
||||
printk(KERN_WARNING "pio: invalid port %u\n", port);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Test if any of the requested pins is already muxed */
|
||||
spin_lock(&pio_lock);
|
||||
if (unlikely(pio->pinmux_mask & pin_mask)) {
|
||||
printk(KERN_WARNING "%s: pin(s) busy (requested 0x%x, busy 0x%x)\n",
|
||||
pio->name, pin_mask, pio->pinmux_mask & pin_mask);
|
||||
spin_unlock(&pio_lock);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
pio->pinmux_mask |= pin_mask;
|
||||
|
||||
/* enable pull ups */
|
||||
pio_writel(pio, PUER, pin_mask);
|
||||
|
||||
/* select either peripheral A or B */
|
||||
if (periph)
|
||||
pio_writel(pio, BSR, pin_mask);
|
||||
else
|
||||
pio_writel(pio, ASR, pin_mask);
|
||||
|
||||
/* enable peripheral control */
|
||||
pio_writel(pio, PDR, pin_mask);
|
||||
|
||||
/* Disable pull ups if not requested. */
|
||||
if (!(flags & AT32_GPIOF_PULLUP))
|
||||
pio_writel(pio, PUDR, pin_mask);
|
||||
|
||||
spin_unlock(&pio_lock);
|
||||
|
||||
return;
|
||||
|
||||
fail:
|
||||
dump_stack();
|
||||
}
|
||||
|
||||
void __init at32_select_gpio(unsigned int pin, unsigned long flags)
|
||||
{
|
||||
struct pio_device *pio;
|
||||
unsigned int pin_index = pin & 0x1f;
|
||||
u32 mask = 1 << pin_index;
|
||||
|
||||
pio = gpio_to_pio(pin);
|
||||
if (unlikely(!pio)) {
|
||||
printk("pio: invalid pin %u\n", pin);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (unlikely(test_and_set_bit(pin_index, &pio->pinmux_mask))) {
|
||||
printk("%s: pin %u is busy\n", pio->name, pin_index);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (flags & AT32_GPIOF_OUTPUT) {
|
||||
if (flags & AT32_GPIOF_HIGH)
|
||||
pio_writel(pio, SODR, mask);
|
||||
else
|
||||
pio_writel(pio, CODR, mask);
|
||||
if (flags & AT32_GPIOF_MULTIDRV)
|
||||
pio_writel(pio, MDER, mask);
|
||||
else
|
||||
pio_writel(pio, MDDR, mask);
|
||||
pio_writel(pio, PUDR, mask);
|
||||
pio_writel(pio, OER, mask);
|
||||
} else {
|
||||
if (flags & AT32_GPIOF_PULLUP)
|
||||
pio_writel(pio, PUER, mask);
|
||||
else
|
||||
pio_writel(pio, PUDR, mask);
|
||||
if (flags & AT32_GPIOF_DEGLITCH)
|
||||
pio_writel(pio, IFER, mask);
|
||||
else
|
||||
pio_writel(pio, IFDR, mask);
|
||||
pio_writel(pio, ODR, mask);
|
||||
}
|
||||
|
||||
pio_writel(pio, PER, mask);
|
||||
|
||||
return;
|
||||
|
||||
fail:
|
||||
dump_stack();
|
||||
}
|
||||
|
||||
/*
|
||||
* Undo a previous pin reservation. Will not affect the hardware
|
||||
* configuration.
|
||||
*/
|
||||
void at32_deselect_pin(unsigned int pin)
|
||||
{
|
||||
struct pio_device *pio;
|
||||
unsigned int pin_index = pin & 0x1f;
|
||||
|
||||
pio = gpio_to_pio(pin);
|
||||
if (unlikely(!pio)) {
|
||||
printk("pio: invalid pin %u\n", pin);
|
||||
dump_stack();
|
||||
return;
|
||||
}
|
||||
|
||||
clear_bit(pin_index, &pio->pinmux_mask);
|
||||
}
|
||||
|
||||
/* Reserve a pin, preventing anyone else from changing its configuration. */
|
||||
void __init at32_reserve_pin(unsigned int port, u32 pin_mask)
|
||||
{
|
||||
struct pio_device *pio;
|
||||
|
||||
/* assign and verify pio */
|
||||
pio = gpio_to_pio(port);
|
||||
if (unlikely(!pio)) {
|
||||
printk(KERN_WARNING "pio: invalid port %u\n", port);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Test if any of the requested pins is already muxed */
|
||||
spin_lock(&pio_lock);
|
||||
if (unlikely(pio->pinmux_mask & pin_mask)) {
|
||||
printk(KERN_WARNING "%s: pin(s) busy (req. 0x%x, busy 0x%x)\n",
|
||||
pio->name, pin_mask, pio->pinmux_mask & pin_mask);
|
||||
spin_unlock(&pio_lock);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Reserve pins */
|
||||
pio->pinmux_mask |= pin_mask;
|
||||
spin_unlock(&pio_lock);
|
||||
return;
|
||||
|
||||
fail:
|
||||
dump_stack();
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/* GPIO API */
|
||||
|
||||
static int direction_input(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
struct pio_device *pio = container_of(chip, struct pio_device, chip);
|
||||
u32 mask = 1 << offset;
|
||||
|
||||
if (!(pio_readl(pio, PSR) & mask))
|
||||
return -EINVAL;
|
||||
|
||||
pio_writel(pio, ODR, mask);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gpio_get(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
struct pio_device *pio = container_of(chip, struct pio_device, chip);
|
||||
|
||||
return (pio_readl(pio, PDSR) >> offset) & 1;
|
||||
}
|
||||
|
||||
static void gpio_set(struct gpio_chip *chip, unsigned offset, int value);
|
||||
|
||||
static int direction_output(struct gpio_chip *chip, unsigned offset, int value)
|
||||
{
|
||||
struct pio_device *pio = container_of(chip, struct pio_device, chip);
|
||||
u32 mask = 1 << offset;
|
||||
|
||||
if (!(pio_readl(pio, PSR) & mask))
|
||||
return -EINVAL;
|
||||
|
||||
gpio_set(chip, offset, value);
|
||||
pio_writel(pio, OER, mask);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void gpio_set(struct gpio_chip *chip, unsigned offset, int value)
|
||||
{
|
||||
struct pio_device *pio = container_of(chip, struct pio_device, chip);
|
||||
u32 mask = 1 << offset;
|
||||
|
||||
if (value)
|
||||
pio_writel(pio, SODR, mask);
|
||||
else
|
||||
pio_writel(pio, CODR, mask);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/* GPIO IRQ support */
|
||||
|
||||
static void gpio_irq_mask(struct irq_data *d)
|
||||
{
|
||||
unsigned gpio = irq_to_gpio(d->irq);
|
||||
struct pio_device *pio = &pio_dev[gpio >> 5];
|
||||
|
||||
pio_writel(pio, IDR, 1 << (gpio & 0x1f));
|
||||
}
|
||||
|
||||
static void gpio_irq_unmask(struct irq_data *d)
|
||||
{
|
||||
unsigned gpio = irq_to_gpio(d->irq);
|
||||
struct pio_device *pio = &pio_dev[gpio >> 5];
|
||||
|
||||
pio_writel(pio, IER, 1 << (gpio & 0x1f));
|
||||
}
|
||||
|
||||
static int gpio_irq_type(struct irq_data *d, unsigned type)
|
||||
{
|
||||
if (type != IRQ_TYPE_EDGE_BOTH && type != IRQ_TYPE_NONE)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct irq_chip gpio_irqchip = {
|
||||
.name = "gpio",
|
||||
.irq_mask = gpio_irq_mask,
|
||||
.irq_unmask = gpio_irq_unmask,
|
||||
.irq_set_type = gpio_irq_type,
|
||||
};
|
||||
|
||||
static void gpio_irq_handler(unsigned irq, struct irq_desc *desc)
|
||||
{
|
||||
struct pio_device *pio = irq_desc_get_chip_data(desc);
|
||||
unsigned gpio_irq;
|
||||
|
||||
gpio_irq = (unsigned) irq_get_handler_data(irq);
|
||||
for (;;) {
|
||||
u32 isr;
|
||||
|
||||
/* ack pending GPIO interrupts */
|
||||
isr = pio_readl(pio, ISR) & pio_readl(pio, IMR);
|
||||
if (!isr)
|
||||
break;
|
||||
do {
|
||||
int i;
|
||||
|
||||
i = ffs(isr) - 1;
|
||||
isr &= ~(1 << i);
|
||||
|
||||
i += gpio_irq;
|
||||
generic_handle_irq(i);
|
||||
} while (isr);
|
||||
}
|
||||
}
|
||||
|
||||
static void __init
|
||||
gpio_irq_setup(struct pio_device *pio, int irq, int gpio_irq)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
irq_set_chip_data(irq, pio);
|
||||
irq_set_handler_data(irq, (void *)gpio_irq);
|
||||
|
||||
for (i = 0; i < 32; i++, gpio_irq++) {
|
||||
irq_set_chip_data(gpio_irq, pio);
|
||||
irq_set_chip_and_handler(gpio_irq, &gpio_irqchip,
|
||||
handle_simple_irq);
|
||||
}
|
||||
|
||||
irq_set_chained_handler(irq, gpio_irq_handler);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
|
||||
#include <linux/seq_file.h>
|
||||
|
||||
/*
|
||||
* This shows more info than the generic gpio dump code:
|
||||
* pullups, deglitching, open drain drive.
|
||||
*/
|
||||
static void pio_bank_show(struct seq_file *s, struct gpio_chip *chip)
|
||||
{
|
||||
struct pio_device *pio = container_of(chip, struct pio_device, chip);
|
||||
u32 psr, osr, imr, pdsr, pusr, ifsr, mdsr;
|
||||
unsigned i;
|
||||
u32 mask;
|
||||
char bank;
|
||||
|
||||
psr = pio_readl(pio, PSR);
|
||||
osr = pio_readl(pio, OSR);
|
||||
imr = pio_readl(pio, IMR);
|
||||
pdsr = pio_readl(pio, PDSR);
|
||||
pusr = pio_readl(pio, PUSR);
|
||||
ifsr = pio_readl(pio, IFSR);
|
||||
mdsr = pio_readl(pio, MDSR);
|
||||
|
||||
bank = 'A' + pio->pdev->id;
|
||||
|
||||
for (i = 0, mask = 1; i < 32; i++, mask <<= 1) {
|
||||
const char *label;
|
||||
|
||||
label = gpiochip_is_requested(chip, i);
|
||||
if (!label && (imr & mask))
|
||||
label = "[irq]";
|
||||
if (!label)
|
||||
continue;
|
||||
|
||||
seq_printf(s, " gpio-%-3d P%c%-2d (%-12s) %s %s %s",
|
||||
chip->base + i, bank, i,
|
||||
label,
|
||||
(osr & mask) ? "out" : "in ",
|
||||
(mask & pdsr) ? "hi" : "lo",
|
||||
(mask & pusr) ? " " : "up");
|
||||
if (ifsr & mask)
|
||||
seq_printf(s, " deglitch");
|
||||
if ((osr & mdsr) & mask)
|
||||
seq_printf(s, " open-drain");
|
||||
if (imr & mask)
|
||||
seq_printf(s, " irq-%d edge-both",
|
||||
gpio_to_irq(chip->base + i));
|
||||
seq_printf(s, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
#define pio_bank_show NULL
|
||||
#endif
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
static int __init pio_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct pio_device *pio = NULL;
|
||||
int irq = platform_get_irq(pdev, 0);
|
||||
int gpio_irq_base = GPIO_IRQ_BASE + pdev->id * 32;
|
||||
|
||||
BUG_ON(pdev->id >= MAX_NR_PIO_DEVICES);
|
||||
pio = &pio_dev[pdev->id];
|
||||
BUG_ON(!pio->regs);
|
||||
|
||||
pio->chip.label = pio->name;
|
||||
pio->chip.base = pdev->id * 32;
|
||||
pio->chip.ngpio = 32;
|
||||
pio->chip.dev = &pdev->dev;
|
||||
pio->chip.owner = THIS_MODULE;
|
||||
|
||||
pio->chip.direction_input = direction_input;
|
||||
pio->chip.get = gpio_get;
|
||||
pio->chip.direction_output = direction_output;
|
||||
pio->chip.set = gpio_set;
|
||||
pio->chip.dbg_show = pio_bank_show;
|
||||
|
||||
gpiochip_add(&pio->chip);
|
||||
|
||||
gpio_irq_setup(pio, irq, gpio_irq_base);
|
||||
|
||||
platform_set_drvdata(pdev, pio);
|
||||
|
||||
printk(KERN_DEBUG "%s: base 0x%p, irq %d chains %d..%d\n",
|
||||
pio->name, pio->regs, irq, gpio_irq_base, gpio_irq_base + 31);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver pio_driver = {
|
||||
.driver = {
|
||||
.name = "pio",
|
||||
},
|
||||
};
|
||||
|
||||
static int __init pio_init(void)
|
||||
{
|
||||
return platform_driver_probe(&pio_driver, pio_probe);
|
||||
}
|
||||
postcore_initcall(pio_init);
|
||||
|
||||
void __init at32_init_pio(struct platform_device *pdev)
|
||||
{
|
||||
struct resource *regs;
|
||||
struct pio_device *pio;
|
||||
|
||||
if (pdev->id > MAX_NR_PIO_DEVICES) {
|
||||
dev_err(&pdev->dev, "only %d PIO devices supported\n",
|
||||
MAX_NR_PIO_DEVICES);
|
||||
return;
|
||||
}
|
||||
|
||||
pio = &pio_dev[pdev->id];
|
||||
snprintf(pio->name, sizeof(pio->name), "pio%d", pdev->id);
|
||||
|
||||
regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!regs) {
|
||||
dev_err(&pdev->dev, "no mmio resource defined\n");
|
||||
return;
|
||||
}
|
||||
|
||||
pio->clk = clk_get(&pdev->dev, "mck");
|
||||
if (IS_ERR(pio->clk))
|
||||
/*
|
||||
* This is a fatal error, but if we continue we might
|
||||
* be so lucky that we manage to initialize the
|
||||
* console and display this message...
|
||||
*/
|
||||
dev_err(&pdev->dev, "no mck clock defined\n");
|
||||
else
|
||||
clk_enable(pio->clk);
|
||||
|
||||
pio->pdev = pdev;
|
||||
pio->regs = ioremap(regs->start, resource_size(regs));
|
||||
|
||||
/* start with irqs disabled and acked */
|
||||
pio_writel(pio, IDR, ~0UL);
|
||||
(void) pio_readl(pio, ISR);
|
||||
}
|
180
arch/avr32/mach-at32ap/pio.h
Normal file
180
arch/avr32/mach-at32ap/pio.h
Normal file
|
@ -0,0 +1,180 @@
|
|||
/*
|
||||
* Atmel PIO2 Port Multiplexer support
|
||||
*
|
||||
* Copyright (C) 2004-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 __ARCH_AVR32_AT32AP_PIO_H__
|
||||
#define __ARCH_AVR32_AT32AP_PIO_H__
|
||||
|
||||
/* PIO register offsets */
|
||||
#define PIO_PER 0x0000
|
||||
#define PIO_PDR 0x0004
|
||||
#define PIO_PSR 0x0008
|
||||
#define PIO_OER 0x0010
|
||||
#define PIO_ODR 0x0014
|
||||
#define PIO_OSR 0x0018
|
||||
#define PIO_IFER 0x0020
|
||||
#define PIO_IFDR 0x0024
|
||||
#define PIO_IFSR 0x0028
|
||||
#define PIO_SODR 0x0030
|
||||
#define PIO_CODR 0x0034
|
||||
#define PIO_ODSR 0x0038
|
||||
#define PIO_PDSR 0x003c
|
||||
#define PIO_IER 0x0040
|
||||
#define PIO_IDR 0x0044
|
||||
#define PIO_IMR 0x0048
|
||||
#define PIO_ISR 0x004c
|
||||
#define PIO_MDER 0x0050
|
||||
#define PIO_MDDR 0x0054
|
||||
#define PIO_MDSR 0x0058
|
||||
#define PIO_PUDR 0x0060
|
||||
#define PIO_PUER 0x0064
|
||||
#define PIO_PUSR 0x0068
|
||||
#define PIO_ASR 0x0070
|
||||
#define PIO_BSR 0x0074
|
||||
#define PIO_ABSR 0x0078
|
||||
#define PIO_OWER 0x00a0
|
||||
#define PIO_OWDR 0x00a4
|
||||
#define PIO_OWSR 0x00a8
|
||||
|
||||
/* Bitfields in PER */
|
||||
|
||||
/* Bitfields in PDR */
|
||||
|
||||
/* Bitfields in PSR */
|
||||
|
||||
/* Bitfields in OER */
|
||||
|
||||
/* Bitfields in ODR */
|
||||
|
||||
/* Bitfields in OSR */
|
||||
|
||||
/* Bitfields in IFER */
|
||||
|
||||
/* Bitfields in IFDR */
|
||||
|
||||
/* Bitfields in IFSR */
|
||||
|
||||
/* Bitfields in SODR */
|
||||
|
||||
/* Bitfields in CODR */
|
||||
|
||||
/* Bitfields in ODSR */
|
||||
|
||||
/* Bitfields in PDSR */
|
||||
|
||||
/* Bitfields in IER */
|
||||
|
||||
/* Bitfields in IDR */
|
||||
|
||||
/* Bitfields in IMR */
|
||||
|
||||
/* Bitfields in ISR */
|
||||
|
||||
/* Bitfields in MDER */
|
||||
|
||||
/* Bitfields in MDDR */
|
||||
|
||||
/* Bitfields in MDSR */
|
||||
|
||||
/* Bitfields in PUDR */
|
||||
|
||||
/* Bitfields in PUER */
|
||||
|
||||
/* Bitfields in PUSR */
|
||||
|
||||
/* Bitfields in ASR */
|
||||
|
||||
/* Bitfields in BSR */
|
||||
|
||||
/* Bitfields in ABSR */
|
||||
#define PIO_P0_OFFSET 0
|
||||
#define PIO_P0_SIZE 1
|
||||
#define PIO_P1_OFFSET 1
|
||||
#define PIO_P1_SIZE 1
|
||||
#define PIO_P2_OFFSET 2
|
||||
#define PIO_P2_SIZE 1
|
||||
#define PIO_P3_OFFSET 3
|
||||
#define PIO_P3_SIZE 1
|
||||
#define PIO_P4_OFFSET 4
|
||||
#define PIO_P4_SIZE 1
|
||||
#define PIO_P5_OFFSET 5
|
||||
#define PIO_P5_SIZE 1
|
||||
#define PIO_P6_OFFSET 6
|
||||
#define PIO_P6_SIZE 1
|
||||
#define PIO_P7_OFFSET 7
|
||||
#define PIO_P7_SIZE 1
|
||||
#define PIO_P8_OFFSET 8
|
||||
#define PIO_P8_SIZE 1
|
||||
#define PIO_P9_OFFSET 9
|
||||
#define PIO_P9_SIZE 1
|
||||
#define PIO_P10_OFFSET 10
|
||||
#define PIO_P10_SIZE 1
|
||||
#define PIO_P11_OFFSET 11
|
||||
#define PIO_P11_SIZE 1
|
||||
#define PIO_P12_OFFSET 12
|
||||
#define PIO_P12_SIZE 1
|
||||
#define PIO_P13_OFFSET 13
|
||||
#define PIO_P13_SIZE 1
|
||||
#define PIO_P14_OFFSET 14
|
||||
#define PIO_P14_SIZE 1
|
||||
#define PIO_P15_OFFSET 15
|
||||
#define PIO_P15_SIZE 1
|
||||
#define PIO_P16_OFFSET 16
|
||||
#define PIO_P16_SIZE 1
|
||||
#define PIO_P17_OFFSET 17
|
||||
#define PIO_P17_SIZE 1
|
||||
#define PIO_P18_OFFSET 18
|
||||
#define PIO_P18_SIZE 1
|
||||
#define PIO_P19_OFFSET 19
|
||||
#define PIO_P19_SIZE 1
|
||||
#define PIO_P20_OFFSET 20
|
||||
#define PIO_P20_SIZE 1
|
||||
#define PIO_P21_OFFSET 21
|
||||
#define PIO_P21_SIZE 1
|
||||
#define PIO_P22_OFFSET 22
|
||||
#define PIO_P22_SIZE 1
|
||||
#define PIO_P23_OFFSET 23
|
||||
#define PIO_P23_SIZE 1
|
||||
#define PIO_P24_OFFSET 24
|
||||
#define PIO_P24_SIZE 1
|
||||
#define PIO_P25_OFFSET 25
|
||||
#define PIO_P25_SIZE 1
|
||||
#define PIO_P26_OFFSET 26
|
||||
#define PIO_P26_SIZE 1
|
||||
#define PIO_P27_OFFSET 27
|
||||
#define PIO_P27_SIZE 1
|
||||
#define PIO_P28_OFFSET 28
|
||||
#define PIO_P28_SIZE 1
|
||||
#define PIO_P29_OFFSET 29
|
||||
#define PIO_P29_SIZE 1
|
||||
#define PIO_P30_OFFSET 30
|
||||
#define PIO_P30_SIZE 1
|
||||
#define PIO_P31_OFFSET 31
|
||||
#define PIO_P31_SIZE 1
|
||||
|
||||
/* Bitfields in OWER */
|
||||
|
||||
/* Bitfields in OWDR */
|
||||
|
||||
/* Bitfields in OWSR */
|
||||
|
||||
/* Bit manipulation macros */
|
||||
#define PIO_BIT(name) (1 << PIO_##name##_OFFSET)
|
||||
#define PIO_BF(name,value) (((value) & ((1 << PIO_##name##_SIZE) - 1)) << PIO_##name##_OFFSET)
|
||||
#define PIO_BFEXT(name,value) (((value) >> PIO_##name##_OFFSET) & ((1 << PIO_##name##_SIZE) - 1))
|
||||
#define PIO_BFINS(name,value,old) (((old) & ~(((1 << PIO_##name##_SIZE) - 1) << PIO_##name##_OFFSET)) | PIO_BF(name,value))
|
||||
|
||||
/* Register access macros */
|
||||
#define pio_readl(port,reg) \
|
||||
__raw_readl((port)->regs + PIO_##reg)
|
||||
#define pio_writel(port,reg,value) \
|
||||
__raw_writel((value), (port)->regs + PIO_##reg)
|
||||
|
||||
void at32_init_pio(struct platform_device *pdev);
|
||||
|
||||
#endif /* __ARCH_AVR32_AT32AP_PIO_H__ */
|
167
arch/avr32/mach-at32ap/pm-at32ap700x.S
Normal file
167
arch/avr32/mach-at32ap/pm-at32ap700x.S
Normal file
|
@ -0,0 +1,167 @@
|
|||
/*
|
||||
* 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 <mach/pm.h>
|
||||
|
||||
#include "pm.h"
|
||||
#include "sdramc.h"
|
||||
|
||||
/* Same as 0xfff00000 but fits in a 21 bit signed immediate */
|
||||
#define PM_BASE -0x100000
|
||||
|
||||
/* 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_enter_idle, . - cpu_enter_idle
|
||||
|
||||
/*
|
||||
* 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
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
.section .init.text, "ax", @progbits
|
||||
|
||||
.global pm_exception
|
||||
.type pm_exception, @function
|
||||
pm_exception:
|
||||
/*
|
||||
* Exceptions are masked when we switch to this handler, so
|
||||
* we'll only get "unrecoverable" exceptions (offset 0.)
|
||||
*/
|
||||
sub r12, pc, . - .Lpanic_msg
|
||||
lddpc pc, .Lpanic_addr
|
||||
|
||||
.align 2
|
||||
.Lpanic_addr:
|
||||
.long panic
|
||||
.Lpanic_msg:
|
||||
.asciz "Unrecoverable exception during suspend\n"
|
||||
.size pm_exception, . - pm_exception
|
||||
|
||||
.global pm_irq0
|
||||
.type pm_irq0, @function
|
||||
pm_irq0:
|
||||
/* Disable interrupts and return after the sleep instruction */
|
||||
mfsr r9, SYSREG_RSR_INT0
|
||||
mtsr SYSREG_RAR_INT0, r8
|
||||
sbr r9, SYSREG_GM_OFFSET
|
||||
mtsr SYSREG_RSR_INT0, r9
|
||||
rete
|
||||
|
||||
/*
|
||||
* void cpu_enter_standby(unsigned long sdramc_base)
|
||||
*
|
||||
* Enter PM_SUSPEND_STANDBY mode. At this point, all drivers
|
||||
* are suspended and interrupts are disabled. Interrupts
|
||||
* marked as 'wakeup' event sources may still come along and
|
||||
* get us out of here.
|
||||
*
|
||||
* The SDRAM will be put into self-refresh mode (which does
|
||||
* not require a clock from the CPU), and the CPU will be put
|
||||
* into "frozen" mode (HSB bus stopped). The SDRAM controller
|
||||
* will automatically bring the SDRAM into normal mode on the
|
||||
* first access, and the power manager will automatically
|
||||
* start the HSB and CPU clocks upon a wakeup event.
|
||||
*
|
||||
* This code uses the same "skip sleep" technique as above.
|
||||
* It is very important that we jump directly to
|
||||
* cpu_after_sleep after the sleep instruction since that's
|
||||
* where we'll end up if the interrupt handler decides that we
|
||||
* need to skip the sleep instruction.
|
||||
*/
|
||||
.global pm_standby
|
||||
.type pm_standby, @function
|
||||
pm_standby:
|
||||
/*
|
||||
* interrupts are already masked at this point, and EVBA
|
||||
* points to pm_exception above.
|
||||
*/
|
||||
ld.w r10, r12[SDRAMC_LPR]
|
||||
sub r8, pc, . - 1f /* return address for irq handler */
|
||||
mov r11, SDRAMC_LPR_LPCB_SELF_RFR
|
||||
bfins r10, r11, 0, 2 /* LPCB <- self Refresh */
|
||||
sync 0 /* flush write buffer */
|
||||
st.w r12[SDRAMC_LPR], r10 /* put SDRAM in self-refresh mode */
|
||||
ld.w r11, r12[SDRAMC_LPR]
|
||||
unmask_interrupts
|
||||
sleep CPU_SLEEP_FROZEN
|
||||
1: mask_interrupts
|
||||
retal r12
|
||||
.size pm_standby, . - pm_standby
|
||||
|
||||
.global pm_suspend_to_ram
|
||||
.type pm_suspend_to_ram, @function
|
||||
pm_suspend_to_ram:
|
||||
/*
|
||||
* interrupts are already masked at this point, and EVBA
|
||||
* points to pm_exception above.
|
||||
*/
|
||||
mov r11, 0
|
||||
cache r11[2], 8 /* clean all dcache lines */
|
||||
sync 0 /* flush write buffer */
|
||||
ld.w r10, r12[SDRAMC_LPR]
|
||||
sub r8, pc, . - 1f /* return address for irq handler */
|
||||
mov r11, SDRAMC_LPR_LPCB_SELF_RFR
|
||||
bfins r10, r11, 0, 2 /* LPCB <- self refresh */
|
||||
st.w r12[SDRAMC_LPR], r10 /* put SDRAM in self-refresh mode */
|
||||
ld.w r11, r12[SDRAMC_LPR]
|
||||
|
||||
unmask_interrupts
|
||||
sleep CPU_SLEEP_STOP
|
||||
1: mask_interrupts
|
||||
|
||||
retal r12
|
||||
.size pm_suspend_to_ram, . - pm_suspend_to_ram
|
||||
|
||||
.global pm_sram_end
|
||||
.type pm_sram_end, @function
|
||||
pm_sram_end:
|
||||
.size pm_sram_end, 0
|
||||
|
||||
#endif /* CONFIG_PM */
|
243
arch/avr32/mach-at32ap/pm.c
Normal file
243
arch/avr32/mach-at32ap/pm.c
Normal file
|
@ -0,0 +1,243 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
#include <linux/io.h>
|
||||
#include <linux/suspend.h>
|
||||
#include <linux/vmalloc.h>
|
||||
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/sysreg.h>
|
||||
|
||||
#include <mach/chip.h>
|
||||
#include <mach/pm.h>
|
||||
#include <mach/sram.h>
|
||||
|
||||
#include "sdramc.h"
|
||||
|
||||
#define SRAM_PAGE_FLAGS (SYSREG_BIT(TLBELO_D) | SYSREG_BF(SZ, 1) \
|
||||
| SYSREG_BF(AP, 3) | SYSREG_BIT(G))
|
||||
|
||||
|
||||
static unsigned long pm_sram_start;
|
||||
static size_t pm_sram_size;
|
||||
static struct vm_struct *pm_sram_area;
|
||||
|
||||
static void (*avr32_pm_enter_standby)(unsigned long sdramc_base);
|
||||
static void (*avr32_pm_enter_str)(unsigned long sdramc_base);
|
||||
|
||||
/*
|
||||
* Must be called with interrupts disabled. Exceptions will be masked
|
||||
* on return (i.e. all exceptions will be "unrecoverable".)
|
||||
*/
|
||||
static void *avr32_pm_map_sram(void)
|
||||
{
|
||||
unsigned long vaddr;
|
||||
unsigned long page_addr;
|
||||
u32 tlbehi;
|
||||
u32 mmucr;
|
||||
|
||||
vaddr = (unsigned long)pm_sram_area->addr;
|
||||
page_addr = pm_sram_start & PAGE_MASK;
|
||||
|
||||
/*
|
||||
* Mask exceptions and grab the first TLB entry. We won't be
|
||||
* needing it while sleeping.
|
||||
*/
|
||||
asm volatile("ssrf %0" : : "i"(SYSREG_EM_OFFSET) : "memory");
|
||||
|
||||
mmucr = sysreg_read(MMUCR);
|
||||
tlbehi = sysreg_read(TLBEHI);
|
||||
sysreg_write(MMUCR, SYSREG_BFINS(DRP, 0, mmucr));
|
||||
|
||||
tlbehi = SYSREG_BF(ASID, SYSREG_BFEXT(ASID, tlbehi));
|
||||
tlbehi |= vaddr & PAGE_MASK;
|
||||
tlbehi |= SYSREG_BIT(TLBEHI_V);
|
||||
|
||||
sysreg_write(TLBELO, page_addr | SRAM_PAGE_FLAGS);
|
||||
sysreg_write(TLBEHI, tlbehi);
|
||||
__builtin_tlbw();
|
||||
|
||||
return (void *)(vaddr + pm_sram_start - page_addr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Must be called with interrupts disabled. Exceptions will be
|
||||
* unmasked on return.
|
||||
*/
|
||||
static void avr32_pm_unmap_sram(void)
|
||||
{
|
||||
u32 mmucr;
|
||||
u32 tlbehi;
|
||||
u32 tlbarlo;
|
||||
|
||||
/* Going to update TLB entry at index 0 */
|
||||
mmucr = sysreg_read(MMUCR);
|
||||
tlbehi = sysreg_read(TLBEHI);
|
||||
sysreg_write(MMUCR, SYSREG_BFINS(DRP, 0, mmucr));
|
||||
|
||||
/* Clear the "valid" bit */
|
||||
tlbehi = SYSREG_BF(ASID, SYSREG_BFEXT(ASID, tlbehi));
|
||||
sysreg_write(TLBEHI, tlbehi);
|
||||
|
||||
/* Mark it as "not accessed" */
|
||||
tlbarlo = sysreg_read(TLBARLO);
|
||||
sysreg_write(TLBARLO, tlbarlo | 0x80000000U);
|
||||
|
||||
/* Update the TLB */
|
||||
__builtin_tlbw();
|
||||
|
||||
/* Unmask exceptions */
|
||||
asm volatile("csrf %0" : : "i"(SYSREG_EM_OFFSET) : "memory");
|
||||
}
|
||||
|
||||
static int avr32_pm_valid_state(suspend_state_t state)
|
||||
{
|
||||
switch (state) {
|
||||
case PM_SUSPEND_ON:
|
||||
case PM_SUSPEND_STANDBY:
|
||||
case PM_SUSPEND_MEM:
|
||||
return 1;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int avr32_pm_enter(suspend_state_t state)
|
||||
{
|
||||
u32 lpr_saved;
|
||||
u32 evba_saved;
|
||||
void *sram;
|
||||
|
||||
switch (state) {
|
||||
case PM_SUSPEND_STANDBY:
|
||||
sram = avr32_pm_map_sram();
|
||||
|
||||
/* Switch to in-sram exception handlers */
|
||||
evba_saved = sysreg_read(EVBA);
|
||||
sysreg_write(EVBA, (unsigned long)sram);
|
||||
|
||||
/*
|
||||
* Save the LPR register so that we can re-enable
|
||||
* SDRAM Low Power mode on resume.
|
||||
*/
|
||||
lpr_saved = sdramc_readl(LPR);
|
||||
pr_debug("%s: Entering standby...\n", __func__);
|
||||
avr32_pm_enter_standby(SDRAMC_BASE);
|
||||
sdramc_writel(LPR, lpr_saved);
|
||||
|
||||
/* Switch back to regular exception handlers */
|
||||
sysreg_write(EVBA, evba_saved);
|
||||
|
||||
avr32_pm_unmap_sram();
|
||||
break;
|
||||
|
||||
case PM_SUSPEND_MEM:
|
||||
sram = avr32_pm_map_sram();
|
||||
|
||||
/* Switch to in-sram exception handlers */
|
||||
evba_saved = sysreg_read(EVBA);
|
||||
sysreg_write(EVBA, (unsigned long)sram);
|
||||
|
||||
/*
|
||||
* Save the LPR register so that we can re-enable
|
||||
* SDRAM Low Power mode on resume.
|
||||
*/
|
||||
lpr_saved = sdramc_readl(LPR);
|
||||
pr_debug("%s: Entering suspend-to-ram...\n", __func__);
|
||||
avr32_pm_enter_str(SDRAMC_BASE);
|
||||
sdramc_writel(LPR, lpr_saved);
|
||||
|
||||
/* Switch back to regular exception handlers */
|
||||
sysreg_write(EVBA, evba_saved);
|
||||
|
||||
avr32_pm_unmap_sram();
|
||||
break;
|
||||
|
||||
case PM_SUSPEND_ON:
|
||||
pr_debug("%s: Entering idle...\n", __func__);
|
||||
cpu_enter_idle();
|
||||
break;
|
||||
|
||||
default:
|
||||
pr_debug("%s: Invalid suspend state %d\n", __func__, state);
|
||||
goto out;
|
||||
}
|
||||
|
||||
pr_debug("%s: wakeup\n", __func__);
|
||||
|
||||
out:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct platform_suspend_ops avr32_pm_ops = {
|
||||
.valid = avr32_pm_valid_state,
|
||||
.enter = avr32_pm_enter,
|
||||
};
|
||||
|
||||
static unsigned long __init avr32_pm_offset(void *symbol)
|
||||
{
|
||||
extern u8 pm_exception[];
|
||||
|
||||
return (unsigned long)symbol - (unsigned long)pm_exception;
|
||||
}
|
||||
|
||||
static int __init avr32_pm_init(void)
|
||||
{
|
||||
extern u8 pm_exception[];
|
||||
extern u8 pm_irq0[];
|
||||
extern u8 pm_standby[];
|
||||
extern u8 pm_suspend_to_ram[];
|
||||
extern u8 pm_sram_end[];
|
||||
void *dst;
|
||||
|
||||
/*
|
||||
* To keep things simple, we depend on not needing more than a
|
||||
* single page.
|
||||
*/
|
||||
pm_sram_size = avr32_pm_offset(pm_sram_end);
|
||||
if (pm_sram_size > PAGE_SIZE)
|
||||
goto err;
|
||||
|
||||
pm_sram_start = sram_alloc(pm_sram_size);
|
||||
if (!pm_sram_start)
|
||||
goto err_alloc_sram;
|
||||
|
||||
/* Grab a virtual area we can use later on. */
|
||||
pm_sram_area = get_vm_area(pm_sram_size, VM_IOREMAP);
|
||||
if (!pm_sram_area)
|
||||
goto err_vm_area;
|
||||
pm_sram_area->phys_addr = pm_sram_start;
|
||||
|
||||
local_irq_disable();
|
||||
dst = avr32_pm_map_sram();
|
||||
memcpy(dst, pm_exception, pm_sram_size);
|
||||
flush_dcache_region(dst, pm_sram_size);
|
||||
invalidate_icache_region(dst, pm_sram_size);
|
||||
avr32_pm_unmap_sram();
|
||||
local_irq_enable();
|
||||
|
||||
avr32_pm_enter_standby = dst + avr32_pm_offset(pm_standby);
|
||||
avr32_pm_enter_str = dst + avr32_pm_offset(pm_suspend_to_ram);
|
||||
intc_set_suspend_handler(avr32_pm_offset(pm_irq0));
|
||||
|
||||
suspend_set_ops(&avr32_pm_ops);
|
||||
|
||||
printk("AVR32 AP Power Management enabled\n");
|
||||
|
||||
return 0;
|
||||
|
||||
err_vm_area:
|
||||
sram_free(pm_sram_start, pm_sram_size);
|
||||
err_alloc_sram:
|
||||
err:
|
||||
pr_err("AVR32 Power Management initialization failed\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
arch_initcall(avr32_pm_init);
|
112
arch/avr32/mach-at32ap/pm.h
Normal file
112
arch/avr32/mach-at32ap/pm.h
Normal file
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
* 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 __force *)PM_BASE + PM_##reg)
|
||||
#define pm_writel(reg,value) \
|
||||
__raw_writel((value), (void __iomem __force *)PM_BASE + PM_##reg)
|
||||
|
||||
#endif /* __ARCH_AVR32_MACH_AT32AP_PM_H__ */
|
76
arch/avr32/mach-at32ap/sdramc.h
Normal file
76
arch/avr32/mach-at32ap/sdramc.h
Normal file
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* Register definitions for the AT32AP SDRAM Controller
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* Register offsets */
|
||||
#define SDRAMC_MR 0x0000
|
||||
#define SDRAMC_TR 0x0004
|
||||
#define SDRAMC_CR 0x0008
|
||||
#define SDRAMC_HSR 0x000c
|
||||
#define SDRAMC_LPR 0x0010
|
||||
#define SDRAMC_IER 0x0014
|
||||
#define SDRAMC_IDR 0x0018
|
||||
#define SDRAMC_IMR 0x001c
|
||||
#define SDRAMC_ISR 0x0020
|
||||
#define SDRAMC_MDR 0x0024
|
||||
|
||||
/* MR - Mode Register */
|
||||
#define SDRAMC_MR_MODE_NORMAL ( 0 << 0)
|
||||
#define SDRAMC_MR_MODE_NOP ( 1 << 0)
|
||||
#define SDRAMC_MR_MODE_BANKS_PRECHARGE ( 2 << 0)
|
||||
#define SDRAMC_MR_MODE_LOAD_MODE ( 3 << 0)
|
||||
#define SDRAMC_MR_MODE_AUTO_REFRESH ( 4 << 0)
|
||||
#define SDRAMC_MR_MODE_EXT_LOAD_MODE ( 5 << 0)
|
||||
#define SDRAMC_MR_MODE_POWER_DOWN ( 6 << 0)
|
||||
|
||||
/* CR - Configuration Register */
|
||||
#define SDRAMC_CR_NC_8_BITS ( 0 << 0)
|
||||
#define SDRAMC_CR_NC_9_BITS ( 1 << 0)
|
||||
#define SDRAMC_CR_NC_10_BITS ( 2 << 0)
|
||||
#define SDRAMC_CR_NC_11_BITS ( 3 << 0)
|
||||
#define SDRAMC_CR_NR_11_BITS ( 0 << 2)
|
||||
#define SDRAMC_CR_NR_12_BITS ( 1 << 2)
|
||||
#define SDRAMC_CR_NR_13_BITS ( 2 << 2)
|
||||
#define SDRAMC_CR_NB_2_BANKS ( 0 << 4)
|
||||
#define SDRAMC_CR_NB_4_BANKS ( 1 << 4)
|
||||
#define SDRAMC_CR_CAS(x) ((x) << 5)
|
||||
#define SDRAMC_CR_DBW_32_BITS ( 0 << 7)
|
||||
#define SDRAMC_CR_DBW_16_BITS ( 1 << 7)
|
||||
#define SDRAMC_CR_TWR(x) ((x) << 8)
|
||||
#define SDRAMC_CR_TRC(x) ((x) << 12)
|
||||
#define SDRAMC_CR_TRP(x) ((x) << 16)
|
||||
#define SDRAMC_CR_TRCD(x) ((x) << 20)
|
||||
#define SDRAMC_CR_TRAS(x) ((x) << 24)
|
||||
#define SDRAMC_CR_TXSR(x) ((x) << 28)
|
||||
|
||||
/* HSR - High Speed Register */
|
||||
#define SDRAMC_HSR_DA ( 1 << 0)
|
||||
|
||||
/* LPR - Low Power Register */
|
||||
#define SDRAMC_LPR_LPCB_INHIBIT ( 0 << 0)
|
||||
#define SDRAMC_LPR_LPCB_SELF_RFR ( 1 << 0)
|
||||
#define SDRAMC_LPR_LPCB_PDOWN ( 2 << 0)
|
||||
#define SDRAMC_LPR_LPCB_DEEP_PDOWN ( 3 << 0)
|
||||
#define SDRAMC_LPR_PASR(x) ((x) << 4)
|
||||
#define SDRAMC_LPR_TCSR(x) ((x) << 8)
|
||||
#define SDRAMC_LPR_DS(x) ((x) << 10)
|
||||
#define SDRAMC_LPR_TIMEOUT(x) ((x) << 12)
|
||||
|
||||
/* IER/IDR/IMR/ISR - Interrupt Enable/Disable/Mask/Status Register */
|
||||
#define SDRAMC_ISR_RES ( 1 << 0)
|
||||
|
||||
/* MDR - Memory Device Register */
|
||||
#define SDRAMC_MDR_MD_SDRAM ( 0 << 0)
|
||||
#define SDRAMC_MDR_MD_LOW_PWR_SDRAM ( 1 << 0)
|
||||
|
||||
/* Register access macros */
|
||||
#define sdramc_readl(reg) \
|
||||
__raw_readl((void __iomem __force *)SDRAMC_BASE + SDRAMC_##reg)
|
||||
#define sdramc_writel(reg, value) \
|
||||
__raw_writel(value, (void __iomem __force *)SDRAMC_BASE + SDRAMC_##reg)
|
Loading…
Add table
Add a link
Reference in a new issue