diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-23 00:12:27 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-23 00:12:27 -0400 |
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 @@ | |||
1 | /* | 1 | /* |
2 | * GPIO Abstraction Layer | 2 | * GPIO Abstraction Layer |
3 | * | 3 | * |
4 | * Copyright 2006-2009 Analog Devices Inc. | 4 | * Copyright 2006-2010 Analog Devices Inc. |
5 | * | 5 | * |
6 | * Licensed under the GPL-2 or later | 6 | * Licensed under the GPL-2 or later |
7 | */ | 7 | */ |
@@ -215,82 +215,91 @@ static void port_setup(unsigned gpio, unsigned short usage) | |||
215 | } | 215 | } |
216 | 216 | ||
217 | #ifdef BF537_FAMILY | 217 | #ifdef BF537_FAMILY |
218 | static struct { | 218 | static const s8 port_mux[] = { |
219 | unsigned short res; | 219 | [GPIO_PF0] = 3, |
220 | unsigned short offset; | 220 | [GPIO_PF1] = 3, |
221 | } port_mux_lut[] = { | 221 | [GPIO_PF2] = 4, |
222 | {.res = P_PPI0_D13, .offset = 11}, | 222 | [GPIO_PF3] = 4, |
223 | {.res = P_PPI0_D14, .offset = 11}, | 223 | [GPIO_PF4] = 5, |
224 | {.res = P_PPI0_D15, .offset = 11}, | 224 | [GPIO_PF5] = 6, |
225 | {.res = P_SPORT1_TFS, .offset = 11}, | 225 | [GPIO_PF6] = 7, |
226 | {.res = P_SPORT1_TSCLK, .offset = 11}, | 226 | [GPIO_PF7] = 8, |
227 | {.res = P_SPORT1_DTPRI, .offset = 11}, | 227 | [GPIO_PF8 ... GPIO_PF15] = -1, |
228 | {.res = P_PPI0_D10, .offset = 10}, | 228 | [GPIO_PG0 ... GPIO_PG7] = -1, |
229 | {.res = P_PPI0_D11, .offset = 10}, | 229 | [GPIO_PG8] = 9, |
230 | {.res = P_PPI0_D12, .offset = 10}, | 230 | [GPIO_PG9] = 9, |
231 | {.res = P_SPORT1_RSCLK, .offset = 10}, | 231 | [GPIO_PG10] = 10, |
232 | {.res = P_SPORT1_RFS, .offset = 10}, | 232 | [GPIO_PG11] = 10, |
233 | {.res = P_SPORT1_DRPRI, .offset = 10}, | 233 | [GPIO_PG12] = 10, |
234 | {.res = P_PPI0_D8, .offset = 9}, | 234 | [GPIO_PG13] = 11, |
235 | {.res = P_PPI0_D9, .offset = 9}, | 235 | [GPIO_PG14] = 11, |
236 | {.res = P_SPORT1_DRSEC, .offset = 9}, | 236 | [GPIO_PG15] = 11, |
237 | {.res = P_SPORT1_DTSEC, .offset = 9}, | 237 | [GPIO_PH0 ... GPIO_PH15] = -1, |
238 | {.res = P_TMR2, .offset = 8}, | 238 | [PORT_PJ0 ... PORT_PJ3] = -1, |
239 | {.res = P_PPI0_FS3, .offset = 8}, | 239 | [PORT_PJ4] = 1, |
240 | {.res = P_TMR3, .offset = 7}, | 240 | [PORT_PJ5] = 1, |
241 | {.res = P_SPI0_SSEL4, .offset = 7}, | 241 | [PORT_PJ6 ... PORT_PJ9] = -1, |
242 | {.res = P_TMR4, .offset = 6}, | 242 | [PORT_PJ10] = 0, |
243 | {.res = P_SPI0_SSEL5, .offset = 6}, | 243 | [PORT_PJ11] = 0, |
244 | {.res = P_TMR5, .offset = 5}, | ||
245 | {.res = P_SPI0_SSEL6, .offset = 5}, | ||
246 | {.res = P_UART1_RX, .offset = 4}, | ||
247 | {.res = P_UART1_TX, .offset = 4}, | ||
248 | {.res = P_TMR6, .offset = 4}, | ||
249 | {.res = P_TMR7, .offset = 4}, | ||
250 | {.res = P_UART0_RX, .offset = 3}, | ||
251 | {.res = P_UART0_TX, .offset = 3}, | ||
252 | {.res = P_DMAR0, .offset = 3}, | ||
253 | {.res = P_DMAR1, .offset = 3}, | ||
254 | {.res = P_SPORT0_DTSEC, .offset = 1}, | ||
255 | {.res = P_SPORT0_DRSEC, .offset = 1}, | ||
256 | {.res = P_CAN0_RX, .offset = 1}, | ||
257 | {.res = P_CAN0_TX, .offset = 1}, | ||
258 | {.res = P_SPI0_SSEL7, .offset = 1}, | ||
259 | {.res = P_SPORT0_TFS, .offset = 0}, | ||
260 | {.res = P_SPORT0_DTPRI, .offset = 0}, | ||
261 | {.res = P_SPI0_SSEL2, .offset = 0}, | ||
262 | {.res = P_SPI0_SSEL3, .offset = 0}, | ||
263 | }; | 244 | }; |
264 | 245 | ||
265 | static void portmux_setup(unsigned short per) | 246 | static int portmux_group_check(unsigned short per) |
266 | { | 247 | { |
267 | u16 y, offset, muxreg; | 248 | u16 ident = P_IDENT(per); |
268 | u16 function = P_FUNCT2MUX(per); | 249 | u16 function = P_FUNCT2MUX(per); |
250 | s8 offset = port_mux[ident]; | ||
251 | u16 m, pmux, pfunc; | ||
269 | 252 | ||
270 | for (y = 0; y < ARRAY_SIZE(port_mux_lut); y++) { | 253 | if (offset < 0) |
271 | if (port_mux_lut[y].res == per) { | 254 | return 0; |
272 | |||
273 | /* SET PORTMUX REG */ | ||
274 | |||
275 | offset = port_mux_lut[y].offset; | ||
276 | muxreg = bfin_read_PORT_MUX(); | ||
277 | 255 | ||
278 | if (offset != 1) | 256 | pmux = bfin_read_PORT_MUX(); |
279 | muxreg &= ~(1 << offset); | 257 | for (m = 0; m < ARRAY_SIZE(port_mux); ++m) { |
280 | else | 258 | if (m == ident) |
281 | muxreg &= ~(3 << 1); | 259 | continue; |
260 | if (port_mux[m] != offset) | ||
261 | continue; | ||
262 | if (!is_reserved(peri, m, 1)) | ||
263 | continue; | ||
282 | 264 | ||
283 | muxreg |= (function << offset); | 265 | if (offset == 1) |
284 | bfin_write_PORT_MUX(muxreg); | 266 | pfunc = (pmux >> offset) & 3; |
267 | else | ||
268 | pfunc = (pmux >> offset) & 1; | ||
269 | if (pfunc != function) { | ||
270 | pr_err("pin group conflict! request pin %d func %d conflict with pin %d func %d\n", | ||
271 | ident, function, m, pfunc); | ||
272 | return -EINVAL; | ||
285 | } | 273 | } |
286 | } | 274 | } |
275 | |||
276 | return 0; | ||
277 | } | ||
278 | |||
279 | static void portmux_setup(unsigned short per) | ||
280 | { | ||
281 | u16 ident = P_IDENT(per); | ||
282 | u16 function = P_FUNCT2MUX(per); | ||
283 | s8 offset = port_mux[ident]; | ||
284 | u16 pmux; | ||
285 | |||
286 | if (offset == -1) | ||
287 | return; | ||
288 | |||
289 | pmux = bfin_read_PORT_MUX(); | ||
290 | if (offset != 1) | ||
291 | pmux &= ~(1 << offset); | ||
292 | else | ||
293 | pmux &= ~(3 << 1); | ||
294 | pmux |= (function << offset); | ||
295 | bfin_write_PORT_MUX(pmux); | ||
287 | } | 296 | } |
288 | #elif defined(CONFIG_BF54x) | 297 | #elif defined(CONFIG_BF54x) |
289 | inline void portmux_setup(unsigned short per) | 298 | inline void portmux_setup(unsigned short per) |
290 | { | 299 | { |
291 | u32 pmux; | ||
292 | u16 ident = P_IDENT(per); | 300 | u16 ident = P_IDENT(per); |
293 | u16 function = P_FUNCT2MUX(per); | 301 | u16 function = P_FUNCT2MUX(per); |
302 | u32 pmux; | ||
294 | 303 | ||
295 | pmux = gpio_array[gpio_bank(ident)]->port_mux; | 304 | pmux = gpio_array[gpio_bank(ident)]->port_mux; |
296 | 305 | ||
@@ -302,20 +311,54 @@ inline void portmux_setup(unsigned short per) | |||
302 | 311 | ||
303 | inline u16 get_portmux(unsigned short per) | 312 | inline u16 get_portmux(unsigned short per) |
304 | { | 313 | { |
305 | u32 pmux; | ||
306 | u16 ident = P_IDENT(per); | 314 | u16 ident = P_IDENT(per); |
307 | 315 | u32 pmux = gpio_array[gpio_bank(ident)]->port_mux; | |
308 | pmux = gpio_array[gpio_bank(ident)]->port_mux; | ||
309 | |||
310 | return (pmux >> (2 * gpio_sub_n(ident)) & 0x3); | 316 | return (pmux >> (2 * gpio_sub_n(ident)) & 0x3); |
311 | } | 317 | } |
318 | static int portmux_group_check(unsigned short per) | ||
319 | { | ||
320 | return 0; | ||
321 | } | ||
312 | #elif defined(CONFIG_BF52x) || defined(CONFIG_BF51x) | 322 | #elif defined(CONFIG_BF52x) || defined(CONFIG_BF51x) |
323 | static int portmux_group_check(unsigned short per) | ||
324 | { | ||
325 | u16 ident = P_IDENT(per); | ||
326 | u16 function = P_FUNCT2MUX(per); | ||
327 | u8 offset = pmux_offset[gpio_bank(ident)][gpio_sub_n(ident)]; | ||
328 | u16 pin, gpiopin, pfunc; | ||
329 | |||
330 | for (pin = 0; pin < GPIO_BANKSIZE; ++pin) { | ||
331 | if (offset != pmux_offset[gpio_bank(ident)][pin]) | ||
332 | continue; | ||
333 | |||
334 | gpiopin = gpio_bank(ident) * GPIO_BANKSIZE + pin; | ||
335 | if (gpiopin == ident) | ||
336 | continue; | ||
337 | if (!is_reserved(peri, gpiopin, 1)) | ||
338 | continue; | ||
339 | |||
340 | pfunc = *port_mux[gpio_bank(ident)]; | ||
341 | pfunc = (pfunc >> offset) & 3; | ||
342 | if (pfunc != function) { | ||
343 | pr_err("pin group conflict! request pin %d func %d conflict with pin %d func %d\n", | ||
344 | ident, function, gpiopin, pfunc); | ||
345 | return -EINVAL; | ||
346 | } | ||
347 | } | ||
348 | |||
349 | return 0; | ||
350 | } | ||
351 | |||
313 | inline void portmux_setup(unsigned short per) | 352 | inline void portmux_setup(unsigned short per) |
314 | { | 353 | { |
315 | u16 pmux, ident = P_IDENT(per), function = P_FUNCT2MUX(per); | 354 | u16 ident = P_IDENT(per); |
355 | u16 function = P_FUNCT2MUX(per); | ||
316 | u8 offset = pmux_offset[gpio_bank(ident)][gpio_sub_n(ident)]; | 356 | u8 offset = pmux_offset[gpio_bank(ident)][gpio_sub_n(ident)]; |
357 | u16 pmux; | ||
317 | 358 | ||
318 | pmux = *port_mux[gpio_bank(ident)]; | 359 | pmux = *port_mux[gpio_bank(ident)]; |
360 | if (((pmux >> offset) & 3) == function) | ||
361 | return; | ||
319 | pmux &= ~(3 << offset); | 362 | pmux &= ~(3 << offset); |
320 | pmux |= (function & 3) << offset; | 363 | pmux |= (function & 3) << offset; |
321 | *port_mux[gpio_bank(ident)] = pmux; | 364 | *port_mux[gpio_bank(ident)] = pmux; |
@@ -323,6 +366,10 @@ inline void portmux_setup(unsigned short per) | |||
323 | } | 366 | } |
324 | #else | 367 | #else |
325 | # define portmux_setup(...) do { } while (0) | 368 | # define portmux_setup(...) do { } while (0) |
369 | static int portmux_group_check(unsigned short per) | ||
370 | { | ||
371 | return 0; | ||
372 | } | ||
326 | #endif | 373 | #endif |
327 | 374 | ||
328 | #ifndef CONFIG_BF54x | 375 | #ifndef CONFIG_BF54x |
@@ -735,6 +782,10 @@ int peripheral_request(unsigned short per, const char *label) | |||
735 | } | 782 | } |
736 | } | 783 | } |
737 | 784 | ||
785 | if (unlikely(portmux_group_check(per))) { | ||
786 | hard_local_irq_restore(flags); | ||
787 | return -EBUSY; | ||
788 | } | ||
738 | anyway: | 789 | anyway: |
739 | reserve(peri, ident); | 790 | reserve(peri, ident); |
740 | 791 | ||
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) | |||
493 | return 1; | 493 | return 1; |
494 | #endif | 494 | #endif |
495 | 495 | ||
496 | #ifndef CONFIG_EXCEPTION_L1_SCRATCH | ||
497 | if (in_mem_const(addr, size, (unsigned long)l1_stack_base, l1_stack_len)) | ||
498 | return 1; | ||
499 | #endif | ||
500 | |||
496 | aret = in_async(addr, size); | 501 | aret = in_async(addr, size); |
497 | if (aret < 2) | 502 | if (aret < 2) |
498 | return aret; | 503 | 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 @@ | |||
27 | #include <asm/fixed_code.h> | 27 | #include <asm/fixed_code.h> |
28 | #include <asm/cacheflush.h> | 28 | #include <asm/cacheflush.h> |
29 | #include <asm/mem_map.h> | 29 | #include <asm/mem_map.h> |
30 | #include <asm/mmu_context.h> | ||
30 | 31 | ||
31 | /* | 32 | /* |
32 | * does not yet catch signals sent when the child dies. | 33 | * 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) | |||
113 | /* | 114 | /* |
114 | * check that an address falls within the bounds of the target process's memory mappings | 115 | * check that an address falls within the bounds of the target process's memory mappings |
115 | */ | 116 | */ |
116 | static inline int is_user_addr_valid(struct task_struct *child, | 117 | int |
117 | unsigned long start, unsigned long len) | 118 | is_user_addr_valid(struct task_struct *child, unsigned long start, unsigned long len) |
118 | { | 119 | { |
119 | struct vm_area_struct *vma; | 120 | struct vm_area_struct *vma; |
120 | struct sram_list_struct *sraml; | 121 | struct sram_list_struct *sraml; |
@@ -135,6 +136,13 @@ static inline int is_user_addr_valid(struct task_struct *child, | |||
135 | if (start >= FIXED_CODE_START && start + len < FIXED_CODE_END) | 136 | if (start >= FIXED_CODE_START && start + len < FIXED_CODE_END) |
136 | return 0; | 137 | return 0; |
137 | 138 | ||
139 | #ifdef CONFIG_APP_STACK_L1 | ||
140 | if (child->mm->context.l1_stack_save) | ||
141 | if (start >= (unsigned long)l1_stack_base && | ||
142 | start + len < (unsigned long)l1_stack_base + l1_stack_len) | ||
143 | return 0; | ||
144 | #endif | ||
145 | |||
138 | return -EIO; | 146 | return -EIO; |
139 | } | 147 | } |
140 | 148 | ||
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 @@ | |||
21 | 21 | ||
22 | #include <asm/cacheflush.h> | 22 | #include <asm/cacheflush.h> |
23 | #include <asm/dma.h> | 23 | #include <asm/dma.h> |
24 | #include <asm/cachectl.h> | ||
25 | #include <asm/ptrace.h> | ||
24 | 26 | ||
25 | asmlinkage void *sys_sram_alloc(size_t size, unsigned long flags) | 27 | asmlinkage void *sys_sram_alloc(size_t size, unsigned long flags) |
26 | { | 28 | { |
@@ -70,3 +72,16 @@ asmlinkage int sys_bfin_spinlock(int *p) | |||
70 | 72 | ||
71 | return ret; | 73 | return ret; |
72 | } | 74 | } |
75 | |||
76 | SYSCALL_DEFINE3(cacheflush, unsigned long, addr, unsigned long, len, int, op) | ||
77 | { | ||
78 | if (is_user_addr_valid(current, addr, len) != 0) | ||
79 | return -EINVAL; | ||
80 | |||
81 | if (op & DCACHE) | ||
82 | blackfin_dcache_flush_range(addr, addr + len); | ||
83 | if (op & ICACHE) | ||
84 | blackfin_icache_flush_range(addr, addr + len); | ||
85 | |||
86 | return 0; | ||
87 | } | ||