From 2417a130bd4013f804983c62cb116bc9ec7f8e2d Mon Sep 17 00:00:00 2001 From: Haavard Skinnemoen Date: Thu, 16 Aug 2007 11:12:47 +0200 Subject: [AVR32] Move AT32_PM_BASE definition into pm.h We don't want to redefine this in every file that needs to access the PM. Signed-off-by: Haavard Skinnemoen --- arch/avr32/mach-at32ap/at32ap7000.c | 6 ------ arch/avr32/mach-at32ap/pm.h | 8 ++++++++ 2 files changed, 8 insertions(+), 6 deletions(-) (limited to 'arch') diff --git a/arch/avr32/mach-at32ap/at32ap7000.c b/arch/avr32/mach-at32ap/at32ap7000.c index 64cc5583ddfb..373242aab976 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) \ { \ 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 -- cgit v1.2.3-58-ga151 From d938b89392bd3ff64e0610d8c4e0d3f7091d98db Mon Sep 17 00:00:00 2001 From: David Brownell Date: Thu, 9 Aug 2007 20:56:07 -0700 Subject: [AVR32] /sys/kernel/debug/at32ap_clk When debugfs is available, /sys/kernel/debug/at32ap_clk will provide a dump of the power manager registers and of the current clock tree. This can help sorting out various surprises, and when making runtime PM work. Signed-off-by: David Brownell Signed-off-by: Haavard Skinnemoen --- arch/avr32/mach-at32ap/clock.c | 116 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) (limited to 'arch') 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 +#include +#include +#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; + + /* name */ + 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 -- cgit v1.2.3-58-ga151 From 7808fa4853728a776d7e76d68fb406f515a4119c Mon Sep 17 00:00:00 2001 From: Matteo Vit Date: Thu, 9 Aug 2007 14:55:34 +0200 Subject: [AVR32] add multidrive support for pio driver This patch add multidrive support for pio driver Signed-off-by: Matteo Vit - Dave S.r.l. Signed-off-by: Haavard Skinnemoen --- arch/avr32/mach-at32ap/pio.c | 4 ++++ include/asm-avr32/arch-at32ap/portmux.h | 1 + 2 files changed, 5 insertions(+) (limited to 'arch') 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/include/asm-avr32/arch-at32ap/portmux.h b/include/asm-avr32/arch-at32ap/portmux.h index 9930871decde..b1abe6b4e4ef 100644 --- a/include/asm-avr32/arch-at32ap/portmux.h +++ b/include/asm-avr32/arch-at32ap/portmux.h @@ -19,6 +19,7 @@ #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 pin, unsigned int periph, unsigned long flags); -- cgit v1.2.3-58-ga151 From 6fcf0615117dcfa126083f2163c4dcea3098bbe3 Mon Sep 17 00:00:00 2001 From: Haavard Skinnemoen Date: Thu, 14 Jun 2007 17:37:31 +0200 Subject: [AVR32] Wire up USBA device Implement at32_add_device_usba() and use it to wire up the USBA device on ATSTK1000 and ATNGW100. Signed-off-by: Haavard Skinnemoen --- arch/avr32/boards/atngw100/setup.c | 1 + arch/avr32/boards/atstk1000/atstk1002.c | 1 + arch/avr32/mach-at32ap/at32ap7000.c | 68 +++++++++++++++++++++++++++++++++ include/asm-avr32/arch-at32ap/board.h | 8 ++++ 4 files changed, 78 insertions(+) (limited to 'arch') diff --git a/arch/avr32/boards/atngw100/setup.c b/arch/avr32/boards/atngw100/setup.c index ef801563bbf5..6e180f435253 100644 --- a/arch/avr32/boards/atngw100/setup.c +++ b/arch/avr32/boards/atngw100/setup.c @@ -154,6 +154,7 @@ static int __init atngw100_init(void) set_hw_addr(at32_add_device_eth(1, ð_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, 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/mach-at32ap/at32ap7000.c b/arch/avr32/mach-at32ap/at32ap7000.c index 373242aab976..f6d154ca4d24 100644 --- a/arch/avr32/mach-at32ap/at32ap7000.c +++ b/arch/avr32/mach-at32ap/at32ap7000.c @@ -1161,6 +1161,72 @@ at32_add_device_ssc(unsigned int id, unsigned int flags) return pdev; } +/* -------------------------------------------------------------------- + * 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 * -------------------------------------------------------------------- */ @@ -1246,6 +1312,8 @@ struct clk *at32_clock_list[] = { &ssc0_pclk, &ssc1_pclk, &ssc2_pclk, + &usba0_hclk, + &usba0_pclk, &gclk0, &gclk1, &gclk2, diff --git a/include/asm-avr32/arch-at32ap/board.h b/include/asm-avr32/arch-at32ap/board.h index 0215965dc586..7dbd603c38cc 100644 --- a/include/asm-avr32/arch-at32ap/board.h +++ b/include/asm-avr32/arch-at32ap/board.h @@ -6,6 +6,8 @@ #include +#define GPIO_PIN_NONE (-1) + /* Add basic devices: system manager, interrupt controller, portmuxes, etc. */ void at32_add_system_devices(void); @@ -36,6 +38,12 @@ struct platform_device * at32_add_device_lcdc(unsigned int id, struct atmel_lcdfb_info *data, unsigned long fbmem_start, unsigned long fbmem_len); +struct usba_platform_data { + int vbus_pin; +}; +struct platform_device * +at32_add_device_usba(unsigned int id, struct usba_platform_data *data); + /* depending on what's hooked up, not all SSC pins will be used */ #define ATMEL_SSC_TK 0x01 #define ATMEL_SSC_TF 0x02 -- cgit v1.2.3-58-ga151 From fe57f84efe3165a1e2ec477b256870f3d43b698a Mon Sep 17 00:00:00 2001 From: Matteo Vit Date: Wed, 29 Aug 2007 10:19:40 +0200 Subject: [AVR32] fix command line parsing in early_parse_fbmem Signed-off-by: Matteo Vit - Dave S.r.l. Signed-off-by: Haavard Skinnemoen --- arch/avr32/kernel/setup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') 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"); -- cgit v1.2.3-58-ga151 From 4e59629bf68e8a6f19b806f8ace3d0f31221c4a4 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Sat, 15 Sep 2007 22:47:02 +0200 Subject: [AVR32] rename vmlinux.lds Rename vmlinux.lds to a .S file to match other architectures. Simplify Makefile to match the rename and deleted the unused USE_STANDARD_AS_RULE Signed-off-by: Sam Ravnborg Signed-off-by: Haavard Skinnemoen --- arch/avr32/kernel/Makefile | 5 -- arch/avr32/kernel/vmlinux.lds.S | 142 ++++++++++++++++++++++++++++++++++++++++ arch/avr32/kernel/vmlinux.lds.c | 142 ---------------------------------------- 3 files changed, 142 insertions(+), 147 deletions(-) create mode 100644 arch/avr32/kernel/vmlinux.lds.S delete mode 100644 arch/avr32/kernel/vmlinux.lds.c (limited to 'arch') 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/vmlinux.lds.S b/arch/avr32/kernel/vmlinux.lds.S new file mode 100644 index 000000000000..db0438f35c00 --- /dev/null +++ b/arch/avr32/kernel/vmlinux.lds.S @@ -0,0 +1,142 @@ +/* + * AVR32 linker script for the Linux kernel + * + * 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. + */ +#define LOAD_OFFSET 0x00000000 +#include + +OUTPUT_FORMAT("elf32-avr32", "elf32-avr32", "elf32-avr32") +OUTPUT_ARCH(avr32) +ENTRY(_start) + +/* Big endian */ +jiffies = jiffies_64 + 4; + +SECTIONS +{ + . = CONFIG_ENTRY_ADDRESS; + .init : AT(ADDR(.init) - LOAD_OFFSET) { + _stext = .; + __init_begin = .; + _sinittext = .; + *(.text.reset) + *(.init.text) + /* + * .exit.text is discarded at runtime, not + * link time, to deal with references from + * __bug_table + */ + *(.exit.text) + _einittext = .; + . = ALIGN(4); + __tagtable_begin = .; + *(.taglist.init) + __tagtable_end = .; + *(.init.data) + . = ALIGN(16); + __setup_start = .; + *(.init.setup) + __setup_end = .; + . = ALIGN(4); + __initcall_start = .; + INITCALLS + __initcall_end = .; + __con_initcall_start = .; + *(.con_initcall.init) + __con_initcall_end = .; + __security_initcall_start = .; + *(.security_initcall.init) + __security_initcall_end = .; +#ifdef CONFIG_BLK_DEV_INITRD + . = ALIGN(32); + __initramfs_start = .; + *(.init.ramfs) + __initramfs_end = .; +#endif + . = ALIGN(4096); + __init_end = .; + } + + . = ALIGN(8192); + .text : AT(ADDR(.text) - LOAD_OFFSET) { + _evba = .; + _text = .; + *(.ex.text) + . = 0x50; + *(.tlbx.ex.text) + . = 0x60; + *(.tlbr.ex.text) + . = 0x70; + *(.tlbw.ex.text) + . = 0x100; + *(.scall.text) + *(.irq.text) + TEXT_TEXT + SCHED_TEXT + LOCK_TEXT + KPROBES_TEXT + *(.fixup) + *(.gnu.warning) + _etext = .; + } = 0xd703d703 + + . = ALIGN(4); + __ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) { + __start___ex_table = .; + *(__ex_table) + __stop___ex_table = .; + } + + BUG_TABLE + + RODATA + + . = ALIGN(8192); + + .data : AT(ADDR(.data) - LOAD_OFFSET) { + _data = .; + _sdata = .; + /* + * First, the init task union, aligned to an 8K boundary. + */ + *(.data.init_task) + + /* Then, the cacheline aligned data */ + . = ALIGN(32); + *(.data.cacheline_aligned) + + /* And the rest... */ + *(.data.rel*) + DATA_DATA + CONSTRUCTORS + + _edata = .; + } + + + . = ALIGN(8); + .bss : AT(ADDR(.bss) - LOAD_OFFSET) { + __bss_start = .; + *(.bss) + *(COMMON) + . = ALIGN(8); + __bss_stop = .; + _end = .; + } + + /* When something in the kernel is NOT compiled as a module, the module + * cleanup code and data are put into these segments. Both can then be + * thrown away, as cleanup code is never called unless it's a module. + */ + /DISCARD/ : { + *(.exit.data) + *(.exitcall.exit) + } + + DWARF_DEBUG +} diff --git a/arch/avr32/kernel/vmlinux.lds.c b/arch/avr32/kernel/vmlinux.lds.c deleted file mode 100644 index db0438f35c00..000000000000 --- a/arch/avr32/kernel/vmlinux.lds.c +++ /dev/null @@ -1,142 +0,0 @@ -/* - * AVR32 linker script for the Linux kernel - * - * 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. - */ -#define LOAD_OFFSET 0x00000000 -#include - -OUTPUT_FORMAT("elf32-avr32", "elf32-avr32", "elf32-avr32") -OUTPUT_ARCH(avr32) -ENTRY(_start) - -/* Big endian */ -jiffies = jiffies_64 + 4; - -SECTIONS -{ - . = CONFIG_ENTRY_ADDRESS; - .init : AT(ADDR(.init) - LOAD_OFFSET) { - _stext = .; - __init_begin = .; - _sinittext = .; - *(.text.reset) - *(.init.text) - /* - * .exit.text is discarded at runtime, not - * link time, to deal with references from - * __bug_table - */ - *(.exit.text) - _einittext = .; - . = ALIGN(4); - __tagtable_begin = .; - *(.taglist.init) - __tagtable_end = .; - *(.init.data) - . = ALIGN(16); - __setup_start = .; - *(.init.setup) - __setup_end = .; - . = ALIGN(4); - __initcall_start = .; - INITCALLS - __initcall_end = .; - __con_initcall_start = .; - *(.con_initcall.init) - __con_initcall_end = .; - __security_initcall_start = .; - *(.security_initcall.init) - __security_initcall_end = .; -#ifdef CONFIG_BLK_DEV_INITRD - . = ALIGN(32); - __initramfs_start = .; - *(.init.ramfs) - __initramfs_end = .; -#endif - . = ALIGN(4096); - __init_end = .; - } - - . = ALIGN(8192); - .text : AT(ADDR(.text) - LOAD_OFFSET) { - _evba = .; - _text = .; - *(.ex.text) - . = 0x50; - *(.tlbx.ex.text) - . = 0x60; - *(.tlbr.ex.text) - . = 0x70; - *(.tlbw.ex.text) - . = 0x100; - *(.scall.text) - *(.irq.text) - TEXT_TEXT - SCHED_TEXT - LOCK_TEXT - KPROBES_TEXT - *(.fixup) - *(.gnu.warning) - _etext = .; - } = 0xd703d703 - - . = ALIGN(4); - __ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) { - __start___ex_table = .; - *(__ex_table) - __stop___ex_table = .; - } - - BUG_TABLE - - RODATA - - . = ALIGN(8192); - - .data : AT(ADDR(.data) - LOAD_OFFSET) { - _data = .; - _sdata = .; - /* - * First, the init task union, aligned to an 8K boundary. - */ - *(.data.init_task) - - /* Then, the cacheline aligned data */ - . = ALIGN(32); - *(.data.cacheline_aligned) - - /* And the rest... */ - *(.data.rel*) - DATA_DATA - CONSTRUCTORS - - _edata = .; - } - - - . = ALIGN(8); - .bss : AT(ADDR(.bss) - LOAD_OFFSET) { - __bss_start = .; - *(.bss) - *(COMMON) - . = ALIGN(8); - __bss_stop = .; - _end = .; - } - - /* When something in the kernel is NOT compiled as a module, the module - * cleanup code and data are put into these segments. Both can then be - * thrown away, as cleanup code is never called unless it's a module. - */ - /DISCARD/ : { - *(.exit.data) - *(.exitcall.exit) - } - - DWARF_DEBUG -} -- cgit v1.2.3-58-ga151 From 7cf6ac2ae240e02ebdd2717a09d083d47cb60251 Mon Sep 17 00:00:00 2001 From: Haavard Skinnemoen Date: Mon, 17 Sep 2007 11:08:28 +0200 Subject: [AVR32] Kill a few hardcoded constants in vmlinux.lds Use PAGE_SIZE, THREAD_SIZE and L1_CACHE_BYTES instead of harcoded constants in places where that's what we really mean. Signed-off-by: Haavard Skinnemoen --- arch/avr32/kernel/vmlinux.lds.S | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/avr32/kernel/vmlinux.lds.S b/arch/avr32/kernel/vmlinux.lds.S index db0438f35c00..fef0e6d322f1 100644 --- a/arch/avr32/kernel/vmlinux.lds.S +++ b/arch/avr32/kernel/vmlinux.lds.S @@ -9,6 +9,8 @@ */ #define LOAD_OFFSET 0x00000000 #include +#include +#include OUTPUT_FORMAT("elf32-avr32", "elf32-avr32", "elf32-avr32") OUTPUT_ARCH(avr32) @@ -58,7 +60,7 @@ SECTIONS *(.init.ramfs) __initramfs_end = .; #endif - . = ALIGN(4096); + . = ALIGN(PAGE_SIZE); __init_end = .; } @@ -96,7 +98,7 @@ SECTIONS RODATA - . = ALIGN(8192); + . = ALIGN(THREAD_SIZE); .data : AT(ADDR(.data) - LOAD_OFFSET) { _data = .; @@ -107,7 +109,7 @@ SECTIONS *(.data.init_task) /* Then, the cacheline aligned data */ - . = ALIGN(32); + . = ALIGN(L1_CACHE_BYTES); *(.data.cacheline_aligned) /* And the rest... */ -- cgit v1.2.3-58-ga151 From 0d2372e5d61ccc1c618aaf5099700c8dc76e234a Mon Sep 17 00:00:00 2001 From: Haavard Skinnemoen Date: Mon, 17 Sep 2007 11:13:45 +0200 Subject: [AVR32] Remove unneeded 8K alignment of .text section __init_end, which comes immediately before .text, is already page aligned, and that should be more than enough for the .text section. The reason why we need to align the .text section is because the interrupt handler offset is ORed with EVBA, so we need to provide enough alignment of EVBA that this OR operation works as an ADD. Currently, the last interrupt handler is not nearly a full page away from EVBA, so it won't be a problem. Signed-off-by: Haavard Skinnemoen --- arch/avr32/kernel/vmlinux.lds.S | 1 - 1 file changed, 1 deletion(-) (limited to 'arch') diff --git a/arch/avr32/kernel/vmlinux.lds.S b/arch/avr32/kernel/vmlinux.lds.S index fef0e6d322f1..ce9ac9659883 100644 --- a/arch/avr32/kernel/vmlinux.lds.S +++ b/arch/avr32/kernel/vmlinux.lds.S @@ -64,7 +64,6 @@ SECTIONS __init_end = .; } - . = ALIGN(8192); .text : AT(ADDR(.text) - LOAD_OFFSET) { _evba = .; _text = .; -- cgit v1.2.3-58-ga151 From 193fdd1a99db8623697cb18a13dbcaa4eadbb1f2 Mon Sep 17 00:00:00 2001 From: "Robert P. J. Day" Date: Wed, 19 Sep 2007 08:43:42 -0400 Subject: [AVR32] Drop support for redundant "keepinitrd" boot-time parm. Given the existing "retain_initrd" boot-time parameter defined in init/initramfs.c, there appears to be no need for the equivalent "keepinitrd" parameter. Signed-off-by: Robert P. J. Day Signed-off-by: Haavard Skinnemoen --- arch/avr32/mm/init.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) (limited to 'arch') 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 -- cgit v1.2.3-58-ga151 From af8184718a322ae589efa583aa69ffdae61bf266 Mon Sep 17 00:00:00 2001 From: Kristoffer Nyborg Gregertsen Date: Fri, 17 Aug 2007 16:59:57 +0200 Subject: [AVR32] SMC configuration in clock cycles This patch makes the SMC configuration take timings in clock cycles instead of nanoseconds. A function to calculate timings in clock cycles is added. This patch removes the rounding troubles of the previous SMC configuration method. [hskinnemoen@atmel.com: fix atstk1002/atngw100 flash config] Signed-off-by: Kristoffer Nyborg Gregertsen Signed-off-by: Haavard Skinnemoen --- arch/avr32/boards/atngw100/flash.c | 5 +- arch/avr32/boards/atstk1000/flash.c | 5 +- arch/avr32/mach-at32ap/hsmc.c | 129 +++++++++++++++++++++++++++++++----- include/asm-avr32/arch-at32ap/smc.h | 51 +++++++++++--- 4 files changed, 161 insertions(+), 29 deletions(-) (limited to 'arch') 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 -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/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 -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/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/include/asm-avr32/arch-at32ap/smc.h b/include/asm-avr32/arch-at32ap/smc.h index 07152b7fd9c9..c98eea44a70a 100644 --- a/include/asm-avr32/arch-at32ap/smc.h +++ b/include/asm-avr32/arch-at32ap/smc.h @@ -15,22 +15,50 @@ /* * 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 */ - u16 ncs_read_setup; - u16 nrd_setup; - u16 ncs_write_setup; - u16 nwe_setup; + u8 ncs_read_setup; + u8 nrd_setup; + u8 ncs_write_setup; + u8 nwe_setup; /* Pulse length of given strobe */ - u16 ncs_read_pulse; - u16 nrd_pulse; - u16 ncs_write_pulse; - u16 nwe_pulse; + u8 ncs_read_pulse; + u8 nrd_pulse; + u8 ncs_write_pulse; + u8 nwe_pulse; /* Total cycle length of given operation */ - u16 read_cycle; - u16 write_cycle; + u8 read_cycle; + u8 write_cycle; /* Bus width in bytes */ u8 bus_width; @@ -76,6 +104,9 @@ struct smc_config { 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); -- cgit v1.2.3-58-ga151 From 82c54f864fea26c4c44f27e2b4c4d9a811dde299 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Tue, 25 Sep 2007 07:17:48 -0700 Subject: [AVR32] ngw100 i2c-gpio tweaks Make the NGW100 bitbang i2c use open drain signaling. Also, speed it up, so it's closer to 100 kHz ... the code paths seem to be long enough that the udelay isn't dominating bit times. The peak bit rate I observed was around 125 kHz, but that's with large delays (usually before ACK/NAK) which hold the overall rate down to around 80 kHz (call it 100 usec/byte on average). Signed-off-by: David Brownell Signed-off-by: Haavard Skinnemoen --- arch/avr32/boards/atngw100/setup.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/avr32/boards/atngw100/setup.c b/arch/avr32/boards/atngw100/setup.c index 6e180f435253..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 = { @@ -162,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; -- cgit v1.2.3-58-ga151 From a7e30b8d91d3291de4543d97849193ebc3ec4c1c Mon Sep 17 00:00:00 2001 From: Philippe Rétornaz Date: Wed, 10 Oct 2007 18:52:24 -0400 Subject: [AVR32] Fix random segfault with preemption MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As explained on: http://www.avrfreaks.net/index.php?nameÿphpBB2&fileÿewtopic&tS307 If the current process is preempted before it can copy RAR_SUP and RSR_SUP both register are lost and the process will segfault as soon as it return from the syscall since the return adress will be corrupted. This patch disable IRQ as soon as we enter the syscall path and reenable them when the copy is done. In the interrupt handlers, check if we are interrupting the srrf instruction, if so disable interrupts and return. The interrupt handler will be re-called immediatly when the interrupts are reenabled. After some stressing workload: - find / > /dev/null in loop - top (in ssh) - ping -f avr32 The segfaults are not seen anymore. Signed-off-by: Philippe Rétornaz Signed-off-by: Haavard Skinnemoen --- arch/avr32/kernel/entry-avr32b.S | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) (limited to 'arch') 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 -- cgit v1.2.3-58-ga151