Commit 064e297c authored by Linus Torvalds's avatar Linus Torvalds

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: (30 commits)
  Blackfin: SMP: fix continuation lines
  Blackfin: acvilon: fix timeout usage for I2C
  Blackfin: fix typo in BF537 IRQ comment
  Blackfin: unify duplicate MEM_MT48LC32M8A2_75 kconfig options
  Blackfin: set ARCH_KMALLOC_MINALIGN
  Blackfin: use atomic kmalloc in L1 alloc so it too can be atomic
  Blackfin: another year of changes (update copyright in boot log)
  Blackfin: optimize strncpy a bit
  Blackfin: isram: clean up ITEST_COMMAND macro and improve the selftests
  Blackfin: move string functions to normal lib/ assembly
  Blackfin: SIC: cut down on IAR MMR reads a bit
  Blackfin: bf537-minotaur: fix build errors due to header changes
  Blackfin: kgdb: pass up the CC register instead of a 0 stub
  Blackfin: handle HW errors in the new "FAULT" printing code
  Blackfin: show the whole accumulator in the pseudo DBG insn
  Blackfin: support all possible registers in the pseudo instructions
  Blackfin: add support for the DBG (debug output) pseudo insn
  Blackfin: change the BUG opcode to an unused 16-bit opcode
  Blackfin: allow NMI watchdog to be used w/RETN as a scratch reg
  Blackfin: add support for the DBGA (debug assert) pseudo insn
  ...
parents f1377118 db52ecc2
......@@ -348,7 +348,7 @@ config MEM_MT48LC16M16A2TG_75
config MEM_MT48LC32M8A2_75
bool
depends on (BFIN537_STAMP || PNAV10 || BFIN538_EZKIT)
depends on (BFIN518F_EZBRD || BFIN537_STAMP || PNAV10 || BFIN538_EZKIT)
default y
config MEM_MT48LC8M32B2B5_7
......@@ -361,11 +361,6 @@ config MEM_MT48LC32M16A2TG_75
depends on (BFIN527_EZKIT || BFIN527_EZKIT_V2 || BFIN532_IP0X || BLACKSTAMP)
default y
config MEM_MT48LC32M8A2_75
bool
depends on (BFIN518F_EZBRD)
default y
config MEM_MT48H32M16LFCJ_75
bool
depends on (BFIN526_EZBRD)
......@@ -791,6 +786,34 @@ config MEMCPY_L1
If enabled, the memcpy function is linked
into L1 instruction memory. (less latency)
config STRCMP_L1
bool "locate strcmp function in L1 Memory"
default y
help
If enabled, the strcmp function is linked
into L1 instruction memory (less latency).
config STRNCMP_L1
bool "locate strncmp function in L1 Memory"
default y
help
If enabled, the strncmp function is linked
into L1 instruction memory (less latency).
config STRCPY_L1
bool "locate strcpy function in L1 Memory"
default y
help
If enabled, the strcpy function is linked
into L1 instruction memory (less latency).
config STRNCPY_L1
bool "locate strncpy function in L1 Memory"
default y
help
If enabled, the strncpy function is linked
into L1 instruction memory (less latency).
config SYS_BFIN_SPINLOCK_L1
bool "Locate sys_bfin_spinlock function in L1 Memory"
default y
......@@ -1187,32 +1210,6 @@ config PM_BFIN_SLEEP
If unsure, select "Sleep Deeper".
endchoice
config PM_WAKEUP_BY_GPIO
bool "Allow Wakeup from Standby by GPIO"
depends on PM && !BF54x
config PM_WAKEUP_GPIO_NUMBER
int "GPIO number"
range 0 47
depends on PM_WAKEUP_BY_GPIO
default 2
choice
prompt "GPIO Polarity"
depends on PM_WAKEUP_BY_GPIO
default PM_WAKEUP_GPIO_POLAR_H
config PM_WAKEUP_GPIO_POLAR_H
bool "Active High"
config PM_WAKEUP_GPIO_POLAR_L
bool "Active Low"
config PM_WAKEUP_GPIO_POLAR_EDGE_F
bool "Falling EDGE"
config PM_WAKEUP_GPIO_POLAR_EDGE_R
bool "Rising EDGE"
config PM_WAKEUP_GPIO_POLAR_EDGE_B
bool "Both EDGE"
endchoice
comment "Possible Suspend Mem / Hibernate Wake-Up Sources"
depends on PM
......
......@@ -238,7 +238,7 @@ config EARLY_PRINTK
config NMI_WATCHDOG
bool "Enable NMI watchdog to help debugging lockup on SMP"
default n
depends on (SMP && !BFIN_SCRATCH_REG_RETN)
depends on SMP
help
If any CPU in the system does not execute the period local timer
interrupt for more than 5 seconds, then the NMI handler dumps debug
......@@ -264,4 +264,13 @@ config BFIN_ISRAM_SELF_TEST
help
Run some self tests of the isram driver code at boot.
config BFIN_PSEUDODBG_INSNS
bool "Support pseudo debug instructions"
default n
help
This option allows the kernel to emulate some pseudo instructions which
allow simulator test cases to be run under Linux with no changes.
Most people should say N here.
endmenu
......@@ -39,9 +39,15 @@ extern unsigned long sclk_to_usecs(unsigned long sclk);
extern unsigned long usecs_to_sclk(unsigned long usecs);
struct pt_regs;
#if defined(CONFIG_DEBUG_VERBOSE)
extern void dump_bfin_process(struct pt_regs *regs);
extern void dump_bfin_mem(struct pt_regs *regs);
extern void dump_bfin_trace_buffer(void);
#else
#define dump_bfin_process(regs)
#define dump_bfin_mem(regs)
#define dump_bfin_trace_buffer()
#endif
/* init functions only */
extern int init_arch_irq(void);
......
......@@ -9,7 +9,12 @@
#ifdef CONFIG_BUG
#define BFIN_BUG_OPCODE 0xefcd
/*
* This can be any undefined 16-bit opcode, meaning
* ((opcode & 0xc000) != 0xc000)
* Anything from 0x0001 to 0x000A (inclusive) will work
*/
#define BFIN_BUG_OPCODE 0x0001
#ifdef CONFIG_DEBUG_BUGVERBOSE
......
......@@ -15,6 +15,8 @@
#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT)
#define SMP_CACHE_BYTES L1_CACHE_BYTES
#define ARCH_KMALLOC_MINALIGN L1_CACHE_BYTES
#ifdef CONFIG_SMP
#define __cacheline_aligned
#else
......
......@@ -167,23 +167,23 @@ int bfin_special_gpio_request(unsigned gpio, const char *label);
#endif
#ifdef CONFIG_PM
int bfin_pm_standby_ctrl(unsigned ctrl);
unsigned int bfin_pm_standby_setup(void);
void bfin_pm_standby_restore(void);
static inline int bfin_pm_standby_setup(void)
{
return bfin_pm_standby_ctrl(1);
}
static inline void bfin_pm_standby_restore(void)
{
bfin_pm_standby_ctrl(0);
}
void bfin_gpio_pm_hibernate_restore(void);
void bfin_gpio_pm_hibernate_suspend(void);
#ifndef CONFIG_BF54x
#define PM_WAKE_RISING 0x1
#define PM_WAKE_FALLING 0x2
#define PM_WAKE_HIGH 0x4
#define PM_WAKE_LOW 0x8
#define PM_WAKE_BOTH_EDGES (PM_WAKE_RISING | PM_WAKE_FALLING)
#define PM_WAKE_IGNORE 0xF0
int gpio_pm_wakeup_request(unsigned gpio, unsigned char type);
void gpio_pm_wakeup_free(unsigned gpio);
int gpio_pm_wakeup_ctrl(unsigned gpio, unsigned ctrl);
struct gpio_port_s {
unsigned short data;
......
......@@ -80,7 +80,8 @@ PTE_BIT_FUNC(mkyoung, |= _PAGE_ACCESSED);
* ZERO_PAGE is a global shared page that is always zero: used
* for zero-mapped memory areas etc..
*/
#define ZERO_PAGE(vaddr) (virt_to_page(0))
#define ZERO_PAGE(vaddr) virt_to_page(empty_zero_page)
extern char empty_zero_page[];
extern unsigned int kobjsize(const void *objp);
......
/*
* header file for pseudo instructions
*
* Copyright 2010 Analog Devices Inc.
*
* Licensed under the GPL-2 or later.
*/
#ifndef _BLACKFIN_PSEUDO_
#define _BLACKFIN_PSEUDO_
#include <linux/types.h>
#include <asm/ptrace.h>
extern bool execute_pseudodbg_assert(struct pt_regs *fp, unsigned int opcode);
extern bool execute_pseudodbg(struct pt_regs *fp, unsigned int opcode);
#endif
......@@ -12,121 +12,16 @@
#ifdef __KERNEL__ /* only set these up for kernel code */
#define __HAVE_ARCH_STRCPY
extern inline char *strcpy(char *dest, const char *src)
{
char *xdest = dest;
char temp = 0;
__asm__ __volatile__ (
"1:"
"%2 = B [%1++] (Z);"
"B [%0++] = %2;"
"CC = %2;"
"if cc jump 1b (bp);"
: "+&a" (dest), "+&a" (src), "=&d" (temp)
:
: "memory", "CC");
return xdest;
}
extern char *strcpy(char *dest, const char *src);
#define __HAVE_ARCH_STRNCPY
extern inline char *strncpy(char *dest, const char *src, size_t n)
{
char *xdest = dest;
char temp = 0;
if (n == 0)
return xdest;
__asm__ __volatile__ (
"1:"
"%3 = B [%1++] (Z);"
"B [%0++] = %3;"
"CC = %3;"
"if ! cc jump 2f;"
"%2 += -1;"
"CC = %2 == 0;"
"if ! cc jump 1b (bp);"
"jump 4f;"
"2:"
/* if src is shorter than n, we need to null pad bytes now */
"%3 = 0;"
"3:"
"%2 += -1;"
"CC = %2 == 0;"
"if cc jump 4f;"
"B [%0++] = %3;"
"jump 3b;"
"4:"
: "+&a" (dest), "+&a" (src), "+&da" (n), "=&d" (temp)
:
: "memory", "CC");
return xdest;
}
extern char *strncpy(char *dest, const char *src, size_t n);
#define __HAVE_ARCH_STRCMP
extern inline int strcmp(const char *cs, const char *ct)
{
/* need to use int's here so the char's in the assembly don't get
* sign extended incorrectly when we don't want them to be
*/
int __res1, __res2;
__asm__ __volatile__ (
"1:"
"%2 = B[%0++] (Z);" /* get *cs */
"%3 = B[%1++] (Z);" /* get *ct */
"CC = %2 == %3;" /* compare a byte */
"if ! cc jump 2f;" /* not equal, break out */
"CC = %2;" /* at end of cs? */
"if cc jump 1b (bp);" /* no, keep going */
"jump.s 3f;" /* strings are equal */
"2:"
"%2 = %2 - %3;" /* *cs - *ct */
"3:"
: "+&a" (cs), "+&a" (ct), "=&d" (__res1), "=&d" (__res2)
:
: "memory", "CC");
return __res1;
}
extern int strcmp(const char *cs, const char *ct);
#define __HAVE_ARCH_STRNCMP
extern inline int strncmp(const char *cs, const char *ct, size_t count)
{
/* need to use int's here so the char's in the assembly don't get
* sign extended incorrectly when we don't want them to be
*/
int __res1, __res2;
if (!count)
return 0;
__asm__ __volatile__ (
"1:"
"%3 = B[%0++] (Z);" /* get *cs */
"%4 = B[%1++] (Z);" /* get *ct */
"CC = %3 == %4;" /* compare a byte */
"if ! cc jump 3f;" /* not equal, break out */
"CC = %3;" /* at end of cs? */
"if ! cc jump 4f;" /* yes, all done */
"%2 += -1;" /* no, adjust count */
"CC = %2 == 0;"
"if ! cc jump 1b;" /* more to do, keep going */
"2:"
"%3 = 0;" /* strings are equal */
"jump.s 4f;"
"3:"
"%3 = %3 - %4;" /* *cs - *ct */
"4:"
: "+&a" (cs), "+&a" (ct), "+&da" (count), "=&d" (__res1), "=&d" (__res2)
:
: "memory", "CC");
return __res1;
}
extern int strncmp(const char *cs, const char *ct, size_t count);
#define __HAVE_ARCH_MEMSET
extern void *memset(void *s, int c, size_t count);
......
#include <asm-generic/tlbflush.h>
#define flush_tlb_kernel_range(s, e) do { } while (0)
......@@ -23,6 +23,13 @@
#ifndef __ASSEMBLY__
extern unsigned long trace_buff_offset;
extern unsigned long software_trace_buff[];
#if defined(CONFIG_DEBUG_VERBOSE)
extern void decode_address(char *buf, unsigned long address);
extern bool get_instruction(unsigned int *val, unsigned short *address);
#else
static inline void decode_address(char *buf, unsigned long address) { }
static inline bool get_instruction(unsigned int *val, unsigned short *address) { return false; }
#endif
/* Trace Macros for C files */
......
......@@ -7,7 +7,8 @@ extra-y := init_task.o vmlinux.lds
obj-y := \
entry.o process.o bfin_ksyms.o ptrace.o setup.o signal.o \
sys_bfin.o traps.o irqchip.o dma-mapping.o flat.o \
fixed_code.o reboot.o bfin_gpio.o bfin_dma_5xx.o
fixed_code.o reboot.o bfin_gpio.o bfin_dma_5xx.o \
exception.o dumpstack.o
ifeq ($(CONFIG_GENERIC_CLOCKEVENTS),y)
obj-y += time-ts.o
......@@ -29,6 +30,8 @@ obj-$(CONFIG_NMI_WATCHDOG) += nmi.o
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
obj-$(CONFIG_EARLY_PRINTK) += shadow_console.o
obj-$(CONFIG_STACKTRACE) += stacktrace.o
obj-$(CONFIG_DEBUG_VERBOSE) += trace.o
obj-$(CONFIG_BFIN_PSEUDODBG_INSNS) += pseudodbg.o
# the kgdb test puts code into L2 and without linker
# relaxation, we need to force long calls to/from it
......
......@@ -475,9 +475,7 @@ GET_GPIO_P(maskb)
#ifdef CONFIG_PM
static unsigned short wakeup_map[GPIO_BANK_NUM];
static unsigned char wakeup_flags_map[MAX_BLACKFIN_GPIOS];
static const unsigned int sic_iwr_irqs[] = {
#if defined(BF533_FAMILY)
......@@ -514,112 +512,26 @@ static const unsigned int sic_iwr_irqs[] = {
*************************************************************
* MODIFICATION HISTORY :
**************************************************************/
int gpio_pm_wakeup_request(unsigned gpio, unsigned char type)
{
unsigned long flags;
if ((check_gpio(gpio) < 0) || !type)
return -EINVAL;
local_irq_save_hw(flags);
wakeup_map[gpio_bank(gpio)] |= gpio_bit(gpio);
wakeup_flags_map[gpio] = type;
local_irq_restore_hw(flags);
return 0;
}
EXPORT_SYMBOL(gpio_pm_wakeup_request);
void gpio_pm_wakeup_free(unsigned gpio)
int gpio_pm_wakeup_ctrl(unsigned gpio, unsigned ctrl)
{
unsigned long flags;
if (check_gpio(gpio) < 0)
return;
return -EINVAL;
local_irq_save_hw(flags);
wakeup_map[gpio_bank(gpio)] &= ~gpio_bit(gpio);
local_irq_restore_hw(flags);
}
EXPORT_SYMBOL(gpio_pm_wakeup_free);
static int bfin_gpio_wakeup_type(unsigned gpio, unsigned char type)
{
port_setup(gpio, GPIO_USAGE);
set_gpio_dir(gpio, 0);
set_gpio_inen(gpio, 1);
if (type & (PM_WAKE_RISING | PM_WAKE_FALLING))
set_gpio_edge(gpio, 1);
else
set_gpio_edge(gpio, 0);
if ((type & (PM_WAKE_BOTH_EDGES)) == (PM_WAKE_BOTH_EDGES))
set_gpio_both(gpio, 1);
if (ctrl)
wakeup_map[gpio_bank(gpio)] |= gpio_bit(gpio);
else
set_gpio_both(gpio, 0);
if ((type & (PM_WAKE_FALLING | PM_WAKE_LOW)))
set_gpio_polar(gpio, 1);
else
set_gpio_polar(gpio, 0);
wakeup_map[gpio_bank(gpio)] &= ~gpio_bit(gpio);
SSYNC();
return 0;
}
u32 bfin_pm_standby_setup(void)
{
u16 bank, mask, i, gpio;
for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {
mask = wakeup_map[gpio_bank(i)];
bank = gpio_bank(i);
gpio_bank_saved[bank].maskb = gpio_array[bank]->maskb;
gpio_array[bank]->maskb = 0;
if (mask) {
#if defined(CONFIG_BF52x) || defined(BF537_FAMILY) || defined(CONFIG_BF51x)
gpio_bank_saved[bank].fer = *port_fer[bank];
#endif
gpio_bank_saved[bank].inen = gpio_array[bank]->inen;
gpio_bank_saved[bank].polar = gpio_array[bank]->polar;
gpio_bank_saved[bank].dir = gpio_array[bank]->dir;
gpio_bank_saved[bank].edge = gpio_array[bank]->edge;
gpio_bank_saved[bank].both = gpio_array[bank]->both;
gpio_bank_saved[bank].reserved =
reserved_gpio_map[bank];
gpio = i;
while (mask) {
if ((mask & 1) && (wakeup_flags_map[gpio] !=
PM_WAKE_IGNORE)) {
reserved_gpio_map[gpio_bank(gpio)] |=
gpio_bit(gpio);
bfin_gpio_wakeup_type(gpio,
wakeup_flags_map[gpio]);
set_gpio_data(gpio, 0); /*Clear*/
}
gpio++;
mask >>= 1;
}
bfin_internal_set_wake(sic_iwr_irqs[bank], 1);
gpio_array[bank]->maskb_set = wakeup_map[gpio_bank(i)];
}
}
AWA_DUMMY_READ(maskb_set);
set_gpio_maskb(gpio, ctrl);
local_irq_restore_hw(flags);
return 0;
}
void bfin_pm_standby_restore(void)
int bfin_pm_standby_ctrl(unsigned ctrl)
{
u16 bank, mask, i;
......@@ -627,24 +539,10 @@ void bfin_pm_standby_restore(void)
mask = wakeup_map[gpio_bank(i)];
bank = gpio_bank(i);
if (mask) {
#if defined(CONFIG_BF52x) || defined(BF537_FAMILY) || defined(CONFIG_BF51x)
*port_fer[bank] = gpio_bank_saved[bank].fer;
#endif
gpio_array[bank]->inen = gpio_bank_saved[bank].inen;
gpio_array[bank]->dir = gpio_bank_saved[bank].dir;
gpio_array[bank]->polar = gpio_bank_saved[bank].polar;
gpio_array[bank]->edge = gpio_bank_saved[bank].edge;
gpio_array[bank]->both = gpio_bank_saved[bank].both;
reserved_gpio_map[bank] =
gpio_bank_saved[bank].reserved;
bfin_internal_set_wake(sic_iwr_irqs[bank], 0);
}
gpio_array[bank]->maskb = gpio_bank_saved[bank].maskb;
if (mask)
bfin_internal_set_wake(sic_iwr_irqs[bank], ctrl);
}
AWA_DUMMY_READ(maskb);
return 0;
}
void bfin_gpio_pm_hibernate_suspend(void)
......@@ -708,16 +606,11 @@ void bfin_gpio_pm_hibernate_restore(void)
#else /* CONFIG_BF54x */
#ifdef CONFIG_PM
u32 bfin_pm_standby_setup(void)
int bfin_pm_standby_ctrl(unsigned ctrl)
{
return 0;
}
void bfin_pm_standby_restore(void)
{
}
void bfin_gpio_pm_hibernate_suspend(void)
{
int i, bank;
......
......@@ -32,6 +32,18 @@ EXPORT_SYMBOL(memcmp);
EXPORT_SYMBOL(memmove);
EXPORT_SYMBOL(memchr);
/*
* Because string functions are both inline and exported functions and
* folder arch/blackfin/lib is configured as a library path in Makefile,
* symbols exported in folder lib is not linked into built-in.o but
* inlined only. In order to export string symbols to kernel module
* properly, they should be exported here.
*/
EXPORT_SYMBOL(strcpy);
EXPORT_SYMBOL(strncpy);
EXPORT_SYMBOL(strcmp);
EXPORT_SYMBOL(strncmp);
/*
* libgcc functions - functions that are used internally by the
* compiler... (prototypes are not correct though, but that
......
/* Provide basic stack dumping functions
*
* Copyright 2004-2009 Analog Devices Inc.
*
* Licensed under the GPL-2 or later
*/
#include <linux/kernel.h>
#include <linux/thread_info.h>
#include <linux/mm.h>
#include <linux/uaccess.h>
#include <linux/module.h>
#include <asm/trace.h>
/*
* Checks to see if the address pointed to is either a
* 16-bit CALL instruction, or a 32-bit CALL instruction
*/
static bool is_bfin_call(unsigned short *addr)
{
unsigned int opcode;
if (!get_instruction(&opcode, addr))
return false;
if ((opcode >= 0x0060 && opcode <= 0x0067) ||
(opcode >= 0x0070 && opcode <= 0x0077) ||
(opcode >= 0xE3000000 && opcode <= 0xE3FFFFFF))
return true;
return false;
}
void show_stack(struct task_struct *task, unsigned long *stack)
{
#ifdef CONFIG_PRINTK
unsigned int *addr, *endstack, *fp = 0, *frame;
unsigned short *ins_addr;
char buf[150];
unsigned int i, j, ret_addr, frame_no = 0;
/*
* If we have been passed a specific stack, use that one otherwise
* if we have been passed a task structure, use that, otherwise
* use the stack of where the variable "stack" exists
*/
if (stack == NULL) {
if (task) {
/* We know this is a kernel stack, so this is the start/end */
stack = (unsigned long *)task->thread.ksp;
endstack = (unsigned int *)(((unsigned int)(stack) & ~(THREAD_SIZE - 1)) + THREAD_SIZE);
} else {
/* print out the existing stack info */
stack = (unsigned long *)&stack;
endstack = (unsigned int *)PAGE_ALIGN((unsigned int)stack);
}
} else
endstack = (unsigned int *)PAGE_ALIGN((unsigned int)stack);
printk(KERN_NOTICE "Stack info:\n");
decode_address(buf, (unsigned int)stack);
printk(KERN_NOTICE " SP: [0x%p] %s\n", stack, buf);
if (!access_ok(VERIFY_READ, stack, (unsigned int)endstack - (unsigned int)stack)) {
printk(KERN_NOTICE "Invalid stack pointer\n");
return;
}
/* First thing is to look for a frame pointer */
for (addr = (unsigned int *)((unsigned int)stack & ~0xF); addr < endstack; addr++) {
if (*addr & 0x1)
continue;
ins_addr = (unsigned short *)*addr;
ins_addr--;
if (is_bfin_call(ins_addr))
fp = addr - 1;
if (fp) {
/* Let's check to see if it is a frame pointer */
while (fp >= (addr - 1) && fp < endstack
&& fp && ((unsigned int) fp & 0x3) == 0)
fp = (unsigned int *)*fp;
if (fp == 0 || fp == endstack) {
fp = addr - 1;
break;
}
fp = 0;
}
}
if (fp) {
frame = fp;
printk(KERN_NOTICE " FP: (0x%p)\n", fp);
} else
frame = 0;
/*
* Now that we think we know where things are, we
* walk the stack again, this time printing things out
* incase there is no frame pointer, we still look for
* valid return addresses
*/
/* First time print out data, next time, print out symbols */
for (j = 0; j <= 1; j++) {
if (j)
printk(KERN_NOTICE "Return addresses in stack:\n");
else
printk(KERN_NOTICE " Memory from 0x%08lx to %p", ((long unsigned int)stack & ~0xF), endstack);
fp = frame;
frame_no = 0;
for (addr = (unsigned int *)((unsigned int)stack & ~0xF), i = 0;
addr < endstack; addr++, i++) {
ret_addr = 0;
if (!j && i % 8 == 0)
printk(KERN_NOTICE "%p:", addr);
/* if it is an odd address, or zero, just skip it */
if (*addr & 0x1 || !*addr)
goto print;
ins_addr = (unsigned short *)*addr;
/* Go back one instruction, and see if it is a CALL */
ins_addr--;
ret_addr = is_bfin_call(ins_addr);
print:
if (!j && stack == (unsigned long *)addr)
printk("[%08x]", *addr);
else if (ret_addr)
if (j) {
decode_address(buf, (unsigned int)*addr);
if (frame == addr) {
printk(KERN_NOTICE " frame %2i : %s\n", frame_no, buf);
continue;
}
printk(KERN_NOTICE " address : %s\n", buf);
} else
printk("<%08x>", *addr);
else if (fp == addr) {
if (j)
frame = addr+1;
else
printk("(%08x)", *addr);
fp = (unsigned int *)*addr;
frame_no++;
} else if (!j)
printk(" %08x ", *addr);
}
if (!j)
printk("\n");
}
#endif
}
EXPORT_SYMBOL(show_stack);
void dump_stack(void)
{
unsigned long stack;
#ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON
int tflags;
#endif
trace_buffer_save(tflags);
dump_bfin_trace_buffer();
show_stack(current, &stack);
trace_buffer_restore(tflags);
}
EXPORT_SYMBOL(dump_stack);
/* Basic functions for adding/removing custom exception handlers
*
* Copyright 2004-2009 Analog Devices Inc.
*
* Licensed under the GPL-2 or later
*/
#include <linux/module.h>
#include <asm/irq_handler.h>
int bfin_request_exception(unsigned int exception, void (*handler)(void))
{
void (*curr_handler)(void);
if (exception > 0x3F)
return -EINVAL;
curr_handler = ex_table[exception];
if (curr_handler != ex_replaceable)
return -EBUSY;
ex_table[exception] = handler;
return 0;
}
EXPORT_SYMBOL(bfin_request_exception);
int bfin_free_exception(unsigned int exception, void (*handler)(void))
{
void (*curr_handler)(void);
if (exception > 0x3F)
return -EINVAL;
curr_handler = ex_table[exception];
if (curr_handler != handler)
return -EBUSY;
ex_table[exception] = ex_replaceable;
return 0;
}
EXPORT_SYMBOL(bfin_free_exception);
......@@ -66,7 +66,7 @@ void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
gdb_regs[BFIN_RETN] = regs->retn;
gdb_regs[BFIN_RETE] = regs->rete;
gdb_regs[BFIN_PC] = regs->pc;
gdb_regs[BFIN_CC] = 0;
gdb_regs[BFIN_CC] = (regs->astat >> 5) & 1;
gdb_regs[BFIN_EXTRA1] = 0;
gdb_regs[BFIN_EXTRA2] = 0;
gdb_regs[BFIN_EXTRA3] = 0;
......
/* The fake debug assert instructions
*
* Copyright 2010 Analog Devices Inc.
*
* Licensed under the GPL-2 or later
*/
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/ptrace.h>
const char * const greg_names[] = {
"R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7",
"P0", "P1", "P2", "P3", "P4", "P5", "SP", "FP",
"I0", "I1", "I2", "I3", "M0", "M1", "M2", "M3",
"B0", "B1", "B2", "B3", "L0", "L1", "L2", "L3",
"A0.X", "A0.W", "A1.X", "A1.W", "<res>", "<res>", "ASTAT", "RETS",
"<res>", "<res>", "<res>", "<res>", "<res>", "<res>", "<res>", "<res>",
"LC0", "LT0", "LB0", "LC1", "LT1", "LB1", "CYCLES", "CYCLES2",
"USP", "SEQSTAT", "SYSCFG", "RETI", "RETX", "RETN", "RETE", "EMUDAT",
};
static const char *get_allreg_name(int grp, int reg)
{
return greg_names[(grp << 3) | reg];
}
/*
* Unfortunately, the pt_regs structure is not laid out the same way as the
* hardware register file, so we need to do some fix ups.
*
* CYCLES is not stored in the pt_regs structure - so, we just read it from
* the hardware.
*
* Don't support:
* - All reserved registers
* - All in group 7 are (supervisors only)
*/
static bool fix_up_reg(struct pt_regs *fp, long *value, int grp, int reg)
{
long *val = &fp->r0;
unsigned long tmp;
/* Only do Dregs and Pregs for now */
if (grp == 5 ||
(grp == 4 && (reg == 4 || reg == 5)) ||
(grp == 7))
return false;
if (grp == 0 || (grp == 1 && reg < 6))
val -= (reg + 8 * grp);
else if (grp == 1 && reg == 6)
val = &fp->usp;
else if (grp == 1 && reg == 7)
val = &fp->fp;
else if (grp == 2) {
val = &fp->i0;
val -= reg;
} else if (grp == 3 && reg >= 4) {
val = &fp->l0;
val -= (reg - 4);
} else if (grp == 3 && reg < 4) {
val = &fp->b0;
val -= reg;
} else if (grp == 4 && reg < 4) {
val = &fp->a0x;
val -= reg;
} else if (grp == 4 && reg == 6)
val = &fp->astat;
else if (grp == 4 && reg == 7)
val = &fp->rets;
else if (grp == 6 && reg < 6) {
val = &fp->lc0;
val -= reg;
} else if (grp == 6 && reg == 6) {
__asm__ __volatile__("%0 = cycles;\n" : "=d"(tmp));
val = &tmp;
} else if (grp == 6 && reg == 7) {
__asm__ __volatile__("%0 = cycles2;\n" : "=d"(tmp));
val = &tmp;
}
*value = *val;
return true;
}
#define PseudoDbg_Assert_opcode 0xf0000000
#define PseudoDbg_Assert_expected_bits 0
#define PseudoDbg_Assert_expected_mask 0xffff
#define PseudoDbg_Assert_regtest_bits 16
#define PseudoDbg_Assert_regtest_mask 0x7
#define PseudoDbg_Assert_grp_bits 19
#define PseudoDbg_Assert_grp_mask 0x7
#define PseudoDbg_Assert_dbgop_bits 22
#define PseudoDbg_Assert_dbgop_mask 0x3
#define PseudoDbg_Assert_dontcare_bits 24
#define PseudoDbg_Assert_dontcare_mask 0x7
#define PseudoDbg_Assert_code_bits 27
#define PseudoDbg_Assert_code_mask 0x1f
/*
* DBGA - debug assert
*/
bool execute_pseudodbg_assert(struct pt_regs *fp, unsigned int opcode)
{
int expected = ((opcode >> PseudoDbg_Assert_expected_bits) & PseudoDbg_Assert_expected_mask);
int dbgop = ((opcode >> (PseudoDbg_Assert_dbgop_bits)) & PseudoDbg_Assert_dbgop_mask);
int grp = ((opcode >> (PseudoDbg_Assert_grp_bits)) & PseudoDbg_Assert_grp_mask);
int regtest = ((opcode >> (PseudoDbg_Assert_regtest_bits)) & PseudoDbg_Assert_regtest_mask);
long value;
if ((opcode & 0xFF000000) != PseudoDbg_Assert_opcode)
return false;
if (!fix_up_reg(fp, &value, grp, regtest))
return false;
if (dbgop == 0 || dbgop == 2) {
/* DBGA ( regs_lo , uimm16 ) */
/* DBGAL ( regs , uimm16 ) */
if (expected != (value & 0xFFFF)) {
pr_notice("DBGA (%s.L,0x%x) failure, got 0x%x\n",
get_allreg_name(grp, regtest),
expected, (unsigned int)(value & 0xFFFF));
return false;
}
} else if (dbgop == 1 || dbgop == 3) {
/* DBGA ( regs_hi , uimm16 ) */
/* DBGAH ( regs , uimm16 ) */
if (expected != ((value >> 16) & 0xFFFF)) {
pr_notice("DBGA (%s.H,0x%x) failure, got 0x%x\n",
get_allreg_name(grp, regtest),
expected, (unsigned int)((value >> 16) & 0xFFFF));
return false;
}
}
fp->pc += 4;
return true;
}
#define PseudoDbg_opcode 0xf8000000
#define PseudoDbg_reg_bits 0
#define PseudoDbg_reg_mask 0x7
#define PseudoDbg_grp_bits 3
#define PseudoDbg_grp_mask 0x7
#define PseudoDbg_fn_bits 6
#define PseudoDbg_fn_mask 0x3
#define PseudoDbg_code_bits 8
#define PseudoDbg_code_mask 0xff
/*
* DBG - debug (dump a register value out)
*/
bool execute_pseudodbg(struct pt_regs *fp, unsigned int opcode)
{
int grp, fn, reg;
long value, value1;
if ((opcode & 0xFF000000) != PseudoDbg_opcode)
return false;
opcode >>= 16;
grp = ((opcode >> PseudoDbg_grp_bits) & PseudoDbg_reg_mask);
fn = ((opcode >> PseudoDbg_fn_bits) & PseudoDbg_fn_mask);
reg = ((opcode >> PseudoDbg_reg_bits) & PseudoDbg_reg_mask);
if (fn == 3 && (reg == 0 || reg == 1)) {
if (!fix_up_reg(fp, &value, 4, 2 * reg))
return false;
if (!fix_up_reg(fp, &value1, 4, 2 * reg + 1))
return false;
pr_notice("DBG A%i = %02lx%08lx\n", reg, value & 0xFF, value1);
fp->pc += 2;
return true;
} else if (fn == 0) {
if (!fix_up_reg(fp, &value, grp, reg))
return false;
pr_notice("DBG %s = %08lx\n", get_allreg_name(grp, reg), value);
fp->pc += 2;
return true;
}
return false;
}
/*
* Copyright 2004-2009 Analog Devices Inc.
* Copyright 2004-2010 Analog Devices Inc.
*
* Licensed under the GPL-2 or later.
*/
......@@ -925,7 +925,7 @@ void __init setup_arch(char **cmdline_p)
else if (_bfin_swrst & RESET_SOFTWARE)
printk(KERN_NOTICE "Reset caused by Software reset\n");
printk(KERN_INFO "Blackfin support (C) 2004-2009 Analog Devices, Inc.\n");
printk(KERN_INFO "Blackfin support (C) 2004-2010 Analog Devices, Inc.\n");
if (bfin_compiled_revid() == 0xffff)
printk(KERN_INFO "Compiled for ADSP-%s Rev any, running on 0.%d\n", CPU, bfin_revid());
else if (bfin_compiled_revid() == -1)
......
......@@ -47,3 +47,26 @@ unsigned long get_fb_unmapped_area(struct file *filp, unsigned long orig_addr,
}
EXPORT_SYMBOL(get_fb_unmapped_area);
#endif
/* Needed for legacy userspace atomic emulation */
static DEFINE_SPINLOCK(bfin_spinlock_lock);
#ifdef CONFIG_SYS_BFIN_SPINLOCK_L1
__attribute__((l1_text))
#endif
asmlinkage int sys_bfin_spinlock(int *p)
{
int ret, tmp = 0;
spin_lock(&bfin_spinlock_lock); /* This would also hold kernel preemption. */
ret = get_user(tmp, p);
if (likely(ret == 0)) {
if (unlikely(tmp))
ret = 1;
else
put_user(1, p);
}
spin_unlock(&bfin_spinlock_lock);
return ret;
}
This diff is collapsed.
This diff is collapsed.
......@@ -20,6 +20,7 @@
* R1 = filler byte
* R2 = count
* Favours word aligned data.
* The strncpy assumes that I0 and I1 are not used in this function
*/
ENTRY(_memset)
......
/*
* Copyright 2005-2010 Analog Devices Inc.
*
* Licensed under the ADI BSD license or the GPL-2 (or later)
*/
#include <linux/linkage.h>
/* void *strcmp(char *s1, const char *s2);
* R0 = address (s1)
* R1 = address (s2)
*
* Returns an integer less than, equal to, or greater than zero if s1
* (or the first n bytes thereof) is found, respectively, to be less
* than, to match, or be greater than s2.
*/
#ifdef CONFIG_STRCMP_L1
.section .l1.text
#else
.text
#endif
.align 2
ENTRY(_strcmp)
P0 = R0 ; /* s1 */
P1 = R1 ; /* s2 */
1:
R0 = B[P0++] (Z); /* get *s1 */
R1 = B[P1++] (Z); /* get *s2 */
CC = R0 == R1; /* compare a byte */
if ! cc jump 2f; /* not equal, break out */
CC = R0; /* at end of s1? */
if cc jump 1b (bp); /* no, keep going */
jump.s 3f; /* strings are equal */
2:
R0 = R0 - R1; /* *s1 - *s2 */
3:
RTS;
ENDPROC(_strcmp)
/*
* Provide symbol in case str func is not inlined.
*
* Copyright (c) 2006-2007 Analog Devices Inc.
*
* Licensed under the GPL-2 or later.
*/
#define strcmp __inline_strcmp
#include <asm/string.h>
#undef strcmp
#include <linux/module.h>
int strcmp(const char *dest, const char *src)
{
return __inline_strcmp(dest, src);
}
EXPORT_SYMBOL(strcmp);
/*
* Copyright 2005-2010 Analog Devices Inc.
*
* Licensed under the ADI BSD license or the GPL-2 (or later)
*/
#include <linux/linkage.h>
/* void *strcpy(char *dest, const char *src);
* R0 = address (dest)
* R1 = address (src)
*
* Returns a pointer to the destination string dest
*/
#ifdef CONFIG_STRCPY_L1
.section .l1.text
#else
.text
#endif
.align 2
ENTRY(_strcpy)
P0 = R0 ; /* dst*/
P1 = R1 ; /* src*/
1:
R1 = B [P1++] (Z);
B [P0++] = R1;
CC = R1;
if cc jump 1b (bp);
RTS;
ENDPROC(_strcpy)
/*
* Provide symbol in case str func is not inlined.
*
* Copyright (c) 2006-2007 Analog Devices Inc.
*
* Licensed under the GPL-2 or later.
*/
#define strcpy __inline_strcpy
#include <asm/string.h>
#undef strcpy
#include <linux/module.h>
char *strcpy(char *dest, const char *src)
{
return __inline_strcpy(dest, src);
}
EXPORT_SYMBOL(strcpy);
/*
* Copyright 2005-2010 Analog Devices Inc.
*
* Licensed under the ADI BSD license or the GPL-2 (or later)
*/
#include <linux/linkage.h>
/* void *strncpy(char *s1, const char *s2, size_t n);
* R0 = address (dest)
* R1 = address (src)
* R2 = size (n)
* Returns a pointer to the destination string dest
*/
#ifdef CONFIG_STRNCMP_L1
.section .l1.text
#else
.text
#endif
.align 2
ENTRY(_strncmp)
CC = R2 == 0;
if CC JUMP 5f;
P0 = R0 ; /* s1 */
P1 = R1 ; /* s2 */
1:
R0 = B[P0++] (Z); /* get *s1 */
R1 = B[P1++] (Z); /* get *s2 */
CC = R0 == R1; /* compare a byte */
if ! cc jump 3f; /* not equal, break out */
CC = R0; /* at end of s1? */
if ! cc jump 4f; /* yes, all done */
R2 += -1; /* no, adjust count */
CC = R2 == 0;
if ! cc jump 1b (bp); /* more to do, keep going */
2:
R0 = 0; /* strings are equal */
jump.s 4f;
3:
R0 = R0 - R1; /* *s1 - *s2 */
4:
RTS;
5:
R0 = 0;
RTS;
ENDPROC(_strncmp)
/*
* Provide symbol in case str func is not inlined.
*
* Copyright (c) 2006-2007 Analog Devices Inc.
*
* Licensed under the GPL-2 or later.
*/
#define strncmp __inline_strncmp
#include <asm/string.h>
#include <linux/module.h>
#undef strncmp
int strncmp(const char *cs, const char *ct, size_t count)
{
return __inline_strncmp(cs, ct, count);
}
EXPORT_SYMBOL(strncmp);
/*
* Copyright 2005-2010 Analog Devices Inc.
*
* Licensed under the ADI BSD license or the GPL-2 (or later)
*/
#include <linux/linkage.h>
#include <asm/context.S>
/* void *strncpy(char *dest, const char *src, size_t n);
* R0 = address (dest)
* R1 = address (src)
* R2 = size
* Returns a pointer (R0) to the destination string dest
* we do this by not changing R0
*/
#ifdef CONFIG_STRNCPY_L1
.section .l1.text
#else
.text
#endif
.align 2
ENTRY(_strncpy)
CC = R2 == 0;
if CC JUMP 4f;
P2 = R2 ; /* size */
P0 = R0 ; /* dst*/
P1 = R1 ; /* src*/
LSETUP (1f, 2f) LC0 = P2;
1:
R1 = B [P1++] (Z);
B [P0++] = R1;
CC = R1 == 0;
2:
if CC jump 3f;
RTS;
/* if src is shorter than n, we need to null pad bytes in dest
* but, we can get here when the last byte is zero, and we don't
* want to copy an extra byte at the end, so we need to check
*/
3:
R2 = LC0;
CC = R2
if ! CC jump 6f;
/* if the required null padded portion is small, do it here, rather than
* handling the overhead of memset (which is OK when things are big).
*/
R3 = 0x20;
CC = R2 < R3;
IF CC jump 4f;
R2 += -1;
/* Set things up for memset
* R0 = address
* R1 = filler byte (this case it's zero, set above)
* R2 = count (set above)
*/
I1 = R0;
R0 = RETS;
I0 = R0;
R0 = P0;
pseudo_long_call _memset, p0;
R0 = I0;
RETS = R0;
R0 = I1;
RTS;
4:
LSETUP(5f, 5f) LC0;
5:
B [P0++] = R1;
6:
RTS;
ENDPROC(_strncpy)
/*
* Provide symbol in case str func is not inlined.
*
* Copyright (c) 2006-2007 Analog Devices Inc.
*
* Licensed under the GPL-2 or later.
*/
#define strncpy __inline_strncpy
#include <asm/string.h>
#undef strncpy
#include <linux/module.h>
char *strncpy(char *dest, const char *src, size_t n)
{
return __inline_strncpy(dest, src, n);
}
EXPORT_SYMBOL(strncpy);
......@@ -98,6 +98,10 @@ static struct musb_hdrc_config musb_config = {
.num_eps = 8,
.dma_channels = 8,
.gpio_vrsel = GPIO_PF11,
/* Some custom boards need to be active low, just set it to "0"
* if it is the case.
*/
.gpio_vrsel_active = 1,
};
static struct musb_hdrc_platform_data musb_plat = {
......
......@@ -62,6 +62,10 @@ static struct musb_hdrc_config musb_config = {
.num_eps = 8,
.dma_channels = 8,
.gpio_vrsel = GPIO_PG13,
/* Some custom boards need to be active low, just set it to "0"
* if it is the case.
*/
.gpio_vrsel_active = 1,
};
static struct musb_hdrc_platform_data musb_plat = {
......
......@@ -102,6 +102,10 @@ static struct musb_hdrc_config musb_config = {
.num_eps = 8,
.dma_channels = 8,
.gpio_vrsel = GPIO_PG13,
/* Some custom boards need to be active low, just set it to "0"
* if it is the case.
*/
.gpio_vrsel_active = 1,
};
static struct musb_hdrc_platform_data musb_plat = {
......
......@@ -23,12 +23,13 @@
#include <asm/dma.h>
#include <asm/bfin5xx_spi.h>
#include <asm/reboot.h>
#include <asm/portmux.h>
#include <linux/spi/ad7877.h>
/*
* Name the Board for the /proc/cpuinfo
*/
char *bfin_board_name = "CamSig Minotaur BF537";
const char bfin_board_name[] = "CamSig Minotaur BF537";
#if defined(CONFIG_BFIN_CFPCMCIA) || defined(CONFIG_BFIN_CFPCMCIA_MODULE)
static struct resource bfin_pcmcia_cf_resources[] = {
......
......@@ -74,7 +74,7 @@
#define IRQ_PPI_ERROR 42 /*PPI Error Interrupt */
#define IRQ_CAN_ERROR 43 /*CAN Error Interrupt */
#define IRQ_MAC_ERROR 44 /*PPI Error Interrupt */
#define IRQ_MAC_ERROR 44 /*MAC Status/Error Interrupt */
#define IRQ_SPORT0_ERROR 45 /*SPORT0 Error Interrupt */
#define IRQ_SPORT1_ERROR 46 /*SPORT1 Error Interrupt */
#define IRQ_SPI_ERROR 47 /*SPI Error Interrupt */
......
......@@ -498,6 +498,10 @@ static struct musb_hdrc_config musb_config = {
.num_eps = 8,
.dma_channels = 8,
.gpio_vrsel = GPIO_PH6,
/* Some custom boards need to be active low, just set it to "0"
* if it is the case.
*/
.gpio_vrsel_active = 1,
};
static struct musb_hdrc_platform_data musb_plat = {
......
......@@ -603,6 +603,10 @@ static struct musb_hdrc_config musb_config = {
.num_eps = 8,
.dma_channels = 8,
.gpio_vrsel = GPIO_PE7,
/* Some custom boards need to be active low, just set it to "0"
* if it is the case.
*/
.gpio_vrsel_active = 1,
};
static struct musb_hdrc_platform_data musb_plat = {
......
......@@ -44,6 +44,7 @@
#include <linux/spi/flash.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/jiffies.h>
#include <linux/i2c-pca-platform.h>
#include <linux/delay.h>
#include <linux/io.h>
......@@ -112,7 +113,7 @@ static struct resource bfin_i2c_pca_resources[] = {
struct i2c_pca9564_pf_platform_data pca9564_platform_data = {
.gpio = -1,
.i2c_clock_speed = 330000,
.timeout = 10000
.timeout = HZ,
};
/* PCA9564 I2C Bus driver */
......
......@@ -92,26 +92,29 @@ static void __init search_IAR(void)
{
unsigned ivg, irq_pos = 0;
for (ivg = 0; ivg <= IVG13 - IVG7; ivg++) {
int irqn;
int irqN;
ivg7_13[ivg].istop = ivg7_13[ivg].ifirst = &ivg_table[irq_pos];
for (irqn = 0; irqn < NR_PERI_INTS; irqn++) {
int iar_shift = (irqn & 7) * 4;
if (ivg == (0xf &
#if defined(CONFIG_BF52x) || defined(CONFIG_BF538) \
|| defined(CONFIG_BF539) || defined(CONFIG_BF51x)
bfin_read32((unsigned long *)SIC_IAR0 +
((irqn % 32) >> 3) + ((irqn / 32) *
((SIC_IAR4 - SIC_IAR0) / 4))) >> iar_shift)) {
for (irqN = 0; irqN < NR_PERI_INTS; irqN += 4) {
int irqn;
u32 iar = bfin_read32((unsigned long *)SIC_IAR0 +
#if defined(CONFIG_BF51x) || defined(CONFIG_BF52x) || \
defined(CONFIG_BF538) || defined(CONFIG_BF539)
((irqN % 32) >> 3) + ((irqN / 32) * ((SIC_IAR4 - SIC_IAR0) / 4))
#else
bfin_read32((unsigned long *)SIC_IAR0 +
(irqn >> 3)) >> iar_shift)) {
(irqN >> 3)
#endif
ivg_table[irq_pos].irqno = IVG7 + irqn;
ivg_table[irq_pos].isrflag = 1 << (irqn % 32);
ivg7_13[ivg].istop++;
irq_pos++;
);
for (irqn = irqN; irqn < irqN + 4; ++irqn) {
int iar_shift = (irqn & 7) * 4;
if (ivg == (0xf & (iar >> iar_shift))) {
ivg_table[irq_pos].irqno = IVG7 + irqn;
ivg_table[irq_pos].isrflag = 1 << (irqn % 32);
ivg7_13[ivg].istop++;
irq_pos++;
}
}
}
}
......@@ -662,14 +665,7 @@ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type)
#ifdef CONFIG_PM
int bfin_gpio_set_wake(unsigned int irq, unsigned int state)
{
unsigned gpio = irq_to_gpio(irq);
if (state)
gpio_pm_wakeup_request(gpio, PM_WAKE_IGNORE);
else
gpio_pm_wakeup_free(gpio);
return 0;
return gpio_pm_wakeup_ctrl(irq_to_gpio(irq), state);
}
#endif
......
......@@ -20,35 +20,11 @@
#include <asm/dma.h>
#include <asm/dpmc.h>
#ifdef CONFIG_PM_WAKEUP_GPIO_POLAR_H
#define WAKEUP_TYPE PM_WAKE_HIGH
#endif
#ifdef CONFIG_PM_WAKEUP_GPIO_POLAR_L
#define WAKEUP_TYPE PM_WAKE_LOW
#endif
#ifdef CONFIG_PM_WAKEUP_GPIO_POLAR_EDGE_F
#define WAKEUP_TYPE PM_WAKE_FALLING
#endif
#ifdef CONFIG_PM_WAKEUP_GPIO_POLAR_EDGE_R
#define WAKEUP_TYPE PM_WAKE_RISING
#endif
#ifdef CONFIG_PM_WAKEUP_GPIO_POLAR_EDGE_B
#define WAKEUP_TYPE PM_WAKE_BOTH_EDGES
#endif
void bfin_pm_suspend_standby_enter(void)
{
unsigned long flags;
#ifdef CONFIG_PM_WAKEUP_BY_GPIO
gpio_pm_wakeup_request(CONFIG_PM_WAKEUP_GPIO_NUMBER, WAKEUP_TYPE);
#endif
local_irq_save_hw(flags);
bfin_pm_standby_setup();
......
......@@ -170,8 +170,8 @@ static irqreturn_t ipi_handler(int irq, void *dev_instance)
kfree(msg);
break;
default:
printk(KERN_CRIT "CPU%u: Unknown IPI message \
0x%lx\n", cpu, msg->type);
printk(KERN_CRIT "CPU%u: Unknown IPI message 0x%lx\n",
cpu, msg->type);
kfree(msg);
break;
}
......
......@@ -15,23 +15,11 @@
#include "blackfin_sram.h"
/*
* BAD_PAGE is the page that is used for page faults when linux
* is out-of-memory. Older versions of linux just did a
* do_exit(), but using this instead means there is less risk
* for a process dying in kernel mode, possibly leaving a inode
* unused etc..
*
* BAD_PAGETABLE is the accompanying page-table: it is initialized
* to point to BAD_PAGE entries.
*
* ZERO_PAGE is a special page that is used for zero-initialized
* data and COW.
* ZERO_PAGE is a special page that is used for zero-initialized data and COW.
* Let the bss do its zero-init magic so we don't have to do it ourselves.
*/
static unsigned long empty_bad_page_table;
static unsigned long empty_bad_page;
static unsigned long empty_zero_page;
char empty_zero_page[PAGE_SIZE] __attribute__((aligned(PAGE_SIZE)));
EXPORT_SYMBOL(empty_zero_page);
#ifndef CONFIG_EXCEPTION_L1_SCRATCH
#if defined CONFIG_SYSCALL_TAB_L1
......@@ -52,40 +40,26 @@ EXPORT_SYMBOL(cpu_pda);
void __init paging_init(void)
{
/*
* make sure start_mem is page aligned, otherwise bootmem and
* page_alloc get different views og the world
* make sure start_mem is page aligned, otherwise bootmem and
* page_alloc get different views of the world
*/
unsigned long end_mem = memory_end & PAGE_MASK;
pr_debug("start_mem is %#lx virtual_end is %#lx\n", PAGE_ALIGN(memory_start), end_mem);
/*
* initialize the bad page table and bad page to point
* to a couple of allocated pages
*/
empty_bad_page_table = (unsigned long)alloc_bootmem_pages(PAGE_SIZE);
empty_bad_page = (unsigned long)alloc_bootmem_pages(PAGE_SIZE);
empty_zero_page = (unsigned long)alloc_bootmem_pages(PAGE_SIZE);
memset((void *)empty_zero_page, 0, PAGE_SIZE);
unsigned long zones_size[MAX_NR_ZONES] = {
[0] = 0,
[ZONE_DMA] = (end_mem - PAGE_OFFSET) >> PAGE_SHIFT,
[ZONE_NORMAL] = 0,
#ifdef CONFIG_HIGHMEM
[ZONE_HIGHMEM] = 0,
#endif
};
/*
* Set up SFC/DFC registers (user data space)
*/
/* Set up SFC/DFC registers (user data space) */
set_fs(KERNEL_DS);
pr_debug("free_area_init -> start_mem is %#lx virtual_end is %#lx\n",
pr_debug("free_area_init -> start_mem is %#lx virtual_end is %#lx\n",
PAGE_ALIGN(memory_start), end_mem);
{
unsigned long zones_size[MAX_NR_ZONES] = { 0, };
zones_size[ZONE_DMA] = (end_mem - PAGE_OFFSET) >> PAGE_SHIFT;
zones_size[ZONE_NORMAL] = 0;
#ifdef CONFIG_HIGHMEM
zones_size[ZONE_HIGHMEM] = 0;
#endif
free_area_init(zones_size);
}
free_area_init(zones_size);
}
asmlinkage void __init init_pda(void)
......
......@@ -43,13 +43,12 @@ static DEFINE_SPINLOCK(dtest_lock);
/* Takes a void pointer */
#define IADDR2DTEST(x) \
({ unsigned long __addr = (unsigned long)(x); \
(__addr & 0x47F8) | /* address bits 14 & 10:3 */ \
(__addr & 0x8000) << 23 | /* Bank A/B */ \
(__addr & 0x0800) << 15 | /* address bit 11 */ \
(__addr & 0x3000) << 4 | /* address bits 13:12 */ \
(__addr & 0x8000) << 8 | /* address bit 15 */ \
(0x1000000) | /* instruction access = 1 */ \
(0x4); /* data array = 1 */ \
((__addr & (1 << 11)) << (26 - 11)) | /* addr bit 11 (Way0/Way1) */ \
(1 << 24) | /* instruction access = 1 */ \
((__addr & (1 << 15)) << (23 - 15)) | /* addr bit 15 (Data Bank) */ \
((__addr & (3 << 12)) << (16 - 12)) | /* addr bits 13:12 (Subbank) */ \
(__addr & 0x47F8) | /* addr bits 14 & 10:3 */ \
(1 << 2); /* data array = 1 */ \
})
/* Takes a pointer, and returns the offset (in bits) which things should be shifted */
......@@ -196,7 +195,7 @@ EXPORT_SYMBOL(isram_memcpy);
#ifdef CONFIG_BFIN_ISRAM_SELF_TEST
#define TEST_LEN 0x100
static int test_len = 0x20000;
static __init void hex_dump(unsigned char *buf, int len)
{
......@@ -212,15 +211,15 @@ static __init int isram_read_test(char *sdram, void *l1inst)
pr_info("INFO: running isram_read tests\n");
/* setup some different data to play with */
for (i = 0; i < TEST_LEN; ++i)
sdram[i] = i;
dma_memcpy(l1inst, sdram, TEST_LEN);
for (i = 0; i < test_len; ++i)
sdram[i] = i % 255;
dma_memcpy(l1inst, sdram, test_len);
/* make sure we can read the L1 inst */
for (i = 0; i < TEST_LEN; i += sizeof(uint64_t)) {
for (i = 0; i < test_len; i += sizeof(uint64_t)) {
data1 = isram_read(l1inst + i);
memcpy(&data2, sdram + i, sizeof(data2));
if (memcmp(&data1, &data2, sizeof(uint64_t))) {
if (data1 != data2) {
pr_err("FAIL: isram_read(%p) returned %#llx but wanted %#llx\n",
l1inst + i, data1, data2);
++ret;
......@@ -238,25 +237,25 @@ static __init int isram_write_test(char *sdram, void *l1inst)
pr_info("INFO: running isram_write tests\n");
/* setup some different data to play with */
memset(sdram, 0, TEST_LEN * 2);
dma_memcpy(l1inst, sdram, TEST_LEN);
for (i = 0; i < TEST_LEN; ++i)
sdram[i] = i;
memset(sdram, 0, test_len * 2);
dma_memcpy(l1inst, sdram, test_len);
for (i = 0; i < test_len; ++i)
sdram[i] = i % 255;
/* make sure we can write the L1 inst */
for (i = 0; i < TEST_LEN; i += sizeof(uint64_t)) {
for (i = 0; i < test_len; i += sizeof(uint64_t)) {
memcpy(&data1, sdram + i, sizeof(data1));
isram_write(l1inst + i, data1);
data2 = isram_read(l1inst + i);
if (memcmp(&data1, &data2, sizeof(uint64_t))) {
if (data1 != data2) {
pr_err("FAIL: isram_write(%p, %#llx) != %#llx\n",
l1inst + i, data1, data2);
++ret;
}
}
dma_memcpy(sdram + TEST_LEN, l1inst, TEST_LEN);
if (memcmp(sdram, sdram + TEST_LEN, TEST_LEN)) {
dma_memcpy(sdram + test_len, l1inst, test_len);
if (memcmp(sdram, sdram + test_len, test_len)) {
pr_err("FAIL: isram_write() did not work properly\n");
++ret;
}
......@@ -268,12 +267,12 @@ static __init int
_isram_memcpy_test(char pattern, void *sdram, void *l1inst, const char *smemcpy,
void *(*fmemcpy)(void *, const void *, size_t))
{
memset(sdram, pattern, TEST_LEN);
fmemcpy(l1inst, sdram, TEST_LEN);
fmemcpy(sdram + TEST_LEN, l1inst, TEST_LEN);
if (memcmp(sdram, sdram + TEST_LEN, TEST_LEN)) {
memset(sdram, pattern, test_len);
fmemcpy(l1inst, sdram, test_len);
fmemcpy(sdram + test_len, l1inst, test_len);
if (memcmp(sdram, sdram + test_len, test_len)) {
pr_err("FAIL: %s(%p <=> %p, %#x) failed (data is %#x)\n",
smemcpy, l1inst, sdram, TEST_LEN, pattern);
smemcpy, l1inst, sdram, test_len, pattern);
return 1;
}
return 0;
......@@ -292,12 +291,13 @@ static __init int isram_memcpy_test(char *sdram, void *l1inst)
/* check read of small, unaligned, and hardware 64bit limits */
pr_info("INFO: running isram_memcpy (read) tests\n");
for (i = 0; i < TEST_LEN; ++i)
sdram[i] = i;
dma_memcpy(l1inst, sdram, TEST_LEN);
/* setup some different data to play with */
for (i = 0; i < test_len; ++i)
sdram[i] = i % 255;
dma_memcpy(l1inst, sdram, test_len);
thisret = 0;
for (i = 0; i < TEST_LEN - 32; ++i) {
for (i = 0; i < test_len - 32; ++i) {
unsigned char cmp[32];
for (j = 1; j <= 32; ++j) {
memset(cmp, 0, sizeof(cmp));
......@@ -310,7 +310,7 @@ static __init int isram_memcpy_test(char *sdram, void *l1inst)
pr_cont("\n");
if (++thisret > 20) {
pr_err("FAIL: skipping remaining series\n");
i = TEST_LEN;
i = test_len;
break;
}
}
......@@ -321,11 +321,11 @@ static __init int isram_memcpy_test(char *sdram, void *l1inst)
/* check write of small, unaligned, and hardware 64bit limits */
pr_info("INFO: running isram_memcpy (write) tests\n");
memset(sdram + TEST_LEN, 0, TEST_LEN);
dma_memcpy(l1inst, sdram + TEST_LEN, TEST_LEN);
memset(sdram + test_len, 0, test_len);
dma_memcpy(l1inst, sdram + test_len, test_len);
thisret = 0;
for (i = 0; i < TEST_LEN - 32; ++i) {
for (i = 0; i < test_len - 32; ++i) {
unsigned char cmp[32];
for (j = 1; j <= 32; ++j) {
isram_memcpy(l1inst + i, sdram + i, j);
......@@ -338,7 +338,7 @@ static __init int isram_memcpy_test(char *sdram, void *l1inst)
pr_cont("\n");
if (++thisret > 20) {
pr_err("FAIL: skipping remaining series\n");
i = TEST_LEN;
i = test_len;
break;
}
}
......@@ -355,22 +355,30 @@ static __init int isram_test_init(void)
char *sdram;
void *l1inst;
sdram = kmalloc(TEST_LEN * 2, GFP_KERNEL);
if (!sdram) {
pr_warning("SKIP: could not allocate sdram\n");
return 0;
/* Try to test as much of L1SRAM as possible */
while (test_len) {
test_len >>= 1;
l1inst = l1_inst_sram_alloc(test_len);
if (l1inst)
break;
}
l1inst = l1_inst_sram_alloc(TEST_LEN);
if (!l1inst) {
kfree(sdram);
pr_warning("SKIP: could not allocate L1 inst\n");
return 0;
}
pr_info("INFO: testing %#x bytes (%p - %p)\n",
test_len, l1inst, l1inst + test_len);
sdram = kmalloc(test_len * 2, GFP_KERNEL);
if (!sdram) {
sram_free(l1inst);
pr_warning("SKIP: could not allocate sdram\n");
return 0;
}
/* sanity check initial L1 inst state */
ret = 1;
pr_info("INFO: running initial dma_memcpy checks\n");
pr_info("INFO: running initial dma_memcpy checks %p\n", sdram);
if (_isram_memcpy_test(0xa, sdram, l1inst, dma_memcpy))
goto abort;
if (_isram_memcpy_test(0x5, sdram, l1inst, dma_memcpy))
......
......@@ -256,7 +256,8 @@ static void *_sram_alloc(size_t size, struct sram_piece *pfree_head,
plast->next = pslot->next;
pavail = pslot;
} else {
pavail = kmem_cache_alloc(sram_piece_cache, GFP_KERNEL);
/* use atomic so our L1 allocator can be used atomically */
pavail = kmem_cache_alloc(sram_piece_cache, GFP_ATOMIC);
if (!pavail)
return NULL;
......
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