Fixed MTP to work with TWRP

This commit is contained in:
awab228 2018-06-19 23:16:04 +02:00
commit f6dfaef42e
50820 changed files with 20846062 additions and 0 deletions

View 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

View 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

File diff suppressed because it is too large Load diff

View 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

View 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);

View 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);

View 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);
}

View 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);

View 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__ */

View 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__ */

View 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 */

View 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 */

View 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__ */

View 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 */

View 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 */

View 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 */

View 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__ */

View 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 */

View 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 */

View 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 */

View 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__ */

View 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 */

View 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 */

View 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);

View 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__ */

View 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);

View 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);
}

View 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__ */

View 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
View 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
View 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__ */

View 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)