summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-11 19:13:44 -0700
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-11 19:13:44 -0700
commit55982fd184a065b1c69279d29cbc01dbf424d2f4 (patch)
tree9b309cba341736a0766249ba51972a8ca040e502 /arch
parent1ef3e36251e4edc77a48967d015a87ca3c4283ea (diff)
parenta7e30b8d91d3291de4543d97849193ebc3ec4c1c (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/hskinnemoen/avr32-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/hskinnemoen/avr32-2.6: [AVR32] Fix random segfault with preemption [AVR32] Don't use __builtin_xchg() [AVR32] ngw100 i2c-gpio tweaks [AVR32] Ignore a few irrelevant syscalls [AVR32] SMC configuration in clock cycles [AVR32] Drop support for redundant "keepinitrd" boot-time parm. [AVR32] Make dma_sync_*_for_cpu no-ops [AVR32] Remove unneeded 8K alignment of .text section [AVR32] Kill a few hardcoded constants in vmlinux.lds [AVR32] rename vmlinux.lds [AVR32] fix command line parsing in early_parse_fbmem [AVR32] checkstack support [AVR32] Wire up USBA device [AVR32] add multidrive support for pio driver [AVR32] /sys/kernel/debug/at32ap_clk [AVR32] Move AT32_PM_BASE definition into pm.h
Diffstat (limited to 'arch')
-rw-r--r--arch/avr32/boards/atngw100/flash.c5
-rw-r--r--arch/avr32/boards/atngw100/setup.c14
-rw-r--r--arch/avr32/boards/atstk1000/atstk1002.c1
-rw-r--r--arch/avr32/boards/atstk1000/flash.c5
-rw-r--r--arch/avr32/kernel/Makefile5
-rw-r--r--arch/avr32/kernel/entry-avr32b.S26
-rw-r--r--arch/avr32/kernel/setup.c2
-rw-r--r--arch/avr32/kernel/vmlinux.lds.S (renamed from arch/avr32/kernel/vmlinux.lds.c)9
-rw-r--r--arch/avr32/mach-at32ap/at32ap7000.c74
-rw-r--r--arch/avr32/mach-at32ap/clock.c116
-rw-r--r--arch/avr32/mach-at32ap/hsmc.c129
-rw-r--r--arch/avr32/mach-at32ap/pio.c4
-rw-r--r--arch/avr32/mach-at32ap/pm.h8
-rw-r--r--arch/avr32/mm/init.c12
14 files changed, 359 insertions, 51 deletions
diff --git a/arch/avr32/boards/atngw100/flash.c b/arch/avr32/boards/atngw100/flash.c
index f9b32a8eab9b..b07ae63aa548 100644
--- a/arch/avr32/boards/atngw100/flash.c
+++ b/arch/avr32/boards/atngw100/flash.c
@@ -15,7 +15,7 @@
#include <asm/arch/smc.h>
-static struct smc_config flash_config __initdata = {
+static struct smc_timing flash_timing __initdata = {
.ncs_read_setup = 0,
.nrd_setup = 40,
.ncs_write_setup = 0,
@@ -28,7 +28,9 @@ static struct smc_config flash_config __initdata = {
.read_cycle = 120,
.write_cycle = 120,
+};
+static struct smc_config flash_config __initdata = {
.bus_width = 2,
.nrd_controlled = 1,
.nwe_controlled = 1,
@@ -82,6 +84,7 @@ static int __init atngw100_flash_init(void)
{
int ret;
+ smc_set_timing(&flash_config, &flash_timing);
ret = smc_set_configuration(0, &flash_config);
if (ret < 0) {
printk(KERN_ERR "atngw100: failed to set NOR flash timing\n");
diff --git a/arch/avr32/boards/atngw100/setup.c b/arch/avr32/boards/atngw100/setup.c
index ef801563bbf5..52987c81d668 100644
--- a/arch/avr32/boards/atngw100/setup.c
+++ b/arch/avr32/boards/atngw100/setup.c
@@ -125,8 +125,11 @@ static struct platform_device ngw_gpio_leds = {
};
static struct i2c_gpio_platform_data i2c_gpio_data = {
- .sda_pin = GPIO_PIN_PA(6),
- .scl_pin = GPIO_PIN_PA(7),
+ .sda_pin = GPIO_PIN_PA(6),
+ .scl_pin = GPIO_PIN_PA(7),
+ .sda_is_open_drain = 1,
+ .scl_is_open_drain = 1,
+ .udelay = 2, /* close to 100 kHz */
};
static struct platform_device i2c_gpio_device = {
@@ -154,6 +157,7 @@ static int __init atngw100_init(void)
set_hw_addr(at32_add_device_eth(1, &eth_data[1]));
at32_add_device_spi(0, spi0_board_info, ARRAY_SIZE(spi0_board_info));
+ at32_add_device_usba(0, NULL);
for (i = 0; i < ARRAY_SIZE(ngw_leds); i++) {
at32_select_gpio(ngw_leds[i].gpio,
@@ -161,8 +165,10 @@ static int __init atngw100_init(void)
}
platform_device_register(&ngw_gpio_leds);
- at32_select_gpio(i2c_gpio_data.sda_pin, 0);
- at32_select_gpio(i2c_gpio_data.scl_pin, 0);
+ at32_select_gpio(i2c_gpio_data.sda_pin,
+ AT32_GPIOF_MULTIDRV | AT32_GPIOF_OUTPUT | AT32_GPIOF_HIGH);
+ at32_select_gpio(i2c_gpio_data.scl_pin,
+ AT32_GPIOF_MULTIDRV | AT32_GPIOF_OUTPUT | AT32_GPIOF_HIGH);
platform_device_register(&i2c_gpio_device);
return 0;
diff --git a/arch/avr32/boards/atstk1000/atstk1002.c b/arch/avr32/boards/atstk1000/atstk1002.c
index c9981b731efa..6b9e466104ad 100644
--- a/arch/avr32/boards/atstk1000/atstk1002.c
+++ b/arch/avr32/boards/atstk1000/atstk1002.c
@@ -241,6 +241,7 @@ static int __init atstk1002_init(void)
at32_add_device_lcdc(0, &atstk1000_lcdc_data,
fbmem_start, fbmem_size);
#endif
+ at32_add_device_usba(0, NULL);
#ifndef CONFIG_BOARD_ATSTK1002_SW3_CUSTOM
at32_add_device_ssc(0, ATMEL_SSC_TX);
#endif
diff --git a/arch/avr32/boards/atstk1000/flash.c b/arch/avr32/boards/atstk1000/flash.c
index aac4300cca12..3d0a102ad45e 100644
--- a/arch/avr32/boards/atstk1000/flash.c
+++ b/arch/avr32/boards/atstk1000/flash.c
@@ -15,7 +15,7 @@
#include <asm/arch/smc.h>
-static struct smc_config flash_config __initdata = {
+static struct smc_timing flash_timing __initdata = {
.ncs_read_setup = 0,
.nrd_setup = 40,
.ncs_write_setup = 0,
@@ -28,7 +28,9 @@ static struct smc_config flash_config __initdata = {
.read_cycle = 120,
.write_cycle = 120,
+};
+static struct smc_config flash_config __initdata = {
.bus_width = 2,
.nrd_controlled = 1,
.nwe_controlled = 1,
@@ -82,6 +84,7 @@ static int __init atstk1000_flash_init(void)
{
int ret;
+ smc_set_timing(&flash_config, &flash_timing);
ret = smc_set_configuration(0, &flash_config);
if (ret < 0) {
printk(KERN_ERR "atstk1000: failed to set NOR flash timing\n");
diff --git a/arch/avr32/kernel/Makefile b/arch/avr32/kernel/Makefile
index 90e5afff54a2..989fcd1fef7e 100644
--- a/arch/avr32/kernel/Makefile
+++ b/arch/avr32/kernel/Makefile
@@ -11,8 +11,3 @@ obj-y += signal.o sys_avr32.o process.o time.o
obj-y += init_task.o switch_to.o cpu.o
obj-$(CONFIG_MODULES) += module.o avr32_ksyms.o
obj-$(CONFIG_KPROBES) += kprobes.o
-
-USE_STANDARD_AS_RULE := true
-
-%.lds: %.lds.c FORCE
- $(call if_changed_dep,cpp_lds_S)
diff --git a/arch/avr32/kernel/entry-avr32b.S b/arch/avr32/kernel/entry-avr32b.S
index 42657f1703b2..ccadfd9b438d 100644
--- a/arch/avr32/kernel/entry-avr32b.S
+++ b/arch/avr32/kernel/entry-avr32b.S
@@ -159,11 +159,18 @@ handle_vmalloc_miss:
.section .scall.text,"ax",@progbits
system_call:
+#ifdef CONFIG_PREEMPT
+ mask_interrupts
+#endif
pushm r12 /* r12_orig */
stmts --sp, r0-lr
- zero_fp
+
mfsr r0, SYSREG_RAR_SUP
mfsr r1, SYSREG_RSR_SUP
+#ifdef CONFIG_PREEMPT
+ unmask_interrupts
+#endif
+ zero_fp
stm --sp, r0-r1
/* check for syscall tracing */
@@ -638,6 +645,13 @@ irq_level\level:
stmts --sp,r0-lr
mfsr r8, rar_int\level
mfsr r9, rsr_int\level
+
+#ifdef CONFIG_PREEMPT
+ sub r11, pc, (. - system_call)
+ cp.w r11, r8
+ breq 4f
+#endif
+
pushm r8-r9
mov r11, sp
@@ -668,6 +682,16 @@ irq_level\level:
sub sp, -4 /* ignore r12_orig */
rete
+#ifdef CONFIG_PREEMPT
+4: mask_interrupts
+ mfsr r8, rsr_int\level
+ sbr r8, 16
+ mtsr rsr_int\level, r8
+ ldmts sp++, r0-lr
+ sub sp, -4 /* ignore r12_orig */
+ rete
+#endif
+
2: get_thread_info r0
ld.w r1, r0[TI_flags]
bld r1, TIF_CPU_GOING_TO_SLEEP
diff --git a/arch/avr32/kernel/setup.c b/arch/avr32/kernel/setup.c
index d08b0bc6b2bb..4b4c1884e1c5 100644
--- a/arch/avr32/kernel/setup.c
+++ b/arch/avr32/kernel/setup.c
@@ -248,7 +248,7 @@ static int __init early_parse_fbmem(char *p)
fbmem_size = memparse(p, &p);
if (*p == '@') {
- fbmem_start = memparse(p, &p);
+ fbmem_start = memparse(p + 1, &p);
ret = add_reserved_region(fbmem_start,
fbmem_start + fbmem_size - 1,
"Framebuffer");
diff --git a/arch/avr32/kernel/vmlinux.lds.c b/arch/avr32/kernel/vmlinux.lds.S
index db0438f35c00..ce9ac9659883 100644
--- a/arch/avr32/kernel/vmlinux.lds.c
+++ b/arch/avr32/kernel/vmlinux.lds.S
@@ -9,6 +9,8 @@
*/
#define LOAD_OFFSET 0x00000000
#include <asm-generic/vmlinux.lds.h>
+#include <asm/cache.h>
+#include <asm/thread_info.h>
OUTPUT_FORMAT("elf32-avr32", "elf32-avr32", "elf32-avr32")
OUTPUT_ARCH(avr32)
@@ -58,11 +60,10 @@ SECTIONS
*(.init.ramfs)
__initramfs_end = .;
#endif
- . = ALIGN(4096);
+ . = ALIGN(PAGE_SIZE);
__init_end = .;
}
- . = ALIGN(8192);
.text : AT(ADDR(.text) - LOAD_OFFSET) {
_evba = .;
_text = .;
@@ -96,7 +97,7 @@ SECTIONS
RODATA
- . = ALIGN(8192);
+ . = ALIGN(THREAD_SIZE);
.data : AT(ADDR(.data) - LOAD_OFFSET) {
_data = .;
@@ -107,7 +108,7 @@ SECTIONS
*(.data.init_task)
/* Then, the cacheline aligned data */
- . = ALIGN(32);
+ . = ALIGN(L1_CACHE_BYTES);
*(.data.cacheline_aligned)
/* And the rest... */
diff --git a/arch/avr32/mach-at32ap/at32ap7000.c b/arch/avr32/mach-at32ap/at32ap7000.c
index 64cc5583ddfb..f6d154ca4d24 100644
--- a/arch/avr32/mach-at32ap/at32ap7000.c
+++ b/arch/avr32/mach-at32ap/at32ap7000.c
@@ -25,12 +25,6 @@
#include "pio.h"
#include "pm.h"
-/*
- * We can reduce the code size a bit by using a constant here. Since
- * this file is completely chip-specific, it's safe to not use
- * ioremap. Generic drivers should of course never do this.
- */
-#define AT32_PM_BASE 0xfff00000
#define PBMEM(base) \
{ \
@@ -1168,6 +1162,72 @@ at32_add_device_ssc(unsigned int id, unsigned int flags)
}
/* --------------------------------------------------------------------
+ * USB Device Controller
+ * -------------------------------------------------------------------- */
+static struct resource usba0_resource[] __initdata = {
+ {
+ .start = 0xff300000,
+ .end = 0xff3fffff,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = 0xfff03000,
+ .end = 0xfff033ff,
+ .flags = IORESOURCE_MEM,
+ },
+ IRQ(31),
+};
+static struct clk usba0_pclk = {
+ .name = "pclk",
+ .parent = &pbb_clk,
+ .mode = pbb_clk_mode,
+ .get_rate = pbb_clk_get_rate,
+ .index = 12,
+};
+static struct clk usba0_hclk = {
+ .name = "hclk",
+ .parent = &hsb_clk,
+ .mode = hsb_clk_mode,
+ .get_rate = hsb_clk_get_rate,
+ .index = 6,
+};
+
+struct platform_device *__init
+at32_add_device_usba(unsigned int id, struct usba_platform_data *data)
+{
+ struct platform_device *pdev;
+
+ if (id != 0)
+ return NULL;
+
+ pdev = platform_device_alloc("atmel_usba_udc", 0);
+ if (!pdev)
+ return NULL;
+
+ if (platform_device_add_resources(pdev, usba0_resource,
+ ARRAY_SIZE(usba0_resource)))
+ goto out_free_pdev;
+
+ if (data) {
+ if (platform_device_add_data(pdev, data, sizeof(*data)))
+ goto out_free_pdev;
+
+ if (data->vbus_pin != GPIO_PIN_NONE)
+ at32_select_gpio(data->vbus_pin, 0);
+ }
+
+ usba0_pclk.dev = &pdev->dev;
+ usba0_hclk.dev = &pdev->dev;
+
+ platform_device_add(pdev);
+
+ return pdev;
+
+out_free_pdev:
+ platform_device_put(pdev);
+ return NULL;
+}
+
+/* --------------------------------------------------------------------
* GCLK
* -------------------------------------------------------------------- */
static struct clk gclk0 = {
@@ -1252,6 +1312,8 @@ struct clk *at32_clock_list[] = {
&ssc0_pclk,
&ssc1_pclk,
&ssc2_pclk,
+ &usba0_hclk,
+ &usba0_pclk,
&gclk0,
&gclk1,
&gclk2,
diff --git a/arch/avr32/mach-at32ap/clock.c b/arch/avr32/mach-at32ap/clock.c
index 0f8c89c9f832..4642117cc9ab 100644
--- a/arch/avr32/mach-at32ap/clock.c
+++ b/arch/avr32/mach-at32ap/clock.c
@@ -150,3 +150,119 @@ 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 && !parent->dev->bus_id[0] && !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", parent->dev->bus_id);
+ seq_printf(r->s, "\n");
+
+ /* cost of this scan is small, but not linear... */
+ r->nest = nest + NEST_DELTA;
+ for (i = 3; i < at32_nr_clocks; i++) {
+ clk = at32_clock_list[i];
+ 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;
+
+ /* 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");
+
+ /* show clock tree as derived from the three oscillators
+ * we "know" are at the head of the list
+ */
+ r.s = s;
+ r.nest = 0;
+ dump_clock(at32_clock_list[0], &r);
+ dump_clock(at32_clock_list[1], &r);
+ dump_clock(at32_clock_list[2], &r);
+
+ 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
diff --git a/arch/avr32/mach-at32ap/hsmc.c b/arch/avr32/mach-at32ap/hsmc.c
index 5e22a750632b..704607fbcc69 100644
--- a/arch/avr32/mach-at32ap/hsmc.c
+++ b/arch/avr32/mach-at32ap/hsmc.c
@@ -29,16 +29,25 @@ struct hsmc {
static struct hsmc *hsmc;
-int smc_set_configuration(int cs, const struct smc_config *config)
+void smc_set_timing(struct smc_config *config,
+ const struct smc_timing *timing)
{
+ int recover;
+ int cycle;
+
unsigned long mul;
- unsigned long offset;
- u32 setup, pulse, cycle, mode;
- if (!hsmc)
- return -ENODEV;
- if (cs >= NR_CHIP_SELECTS)
- return -EINVAL;
+ /* 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
@@ -50,16 +59,102 @@ int smc_set_configuration(int cs, const struct smc_config *config)
#define ns2cyc(x) ((((x) * mul) + 65535) >> 16)
- setup = (HSMC_BF(NWE_SETUP, ns2cyc(config->nwe_setup))
- | HSMC_BF(NCS_WR_SETUP, ns2cyc(config->ncs_write_setup))
- | HSMC_BF(NRD_SETUP, ns2cyc(config->nrd_setup))
- | HSMC_BF(NCS_RD_SETUP, ns2cyc(config->ncs_read_setup)));
- pulse = (HSMC_BF(NWE_PULSE, ns2cyc(config->nwe_pulse))
- | HSMC_BF(NCS_WR_PULSE, ns2cyc(config->ncs_write_pulse))
- | HSMC_BF(NRD_PULSE, ns2cyc(config->nrd_pulse))
- | HSMC_BF(NCS_RD_PULSE, ns2cyc(config->ncs_read_pulse)));
- cycle = (HSMC_BF(NWE_CYCLE, ns2cyc(config->write_cycle))
- | HSMC_BF(NRD_CYCLE, ns2cyc(config->read_cycle)));
+ 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:
diff --git a/arch/avr32/mach-at32ap/pio.c b/arch/avr32/mach-at32ap/pio.c
index 1eb99b814f5b..d61a02da898c 100644
--- a/arch/avr32/mach-at32ap/pio.c
+++ b/arch/avr32/mach-at32ap/pio.c
@@ -110,6 +110,10 @@ void __init at32_select_gpio(unsigned int pin, unsigned long flags)
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 {
diff --git a/arch/avr32/mach-at32ap/pm.h b/arch/avr32/mach-at32ap/pm.h
index a1f8aced0a8c..47efd0d1951f 100644
--- a/arch/avr32/mach-at32ap/pm.h
+++ b/arch/avr32/mach-at32ap/pm.h
@@ -4,6 +4,14 @@
#ifndef __ARCH_AVR32_MACH_AT32AP_PM_H__
#define __ARCH_AVR32_MACH_AT32AP_PM_H__
+/*
+ * We can reduce the code size a bit by using a constant here. Since
+ * this file is only used on AVR32 AP CPUs with segmentation enabled,
+ * it's safe to not use ioremap. Generic drivers should of course
+ * never do this.
+ */
+#define AT32_PM_BASE 0xfff00000
+
/* PM register offsets */
#define PM_MCCTRL 0x0000
#define PM_CKSEL 0x0004
diff --git a/arch/avr32/mm/init.c b/arch/avr32/mm/init.c
index 82cf70854b90..480760bde63f 100644
--- a/arch/avr32/mm/init.c
+++ b/arch/avr32/mm/init.c
@@ -224,19 +224,9 @@ void free_initmem(void)
#ifdef CONFIG_BLK_DEV_INITRD
-static int keep_initrd;
-
void free_initrd_mem(unsigned long start, unsigned long end)
{
- if (!keep_initrd)
- free_area(start, end, "initrd");
-}
-
-static int __init keepinitrd_setup(char *__unused)
-{
- keep_initrd = 1;
- return 1;
+ free_area(start, end, "initrd");
}
-__setup("keepinitrd", keepinitrd_setup);
#endif