diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-22 21:12:27 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-22 21:12:27 -0700 |
commit | 7f3883962870dd28b5f2322ac44a9d03640ef448 (patch) | |
tree | 01f7dd2ac2b7c61e5e6726c4fec4484aaca6e7b7 /arch/blackfin/kernel | |
parent | 10f2a2b0f68abf39c06cf519cbc1740fa50f900b (diff) | |
parent | b9ac41e314f0b43641bc01bd553fd2e0458ed832 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/vapier/blackfin
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/vapier/blackfin: (47 commits)
Blackfin: bfin_spi.h: add MMR peripheral layout
Blackfin: bfin_ppi.h: start a common PPI/EPPI header
Blackfin: bfin_can.h: add missing VERSION/VERSION2 MMRs
Blackfin: bf538: add missing SIC_RVECT define
Blackfin: bf561: rewrite SICA_xxx to just SIC_xxx
Blackfin: bf54x: add missing SIC_RVECT definition
Blackfin: H8606: move 8250 irqflags to platform resources
Blackfin: glue XIP/ROM kernel kconfigs
Blackfin: update sparse flags for latest upstream changes
Blackfin: coreb: update ioctl numbers
Blackfin: coreb: add gpl module license
Blackfin: bf518-ezkit: add ssm2603 codec resources
Blackfin: bf51x/bf52x: fix 16/32bit SPORT MMR helpers
Blackfin: tll6527m: new board port
Blackfin: bf526-ezbrd/bf527-ezkit: add NAND partition for u-boot
Blackfin: merge kernel init memory back into main memory region
Blackfin: gpio: add peripheral group check
Blackfin: dma: bf54x: add missing break for SPORT1 TX IRQ
Blackfin: add new cacheflush syscall
Blackfin: bf548-ezkit: increase u-boot partition size
...
Diffstat (limited to 'arch/blackfin/kernel')
-rw-r--r-- | arch/blackfin/kernel/bfin_gpio.c | 185 | ||||
-rw-r--r-- | arch/blackfin/kernel/process.c | 5 | ||||
-rw-r--r-- | arch/blackfin/kernel/ptrace.c | 12 | ||||
-rw-r--r-- | arch/blackfin/kernel/sys_bfin.c | 15 |
4 files changed, 148 insertions, 69 deletions
diff --git a/arch/blackfin/kernel/bfin_gpio.c b/arch/blackfin/kernel/bfin_gpio.c index ca1c1f9debd6..170cf90735ba 100644 --- a/arch/blackfin/kernel/bfin_gpio.c +++ b/arch/blackfin/kernel/bfin_gpio.c @@ -1,7 +1,7 @@ /* * GPIO Abstraction Layer * - * Copyright 2006-2009 Analog Devices Inc. + * Copyright 2006-2010 Analog Devices Inc. * * Licensed under the GPL-2 or later */ @@ -215,82 +215,91 @@ static void port_setup(unsigned gpio, unsigned short usage) } #ifdef BF537_FAMILY -static struct { - unsigned short res; - unsigned short offset; -} port_mux_lut[] = { - {.res = P_PPI0_D13, .offset = 11}, - {.res = P_PPI0_D14, .offset = 11}, - {.res = P_PPI0_D15, .offset = 11}, - {.res = P_SPORT1_TFS, .offset = 11}, - {.res = P_SPORT1_TSCLK, .offset = 11}, - {.res = P_SPORT1_DTPRI, .offset = 11}, - {.res = P_PPI0_D10, .offset = 10}, - {.res = P_PPI0_D11, .offset = 10}, - {.res = P_PPI0_D12, .offset = 10}, - {.res = P_SPORT1_RSCLK, .offset = 10}, - {.res = P_SPORT1_RFS, .offset = 10}, - {.res = P_SPORT1_DRPRI, .offset = 10}, - {.res = P_PPI0_D8, .offset = 9}, - {.res = P_PPI0_D9, .offset = 9}, - {.res = P_SPORT1_DRSEC, .offset = 9}, - {.res = P_SPORT1_DTSEC, .offset = 9}, - {.res = P_TMR2, .offset = 8}, - {.res = P_PPI0_FS3, .offset = 8}, - {.res = P_TMR3, .offset = 7}, - {.res = P_SPI0_SSEL4, .offset = 7}, - {.res = P_TMR4, .offset = 6}, - {.res = P_SPI0_SSEL5, .offset = 6}, - {.res = P_TMR5, .offset = 5}, - {.res = P_SPI0_SSEL6, .offset = 5}, - {.res = P_UART1_RX, .offset = 4}, - {.res = P_UART1_TX, .offset = 4}, - {.res = P_TMR6, .offset = 4}, - {.res = P_TMR7, .offset = 4}, - {.res = P_UART0_RX, .offset = 3}, - {.res = P_UART0_TX, .offset = 3}, - {.res = P_DMAR0, .offset = 3}, - {.res = P_DMAR1, .offset = 3}, - {.res = P_SPORT0_DTSEC, .offset = 1}, - {.res = P_SPORT0_DRSEC, .offset = 1}, - {.res = P_CAN0_RX, .offset = 1}, - {.res = P_CAN0_TX, .offset = 1}, - {.res = P_SPI0_SSEL7, .offset = 1}, - {.res = P_SPORT0_TFS, .offset = 0}, - {.res = P_SPORT0_DTPRI, .offset = 0}, - {.res = P_SPI0_SSEL2, .offset = 0}, - {.res = P_SPI0_SSEL3, .offset = 0}, +static const s8 port_mux[] = { + [GPIO_PF0] = 3, + [GPIO_PF1] = 3, + [GPIO_PF2] = 4, + [GPIO_PF3] = 4, + [GPIO_PF4] = 5, + [GPIO_PF5] = 6, + [GPIO_PF6] = 7, + [GPIO_PF7] = 8, + [GPIO_PF8 ... GPIO_PF15] = -1, + [GPIO_PG0 ... GPIO_PG7] = -1, + [GPIO_PG8] = 9, + [GPIO_PG9] = 9, + [GPIO_PG10] = 10, + [GPIO_PG11] = 10, + [GPIO_PG12] = 10, + [GPIO_PG13] = 11, + [GPIO_PG14] = 11, + [GPIO_PG15] = 11, + [GPIO_PH0 ... GPIO_PH15] = -1, + [PORT_PJ0 ... PORT_PJ3] = -1, + [PORT_PJ4] = 1, + [PORT_PJ5] = 1, + [PORT_PJ6 ... PORT_PJ9] = -1, + [PORT_PJ10] = 0, + [PORT_PJ11] = 0, }; -static void portmux_setup(unsigned short per) +static int portmux_group_check(unsigned short per) { - u16 y, offset, muxreg; + u16 ident = P_IDENT(per); u16 function = P_FUNCT2MUX(per); + s8 offset = port_mux[ident]; + u16 m, pmux, pfunc; - for (y = 0; y < ARRAY_SIZE(port_mux_lut); y++) { - if (port_mux_lut[y].res == per) { - - /* SET PORTMUX REG */ - - offset = port_mux_lut[y].offset; - muxreg = bfin_read_PORT_MUX(); + if (offset < 0) + return 0; - if (offset != 1) - muxreg &= ~(1 << offset); - else - muxreg &= ~(3 << 1); + pmux = bfin_read_PORT_MUX(); + for (m = 0; m < ARRAY_SIZE(port_mux); ++m) { + if (m == ident) + continue; + if (port_mux[m] != offset) + continue; + if (!is_reserved(peri, m, 1)) + continue; - muxreg |= (function << offset); - bfin_write_PORT_MUX(muxreg); + if (offset == 1) + pfunc = (pmux >> offset) & 3; + else + pfunc = (pmux >> offset) & 1; + if (pfunc != function) { + pr_err("pin group conflict! request pin %d func %d conflict with pin %d func %d\n", + ident, function, m, pfunc); + return -EINVAL; } } + + return 0; +} + +static void portmux_setup(unsigned short per) +{ + u16 ident = P_IDENT(per); + u16 function = P_FUNCT2MUX(per); + s8 offset = port_mux[ident]; + u16 pmux; + + if (offset == -1) + return; + + pmux = bfin_read_PORT_MUX(); + if (offset != 1) + pmux &= ~(1 << offset); + else + pmux &= ~(3 << 1); + pmux |= (function << offset); + bfin_write_PORT_MUX(pmux); } #elif defined(CONFIG_BF54x) inline void portmux_setup(unsigned short per) { - u32 pmux; u16 ident = P_IDENT(per); u16 function = P_FUNCT2MUX(per); + u32 pmux; pmux = gpio_array[gpio_bank(ident)]->port_mux; @@ -302,20 +311,54 @@ inline void portmux_setup(unsigned short per) inline u16 get_portmux(unsigned short per) { - u32 pmux; u16 ident = P_IDENT(per); - - pmux = gpio_array[gpio_bank(ident)]->port_mux; - + u32 pmux = gpio_array[gpio_bank(ident)]->port_mux; return (pmux >> (2 * gpio_sub_n(ident)) & 0x3); } +static int portmux_group_check(unsigned short per) +{ + return 0; +} #elif defined(CONFIG_BF52x) || defined(CONFIG_BF51x) +static int portmux_group_check(unsigned short per) +{ + u16 ident = P_IDENT(per); + u16 function = P_FUNCT2MUX(per); + u8 offset = pmux_offset[gpio_bank(ident)][gpio_sub_n(ident)]; + u16 pin, gpiopin, pfunc; + + for (pin = 0; pin < GPIO_BANKSIZE; ++pin) { + if (offset != pmux_offset[gpio_bank(ident)][pin]) + continue; + + gpiopin = gpio_bank(ident) * GPIO_BANKSIZE + pin; + if (gpiopin == ident) + continue; + if (!is_reserved(peri, gpiopin, 1)) + continue; + + pfunc = *port_mux[gpio_bank(ident)]; + pfunc = (pfunc >> offset) & 3; + if (pfunc != function) { + pr_err("pin group conflict! request pin %d func %d conflict with pin %d func %d\n", + ident, function, gpiopin, pfunc); + return -EINVAL; + } + } + + return 0; +} + inline void portmux_setup(unsigned short per) { - u16 pmux, ident = P_IDENT(per), function = P_FUNCT2MUX(per); + u16 ident = P_IDENT(per); + u16 function = P_FUNCT2MUX(per); u8 offset = pmux_offset[gpio_bank(ident)][gpio_sub_n(ident)]; + u16 pmux; pmux = *port_mux[gpio_bank(ident)]; + if (((pmux >> offset) & 3) == function) + return; pmux &= ~(3 << offset); pmux |= (function & 3) << offset; *port_mux[gpio_bank(ident)] = pmux; @@ -323,6 +366,10 @@ inline void portmux_setup(unsigned short per) } #else # define portmux_setup(...) do { } while (0) +static int portmux_group_check(unsigned short per) +{ + return 0; +} #endif #ifndef CONFIG_BF54x @@ -735,6 +782,10 @@ int peripheral_request(unsigned short per, const char *label) } } + if (unlikely(portmux_group_check(per))) { + hard_local_irq_restore(flags); + return -EBUSY; + } anyway: reserve(peri, ident); diff --git a/arch/blackfin/kernel/process.c b/arch/blackfin/kernel/process.c index c86a3ed5f48f..cd0c090ebc54 100644 --- a/arch/blackfin/kernel/process.c +++ b/arch/blackfin/kernel/process.c @@ -493,6 +493,11 @@ int _access_ok(unsigned long addr, unsigned long size) return 1; #endif +#ifndef CONFIG_EXCEPTION_L1_SCRATCH + if (in_mem_const(addr, size, (unsigned long)l1_stack_base, l1_stack_len)) + return 1; +#endif + aret = in_async(addr, size); if (aret < 2) return aret; diff --git a/arch/blackfin/kernel/ptrace.c b/arch/blackfin/kernel/ptrace.c index 6ec77685df52..b35839354130 100644 --- a/arch/blackfin/kernel/ptrace.c +++ b/arch/blackfin/kernel/ptrace.c @@ -27,6 +27,7 @@ #include <asm/fixed_code.h> #include <asm/cacheflush.h> #include <asm/mem_map.h> +#include <asm/mmu_context.h> /* * does not yet catch signals sent when the child dies. @@ -113,8 +114,8 @@ put_reg(struct task_struct *task, long regno, unsigned long data) /* * check that an address falls within the bounds of the target process's memory mappings */ -static inline int is_user_addr_valid(struct task_struct *child, - unsigned long start, unsigned long len) +int +is_user_addr_valid(struct task_struct *child, unsigned long start, unsigned long len) { struct vm_area_struct *vma; struct sram_list_struct *sraml; @@ -135,6 +136,13 @@ static inline int is_user_addr_valid(struct task_struct *child, if (start >= FIXED_CODE_START && start + len < FIXED_CODE_END) return 0; +#ifdef CONFIG_APP_STACK_L1 + if (child->mm->context.l1_stack_save) + if (start >= (unsigned long)l1_stack_base && + start + len < (unsigned long)l1_stack_base + l1_stack_len) + return 0; +#endif + return -EIO; } diff --git a/arch/blackfin/kernel/sys_bfin.c b/arch/blackfin/kernel/sys_bfin.c index bdc1e2f0da32..89448ed7065d 100644 --- a/arch/blackfin/kernel/sys_bfin.c +++ b/arch/blackfin/kernel/sys_bfin.c @@ -21,6 +21,8 @@ #include <asm/cacheflush.h> #include <asm/dma.h> +#include <asm/cachectl.h> +#include <asm/ptrace.h> asmlinkage void *sys_sram_alloc(size_t size, unsigned long flags) { @@ -70,3 +72,16 @@ asmlinkage int sys_bfin_spinlock(int *p) return ret; } + +SYSCALL_DEFINE3(cacheflush, unsigned long, addr, unsigned long, len, int, op) +{ + if (is_user_addr_valid(current, addr, len) != 0) + return -EINVAL; + + if (op & DCACHE) + blackfin_dcache_flush_range(addr, addr + len); + if (op & ICACHE) + blackfin_icache_flush_range(addr, addr + len); + + return 0; +} |