Commit 36dbe4d6 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://www.atmel.no/~hskinnemoen/linux/kernel/avr32

* 'for-linus' of git://www.atmel.no/~hskinnemoen/linux/kernel/avr32:
  [AVR32] Implement platform hooks for atmel_lcdfb driver
  [AVR32] Wire up signalfd, timerfd and eventfd
  [AVR32] optimize pagefault path
  [AVR32] Remove bogus comment in arch/avr32/kernel/irq.c
parents e0f88db3 d0a2b7af
/*
* 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 */
...@@ -16,6 +16,8 @@ ...@@ -16,6 +16,8 @@
#include <linux/types.h> #include <linux/types.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <video/atmel_lcdc.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/setup.h> #include <asm/setup.h>
#include <asm/arch/at32ap7000.h> #include <asm/arch/at32ap7000.h>
...@@ -23,6 +25,7 @@ ...@@ -23,6 +25,7 @@
#include <asm/arch/init.h> #include <asm/arch/init.h>
#include <asm/arch/portmux.h> #include <asm/arch/portmux.h>
#include "atstk1000.h"
#define SW2_DEFAULT /* MMCI and UART_A available */ #define SW2_DEFAULT /* MMCI and UART_A available */
...@@ -31,9 +34,7 @@ struct eth_addr { ...@@ -31,9 +34,7 @@ struct eth_addr {
}; };
static struct eth_addr __initdata hw_addr[2]; static struct eth_addr __initdata hw_addr[2];
static struct eth_platform_data __initdata eth_data[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 = { static struct spi_board_info spi0_board_info[] __initdata = {
{ {
...@@ -148,9 +149,8 @@ static int __init atstk1002_init(void) ...@@ -148,9 +149,8 @@ static int __init atstk1002_init(void)
set_hw_addr(at32_add_device_eth(0, &eth_data[0])); set_hw_addr(at32_add_device_eth(0, &eth_data[0]));
at32_add_device_spi(0, spi0_board_info, ARRAY_SIZE(spi0_board_info)); at32_add_device_spi(0, spi0_board_info, ARRAY_SIZE(spi0_board_info));
atstk1000_fb0_data.fbmem_start = fbmem_start; at32_add_device_lcdc(0, &atstk1000_lcdc_data,
atstk1000_fb0_data.fbmem_size = fbmem_size; fbmem_start, fbmem_size);
at32_add_device_lcdc(0, &atstk1000_fb0_data);
return 0; return 0;
} }
......
...@@ -8,13 +8,56 @@ ...@@ -8,13 +8,56 @@
* published by the Free Software Foundation. * published by the Free Software Foundation.
*/ */
#include <linux/bootmem.h> #include <linux/bootmem.h>
#include <linux/fb.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/linkage.h> #include <linux/linkage.h>
#include <asm/setup.h> #include <video/atmel_lcdc.h>
#include <asm/setup.h>
#include <asm/arch/board.h> #include <asm/arch/board.h>
#include "atstk1000.h"
/* Initialized by bootloader-specific startup code. */ /* Initialized by bootloader-specific startup code. */
struct tag *bootloader_tags __initdata; 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,
};
...@@ -7,15 +7,6 @@ ...@@ -7,15 +7,6 @@
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation. * 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> #include <linux/interrupt.h>
......
...@@ -179,7 +179,7 @@ static int __kprobes post_kprobe_handler(struct pt_regs *regs) ...@@ -179,7 +179,7 @@ static int __kprobes post_kprobe_handler(struct pt_regs *regs)
return 1; 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(); struct kprobe *cur = kprobe_running();
...@@ -216,11 +216,6 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, ...@@ -216,11 +216,6 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
if (post_kprobe_handler(args->regs)) if (post_kprobe_handler(args->regs))
ret = NOTIFY_STOP; ret = NOTIFY_STOP;
break; break;
case DIE_FAULT:
if (kprobe_running()
&& kprobe_fault_handler(args->regs, args->trapnr))
ret = NOTIFY_STOP;
break;
default: default:
break; break;
} }
......
...@@ -292,4 +292,7 @@ sys_call_table: ...@@ -292,4 +292,7 @@ sys_call_table:
.long sys_shmdt .long sys_shmdt
.long sys_shmctl .long sys_shmctl
.long sys_utimensat .long sys_utimensat
.long sys_signalfd
.long sys_timerfd /* 280 */
.long sys_eventfd
.long sys_ni_syscall /* r8 is saturated at nr_syscalls */ .long sys_ni_syscall /* r8 is saturated at nr_syscalls */
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
* published by the Free Software Foundation. * published by the Free Software Foundation.
*/ */
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/fb.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
...@@ -17,6 +18,8 @@ ...@@ -17,6 +18,8 @@
#include <asm/arch/portmux.h> #include <asm/arch/portmux.h>
#include <asm/arch/sm.h> #include <asm/arch/sm.h>
#include <video/atmel_lcdc.h>
#include "clock.h" #include "clock.h"
#include "hmatrix.h" #include "hmatrix.h"
#include "pio.h" #include "pio.h"
...@@ -881,20 +884,26 @@ at32_add_device_spi(unsigned int id, struct spi_board_info *b, unsigned int n) ...@@ -881,20 +884,26 @@ at32_add_device_spi(unsigned int id, struct spi_board_info *b, unsigned int n)
/* -------------------------------------------------------------------- /* --------------------------------------------------------------------
* LCDC * LCDC
* -------------------------------------------------------------------- */ * -------------------------------------------------------------------- */
static struct lcdc_platform_data lcdc0_data; static struct atmel_lcdfb_info atmel_lcdfb0_data;
static struct resource lcdc0_resource[] = { static struct resource atmel_lcdfb0_resource[] = {
{ {
.start = 0xff000000, .start = 0xff000000,
.end = 0xff000fff, .end = 0xff000fff,
.flags = IORESOURCE_MEM, .flags = IORESOURCE_MEM,
}, },
IRQ(1), IRQ(1),
{
/* Placeholder for pre-allocated fb memory */
.start = 0x00000000,
.end = 0x00000000,
.flags = 0,
},
}; };
DEFINE_DEV_DATA(lcdc, 0); DEFINE_DEV_DATA(atmel_lcdfb, 0);
DEV_CLK(hclk, lcdc0, hsb, 7); DEV_CLK(hck1, atmel_lcdfb0, hsb, 7);
static struct clk lcdc0_pixclk = { static struct clk atmel_lcdfb0_pixclk = {
.name = "pixclk", .name = "lcdc_clk",
.dev = &lcdc0_device.dev, .dev = &atmel_lcdfb0_device.dev,
.mode = genclk_mode, .mode = genclk_mode,
.get_rate = genclk_get_rate, .get_rate = genclk_get_rate,
.set_rate = genclk_set_rate, .set_rate = genclk_set_rate,
...@@ -903,13 +912,34 @@ static struct clk lcdc0_pixclk = { ...@@ -903,13 +912,34 @@ static struct clk lcdc0_pixclk = {
}; };
struct platform_device *__init 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 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) { switch (id) {
case 0: case 0:
pdev = &lcdc0_device; pdev = &atmel_lcdfb0_device;
select_peripheral(PC(19), PERIPH_A, 0); /* CC */ select_peripheral(PC(19), PERIPH_A, 0); /* CC */
select_peripheral(PC(20), PERIPH_A, 0); /* HSYNC */ select_peripheral(PC(20), PERIPH_A, 0); /* HSYNC */
select_peripheral(PC(21), PERIPH_A, 0); /* PCLK */ select_peripheral(PC(21), PERIPH_A, 0); /* PCLK */
...@@ -942,19 +972,32 @@ at32_add_device_lcdc(unsigned int id, struct lcdc_platform_data *data) ...@@ -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(16), PERIPH_A, 0); /* DATA22 */
select_peripheral(PD(17), PERIPH_A, 0); /* DATA23 */ select_peripheral(PD(17), PERIPH_A, 0); /* DATA23 */
clk_set_parent(&lcdc0_pixclk, &pll0); clk_set_parent(&atmel_lcdfb0_pixclk, &pll0);
clk_set_rate(&lcdc0_pixclk, clk_get_rate(&pll0)); clk_set_rate(&atmel_lcdfb0_pixclk, clk_get_rate(&pll0));
break; break;
default: default:
return NULL; goto err_invalid_id;
} }
memcpy(pdev->dev.platform_data, data, if (fbmem_len) {
sizeof(struct lcdc_platform_data)); 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); platform_device_register(pdev);
return pdev; return pdev;
err_invalid_id:
kfree(modedb);
err_dup_modedb:
kfree(monspecs);
return NULL;
} }
/* -------------------------------------------------------------------- /* --------------------------------------------------------------------
...@@ -1037,8 +1080,8 @@ struct clk *at32_clock_list[] = { ...@@ -1037,8 +1080,8 @@ struct clk *at32_clock_list[] = {
&macb1_pclk, &macb1_pclk,
&atmel_spi0_spi_clk, &atmel_spi0_spi_clk,
&atmel_spi1_spi_clk, &atmel_spi1_spi_clk,
&lcdc0_hclk, &atmel_lcdfb0_hck1,
&lcdc0_pixclk, &atmel_lcdfb0_pixclk,
&gclk0, &gclk0,
&gclk1, &gclk1,
&gclk2, &gclk2,
...@@ -1077,7 +1120,7 @@ void __init at32_clock_init(void) ...@@ -1077,7 +1120,7 @@ void __init at32_clock_init(void)
genclk_init_parent(&gclk2); genclk_init_parent(&gclk2);
genclk_init_parent(&gclk3); genclk_init_parent(&gclk3);
genclk_init_parent(&gclk4); 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 * Turn on all clocks that have at least one user already, and
......
...@@ -12,41 +12,30 @@ ...@@ -12,41 +12,30 @@
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/pagemap.h> #include <linux/pagemap.h>
#include <linux/kdebug.h> #include <linux/kdebug.h>
#include <linux/kprobes.h>
#include <asm/mmu_context.h> #include <asm/mmu_context.h>
#include <asm/sysreg.h> #include <asm/sysreg.h>
#include <asm/tlb.h> #include <asm/tlb.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#ifdef CONFIG_KPROBES #ifdef CONFIG_KPROBES
ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain); static inline int notify_page_fault(struct pt_regs *regs, int trap)
/* Hook to register for page fault notifications */
int register_page_fault_notifier(struct notifier_block *nb)
{ {
return atomic_notifier_chain_register(&notify_page_fault_chain, nb); int ret = 0;
}
int unregister_page_fault_notifier(struct notifier_block *nb) if (!user_mode(regs)) {
{ if (kprobe_running() && kprobe_fault_handler(regs, trap))
return atomic_notifier_chain_unregister(&notify_page_fault_chain, nb); ret = 1;
} }
static inline int notify_page_fault(enum die_val val, struct pt_regs *regs, return ret;
int trap, int sig)
{
struct die_args args = {
.regs = regs,
.trapnr = trap,
};
return atomic_notifier_call_chain(&notify_page_fault_chain, val, &args);
} }
#else #else
static inline int notify_page_fault(enum die_val val, struct pt_regs *regs, static inline int notify_page_fault(struct pt_regs *regs, int trap)
int trap, int sig)
{ {
return NOTIFY_DONE; return 0;
} }
#endif #endif
...@@ -76,8 +65,7 @@ asmlinkage void do_page_fault(unsigned long ecr, struct pt_regs *regs) ...@@ -76,8 +65,7 @@ asmlinkage void do_page_fault(unsigned long ecr, struct pt_regs *regs)
long signr; long signr;
int code; int code;
if (notify_page_fault(DIE_PAGE_FAULT, regs, if (notify_page_fault(regs, ecr))
ecr, SIGSEGV) == NOTIFY_STOP)
return; return;
address = sysreg_read(TLBEAR); address = sysreg_read(TLBEAR);
......
...@@ -30,11 +30,9 @@ struct spi_board_info; ...@@ -30,11 +30,9 @@ struct spi_board_info;
struct platform_device * struct platform_device *
at32_add_device_spi(unsigned int id, struct spi_board_info *b, unsigned int n); at32_add_device_spi(unsigned int id, struct spi_board_info *b, unsigned int n);
struct lcdc_platform_data { struct atmel_lcdfb_info;
unsigned long fbmem_start;
unsigned long fbmem_size;
};
struct platform_device * struct platform_device *
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);
#endif /* __ASM_ARCH_BOARD_H */ #endif /* __ASM_ARCH_BOARD_H */
...@@ -5,13 +5,22 @@ ...@@ -5,13 +5,22 @@
/* Grossly misnamed. */ /* Grossly misnamed. */
enum die_val { enum die_val {
DIE_FAULT,
DIE_BREAKPOINT, DIE_BREAKPOINT,
DIE_SSTEP, DIE_SSTEP,
DIE_PAGE_FAULT,
}; };
int register_page_fault_notifier(struct notifier_block *nb); /*
int unregister_page_fault_notifier(struct notifier_block *nb); * These are only here because kprobes.c wants them to implement a
* blatant layering violation. Will hopefully go away soon once all
* architectures are updated.
*/
static inline int register_page_fault_notifier(struct notifier_block *nb)
{
return 0;
}
static inline int unregister_page_fault_notifier(struct notifier_block *nb)
{
return 0;
}
#endif /* __ASM_AVR32_KDEBUG_H */ #endif /* __ASM_AVR32_KDEBUG_H */
...@@ -26,6 +26,7 @@ struct arch_specific_insn { ...@@ -26,6 +26,7 @@ struct arch_specific_insn {
kprobe_opcode_t insn[MAX_INSN_SIZE]; kprobe_opcode_t insn[MAX_INSN_SIZE];
}; };
extern int kprobe_fault_handler(struct pt_regs *regs, int trapnr);
extern int kprobe_exceptions_notify(struct notifier_block *self, extern int kprobe_exceptions_notify(struct notifier_block *self,
unsigned long val, void *data); unsigned long val, void *data);
......
...@@ -296,9 +296,12 @@ ...@@ -296,9 +296,12 @@
#define __NR_shmctl 277 #define __NR_shmctl 277
#define __NR_utimensat 278 #define __NR_utimensat 278
#define __NR_signalfd 279
#define __NR_timerfd 280
#define __NR_eventfd 281
#ifdef __KERNEL__ #ifdef __KERNEL__
#define NR_syscalls 279 #define NR_syscalls 282
#define __ARCH_WANT_IPC_PARSE_VERSION #define __ARCH_WANT_IPC_PARSE_VERSION
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment