 /*
 * Nitin Dhingra, iamnd@ti.com
 * Copyright (C) 2000 Texas Instruments Inc.
 *
 *
 * ########################################################################
 *
 *  This program is free software; you can distribute it and/or modify it
 *  under the terms of the GNU General Public License (Version 2) as
 *  published by the Free Software Foundation.
 *
 *  This program is distributed in the hope it will be useful, but WITHOUT
 *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 *  for more details.
 *
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
 *
 * ########################################################################
 *
 * Defines of the Sead board specific address-MAP, registers, etc.
 *
 */
#ifndef _AVALANCHE_INTC_H
#define _AVALANCHE_INTC_H

#define MIPS_EXCEPTION_OFFSET 8


#include <linux/interrupt.h>
#include "pal.h"

/******************************************************************************
 Avalanche Interrupt number
******************************************************************************/
#define AVINTNUM(x) ((x) - MIPS_EXCEPTION_OFFSET)


/*******************************************************************************
*Linux Interrupt number
*******************************************************************************/
#define LNXINTNUM(x)((x) + MIPS_EXCEPTION_OFFSET)



#define AVALANCHE_INT_END_PRIMARY      (40 + MIPS_EXCEPTION_OFFSET)
#define AVALANCHE_INT_END_SECONDARY    (32 + AVALANCHE_INT_END_PRIMARY)

#define AVALANCHE_INT_END_PRIMARY_REG1 32
#define AVALANCHE_INT_END_PRIMARY_REG2 40

#define AVALANCHE_INTC_END AVALANCHE_INT_END_SECONDARY

#if defined(CONFIG_MIPS_AVALANCHE_VLYNQ)
#define AVALANCHE_INT_END_LOW_VLYNQ  (AVALANCHE_INTC_END + 32)

#ifdef AVALANCHE_VLYNQ_HIGH_CONTROL_BASE
#define AVALANCHE_INT_END_VLYNQ      (AVALANCHE_INTC_END + 32 * 2) 
#else
#define AVALANCHE_INT_END_VLYNQ      (AVALANCHE_INTC_END + 32 * 1) 
#endif

	#if defined( CONFIG_MIPS_AVALANCHE_PCI )
		#define AVALANCHE_INT_PCI_BEGIN		( AVALANCHE_INT_END_VLYNQ + 1 )
		#define AVALANCHE_INT_PCI_END		( AVALANCHE_INT_PCI_BEGIN + 4 )
		#define AVALANCHE_INT_END		AVALANCHE_INT_PCI_END
		#define AV_PCI_INTA_SWIRQ		AVALANCHE_INT_PCI_BEGIN
		#define AV_PCI_INTD_SWIRQ		AVALANCHE_INT_PCI_END
	#else
		#define AVALANCHE_INT_END             AVALANCHE_INT_END_VLYNQ
	#endif
#else
	#if defined( CONFIG_MIPS_AVALANCHE_PCI )
		#define AVALANCHE_INT_PCI_BEGIN		( AVALANCHE_INTC_END + 1 )
		#define AVALANCHE_INT_PCI_END		( AVALANCHE_INT_PCI_BEGIN + 4 )
		#define AVALANCHE_INT_END		AVALANCHE_INT_PCI_END
		#define AV_PCI_INTA_SWIRQ		AVALANCHE_INT_PCI_BEGIN
		#define AV_PCI_INTD_SWIRQ		AVALANCHE_INT_PCI_END
#else
#define AVALANCHE_INT_END             AVALANCHE_INTC_END
#endif
#endif

/* ******************** AVALANCHE INTC S/W IRQ SUPPORT **************************** */

/* This structure holds private functions (which cannot be poppulated in irq_desc_t */
struct avalanche_intc_private_t
{
	int  (*av_set_irq_pol_fn)(unsigned int, unsigned int);
	int  (*av_get_irq_pol_fn)(unsigned int);
	int  (*av_set_irq_type_fn)(unsigned int, unsigned int);
	int  (*av_get_irq_type_fn)(unsigned int);

	void (*av_dis_irq_fn)(unsigned int);
	void (*av_en_irq_fn)(unsigned int);
	int  (*av_req_irq_fn)(unsigned int , irqreturn_t (*handler)(int , void *, struct pt_regs *), unsigned long , const char* , void* );
	void (*av_free_irq_fn)(unsigned int, void*);
	int  (*av_irq_list_fn)(char*);
};

/* Structure to store irq_desc_t information and private interfaces for an irq */
struct avalanche_intc_vect_t
{
	irq_desc_t *irq_desc;
	struct avalanche_intc_private_t *priv;
};


int avalanche_intc_set_desc(int irq_n, struct avalanche_intc_vect_t vect);
struct avalanche_intc_vect_t* avalanche_intc_get_desc(int irq_n);


/* ************************************************************************** */


/*
 * Avalanche interrupt controller register base (primary)
 */
#define AVALANCHE_ICTRL_REGS_BASE  AVALANCHE_INTC_BASE

/******************************************************************************
 * Avalanche exception controller register base (secondary)
 ******************************************************************************/
#define AVALANCHE_ECTRL_REGS_BASE  (AVALANCHE_ICTRL_REGS_BASE + 0x80)


/******************************************************************************
 *  Avalanche Interrupt pacing register base (secondary)
 ******************************************************************************/
#define AVALANCHE_IPACE_REGS_BASE  (AVALANCHE_ICTRL_REGS_BASE + 0xA0)



/******************************************************************************
 * Avalanche Interrupt Channel Control register base
 *****************************************************************************/
#define AVALANCHE_CHCTRL_REGS_BASE (AVALANCHE_ICTRL_REGS_BASE + 0x200)


struct avalanche_ictrl_regs /* Avalanche Interrupt control registers */
{
  volatile unsigned long intsr1;    /* Interrupt Status/Set Register 1   0x00 */
  volatile unsigned long intsr2;    /* Interrupt Status/Set Register 2   0x04 */
  volatile unsigned long unused1;                                      /*0x08 */
  volatile unsigned long unused2;                                      /*0x0C */
  volatile unsigned long intcr1;    /* Interrupt Clear Register 1        0x10 */
  volatile unsigned long intcr2;    /* Interrupt Clear Register 2        0x14 */
  volatile unsigned long unused3;                                      /*0x18 */
  volatile unsigned long unused4;                                      /*0x1C */
  volatile unsigned long intesr1;   /* Interrupt Enable (Set) Register 1 0x20 */
  volatile unsigned long intesr2;   /* Interrupt Enable (Set) Register 2 0x24 */
  volatile unsigned long unused5;                                      /*0x28 */
  volatile unsigned long unused6;                                      /*0x2C */
  volatile unsigned long intecr1;   /* Interrupt Enable Clear Register 1 0x30 */
  volatile unsigned long intecr2;   /* Interrupt Enable Clear Register 2 0x34 */
  volatile unsigned long unused7;                                     /* 0x38 */
  volatile unsigned long unused8;                                     /* 0x3c */
  volatile unsigned long pintir;    /* Priority Interrupt Index Register 0x40 */
  volatile unsigned long intmsr;    /* Priority Interrupt Mask Index Reg 0x44 */
  volatile unsigned long unused9;                                     /* 0x48 */
  volatile unsigned long unused10;                                    /* 0x4C */
  volatile unsigned long intpolr1;  /* Interrupt Polarity Mask register 10x50 */
  volatile unsigned long intpolr2;  /* Interrupt Polarity Mask register 20x54 */
  volatile unsigned long unused11;                                    /* 0x58 */
  volatile unsigned long unused12;                                   /*0x5C */
  volatile unsigned long inttypr1;  /* Interrupt Type     Mask register 10x60 */
  volatile unsigned long inttypr2;  /* Interrupt Type     Mask register 20x64 */
};

struct avalanche_exctrl_regs   /* Avalanche Exception control registers */
{
  volatile unsigned long exsr;      /* Exceptions Status/Set register    0x80 */
  volatile unsigned long reserved;                                     /*0x84 */
  volatile unsigned long excr;      /* Exceptions Clear Register         0x88 */
  volatile unsigned long reserved1;                                    /*0x8c */
  volatile unsigned long exiesr;    /* Exceptions Interrupt Enable (set) 0x90 */
  volatile unsigned long reserved2;                                    /*0x94 */
  volatile unsigned long exiecr;    /* Exceptions Interrupt Enable(clear)0x98 */
};
struct avalanche_ipace_regs
{

  volatile unsigned long ipacep;    /* Interrupt pacing register         0xa0 */
  volatile unsigned long ipacemap;  /*Interrupt Pacing Map Register      0xa4 */
  volatile unsigned long ipacemax;  /*Interrupt Pacing Max Register      0xa8 */
};
struct avalanche_channel_int_number
{
  volatile unsigned long cintnr[40];   /* Channel Interrupt Number Registers */
};

struct avalanche_interrupt_line_to_channel
{
  unsigned long int_line[40];    /* Start of primary interrupts */
};


/* Interrupt Line #'s  (Sangam peripherals) */

extern void avalanche_int_set(int channel, int line);

#if defined(CONFIG_AVALANCHE_INTC_PACING)
int avalanche_request_intr_pacing(int irq_nr, unsigned int blk_num,
		             unsigned int pace_value);
int avalanche_free_intr_pacing(unsigned int blk_num);
#endif

#if defined(CONFIG_AVALANCHE_INTC_TYPE)
int avalanche_intr_type_set(unsigned int irq_nr, unsigned long type_val);
int avalanche_intr_type_get(unsigned int irq_nr);
#endif

int avalanche_intr_polarity_set(unsigned int irq_nr, unsigned long type_val);
int avalanche_intr_polarity_get(unsigned int irq_nr);


#endif /* _AVALANCHE_INTC_H */


