diff options
Diffstat (limited to 'arch/avr32')
-rw-r--r-- | arch/avr32/Makefile | 2 | ||||
-rw-r--r-- | arch/avr32/boards/atstk1000/atstk1000.h | 15 | ||||
-rw-r--r-- | arch/avr32/boards/atstk1000/atstk1002.c | 10 | ||||
-rw-r--r-- | arch/avr32/boards/atstk1000/setup.c | 45 | ||||
-rw-r--r-- | arch/avr32/kernel/irq.c | 9 | ||||
-rw-r--r-- | arch/avr32/kernel/kprobes.c | 9 | ||||
-rw-r--r-- | arch/avr32/kernel/process.c | 6 | ||||
-rw-r--r-- | arch/avr32/kernel/ptrace.c | 7 | ||||
-rw-r--r-- | arch/avr32/kernel/syscall_table.S | 4 | ||||
-rw-r--r-- | arch/avr32/kernel/traps.c | 16 | ||||
-rw-r--r-- | arch/avr32/kernel/vmlinux.lds.c | 6 | ||||
-rw-r--r-- | arch/avr32/mach-at32ap/at32ap7000.c | 77 | ||||
-rw-r--r-- | arch/avr32/mach-at32ap/clock.c | 2 | ||||
-rw-r--r-- | arch/avr32/mm/dma-coherent.c | 12 | ||||
-rw-r--r-- | arch/avr32/mm/fault.c | 36 |
15 files changed, 162 insertions, 94 deletions
diff --git a/arch/avr32/Makefile b/arch/avr32/Makefile index 6115fc1..dc6bc01 100644 --- a/arch/avr32/Makefile +++ b/arch/avr32/Makefile @@ -16,7 +16,7 @@ AFLAGS += -mrelax -mno-pic CFLAGS_MODULE += -mno-relax LDFLAGS_vmlinux += --relax -cpuflags-$(CONFIG_CPU_AP7000) += -mcpu=ap7000 +cpuflags-$(CONFIG_CPU_AT32AP7000) += -mcpu=ap7000 CFLAGS += $(cpuflags-y) AFLAGS += $(cpuflags-y) diff --git a/arch/avr32/boards/atstk1000/atstk1000.h b/arch/avr32/boards/atstk1000/atstk1000.h new file mode 100644 index 0000000..9a49ed0 --- /dev/null +++ b/arch/avr32/boards/atstk1000/atstk1000.h @@ -0,0 +1,15 @@ +/* + * ATSTK1000 setup code: Daughterboard interface + * + * 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 __ARCH_AVR32_BOARDS_ATSTK1000_ATSTK1000_H +#define __ARCH_AVR32_BOARDS_ATSTK1000_ATSTK1000_H + +extern struct atmel_lcdfb_info atstk1000_lcdc_data; + +#endif /* __ARCH_AVR32_BOARDS_ATSTK1000_ATSTK1000_H */ diff --git a/arch/avr32/boards/atstk1000/atstk1002.c b/arch/avr32/boards/atstk1000/atstk1002.c index abe6ca2..fe1dbe2 100644 --- a/arch/avr32/boards/atstk1000/atstk1002.c +++ b/arch/avr32/boards/atstk1000/atstk1002.c @@ -16,6 +16,8 @@ #include <linux/types.h> #include <linux/spi/spi.h> +#include <video/atmel_lcdc.h> + #include <asm/io.h> #include <asm/setup.h> #include <asm/arch/at32ap7000.h> @@ -23,6 +25,7 @@ #include <asm/arch/init.h> #include <asm/arch/portmux.h> +#include "atstk1000.h" #define SW2_DEFAULT /* MMCI and UART_A available */ @@ -31,9 +34,7 @@ struct eth_addr { }; static struct eth_addr __initdata hw_addr[2]; - static struct eth_platform_data __initdata eth_data[2]; -static struct lcdc_platform_data atstk1000_fb0_data; static struct spi_board_info spi0_board_info[] __initdata = { { @@ -148,9 +149,8 @@ static int __init atstk1002_init(void) set_hw_addr(at32_add_device_eth(0, ð_data[0])); at32_add_device_spi(0, spi0_board_info, ARRAY_SIZE(spi0_board_info)); - atstk1000_fb0_data.fbmem_start = fbmem_start; - atstk1000_fb0_data.fbmem_size = fbmem_size; - at32_add_device_lcdc(0, &atstk1000_fb0_data); + at32_add_device_lcdc(0, &atstk1000_lcdc_data, + fbmem_start, fbmem_size); return 0; } diff --git a/arch/avr32/boards/atstk1000/setup.c b/arch/avr32/boards/atstk1000/setup.c index 2bc4b88..c9af409 100644 --- a/arch/avr32/boards/atstk1000/setup.c +++ b/arch/avr32/boards/atstk1000/setup.c @@ -8,13 +8,56 @@ * published by the Free Software Foundation. */ #include <linux/bootmem.h> +#include <linux/fb.h> #include <linux/init.h> #include <linux/types.h> #include <linux/linkage.h> -#include <asm/setup.h> +#include <video/atmel_lcdc.h> +#include <asm/setup.h> #include <asm/arch/board.h> +#include "atstk1000.h" + /* Initialized by bootloader-specific startup code. */ struct tag *bootloader_tags __initdata; + +static struct fb_videomode __initdata ltv350qv_modes[] = { + { + .name = "320x240 @ 75", + .refresh = 75, + .xres = 320, .yres = 240, + .pixclock = KHZ2PICOS(6891), + + .left_margin = 17, .right_margin = 33, + .upper_margin = 10, .lower_margin = 10, + .hsync_len = 16, .vsync_len = 1, + + .sync = 0, + .vmode = FB_VMODE_NONINTERLACED, + }, +}; + +static struct fb_monspecs __initdata atstk1000_default_monspecs = { + .manufacturer = "SNG", + .monitor = "LTV350QV", + .modedb = ltv350qv_modes, + .modedb_len = ARRAY_SIZE(ltv350qv_modes), + .hfmin = 14820, + .hfmax = 22230, + .vfmin = 60, + .vfmax = 90, + .dclkmax = 30000000, +}; + +struct atmel_lcdfb_info __initdata atstk1000_lcdc_data = { + .default_bpp = 24, + .default_dmacon = ATMEL_LCDC_DMAEN | ATMEL_LCDC_DMA2DEN, + .default_lcdcon2 = (ATMEL_LCDC_DISTYPE_TFT + | ATMEL_LCDC_INVCLK + | ATMEL_LCDC_CLKMOD_ALWAYSACTIVE + | ATMEL_LCDC_MEMOR_BIG), + .default_monspecs = &atstk1000_default_monspecs, + .guard_time = 2, +}; diff --git a/arch/avr32/kernel/irq.c b/arch/avr32/kernel/irq.c index fd31124..61f2de2 100644 --- a/arch/avr32/kernel/irq.c +++ b/arch/avr32/kernel/irq.c @@ -7,15 +7,6 @@ * 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. - * - * This file contains the code used by various IRQ handling routines: - * asking for different IRQ's should be done through these routines - * instead of just grabbing them. Thus setups with different IRQ numbers - * shouldn't result in any weird surprises, and installing new handlers - * should be easier. - * - * IRQ's are in fact implemented a bit like signal handlers for the kernel. - * Naturally it's not a 1:1 relation, but there are similarities. */ #include <linux/interrupt.h> diff --git a/arch/avr32/kernel/kprobes.c b/arch/avr32/kernel/kprobes.c index d0abbca..4942ee6 100644 --- a/arch/avr32/kernel/kprobes.c +++ b/arch/avr32/kernel/kprobes.c @@ -15,7 +15,7 @@ #include <linux/ptrace.h> #include <asm/cacheflush.h> -#include <asm/kdebug.h> +#include <linux/kdebug.h> #include <asm/ocd.h> DEFINE_PER_CPU(struct kprobe *, current_kprobe); @@ -179,7 +179,7 @@ static int __kprobes post_kprobe_handler(struct pt_regs *regs) return 1; } -static int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr) +int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr) { struct kprobe *cur = kprobe_running(); @@ -216,11 +216,6 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, if (post_kprobe_handler(args->regs)) ret = NOTIFY_STOP; break; - case DIE_FAULT: - if (kprobe_running() - && kprobe_fault_handler(args->regs, args->trapnr)) - ret = NOTIFY_STOP; - break; default: break; } diff --git a/arch/avr32/kernel/process.c b/arch/avr32/kernel/process.c index 4e4181e..13f9884 100644 --- a/arch/avr32/kernel/process.c +++ b/arch/avr32/kernel/process.c @@ -330,13 +330,13 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, { struct pt_regs *childregs; - childregs = ((struct pt_regs *)(THREAD_SIZE + (unsigned long)p->thread_info)) - 1; + childregs = ((struct pt_regs *)(THREAD_SIZE + (unsigned long)task_stack_page(p))) - 1; *childregs = *regs; if (user_mode(regs)) childregs->sp = usp; else - childregs->sp = (unsigned long)p->thread_info + THREAD_SIZE; + childregs->sp = (unsigned long)task_stack_page(p) + THREAD_SIZE; childregs->r12 = 0; /* Set return value for child */ @@ -403,7 +403,7 @@ unsigned long get_wchan(struct task_struct *p) if (!p || p == current || p->state == TASK_RUNNING) return 0; - stack_page = (unsigned long)p->thread_info; + stack_page = (unsigned long)task_stack_page(p); BUG_ON(!stack_page); /* diff --git a/arch/avr32/kernel/ptrace.c b/arch/avr32/kernel/ptrace.c index 6f4388f..3c36c2d 100644 --- a/arch/avr32/kernel/ptrace.c +++ b/arch/avr32/kernel/ptrace.c @@ -9,7 +9,6 @@ #include <linux/kernel.h> #include <linux/sched.h> #include <linux/mm.h> -#include <linux/smp_lock.h> #include <linux/ptrace.h> #include <linux/errno.h> #include <linux/user.h> @@ -21,11 +20,11 @@ #include <asm/uaccess.h> #include <asm/ocd.h> #include <asm/mmu_context.h> -#include <asm/kdebug.h> +#include <linux/kdebug.h> static struct pt_regs *get_user_regs(struct task_struct *tsk) { - return (struct pt_regs *)((unsigned long) tsk->thread_info + + return (struct pt_regs *)((unsigned long)task_stack_page(tsk) + THREAD_SIZE - sizeof(struct pt_regs)); } @@ -300,7 +299,7 @@ asmlinkage void do_debug_priv(struct pt_regs *regs) else die_val = DIE_BREAKPOINT; - if (notify_die(die_val, regs, 0, SIGTRAP) == NOTIFY_STOP) + if (notify_die(die_val, "ptrace", regs, 0, 0, SIGTRAP) == NOTIFY_STOP) return; if (likely(ds & DS_SSS)) { diff --git a/arch/avr32/kernel/syscall_table.S b/arch/avr32/kernel/syscall_table.S index 7c27958..75c81f2 100644 --- a/arch/avr32/kernel/syscall_table.S +++ b/arch/avr32/kernel/syscall_table.S @@ -291,4 +291,8 @@ sys_call_table: .long sys_shmget /* 275 */ .long sys_shmdt .long sys_shmctl + .long sys_utimensat + .long sys_signalfd + .long sys_timerfd /* 280 */ + .long sys_eventfd .long sys_ni_syscall /* r8 is saturated at nr_syscalls */ diff --git a/arch/avr32/kernel/traps.c b/arch/avr32/kernel/traps.c index 4f0382d..86d1075 100644 --- a/arch/avr32/kernel/traps.c +++ b/arch/avr32/kernel/traps.c @@ -20,20 +20,6 @@ #include <asm/sysreg.h> #include <asm/traps.h> -ATOMIC_NOTIFIER_HEAD(avr32_die_chain); - -int register_die_notifier(struct notifier_block *nb) -{ - return atomic_notifier_chain_register(&avr32_die_chain, nb); -} -EXPORT_SYMBOL(register_die_notifier); - -int unregister_die_notifier(struct notifier_block *nb) -{ - return atomic_notifier_chain_unregister(&avr32_die_chain, nb); -} -EXPORT_SYMBOL(unregister_die_notifier); - static DEFINE_SPINLOCK(die_lock); void NORET_TYPE die(const char *str, struct pt_regs *regs, long err) @@ -137,7 +123,7 @@ asmlinkage void do_address_exception(unsigned long ecr, struct pt_regs *regs) /* This way of handling undefined instructions is stolen from ARM */ static LIST_HEAD(undef_hook); -static spinlock_t undef_lock = SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(undef_lock); void register_undef_hook(struct undef_hook *hook) { diff --git a/arch/avr32/kernel/vmlinux.lds.c b/arch/avr32/kernel/vmlinux.lds.c index 7ad20cf..db0438f 100644 --- a/arch/avr32/kernel/vmlinux.lds.c +++ b/arch/avr32/kernel/vmlinux.lds.c @@ -35,7 +35,7 @@ SECTIONS _einittext = .; . = ALIGN(4); __tagtable_begin = .; - *(.taglist) + *(.taglist.init) __tagtable_end = .; *(.init.data) . = ALIGN(16); @@ -76,7 +76,7 @@ SECTIONS . = 0x100; *(.scall.text) *(.irq.text) - *(.text) + TEXT_TEXT SCHED_TEXT LOCK_TEXT KPROBES_TEXT @@ -112,7 +112,7 @@ SECTIONS /* And the rest... */ *(.data.rel*) - *(.data) + DATA_DATA CONSTRUCTORS _edata = .; diff --git a/arch/avr32/mach-at32ap/at32ap7000.c b/arch/avr32/mach-at32ap/at32ap7000.c index 56db45b..1d2bf34 100644 --- a/arch/avr32/mach-at32ap/at32ap7000.c +++ b/arch/avr32/mach-at32ap/at32ap7000.c @@ -6,6 +6,7 @@ * published by the Free Software Foundation. */ #include <linux/clk.h> +#include <linux/fb.h> #include <linux/init.h> #include <linux/platform_device.h> #include <linux/spi/spi.h> @@ -17,6 +18,8 @@ #include <asm/arch/portmux.h> #include <asm/arch/sm.h> +#include <video/atmel_lcdc.h> + #include "clock.h" #include "hmatrix.h" #include "pio.h" @@ -881,20 +884,26 @@ at32_add_device_spi(unsigned int id, struct spi_board_info *b, unsigned int n) /* -------------------------------------------------------------------- * LCDC * -------------------------------------------------------------------- */ -static struct lcdc_platform_data lcdc0_data; -static struct resource lcdc0_resource[] = { +static struct atmel_lcdfb_info atmel_lcdfb0_data; +static struct resource atmel_lcdfb0_resource[] = { { .start = 0xff000000, .end = 0xff000fff, .flags = IORESOURCE_MEM, }, IRQ(1), + { + /* Placeholder for pre-allocated fb memory */ + .start = 0x00000000, + .end = 0x00000000, + .flags = 0, + }, }; -DEFINE_DEV_DATA(lcdc, 0); -DEV_CLK(hclk, lcdc0, hsb, 7); -static struct clk lcdc0_pixclk = { - .name = "pixclk", - .dev = &lcdc0_device.dev, +DEFINE_DEV_DATA(atmel_lcdfb, 0); +DEV_CLK(hck1, atmel_lcdfb0, hsb, 7); +static struct clk atmel_lcdfb0_pixclk = { + .name = "lcdc_clk", + .dev = &atmel_lcdfb0_device.dev, .mode = genclk_mode, .get_rate = genclk_get_rate, .set_rate = genclk_set_rate, @@ -903,13 +912,34 @@ static struct clk lcdc0_pixclk = { }; struct platform_device *__init -at32_add_device_lcdc(unsigned int id, struct lcdc_platform_data *data) +at32_add_device_lcdc(unsigned int id, struct atmel_lcdfb_info *data, + unsigned long fbmem_start, unsigned long fbmem_len) { struct platform_device *pdev; + struct atmel_lcdfb_info *info; + struct fb_monspecs *monspecs; + struct fb_videomode *modedb; + unsigned int modedb_size; + + /* + * Do a deep copy of the fb data, monspecs and modedb. Make + * sure all allocations are done before setting up the + * portmux. + */ + monspecs = kmemdup(data->default_monspecs, + sizeof(struct fb_monspecs), GFP_KERNEL); + if (!monspecs) + return NULL; + + modedb_size = sizeof(struct fb_videomode) * monspecs->modedb_len; + modedb = kmemdup(monspecs->modedb, modedb_size, GFP_KERNEL); + if (!modedb) + goto err_dup_modedb; + monspecs->modedb = modedb; switch (id) { case 0: - pdev = &lcdc0_device; + pdev = &atmel_lcdfb0_device; select_peripheral(PC(19), PERIPH_A, 0); /* CC */ select_peripheral(PC(20), PERIPH_A, 0); /* HSYNC */ select_peripheral(PC(21), PERIPH_A, 0); /* PCLK */ @@ -942,19 +972,32 @@ at32_add_device_lcdc(unsigned int id, struct lcdc_platform_data *data) select_peripheral(PD(16), PERIPH_A, 0); /* DATA22 */ select_peripheral(PD(17), PERIPH_A, 0); /* DATA23 */ - clk_set_parent(&lcdc0_pixclk, &pll0); - clk_set_rate(&lcdc0_pixclk, clk_get_rate(&pll0)); + clk_set_parent(&atmel_lcdfb0_pixclk, &pll0); + clk_set_rate(&atmel_lcdfb0_pixclk, clk_get_rate(&pll0)); break; default: - return NULL; + goto err_invalid_id; } - memcpy(pdev->dev.platform_data, data, - sizeof(struct lcdc_platform_data)); + if (fbmem_len) { + pdev->resource[2].start = fbmem_start; + pdev->resource[2].end = fbmem_start + fbmem_len - 1; + pdev->resource[2].flags = IORESOURCE_MEM; + } + + info = pdev->dev.platform_data; + memcpy(info, data, sizeof(struct atmel_lcdfb_info)); + info->default_monspecs = monspecs; platform_device_register(pdev); return pdev; + +err_invalid_id: + kfree(modedb); +err_dup_modedb: + kfree(monspecs); + return NULL; } /* -------------------------------------------------------------------- @@ -1037,8 +1080,8 @@ struct clk *at32_clock_list[] = { &macb1_pclk, &atmel_spi0_spi_clk, &atmel_spi1_spi_clk, - &lcdc0_hclk, - &lcdc0_pixclk, + &atmel_lcdfb0_hck1, + &atmel_lcdfb0_pixclk, &gclk0, &gclk1, &gclk2, @@ -1077,7 +1120,7 @@ void __init at32_clock_init(void) genclk_init_parent(&gclk2); genclk_init_parent(&gclk3); genclk_init_parent(&gclk4); - genclk_init_parent(&lcdc0_pixclk); + genclk_init_parent(&atmel_lcdfb0_pixclk); /* * Turn on all clocks that have at least one user already, and diff --git a/arch/avr32/mach-at32ap/clock.c b/arch/avr32/mach-at32ap/clock.c index 00c4354..0f8c89c 100644 --- a/arch/avr32/mach-at32ap/clock.c +++ b/arch/avr32/mach-at32ap/clock.c @@ -18,7 +18,7 @@ #include "clock.h" -static spinlock_t clk_lock = SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(clk_lock); struct clk *clk_get(struct device *dev, const char *id) { diff --git a/arch/avr32/mm/dma-coherent.c b/arch/avr32/mm/dma-coherent.c index b68d669..099212d 100644 --- a/arch/avr32/mm/dma-coherent.c +++ b/arch/avr32/mm/dma-coherent.c @@ -112,16 +112,21 @@ void dma_free_coherent(struct device *dev, size_t size, } EXPORT_SYMBOL(dma_free_coherent); -#if 0 void *dma_alloc_writecombine(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp) { struct page *page; + dma_addr_t phys; page = __dma_alloc(dev, size, handle, gfp); + if (!page) + return NULL; + + phys = page_to_phys(page); + *handle = phys; /* Now, map the page into P3 with write-combining turned on */ - return __ioremap(page_to_phys(page), size, _PAGE_BUFFER); + return __ioremap(phys, size, _PAGE_BUFFER); } EXPORT_SYMBOL(dma_alloc_writecombine); @@ -132,8 +137,7 @@ void dma_free_writecombine(struct device *dev, size_t size, iounmap(cpu_addr); - page = bus_to_page(handle); + page = phys_to_page(handle); __dma_free(dev, size, page, handle); } EXPORT_SYMBOL(dma_free_writecombine); -#endif diff --git a/arch/avr32/mm/fault.c b/arch/avr32/mm/fault.c index 146ebdb..e011f1c 100644 --- a/arch/avr32/mm/fault.c +++ b/arch/avr32/mm/fault.c @@ -12,41 +12,30 @@ #include <linux/mm.h> #include <linux/module.h> #include <linux/pagemap.h> +#include <linux/kdebug.h> +#include <linux/kprobes.h> -#include <asm/kdebug.h> #include <asm/mmu_context.h> #include <asm/sysreg.h> #include <asm/tlb.h> #include <asm/uaccess.h> #ifdef CONFIG_KPROBES -ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain); - -/* Hook to register for page fault notifications */ -int register_page_fault_notifier(struct notifier_block *nb) +static inline int notify_page_fault(struct pt_regs *regs, int trap) { - return atomic_notifier_chain_register(¬ify_page_fault_chain, nb); -} + int ret = 0; -int unregister_page_fault_notifier(struct notifier_block *nb) -{ - return atomic_notifier_chain_unregister(¬ify_page_fault_chain, nb); -} + if (!user_mode(regs)) { + if (kprobe_running() && kprobe_fault_handler(regs, trap)) + ret = 1; + } -static inline int notify_page_fault(enum die_val val, struct pt_regs *regs, - int trap, int sig) -{ - struct die_args args = { - .regs = regs, - .trapnr = trap, - }; - return atomic_notifier_call_chain(¬ify_page_fault_chain, val, &args); + return ret; } #else -static inline int notify_page_fault(enum die_val val, struct pt_regs *regs, - int trap, int sig) +static inline int notify_page_fault(struct pt_regs *regs, int trap) { - return NOTIFY_DONE; + return 0; } #endif @@ -76,8 +65,7 @@ asmlinkage void do_page_fault(unsigned long ecr, struct pt_regs *regs) long signr; int code; - if (notify_page_fault(DIE_PAGE_FAULT, regs, - ecr, SIGSEGV) == NOTIFY_STOP) + if (notify_page_fault(regs, ecr)) return; address = sysreg_read(TLBEAR); |