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 ...@@ -348,7 +348,7 @@ config MEM_MT48LC16M16A2TG_75
config MEM_MT48LC32M8A2_75 config MEM_MT48LC32M8A2_75
bool bool
depends on (BFIN537_STAMP || PNAV10 || BFIN538_EZKIT) depends on (BFIN518F_EZBRD || BFIN537_STAMP || PNAV10 || BFIN538_EZKIT)
default y default y
config MEM_MT48LC8M32B2B5_7 config MEM_MT48LC8M32B2B5_7
...@@ -361,11 +361,6 @@ config MEM_MT48LC32M16A2TG_75 ...@@ -361,11 +361,6 @@ config MEM_MT48LC32M16A2TG_75
depends on (BFIN527_EZKIT || BFIN527_EZKIT_V2 || BFIN532_IP0X || BLACKSTAMP) depends on (BFIN527_EZKIT || BFIN527_EZKIT_V2 || BFIN532_IP0X || BLACKSTAMP)
default y default y
config MEM_MT48LC32M8A2_75
bool
depends on (BFIN518F_EZBRD)
default y
config MEM_MT48H32M16LFCJ_75 config MEM_MT48H32M16LFCJ_75
bool bool
depends on (BFIN526_EZBRD) depends on (BFIN526_EZBRD)
...@@ -791,6 +786,34 @@ config MEMCPY_L1 ...@@ -791,6 +786,34 @@ config MEMCPY_L1
If enabled, the memcpy function is linked If enabled, the memcpy function is linked
into L1 instruction memory. (less latency) 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 config SYS_BFIN_SPINLOCK_L1
bool "Locate sys_bfin_spinlock function in L1 Memory" bool "Locate sys_bfin_spinlock function in L1 Memory"
default y default y
...@@ -1187,32 +1210,6 @@ config PM_BFIN_SLEEP ...@@ -1187,32 +1210,6 @@ config PM_BFIN_SLEEP
If unsure, select "Sleep Deeper". If unsure, select "Sleep Deeper".
endchoice 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" comment "Possible Suspend Mem / Hibernate Wake-Up Sources"
depends on PM depends on PM
......
...@@ -238,7 +238,7 @@ config EARLY_PRINTK ...@@ -238,7 +238,7 @@ config EARLY_PRINTK
config NMI_WATCHDOG config NMI_WATCHDOG
bool "Enable NMI watchdog to help debugging lockup on SMP" bool "Enable NMI watchdog to help debugging lockup on SMP"
default n default n
depends on (SMP && !BFIN_SCRATCH_REG_RETN) depends on SMP
help help
If any CPU in the system does not execute the period local timer 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 interrupt for more than 5 seconds, then the NMI handler dumps debug
...@@ -264,4 +264,13 @@ config BFIN_ISRAM_SELF_TEST ...@@ -264,4 +264,13 @@ config BFIN_ISRAM_SELF_TEST
help help
Run some self tests of the isram driver code at boot. 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 endmenu
...@@ -39,9 +39,15 @@ extern unsigned long sclk_to_usecs(unsigned long sclk); ...@@ -39,9 +39,15 @@ extern unsigned long sclk_to_usecs(unsigned long sclk);
extern unsigned long usecs_to_sclk(unsigned long usecs); extern unsigned long usecs_to_sclk(unsigned long usecs);
struct pt_regs; struct pt_regs;
#if defined(CONFIG_DEBUG_VERBOSE)
extern void dump_bfin_process(struct pt_regs *regs); extern void dump_bfin_process(struct pt_regs *regs);
extern void dump_bfin_mem(struct pt_regs *regs); extern void dump_bfin_mem(struct pt_regs *regs);
extern void dump_bfin_trace_buffer(void); 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 */ /* init functions only */
extern int init_arch_irq(void); extern int init_arch_irq(void);
......
...@@ -9,7 +9,12 @@ ...@@ -9,7 +9,12 @@
#ifdef CONFIG_BUG #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 #ifdef CONFIG_DEBUG_BUGVERBOSE
......
...@@ -15,6 +15,8 @@ ...@@ -15,6 +15,8 @@
#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) #define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT)
#define SMP_CACHE_BYTES L1_CACHE_BYTES #define SMP_CACHE_BYTES L1_CACHE_BYTES
#define ARCH_KMALLOC_MINALIGN L1_CACHE_BYTES
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
#define __cacheline_aligned #define __cacheline_aligned
#else #else
......
...@@ -167,23 +167,23 @@ int bfin_special_gpio_request(unsigned gpio, const char *label); ...@@ -167,23 +167,23 @@ int bfin_special_gpio_request(unsigned gpio, const char *label);
#endif #endif
#ifdef CONFIG_PM #ifdef CONFIG_PM
int bfin_pm_standby_ctrl(unsigned ctrl);
unsigned int bfin_pm_standby_setup(void); static inline int bfin_pm_standby_setup(void)
void bfin_pm_standby_restore(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_restore(void);
void bfin_gpio_pm_hibernate_suspend(void); void bfin_gpio_pm_hibernate_suspend(void);
#ifndef CONFIG_BF54x #ifndef CONFIG_BF54x
#define PM_WAKE_RISING 0x1 int gpio_pm_wakeup_ctrl(unsigned gpio, unsigned ctrl);
#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);
struct gpio_port_s { struct gpio_port_s {
unsigned short data; unsigned short data;
......
...@@ -80,7 +80,8 @@ PTE_BIT_FUNC(mkyoung, |= _PAGE_ACCESSED); ...@@ -80,7 +80,8 @@ PTE_BIT_FUNC(mkyoung, |= _PAGE_ACCESSED);
* ZERO_PAGE is a global shared page that is always zero: used * ZERO_PAGE is a global shared page that is always zero: used
* for zero-mapped memory areas etc.. * 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); 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 @@ ...@@ -12,121 +12,16 @@
#ifdef __KERNEL__ /* only set these up for kernel code */ #ifdef __KERNEL__ /* only set these up for kernel code */
#define __HAVE_ARCH_STRCPY #define __HAVE_ARCH_STRCPY
extern inline char *strcpy(char *dest, const char *src) extern 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;
}
#define __HAVE_ARCH_STRNCPY #define __HAVE_ARCH_STRNCPY
extern inline char *strncpy(char *dest, const char *src, size_t n) extern 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;
}
#define __HAVE_ARCH_STRCMP #define __HAVE_ARCH_STRCMP
extern inline int strcmp(const char *cs, const char *ct) extern 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;
}
#define __HAVE_ARCH_STRNCMP #define __HAVE_ARCH_STRNCMP
extern inline int strncmp(const char *cs, const char *ct, size_t count) extern 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;
}
#define __HAVE_ARCH_MEMSET #define __HAVE_ARCH_MEMSET
extern void *memset(void *s, int c, size_t count); extern void *memset(void *s, int c, size_t count);
......
#include <asm-generic/tlbflush.h> #include <asm-generic/tlbflush.h>
#define flush_tlb_kernel_range(s, e) do { } while (0)
...@@ -23,6 +23,13 @@ ...@@ -23,6 +23,13 @@
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
extern unsigned long trace_buff_offset; extern unsigned long trace_buff_offset;
extern unsigned long software_trace_buff[]; 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 */ /* Trace Macros for C files */
......
...@@ -7,7 +7,8 @@ extra-y := init_task.o vmlinux.lds ...@@ -7,7 +7,8 @@ extra-y := init_task.o vmlinux.lds
obj-y := \ obj-y := \
entry.o process.o bfin_ksyms.o ptrace.o setup.o signal.o \ 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 \ 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) ifeq ($(CONFIG_GENERIC_CLOCKEVENTS),y)
obj-y += time-ts.o obj-y += time-ts.o
...@@ -29,6 +30,8 @@ obj-$(CONFIG_NMI_WATCHDOG) += nmi.o ...@@ -29,6 +30,8 @@ obj-$(CONFIG_NMI_WATCHDOG) += nmi.o
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
obj-$(CONFIG_EARLY_PRINTK) += shadow_console.o obj-$(CONFIG_EARLY_PRINTK) += shadow_console.o
obj-$(CONFIG_STACKTRACE) += stacktrace.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 # the kgdb test puts code into L2 and without linker
# relaxation, we need to force long calls to/from it # relaxation, we need to force long calls to/from it
......
...@@ -475,9 +475,7 @@ GET_GPIO_P(maskb) ...@@ -475,9 +475,7 @@ GET_GPIO_P(maskb)
#ifdef CONFIG_PM #ifdef CONFIG_PM
static unsigned short wakeup_map[GPIO_BANK_NUM]; static unsigned short wakeup_map[GPIO_BANK_NUM];
static unsigned char wakeup_flags_map[MAX_BLACKFIN_GPIOS];
static const unsigned int sic_iwr_irqs[] = { static const unsigned int sic_iwr_irqs[] = {
#if defined(BF533_FAMILY) #if defined(BF533_FAMILY)
...@@ -514,112 +512,26 @@ static const unsigned int sic_iwr_irqs[] = { ...@@ -514,112 +512,26 @@ static const unsigned int sic_iwr_irqs[] = {
************************************************************* *************************************************************
* MODIFICATION HISTORY : * MODIFICATION HISTORY :
**************************************************************/ **************************************************************/
int gpio_pm_wakeup_request(unsigned gpio, unsigned char type) int gpio_pm_wakeup_ctrl(unsigned gpio, unsigned ctrl)
{
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)
{ {
unsigned long flags; unsigned long flags;
if (check_gpio(gpio) < 0) if (check_gpio(gpio) < 0)
return; return -EINVAL;
local_irq_save_hw(flags); local_irq_save_hw(flags);
if (ctrl)
wakeup_map[gpio_bank(gpio)] &= ~gpio_bit(gpio); 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);
else else
set_gpio_both(gpio, 0); wakeup_map[gpio_bank(gpio)] &= ~gpio_bit(gpio);
if ((type & (PM_WAKE_FALLING | PM_WAKE_LOW)))
set_gpio_polar(gpio, 1);
else
set_gpio_polar(gpio, 0);
SSYNC(); set_gpio_maskb(gpio, ctrl);
local_irq_restore_hw(flags);
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);
return 0; return 0;
} }
void bfin_pm_standby_restore(void) int bfin_pm_standby_ctrl(unsigned ctrl)
{ {
u16 bank, mask, i; u16 bank, mask, i;
...@@ -627,24 +539,10 @@ void bfin_pm_standby_restore(void) ...@@ -627,24 +539,10 @@ void bfin_pm_standby_restore(void)
mask = wakeup_map[gpio_bank(i)]; mask = wakeup_map[gpio_bank(i)];
bank = gpio_bank(i); bank = gpio_bank(i);
if (mask) { if (mask)
#if defined(CONFIG_BF52x) || defined(BF537_FAMILY) || defined(CONFIG_BF51x) bfin_internal_set_wake(sic_iwr_irqs[bank], ctrl);
*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;
} }
AWA_DUMMY_READ(maskb); return 0;
} }
void bfin_gpio_pm_hibernate_suspend(void) void bfin_gpio_pm_hibernate_suspend(void)
...@@ -708,16 +606,11 @@ void bfin_gpio_pm_hibernate_restore(void) ...@@ -708,16 +606,11 @@ void bfin_gpio_pm_hibernate_restore(void)
#else /* CONFIG_BF54x */ #else /* CONFIG_BF54x */
#ifdef CONFIG_PM #ifdef CONFIG_PM
u32 bfin_pm_standby_setup(void) int bfin_pm_standby_ctrl(unsigned ctrl)
{ {
return 0; return 0;
} }
void bfin_pm_standby_restore(void)
{
}
void bfin_gpio_pm_hibernate_suspend(void) void bfin_gpio_pm_hibernate_suspend(void)
{ {
int i, bank; int i, bank;
......
...@@ -32,6 +32,18 @@ EXPORT_SYMBOL(memcmp); ...@@ -32,6 +32,18 @@ EXPORT_SYMBOL(memcmp);
EXPORT_SYMBOL(memmove); EXPORT_SYMBOL(memmove);
EXPORT_SYMBOL(memchr); 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 * libgcc functions - functions that are used internally by the
* compiler... (prototypes are not correct though, but that * 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) ...@@ -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_RETN] = regs->retn;
gdb_regs[BFIN_RETE] = regs->rete; gdb_regs[BFIN_RETE] = regs->rete;
gdb_regs[BFIN_PC] = regs->pc; 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_EXTRA1] = 0;
gdb_regs[BFIN_EXTRA2] = 0; gdb_regs[BFIN_EXTRA2] = 0;
gdb_regs[BFIN_EXTRA3] = 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. * Licensed under the GPL-2 or later.
*/ */
...@@ -925,7 +925,7 @@ void __init setup_arch(char **cmdline_p) ...@@ -925,7 +925,7 @@ void __init setup_arch(char **cmdline_p)
else if (_bfin_swrst & RESET_SOFTWARE) else if (_bfin_swrst & RESET_SOFTWARE)
printk(KERN_NOTICE "Reset caused by Software reset\n"); 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) if (bfin_compiled_revid() == 0xffff)
printk(KERN_INFO "Compiled for ADSP-%s Rev any, running on 0.%d\n", CPU, bfin_revid()); printk(KERN_INFO "Compiled for ADSP-%s Rev any, running on 0.%d\n", CPU, bfin_revid());
else if (bfin_compiled_revid() == -1) else if (bfin_compiled_revid() == -1)
......
...@@ -47,3 +47,26 @@ unsigned long get_fb_unmapped_area(struct file *filp, unsigned long orig_addr, ...@@ -47,3 +47,26 @@ unsigned long get_fb_unmapped_area(struct file *filp, unsigned long orig_addr,
} }
EXPORT_SYMBOL(get_fb_unmapped_area); EXPORT_SYMBOL(get_fb_unmapped_area);
#endif #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 @@ ...@@ -20,6 +20,7 @@
* R1 = filler byte * R1 = filler byte
* R2 = count * R2 = count
* Favours word aligned data. * Favours word aligned data.
* The strncpy assumes that I0 and I1 are not used in this function
*/ */
ENTRY(_memset) 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 = { ...@@ -98,6 +98,10 @@ static struct musb_hdrc_config musb_config = {
.num_eps = 8, .num_eps = 8,
.dma_channels = 8, .dma_channels = 8,
.gpio_vrsel = GPIO_PF11, .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 = { static struct musb_hdrc_platform_data musb_plat = {
......
...@@ -62,6 +62,10 @@ static struct musb_hdrc_config musb_config = { ...@@ -62,6 +62,10 @@ static struct musb_hdrc_config musb_config = {
.num_eps = 8, .num_eps = 8,
.dma_channels = 8, .dma_channels = 8,
.gpio_vrsel = GPIO_PG13, .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 = { static struct musb_hdrc_platform_data musb_plat = {
......
...@@ -102,6 +102,10 @@ static struct musb_hdrc_config musb_config = { ...@@ -102,6 +102,10 @@ static struct musb_hdrc_config musb_config = {
.num_eps = 8, .num_eps = 8,
.dma_channels = 8, .dma_channels = 8,
.gpio_vrsel = GPIO_PG13, .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 = { static struct musb_hdrc_platform_data musb_plat = {
......
...@@ -23,12 +23,13 @@ ...@@ -23,12 +23,13 @@
#include <asm/dma.h> #include <asm/dma.h>
#include <asm/bfin5xx_spi.h> #include <asm/bfin5xx_spi.h>
#include <asm/reboot.h> #include <asm/reboot.h>
#include <asm/portmux.h>
#include <linux/spi/ad7877.h> #include <linux/spi/ad7877.h>
/* /*
* Name the Board for the /proc/cpuinfo * 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) #if defined(CONFIG_BFIN_CFPCMCIA) || defined(CONFIG_BFIN_CFPCMCIA_MODULE)
static struct resource bfin_pcmcia_cf_resources[] = { static struct resource bfin_pcmcia_cf_resources[] = {
......
...@@ -74,7 +74,7 @@ ...@@ -74,7 +74,7 @@
#define IRQ_PPI_ERROR 42 /*PPI Error Interrupt */ #define IRQ_PPI_ERROR 42 /*PPI Error Interrupt */
#define IRQ_CAN_ERROR 43 /*CAN 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_SPORT0_ERROR 45 /*SPORT0 Error Interrupt */
#define IRQ_SPORT1_ERROR 46 /*SPORT1 Error Interrupt */ #define IRQ_SPORT1_ERROR 46 /*SPORT1 Error Interrupt */
#define IRQ_SPI_ERROR 47 /*SPI Error Interrupt */ #define IRQ_SPI_ERROR 47 /*SPI Error Interrupt */
......
...@@ -498,6 +498,10 @@ static struct musb_hdrc_config musb_config = { ...@@ -498,6 +498,10 @@ static struct musb_hdrc_config musb_config = {
.num_eps = 8, .num_eps = 8,
.dma_channels = 8, .dma_channels = 8,
.gpio_vrsel = GPIO_PH6, .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 = { static struct musb_hdrc_platform_data musb_plat = {
......
...@@ -603,6 +603,10 @@ static struct musb_hdrc_config musb_config = { ...@@ -603,6 +603,10 @@ static struct musb_hdrc_config musb_config = {
.num_eps = 8, .num_eps = 8,
.dma_channels = 8, .dma_channels = 8,
.gpio_vrsel = GPIO_PE7, .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 = { static struct musb_hdrc_platform_data musb_plat = {
......
...@@ -44,6 +44,7 @@ ...@@ -44,6 +44,7 @@
#include <linux/spi/flash.h> #include <linux/spi/flash.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/jiffies.h>
#include <linux/i2c-pca-platform.h> #include <linux/i2c-pca-platform.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/io.h> #include <linux/io.h>
...@@ -112,7 +113,7 @@ static struct resource bfin_i2c_pca_resources[] = { ...@@ -112,7 +113,7 @@ static struct resource bfin_i2c_pca_resources[] = {
struct i2c_pca9564_pf_platform_data pca9564_platform_data = { struct i2c_pca9564_pf_platform_data pca9564_platform_data = {
.gpio = -1, .gpio = -1,
.i2c_clock_speed = 330000, .i2c_clock_speed = 330000,
.timeout = 10000 .timeout = HZ,
}; };
/* PCA9564 I2C Bus driver */ /* PCA9564 I2C Bus driver */
......
...@@ -92,26 +92,29 @@ static void __init search_IAR(void) ...@@ -92,26 +92,29 @@ static void __init search_IAR(void)
{ {
unsigned ivg, irq_pos = 0; unsigned ivg, irq_pos = 0;
for (ivg = 0; ivg <= IVG13 - IVG7; ivg++) { for (ivg = 0; ivg <= IVG13 - IVG7; ivg++) {
int irqn; int irqN;
ivg7_13[ivg].istop = ivg7_13[ivg].ifirst = &ivg_table[irq_pos]; ivg7_13[ivg].istop = ivg7_13[ivg].ifirst = &ivg_table[irq_pos];
for (irqn = 0; irqn < NR_PERI_INTS; irqn++) { for (irqN = 0; irqN < NR_PERI_INTS; irqN += 4) {
int iar_shift = (irqn & 7) * 4; int irqn;
if (ivg == (0xf & u32 iar = bfin_read32((unsigned long *)SIC_IAR0 +
#if defined(CONFIG_BF52x) || defined(CONFIG_BF538) \ #if defined(CONFIG_BF51x) || defined(CONFIG_BF52x) || \
|| defined(CONFIG_BF539) || defined(CONFIG_BF51x) defined(CONFIG_BF538) || defined(CONFIG_BF539)
bfin_read32((unsigned long *)SIC_IAR0 + ((irqN % 32) >> 3) + ((irqN / 32) * ((SIC_IAR4 - SIC_IAR0) / 4))
((irqn % 32) >> 3) + ((irqn / 32) *
((SIC_IAR4 - SIC_IAR0) / 4))) >> iar_shift)) {
#else #else
bfin_read32((unsigned long *)SIC_IAR0 + (irqN >> 3)
(irqn >> 3)) >> iar_shift)) {
#endif #endif
ivg_table[irq_pos].irqno = IVG7 + irqn; );
ivg_table[irq_pos].isrflag = 1 << (irqn % 32);
ivg7_13[ivg].istop++; for (irqn = irqN; irqn < irqN + 4; ++irqn) {
irq_pos++; 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) ...@@ -662,14 +665,7 @@ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type)
#ifdef CONFIG_PM #ifdef CONFIG_PM
int bfin_gpio_set_wake(unsigned int irq, unsigned int state) int bfin_gpio_set_wake(unsigned int irq, unsigned int state)
{ {
unsigned gpio = irq_to_gpio(irq); return gpio_pm_wakeup_ctrl(irq_to_gpio(irq), state);
if (state)
gpio_pm_wakeup_request(gpio, PM_WAKE_IGNORE);
else
gpio_pm_wakeup_free(gpio);
return 0;
} }
#endif #endif
......
...@@ -20,35 +20,11 @@ ...@@ -20,35 +20,11 @@
#include <asm/dma.h> #include <asm/dma.h>
#include <asm/dpmc.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) void bfin_pm_suspend_standby_enter(void)
{ {
unsigned long flags; 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); local_irq_save_hw(flags);
bfin_pm_standby_setup(); bfin_pm_standby_setup();
......
...@@ -170,8 +170,8 @@ static irqreturn_t ipi_handler(int irq, void *dev_instance) ...@@ -170,8 +170,8 @@ static irqreturn_t ipi_handler(int irq, void *dev_instance)
kfree(msg); kfree(msg);
break; break;
default: default:
printk(KERN_CRIT "CPU%u: Unknown IPI message \ printk(KERN_CRIT "CPU%u: Unknown IPI message 0x%lx\n",
0x%lx\n", cpu, msg->type); cpu, msg->type);
kfree(msg); kfree(msg);
break; break;
} }
......
...@@ -15,23 +15,11 @@ ...@@ -15,23 +15,11 @@
#include "blackfin_sram.h" #include "blackfin_sram.h"
/* /*
* BAD_PAGE is the page that is used for page faults when linux * ZERO_PAGE is a special page that is used for zero-initialized data and COW.
* is out-of-memory. Older versions of linux just did a * Let the bss do its zero-init magic so we don't have to do it ourselves.
* 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.
*/ */
static unsigned long empty_bad_page_table; char empty_zero_page[PAGE_SIZE] __attribute__((aligned(PAGE_SIZE)));
EXPORT_SYMBOL(empty_zero_page);
static unsigned long empty_bad_page;
static unsigned long empty_zero_page;
#ifndef CONFIG_EXCEPTION_L1_SCRATCH #ifndef CONFIG_EXCEPTION_L1_SCRATCH
#if defined CONFIG_SYSCALL_TAB_L1 #if defined CONFIG_SYSCALL_TAB_L1
...@@ -52,40 +40,26 @@ EXPORT_SYMBOL(cpu_pda); ...@@ -52,40 +40,26 @@ EXPORT_SYMBOL(cpu_pda);
void __init paging_init(void) void __init paging_init(void)
{ {
/* /*
* make sure start_mem is page aligned, otherwise bootmem and * make sure start_mem is page aligned, otherwise bootmem and
* page_alloc get different views og the world * page_alloc get different views of the world
*/ */
unsigned long end_mem = memory_end & PAGE_MASK; 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); unsigned long zones_size[MAX_NR_ZONES] = {
[0] = 0,
/* [ZONE_DMA] = (end_mem - PAGE_OFFSET) >> PAGE_SHIFT,
* initialize the bad page table and bad page to point [ZONE_NORMAL] = 0,
* to a couple of allocated pages #ifdef CONFIG_HIGHMEM
*/ [ZONE_HIGHMEM] = 0,
empty_bad_page_table = (unsigned long)alloc_bootmem_pages(PAGE_SIZE); #endif
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);
/* /* Set up SFC/DFC registers (user data space) */
* Set up SFC/DFC registers (user data space)
*/
set_fs(KERNEL_DS); 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); PAGE_ALIGN(memory_start), end_mem);
free_area_init(zones_size);
{
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);
}
} }
asmlinkage void __init init_pda(void) asmlinkage void __init init_pda(void)
......
...@@ -43,13 +43,12 @@ static DEFINE_SPINLOCK(dtest_lock); ...@@ -43,13 +43,12 @@ static DEFINE_SPINLOCK(dtest_lock);
/* Takes a void pointer */ /* Takes a void pointer */
#define IADDR2DTEST(x) \ #define IADDR2DTEST(x) \
({ unsigned long __addr = (unsigned long)(x); \ ({ unsigned long __addr = (unsigned long)(x); \
(__addr & 0x47F8) | /* address bits 14 & 10:3 */ \ ((__addr & (1 << 11)) << (26 - 11)) | /* addr bit 11 (Way0/Way1) */ \
(__addr & 0x8000) << 23 | /* Bank A/B */ \ (1 << 24) | /* instruction access = 1 */ \
(__addr & 0x0800) << 15 | /* address bit 11 */ \ ((__addr & (1 << 15)) << (23 - 15)) | /* addr bit 15 (Data Bank) */ \
(__addr & 0x3000) << 4 | /* address bits 13:12 */ \ ((__addr & (3 << 12)) << (16 - 12)) | /* addr bits 13:12 (Subbank) */ \
(__addr & 0x8000) << 8 | /* address bit 15 */ \ (__addr & 0x47F8) | /* addr bits 14 & 10:3 */ \
(0x1000000) | /* instruction access = 1 */ \ (1 << 2); /* data array = 1 */ \
(0x4); /* data array = 1 */ \
}) })
/* Takes a pointer, and returns the offset (in bits) which things should be shifted */ /* Takes a pointer, and returns the offset (in bits) which things should be shifted */
...@@ -196,7 +195,7 @@ EXPORT_SYMBOL(isram_memcpy); ...@@ -196,7 +195,7 @@ EXPORT_SYMBOL(isram_memcpy);
#ifdef CONFIG_BFIN_ISRAM_SELF_TEST #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) static __init void hex_dump(unsigned char *buf, int len)
{ {
...@@ -212,15 +211,15 @@ static __init int isram_read_test(char *sdram, void *l1inst) ...@@ -212,15 +211,15 @@ static __init int isram_read_test(char *sdram, void *l1inst)
pr_info("INFO: running isram_read tests\n"); pr_info("INFO: running isram_read tests\n");
/* setup some different data to play with */ /* setup some different data to play with */
for (i = 0; i < TEST_LEN; ++i) for (i = 0; i < test_len; ++i)
sdram[i] = i; sdram[i] = i % 255;
dma_memcpy(l1inst, sdram, TEST_LEN); dma_memcpy(l1inst, sdram, test_len);
/* make sure we can read the L1 inst */ /* 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); data1 = isram_read(l1inst + i);
memcpy(&data2, sdram + i, sizeof(data2)); 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", pr_err("FAIL: isram_read(%p) returned %#llx but wanted %#llx\n",
l1inst + i, data1, data2); l1inst + i, data1, data2);
++ret; ++ret;
...@@ -238,25 +237,25 @@ static __init int isram_write_test(char *sdram, void *l1inst) ...@@ -238,25 +237,25 @@ static __init int isram_write_test(char *sdram, void *l1inst)
pr_info("INFO: running isram_write tests\n"); pr_info("INFO: running isram_write tests\n");
/* setup some different data to play with */ /* setup some different data to play with */
memset(sdram, 0, TEST_LEN * 2); memset(sdram, 0, test_len * 2);
dma_memcpy(l1inst, sdram, TEST_LEN); dma_memcpy(l1inst, sdram, test_len);
for (i = 0; i < TEST_LEN; ++i) for (i = 0; i < test_len; ++i)
sdram[i] = i; sdram[i] = i % 255;
/* make sure we can write the L1 inst */ /* 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)); memcpy(&data1, sdram + i, sizeof(data1));
isram_write(l1inst + i, data1); isram_write(l1inst + i, data1);
data2 = isram_read(l1inst + i); data2 = isram_read(l1inst + i);
if (memcmp(&data1, &data2, sizeof(uint64_t))) { if (data1 != data2) {
pr_err("FAIL: isram_write(%p, %#llx) != %#llx\n", pr_err("FAIL: isram_write(%p, %#llx) != %#llx\n",
l1inst + i, data1, data2); l1inst + i, data1, data2);
++ret; ++ret;
} }
} }
dma_memcpy(sdram + TEST_LEN, l1inst, TEST_LEN); dma_memcpy(sdram + test_len, l1inst, test_len);
if (memcmp(sdram, sdram + TEST_LEN, TEST_LEN)) { if (memcmp(sdram, sdram + test_len, test_len)) {
pr_err("FAIL: isram_write() did not work properly\n"); pr_err("FAIL: isram_write() did not work properly\n");
++ret; ++ret;
} }
...@@ -268,12 +267,12 @@ static __init int ...@@ -268,12 +267,12 @@ static __init int
_isram_memcpy_test(char pattern, void *sdram, void *l1inst, const char *smemcpy, _isram_memcpy_test(char pattern, void *sdram, void *l1inst, const char *smemcpy,
void *(*fmemcpy)(void *, const void *, size_t)) void *(*fmemcpy)(void *, const void *, size_t))
{ {
memset(sdram, pattern, TEST_LEN); memset(sdram, pattern, test_len);
fmemcpy(l1inst, sdram, TEST_LEN); fmemcpy(l1inst, sdram, test_len);
fmemcpy(sdram + TEST_LEN, l1inst, TEST_LEN); fmemcpy(sdram + test_len, l1inst, test_len);
if (memcmp(sdram, sdram + TEST_LEN, TEST_LEN)) { if (memcmp(sdram, sdram + test_len, test_len)) {
pr_err("FAIL: %s(%p <=> %p, %#x) failed (data is %#x)\n", 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 1;
} }
return 0; return 0;
...@@ -292,12 +291,13 @@ static __init int isram_memcpy_test(char *sdram, void *l1inst) ...@@ -292,12 +291,13 @@ static __init int isram_memcpy_test(char *sdram, void *l1inst)
/* check read of small, unaligned, and hardware 64bit limits */ /* check read of small, unaligned, and hardware 64bit limits */
pr_info("INFO: running isram_memcpy (read) tests\n"); pr_info("INFO: running isram_memcpy (read) tests\n");
for (i = 0; i < TEST_LEN; ++i) /* setup some different data to play with */
sdram[i] = i; for (i = 0; i < test_len; ++i)
dma_memcpy(l1inst, sdram, TEST_LEN); sdram[i] = i % 255;
dma_memcpy(l1inst, sdram, test_len);
thisret = 0; thisret = 0;
for (i = 0; i < TEST_LEN - 32; ++i) { for (i = 0; i < test_len - 32; ++i) {
unsigned char cmp[32]; unsigned char cmp[32];
for (j = 1; j <= 32; ++j) { for (j = 1; j <= 32; ++j) {
memset(cmp, 0, sizeof(cmp)); memset(cmp, 0, sizeof(cmp));
...@@ -310,7 +310,7 @@ static __init int isram_memcpy_test(char *sdram, void *l1inst) ...@@ -310,7 +310,7 @@ static __init int isram_memcpy_test(char *sdram, void *l1inst)
pr_cont("\n"); pr_cont("\n");
if (++thisret > 20) { if (++thisret > 20) {
pr_err("FAIL: skipping remaining series\n"); pr_err("FAIL: skipping remaining series\n");
i = TEST_LEN; i = test_len;
break; break;
} }
} }
...@@ -321,11 +321,11 @@ static __init int isram_memcpy_test(char *sdram, void *l1inst) ...@@ -321,11 +321,11 @@ static __init int isram_memcpy_test(char *sdram, void *l1inst)
/* check write of small, unaligned, and hardware 64bit limits */ /* check write of small, unaligned, and hardware 64bit limits */
pr_info("INFO: running isram_memcpy (write) tests\n"); pr_info("INFO: running isram_memcpy (write) tests\n");
memset(sdram + TEST_LEN, 0, TEST_LEN); memset(sdram + test_len, 0, test_len);
dma_memcpy(l1inst, sdram + TEST_LEN, TEST_LEN); dma_memcpy(l1inst, sdram + test_len, test_len);
thisret = 0; thisret = 0;
for (i = 0; i < TEST_LEN - 32; ++i) { for (i = 0; i < test_len - 32; ++i) {
unsigned char cmp[32]; unsigned char cmp[32];
for (j = 1; j <= 32; ++j) { for (j = 1; j <= 32; ++j) {
isram_memcpy(l1inst + i, sdram + i, j); isram_memcpy(l1inst + i, sdram + i, j);
...@@ -338,7 +338,7 @@ static __init int isram_memcpy_test(char *sdram, void *l1inst) ...@@ -338,7 +338,7 @@ static __init int isram_memcpy_test(char *sdram, void *l1inst)
pr_cont("\n"); pr_cont("\n");
if (++thisret > 20) { if (++thisret > 20) {
pr_err("FAIL: skipping remaining series\n"); pr_err("FAIL: skipping remaining series\n");
i = TEST_LEN; i = test_len;
break; break;
} }
} }
...@@ -355,22 +355,30 @@ static __init int isram_test_init(void) ...@@ -355,22 +355,30 @@ static __init int isram_test_init(void)
char *sdram; char *sdram;
void *l1inst; void *l1inst;
sdram = kmalloc(TEST_LEN * 2, GFP_KERNEL); /* Try to test as much of L1SRAM as possible */
if (!sdram) { while (test_len) {
pr_warning("SKIP: could not allocate sdram\n"); test_len >>= 1;
return 0; l1inst = l1_inst_sram_alloc(test_len);
if (l1inst)
break;
} }
l1inst = l1_inst_sram_alloc(TEST_LEN);
if (!l1inst) { if (!l1inst) {
kfree(sdram);
pr_warning("SKIP: could not allocate L1 inst\n"); pr_warning("SKIP: could not allocate L1 inst\n");
return 0; 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 */ /* sanity check initial L1 inst state */
ret = 1; 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)) if (_isram_memcpy_test(0xa, sdram, l1inst, dma_memcpy))
goto abort; goto abort;
if (_isram_memcpy_test(0x5, sdram, l1inst, dma_memcpy)) 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, ...@@ -256,7 +256,8 @@ static void *_sram_alloc(size_t size, struct sram_piece *pfree_head,
plast->next = pslot->next; plast->next = pslot->next;
pavail = pslot; pavail = pslot;
} else { } 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) if (!pavail)
return NULL; 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