Logo Search packages:      
Sourcecode: linux version File versions  Download package

entry.h

/*
 * Copyright 2004-2009 Analog Devices Inc.
 *
 * Licensed under the GPL-2 or later.
 */

#ifndef __BFIN_ENTRY_H
#define __BFIN_ENTRY_H

#include <asm/setup.h>
#include <asm/page.h>

#ifdef __ASSEMBLY__

#define     LFLUSH_I_AND_D    0x00000808
#define     LSIGTRAP    5

/*
 * NOTE!  The single-stepping code assumes that all interrupt handlers
 * start by saving SYSCFG on the stack with their first instruction.
 */

/* This one is used for exceptions, emulation, and NMI.  It doesn't push
   RETI and doesn't do cli.  */
#define SAVE_ALL_SYS          save_context_no_interrupts
/* This is used for all normal interrupts.  It saves a minimum of registers
   to the stack, loads the IRQ number, and jumps to common code.  */
#ifdef CONFIG_IPIPE
# define LOAD_IPIPE_IPEND \
      P0.l = lo(IPEND); \
      P0.h = hi(IPEND); \
      R1 = [P0];
#else
# define LOAD_IPIPE_IPEND
#endif

/*
 * Workaround for anomalies 05000283 and 05000315
 */
#if ANOMALY_05000283 || ANOMALY_05000315
# define ANOMALY_283_315_WORKAROUND(preg, dreg)       \
      cc = dreg == dreg;                        \
      preg.h = HI(CHIPID);                      \
      preg.l = LO(CHIPID);                      \
      if cc jump 1f;                            \
      dreg.l = W[preg];                   \
1:
#else
# define ANOMALY_283_315_WORKAROUND(preg, dreg)
#endif /* ANOMALY_05000283 || ANOMALY_05000315 */

#ifndef CONFIG_EXACT_HWERR
/* As a debugging aid - we save IPEND when DEBUG_KERNEL is on,
 * otherwise it is a waste of cycles.
 */
# ifndef CONFIG_DEBUG_KERNEL
#define INTERRUPT_ENTRY(N)                                  \
    [--sp] = SYSCFG;                                        \
    [--sp] = P0;  /*orig_p0*/                         \
    [--sp] = R0;  /*orig_r0*/                         \
    [--sp] = (R7:0,P5:0);                                   \
    R0 = (N);                                               \
    LOAD_IPIPE_IPEND                                        \
    jump __common_int_entry;
# else /* CONFIG_DEBUG_KERNEL */
#define INTERRUPT_ENTRY(N)                                  \
    [--sp] = SYSCFG;                                        \
    [--sp] = P0;  /*orig_p0*/                         \
    [--sp] = R0;  /*orig_r0*/                         \
    [--sp] = (R7:0,P5:0);                                   \
    p0.l = lo(IPEND);                                       \
    p0.h = hi(IPEND);                                       \
    r1 = [p0];                                              \
    R0 = (N);                                               \
    LOAD_IPIPE_IPEND                                        \
    jump __common_int_entry;
# endif /* CONFIG_DEBUG_KERNEL */

/* For timer interrupts, we need to save IPEND, since the user_mode
 *macro accesses it to determine where to account time.
 */
#define TIMER_INTERRUPT_ENTRY(N)                            \
    [--sp] = SYSCFG;                                        \
    [--sp] = P0;  /*orig_p0*/                         \
    [--sp] = R0;  /*orig_r0*/                         \
    [--sp] = (R7:0,P5:0);                                   \
    p0.l = lo(IPEND);                                       \
    p0.h = hi(IPEND);                                       \
    r1 = [p0];                                              \
    R0 = (N);                                               \
    jump __common_int_entry;
#else /* CONFIG_EXACT_HWERR is defined */

/* if we want hardware error to be exact, we need to do a SSYNC (which forces
 * read/writes to complete to the memory controllers), and check to see that
 * caused a pending HW error condition. If so, we assume it was caused by user
 * space, by setting the same interrupt that we are in (so it goes off again)
 * and context restore, and a RTI (without servicing anything). This should
 * cause the pending HWERR to fire, and when that is done, this interrupt will
 * be re-serviced properly.
 * As you can see by the code - we actually need to do two SSYNCS - one to
 * make sure the read/writes complete, and another to make sure the hardware
 * error is recognized by the core.
 *
 * The extra nop before the SSYNC is to make sure we work around 05000244,
 * since the 283/315 workaround includes a branch to the end
 */
#define INTERRUPT_ENTRY(N)                                  \
    [--sp] = SYSCFG;                                        \
    [--sp] = P0;  /*orig_p0*/                         \
    [--sp] = R0;  /*orig_r0*/                         \
    [--sp] = (R7:0,P5:0);                                   \
    R1 = ASTAT;                                             \
    ANOMALY_283_315_WORKAROUND(p0, r0)                            \
    P0.L = LO(ILAT);                                        \
    P0.H = HI(ILAT);                                        \
    NOP;                                              \
    SSYNC;                                            \
    SSYNC;                                            \
    R0 = [P0];                                              \
    CC = BITTST(R0, EVT_IVHW_P);                            \
    IF CC JUMP 1f;                                          \
    ASTAT = R1;                                             \
    p0.l = lo(IPEND);                                       \
    p0.h = hi(IPEND);                                       \
    r1 = [p0];                                              \
    R0 = (N);                                               \
    LOAD_IPIPE_IPEND                                        \
    jump __common_int_entry;                                \
1:  ASTAT = R1;                                             \
    RAISE N;                                                \
    (R7:0, P5:0) = [SP++];                                  \
    SP += 0x8;                                              \
    SYSCFG = [SP++];                                        \
    CSYNC;                                            \
    RTI;

#define TIMER_INTERRUPT_ENTRY(N)                            \
    [--sp] = SYSCFG;                                        \
    [--sp] = P0;  /*orig_p0*/                         \
    [--sp] = R0;  /*orig_r0*/                         \
    [--sp] = (R7:0,P5:0);                                   \
    R1 = ASTAT;                                             \
    ANOMALY_283_315_WORKAROUND(p0, r0)                            \
    P0.L = LO(ILAT);                                        \
    P0.H = HI(ILAT);                                        \
    NOP;                                              \
    SSYNC;                                            \
    SSYNC;                                            \
    R0 = [P0];                                              \
    CC = BITTST(R0, EVT_IVHW_P);                            \
    IF CC JUMP 1f;                                          \
    ASTAT = R1;                                             \
    p0.l = lo(IPEND);                                       \
    p0.h = hi(IPEND);                                       \
    r1 = [p0];                                              \
    R0 = (N);                                               \
    jump __common_int_entry;                                \
1:  ASTAT = R1;                                             \
    RAISE N;                                                \
    (R7:0, P5:0) = [SP++];                                  \
    SP += 0x8;                                              \
    SYSCFG = [SP++];                                        \
    CSYNC;                                            \
    RTI;
#endif      /* CONFIG_EXACT_HWERR */

/* This one pushes RETI without using CLI.  Interrupts are enabled.  */
#define SAVE_CONTEXT_SYSCALL  save_context_syscall
#define SAVE_CONTEXT          save_context_with_interrupts
#define SAVE_CONTEXT_CPLB     save_context_cplb

#define RESTORE_ALL_SYS       restore_context_no_interrupts
#define RESTORE_CONTEXT       restore_context_with_interrupts
#define RESTORE_CONTEXT_CPLB  restore_context_cplb

#endif                        /* __ASSEMBLY__ */
#endif                        /* __BFIN_ENTRY_H */

Generated by  Doxygen 1.6.0   Back to index