aboutsummaryrefslogtreecommitdiffstats
path: root/arch/blackfin/kernel
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-10-23 00:12:27 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-10-23 00:12:27 -0400
commit7f3883962870dd28b5f2322ac44a9d03640ef448 (patch)
tree01f7dd2ac2b7c61e5e6726c4fec4484aaca6e7b7 /arch/blackfin/kernel
parent10f2a2b0f68abf39c06cf519cbc1740fa50f900b (diff)
parentb9ac41e314f0b43641bc01bd553fd2e0458ed832 (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.c185
-rw-r--r--arch/blackfin/kernel/process.c5
-rw-r--r--arch/blackfin/kernel/ptrace.c12
-rw-r--r--arch/blackfin/kernel/sys_bfin.c15
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
218static struct { 218static 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
265static void portmux_setup(unsigned short per) 246static 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
279static 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)
289inline void portmux_setup(unsigned short per) 298inline 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
303inline u16 get_portmux(unsigned short per) 312inline 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}
318static 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)
323static 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
313inline void portmux_setup(unsigned short per) 352inline 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)
369static 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 */
116static inline int is_user_addr_valid(struct task_struct *child, 117int
117 unsigned long start, unsigned long len) 118is_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
25asmlinkage void *sys_sram_alloc(size_t size, unsigned long flags) 27asmlinkage 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
76SYSCALL_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}