linuxppc-dev.lists.ozlabs.org archive mirror
 help / color / mirror / Atom feed
* ppc-linux EPIC (OpenPIC) and Interrupts on MPC8240
@ 2001-07-06 21:39 James F Dougherty
  2001-07-09 17:57 ` Dan Malek
  0 siblings, 1 reply; 8+ messages in thread
From: James F Dougherty @ 2001-07-06 21:39 UTC (permalink / raw)
  To: linuxppc-embedded, cort; +Cc: cort


Hi,

I am porting a custom designed MPC8240 board to linuxpcc,
have spent about a month or so getting ppcboot running
on it, and am now in the low-level details of getting
linux setup and running. Here's the details of my hardware
configuration:

200Mhz MPC8240 (Embedded MPC107, EPIC, I2C, I2O) + 64MB SDRAM
512K PLCC (Bootrom)
4MB FLASH mapped via PLD to PortX I/O Bus in range:
NS16550  mapped via PLD to PortX I/O bus starting at 0xffe08080
DEC 21143 Ethernet on MPC107 PCI Bus
ALI 1535 Southbridge
PCI Connector

The board is essentially a Motorola Sandpoint design variant, so
I have started with the MontaVista Sandpoint port of linux-2.3.1
and have had gotten into the sandpoint_setup code. I believe the
interrupt controller driver and serial port are currently broken
however.

IRQ mapping on this system is different then the standard PPC/Linux
configurations I have seen so far as it uses the internal OpenPIC
interrupt controller for all interrupts and does not use the 8259
serial port cascade (Winbond and others).

Vector(s)	Assignment
---------	-------------------
0-15		External (and unused serial interrupts)
16-19		Global timers
20		I2C
21-22		DMA
23		I2O message


Also, the MPC8240 EPIC (OpenPIC) has two modes: serial and discrete
interrupt mode. I need to use Discrete interrupt mode, which allows
for my hardwired interrupt mapping :

#define IRQ_ENET	1	/* Hardwired external EPIC Vector 1*/
#define IRQ_PCI		3	/* Hardwired external EPIC Vector 3*/
#define IRQ_UART	4	/* Hardwired external EPIC Vector 4*/

I have several questions:

1) How do the internal linux IRQ numbers map to EPIC interrupts?
2) What is the procedure by which the interrupt controller will invoke
   a linux interrupt? I know doIRQ is called and ppc_md.cannonicalize_irq()
   will re-number interrupts if need be, but I am not sure what interrupt
   numbers these should map to on the EPIC.
3) How should I handle the serial port? The drivers/char/serial.c
   allows for :

	static struct serial_state rs_table[] = {
		{ 0, 9600, 0xffe08080, 4, STD_COM_FLAGS }, /* ttyS0 */
	};

   however I am not sure this will work since I get no console output
   but I do know that my PIO version of the serial driver works (since
   I have written a ppc_md.progress routine and it spits out text indicating
   where I am)

4) Should I add a new interrupt controller driver? I am sure the open_pic.c
   driver works since it works for sandpoint, however, it only handles routing
   the interrupt to the 8259 cascade (which does the SIO interrupt) which is
   not what I am using (I need the 8240 EPIC in discrete mode EXT4 = COM1).

Here is where I am at bootup:

Initializing...
  CPU:   MPC8240 Revision 1.1 at 302 MHz: 16 kB I-Cache 16 kB D-Cache
  Board:   VOOHA MOUSSE MPC8240/KAHLUA - CHRP (MAP B)
  PLD Revision 1
  Local Bus at 2105 MHz
  DRAM:  64 MB
  FLASH: 16 MB
  Scanning function 0 of each PCI device on bus 0
  bus dev fn venID devID class  rev MBAR0    MBAR1    IPIN ILINE
  00  00  00 1057  0003  060000 11  00000008 00000000 01   00
  00  0d  00 1011  0019  020000 41  00810001 00010000 01   01
  In:    serial
  Out:   serial
  Err:   serial

mousse>boot
DC21143 Ethernet adapter(bus=0, device=13, func=0)
DEC Ethernet iobase=0x80000000 eth0: online
ARP broadcast 1
TFTP from server 192.168.1.133; our IP address is 192.168.1.138
Filename 'vmlinux.img'.
Load address: 0x100000
Loading:
################################################################################
#################
done
Bytes transferred = 492694 (78496 hex)
eth_halt
## Booting image at 00100000 ...
   Image Name:   vmlinux.bin.gz
   Image Type:   PowerPC Linux Kernel Image (gzip compressed)
   Data Size:    492630 Bytes = 481 kB = 0 MB
   Load Address: 00000000
   Entry Point:  00000000
   Verifying Checksum ... OK
   Uncompressing Kernel Image ... OK
arch: exitinit IRQ
openpic enterOpenPIC v1.2
openpic timeropenpic ipisandpoint irq
openpic spuriousopenpic exitdo_IRQ:irq:00000063

 irq_cannon:00000004
                    irq_cannon:00000000
                                       irq_cannon:00000001
                                                          irq_cannon:00000002

irq_cannon:00000003
                irq_cannon:00000004
                                   irq_cannon:00000003
                                                      irq_cannon:00000004

irq_cannon:00000003


I am pretty sure it is mapping the OpenPIC correctly (I get 1.2 in my VxWorks
driver so that looks good). I am not sure why do_IRQ() is called with IRQ=0x63
though, perhaps this is in need of re-mapping? I wrote the irq_cannonicalize
routine to return the IRQ number, and in a desperate hack attempt to get the
serial port to work, I added the same rs_table entry for IRQ 0-4


I am sure someone out there has had to deal with this issue before, so any
pointers in the right direction would be greatly appreciated.

Many thanks in advance.

					-James
James Dougherty
jfd@gigabitnetworks.com
408-776-6634

** Sent via the linuxppc-embedded mail list. See http://lists.linuxppc.org/

^ permalink raw reply	[flat|nested] 8+ messages in thread
* Re: ppc-linux EPIC (OpenPIC) and Interrupts on MPC8240
@ 2001-07-09 21:57 James F Dougherty
  2001-07-09 22:27 ` Andrew Johnson
  2001-07-09 23:46 ` Tom Rini
  0 siblings, 2 replies; 8+ messages in thread
From: James F Dougherty @ 2001-07-09 21:57 UTC (permalink / raw)
  To: dan, anj; +Cc: jfd, linuxppc-embedded, cort

[-- Attachment #1: Type: text/plain, Size: 3173 bytes --]

Thanks Dan, Thanks Andrew,

I am using MVista spdemo-linux-2.3.16-2000.02.10 from
ftp://ftp.mvista.com/pub/Area51/Sandpoint-8240 and
made a change to boot/ns16550.h for COM1 and defined
sandpoint_progress() to get output from the kernel.
Also, I removed the 8259 cascade intterupt and that
got me far enough to see that interrupts are not happening.
It is not a mapping issue though, since the registers can
be dumped and they show the right value.

Dan, is there a more recent version of the kernel source
which I should use?

Andrew, I am using the EPIC in direct (discrete mode) as
you are with EPIC IRQ4=SIO INTR, EPIC IRQ1=Enet Intr,
and EPIC IRQ3=PCI slot. Are you simply defining the
InitSenses[] array with 24 entries and the 0 sense for
UART, 1 for PCI (makes sense since PCI is active high).
If so, what kernel source are you using?

Finally, attached is the MPC8240 EPIC driver I am using
under VxWorks. It simply hooksup the PPC interrupt handler
to use the EPIC interrupt handler and initializes the
controller to run in discrete mode. This seems trivial to
port to Linux, the only question is how to make the
PPC irq handler call the epic IRQ handler.

Many thanks in advance.
					-James


> >
> > I am sure someone out there has had to deal with this issue before, so any
> > pointers in the right direction would be greatly appreciated.
>
> I have HHL2.0 (Linux-2.4.2) running on an MVME2100 board (MPC8240) which
> only uses the interrupts on the built-in EPIC device, no 8259.  I don't
> pretend to fully understand PCI interrupts, but I did discover that the
> OpenPIC_InitSenses[] array is critical to getting interrupts to work, and
> I also had to edit openpic.c to remove the 8259 stuff from
> openpic_get_irq() in my configuration.  You're working with an earlier
> version though, so YMMV.
>
> The openpic driver gets the default number of IRQs from the register on
> the EPIC chip to be 24, but these are not contiguous nor in their
> canonical places, so you need to provide the InitSenses array to let it
> know the real configuration.  I start with 16 zero entries as the first
> EPIC IRQ is offset by 16, then provide up to 16 entries for the real
> serial IRQ inputs to the EPIC.  The value you give to each entry
> determines the polarity / edge-sensitivity; my setup needs 1 for PCI
> devices, but 0 for the 16550 UART.  I'm not sure how you cope with the
> large gap before the I2C and DMA IRQ numbers; it looks like openpic.c
> needs modifying to properly cope with holes in the IRQ space, but it may
> be that you can do this with a cannonicalize_irq() routine (I don't have
> one, but I don't need the high IRQs and they're not essential for Linux to
> run).
>
> I discovered that even without serial interrupts working it was possible
> to type commands to my init shell (mount /proc;cat /proc/interrupts was
> very useful); you just have to wait up to 10 seconds for them to arrive,
> and don't type more than will fill the FIFO; be prepared to wait a while
> for the output to appear too!
>
> - Andrew
> --
> The world is such a cheerful place when viewed from upside-down
> It makes a rise of every fall, a smile of every frown
>
>

[-- Attachment #2: Attachment.txt --]
[-- Type: text/plain, Size: 0 bytes --]



[-- Attachment #3: epic.c --]
[-- Type: text/plain, Size: 7463 bytes --]

#include "vxWorks.h"
#include "intLib.h"
#include "excLib.h"
#include "epic.h"
#include "mpc107.h"
#include "stdio.h"
#include "string.h"

extern ULONG 	sysEUMBBARRead(ULONG regNum);
extern void 	sysEUMBBARWrite(ULONG regNum, ULONG regVal);

IMPORT STATUS	(*_func_intConnectRtn) (VOIDFUNCPTR *, VOIDFUNCPTR, int);
IMPORT int	(*_func_intEnableRtn) (int);
IMPORT int	(*_func_intDisableRtn)  (int);

/*
 * Typedef: epic_table_t
 * Purpose: Defines an entry in the EPIC table indexed by vector.
 *	    Each entry represents a vector that is permanently
 *	    assigned to a specific function as follows (see definitions
 *	    for EPIC_VECTOR_xxx):
 *
 *	Vector(s)	Assignment
 *	---------	-------------------
 *	0-15		External (and unused serial interrupts)
 *	16-19		Global timers
 *	20		I2C
 *	21-22		DMA
 *	23		I2O message
 *
 * NOTE: Higher priority numbers represent higher priority.
 */

typedef struct epic_table_s {
    int		et_prio;	/* Interrupt priority, fixed */
    VOIDFUNCPTR	et_func;	/* Function to call, set when connected */
    int		et_par;		/* Param to func, set when connected */
    UINT32	et_vecadr;	/* Address of EPIC vector register */
    UINT32	et_desadr;	/* Address of EPIC destination register */
} epic_table_t;

static epic_table_t epic_table[EPIC_VECTOR_USED] = {
  /* 0  */  {  5, 0, 0, EPIC_EX_INTx_VEC_REG(0),  EPIC_EX_INTx_DES_REG(0)  },
  /* 1  */  {  5, 0, 0, EPIC_EX_INTx_VEC_REG(1),  EPIC_EX_INTx_DES_REG(1)  },
  /* 2  */  {  5, 0, 0, EPIC_EX_INTx_VEC_REG(2),  EPIC_EX_INTx_DES_REG(2)  },
  /* 3  */  {  5, 0, 0, EPIC_EX_INTx_VEC_REG(3),  EPIC_EX_INTx_DES_REG(3)  },
  /* 4  */  { 10, 0, 0, EPIC_EX_INTx_VEC_REG(4),  EPIC_EX_INTx_DES_REG(4)  },
  /* 5  */  {  5, 0, 0, EPIC_SR_INTx_VEC_REG(5),  EPIC_SR_INTx_DES_REG(5)  },
  /* 6  */  {  5, 0, 0, EPIC_SR_INTx_VEC_REG(6),  EPIC_SR_INTx_DES_REG(6)  },
  /* 7  */  {  5, 0, 0, EPIC_SR_INTx_VEC_REG(7),  EPIC_SR_INTx_DES_REG(7)  },
  /* 8  */  {  5, 0, 0, EPIC_SR_INTx_VEC_REG(8),  EPIC_SR_INTx_DES_REG(8)  },
  /* 9  */  {  5, 0, 0, EPIC_SR_INTx_VEC_REG(9),  EPIC_SR_INTx_DES_REG(9)  },
  /* 10 */  {  5, 0, 0, EPIC_SR_INTx_VEC_REG(10), EPIC_SR_INTx_DES_REG(10) },
  /* 11 */  {  5, 0, 0, EPIC_SR_INTx_VEC_REG(11), EPIC_SR_INTx_DES_REG(11) },
  /* 12 */  {  5, 0, 0, EPIC_SR_INTx_VEC_REG(12), EPIC_SR_INTx_DES_REG(12) },
  /* 13 */  {  5, 0, 0, EPIC_SR_INTx_VEC_REG(13), EPIC_SR_INTx_DES_REG(13) },
  /* 14 */  {  5, 0, 0, EPIC_SR_INTx_VEC_REG(14), EPIC_SR_INTx_DES_REG(14) },
  /* 15 */  {  5, 0, 0, EPIC_SR_INTx_VEC_REG(15), EPIC_SR_INTx_DES_REG(15) },
  /* 16 */  {  8, 0, 0, EPIC_TMx_VEC_REG(0),      EPIC_TMx_DES_REG(0)      },
  /* 17 */  {  5, 0, 0, EPIC_TMx_VEC_REG(1),      EPIC_TMx_DES_REG(1)      },
  /* 18 */  {  5, 0, 0, EPIC_TMx_VEC_REG(2),      EPIC_TMx_DES_REG(2)      },
  /* 19 */  {  5, 0, 0, EPIC_TMx_VEC_REG(3),      EPIC_TMx_DES_REG(3)      },
  /* 20 */  {  5, 0, 0, EPIC_I2C_INT_VEC_REG,     EPIC_I2C_INT_DES_REG     },
  /* 21 */  {  5, 0, 0, EPIC_DMA0_INT_VEC_REG,    EPIC_DMA0_INT_DES_REG    },
  /* 22 */  {  5, 0, 0, EPIC_DMA1_INT_VEC_REG,    EPIC_DMA1_INT_DES_REG    },
  /* 23 */  {  5, 0, 0, EPIC_MSG_INT_VEC_REG,     EPIC_MSG_INT_DES_REG     },
};

STATUS
epic_int_configure(int vec, int prio, VOIDFUNCPTR func, int par)
/*
 * Function: 	epic_int_configure
 * Purpose:	Configure an EPIC interrupt with a given vector and prio.
 * Parameters:	vec - interrupt vector number/level
 *		prio - PPC interrupt priority
 *		func - function to call
 *		par - parameter passed to func on interrupt.
 * Returns:	OK/ERROR
 */
{
    epic_table_t *et = &epic_table[vec];

    if (NULL != et->et_func || vec < 0 || vec >= EPIC_VECTOR_USED) {
	return(ERROR);
    }
    et->et_func	 = func;
    et->et_par	 = par;
    et->et_prio	 = prio;
    return(OK);
}

static STATUS
epic_int_connect(VOIDFUNCPTR *v_ptr, VOIDFUNCPTR rtn, int par)
/*
 * Function: 	epic_int_connect
 * Purpose:	Connect an epic interrupt.
 * Parameters:	v_ptr - vector #.
 *		rtn - function to call.
 *		par - parameter passed to function.
 * Returns:	OK/ERROR
 * Notes:	This routine uses the same priority as found in the table.
 */
{
    int		vec	= (int) v_ptr;

    if (vec < 0 || vec >= EPIC_VECTOR_USED)
	return(ERROR);

    return epic_int_configure(vec, epic_table[vec].et_prio, rtn, par);
}

static	void
epic_int_handler(void)
/*
 * Function: 	epic_int_handler
 * Purpose:	Handle an interrupt from the epic.
 * Parameters:	None.
 * Returns:	Nothing
 */
{
    int	vec;
    ULONG	o_pri;			/* Old priority */
    epic_table_t *et;

    vec = epic_read(EPIC_PROC_INT_ACK_REG) ;
    et  = epic_table + vec;
    if ((vec >= 0) && (vec < EPIC_VECTOR_USED) && (NULL != et->et_func)) {
	o_pri = epic_read(EPIC_PROC_CTASK_PRI_REG); 	/* Save prev level */
	epic_write(EPIC_PROC_CTASK_PRI_REG, et->et_prio);/* Set task level */
	intUnlock (_PPC_MSR_EE);			/* Allow nesting */
	et->et_func(et->et_par);			/* Call handler */
	intLock();
	epic_write(EPIC_PROC_CTASK_PRI_REG, o_pri);	/* Restore  level */
    }
    epic_write(EPIC_PROC_EOI_REG, 0x0);			/* Signal EOI */
}

STATUS
epic_int_enable(int vec)
/*
 * Function: 	epic_int_enable
 * Purpose:	Enable interrupts for the specified vector.
 * Parameters:	vec - vector # to enable interrupts for.
 * Returns:	OK/ERROR
 */
{
    epic_table_t	*et = epic_table + vec;
    UINT32		vecreg;

    if (NULL == et->et_func) {
	return(ERROR);
    }

#if 0
    printf("EPIC: interrupt enable --- <vec=0x%x level=0x%x prio=0x%x>\n",
	   vec, et->et_level, et->et_prio);
#endif

    /*
     * Look up the interrupt level for the vector and enable that level
     * setting the correct vector #, priority,
     */

    vecreg = (et->et_prio << EPIC_VECREG_PRIO_SHFT |
	      vec << EPIC_VECREG_VEC_SHFT);

    if (vec >= EPIC_VECTOR_EXT0 && vec <= EPIC_VECTOR_EXT4)
	vecreg |= EPIC_VECREG_S;	/* Set sense bit */

    epic_write(et->et_vecadr, vecreg);

    /* Direct the interrupt to this processor */
    epic_write(et->et_desadr, 1);

    return(OK);
}

STATUS
epic_int_disable(int vec)
/*
 * Function: 	epic_int_disable
 * Purpose:	Disable interrupts for the specified vector.
 * Parameters:	vec - vector number to disable.
 * Returns:	OK/ERROR
 */
{
    epic_table_t	*et = epic_table + vec;
    UINT32		vecreg;

    if (NULL == et->et_func) {
	return(ERROR);
    }

    /* Set mask bit */

    vecreg = epic_read(et->et_vecadr);
    vecreg |= EPIC_VECREG_M;
    epic_write(et->et_vecadr, vecreg);

    return(OK);
}

void
epic_init(void)
/*
 * Function: 	epic_init
 * Purpose:	Initialize the EPIC for interrupts.
 * Parameters:	None.
 * Returns:	Nothing.
 */
{
    ULONG	tmp;

    /* Set reset bit and wait for reset to complete */

    epic_write(EPIC_GLOBAL_REG, EPIC_GCR_RESET);
    while (epic_read(EPIC_GLOBAL_REG) & EPIC_GCR_RESET)
	;

    /* Discrete ints please */

    epic_write(EPIC_GLOBAL_REG, EPIC_GCR_M);

    /* Set direct interrupts (disable serial interrupts) */

    tmp = epic_read(EPIC_INT_CONF_REG);
    epic_write(EPIC_INT_CONF_REG, tmp & ~EPIC_ICR_SIE);

    /* Clear all pending interrupt */

    while (epic_read(EPIC_PROC_INT_ACK_REG) != 0xff);

    /* Use EPIC only, no winpic stuff. */

    _func_intEnableRtn	= epic_int_enable;
    _func_intDisableRtn = epic_int_disable;
    _func_intConnectRtn = epic_int_connect;

    /* Connect the real PPC vector to our handler. */

    excIntConnect ((VOIDFUNCPTR *) _EXC_OFF_INTR, epic_int_handler);

    /* Set current task priority to 0 */

    epic_write(EPIC_PROC_CTASK_PRI_REG, 0);
}

[-- Attachment #4: epic.h --]
[-- Type: text/plain, Size: 7967 bytes --]



/*********************************************
 * Copyrigh 1999  Motorola Inc.
 *
 * Modification History:
 * =====================
 * 01a,04Feb99,My  Created.
 *
*/

#ifndef EPIC_H
#define EPIC_H

#define epic_write(r, v)	sysEUMBBARWrite((r), (v))
#define epic_read(r)		sysEUMBBARRead(r)

#define EPIC_EUMBBAR  		0x40000			/* EUMBBAR of EPIC  */
#define EPIC_FEATURES_REG	(EPIC_EUMBBAR + 0x01000)/* Feature reporting */
#define EPIC_GLOBAL_REG		(EPIC_EUMBBAR + 0x01020)/* Global config.  */
#define EPIC_INT_CONF_REG	(EPIC_EUMBBAR + 0x01030)/* Interrupt config. */
#define EPIC_VENDOR_ID_REG	(EPIC_EUMBBAR + 0x01080)/* Vendor id */
#define EPIC_PROC_INIT_REG	(EPIC_EUMBBAR + 0x01090)/* Processor init. */
#define EPIC_SPUR_VEC_REG	(EPIC_EUMBBAR + 0x010e0)/* Spurious vector */
#define EPIC_TM_FREQ_REG	(EPIC_EUMBBAR + 0x010f0)/* Timer Frequency */

#define EPIC_TM0_CUR_COUNT_REG	(EPIC_EUMBBAR + 0x01100)/* Gbl TM0 Cur. Count*/
#define EPIC_TM0_BASE_COUNT_REG	(EPIC_EUMBBAR + 0x01110)/* Gbl TM0 Base Count*/
#define EPIC_TM0_VEC_REG	(EPIC_EUMBBAR + 0x01120)/* Gbl TM0 Vector Pri*/
#define EPIC_TM0_DES_REG	(EPIC_EUMBBAR + 0x01130)/* Gbl TM0 Dest. */

#define EPIC_TM1_CUR_COUNT_REG	(EPIC_EUMBBAR + 0x01140)/* Gbl TM1 Cur. Count*/
#define EPIC_TM1_BASE_COUNT_REG	(EPIC_EUMBBAR + 0x01150)/* Gbl TM1 Base Count*/
#define EPIC_TM1_VEC_REG	(EPIC_EUMBBAR + 0x01160)/* Gbl TM1 Vector Pri*/
#define EPIC_TM1_DES_REG	(EPIC_EUMBBAR + 0x01170)/* Gbl TM1 Dest. */

#define EPIC_TM2_CUR_COUNT_REG	(EPIC_EUMBBAR + 0x01180)/* Gbl TM2 Cur. Count*/
#define EPIC_TM2_BASE_COUNT_REG	(EPIC_EUMBBAR + 0x01190)/* Gbl TM2 Base Count*/
#define EPIC_TM2_VEC_REG	(EPIC_EUMBBAR + 0x011a0)/* Gbl TM2 Vector Pri*/
#define EPIC_TM2_DES_REG	(EPIC_EUMBBAR + 0x011b0)/* Gbl TM2 Dest */

#define EPIC_TM3_CUR_COUNT_REG	(EPIC_EUMBBAR + 0x011c0)/* Gbl TM3 Cur. Count*/
#define EPIC_TM3_BASE_COUNT_REG	(EPIC_EUMBBAR + 0x011d0)/* Gbl TM3 Base Count*/
#define EPIC_TM3_VEC_REG	(EPIC_EUMBBAR + 0x011e0)/* Gbl TM3 Vector Pri*/
#define EPIC_TM3_DES_REG	(EPIC_EUMBBAR + 0x011f0)/* Gbl TM3 Dest. */

#define EPIC_TMx_CUR_COUNT_REG(x)	(EPIC_TM0_CUR_COUNT_REG  + 0x40 * (x))
#define EPIC_TMx_BASE_COUNT_REG(x)	(EPIC_TM0_BASE_COUNT_REG + 0x40 * (x))
#define EPIC_TMx_VEC_REG(x)		(EPIC_TM0_VEC_REG        + 0x40 * (x))
#define EPIC_TMx_DES_REG(x)		(EPIC_TM0_DES_REG        + 0x40 * (x))

#define EPIC_EX_INT0_VEC_REG	(EPIC_EUMBBAR + 0x10200)/* Ext. Int. Sr0 Des */
#define EPIC_EX_INT0_DES_REG	(EPIC_EUMBBAR + 0x10210)/* Ext. Int. Sr0 Vect*/
#define EPIC_EX_INT1_VEC_REG	(EPIC_EUMBBAR + 0x10220)/* Ext. Int. Sr1 Des */
#define EPIC_EX_INT1_DES_REG	(EPIC_EUMBBAR + 0x10230)/* Ext. Int. Sr1 Vect*/
#define EPIC_EX_INT2_VEC_REG	(EPIC_EUMBBAR + 0x10240)/* Ext. Int. Sr2 Des */
#define EPIC_EX_INT2_DES_REG	(EPIC_EUMBBAR + 0x10250)/* Ext. Int. Sr2 Vect*/
#define EPIC_EX_INT3_VEC_REG	(EPIC_EUMBBAR + 0x10260)/* Ext. Int. Sr3 Des */
#define EPIC_EX_INT3_DES_REG	(EPIC_EUMBBAR + 0x10270)/* Ext. Int. Sr3 Vect*/
#define EPIC_EX_INT4_VEC_REG	(EPIC_EUMBBAR + 0x10280)/* Ext. Int. Sr4 Des */
#define EPIC_EX_INT4_DES_REG	(EPIC_EUMBBAR + 0x10290)/* Ext. Int. Sr4 Vect*/

#define EPIC_EX_INTx_VEC_REG(x)		(EPIC_EX_INT0_VEC_REG + (x) * 0x20)
#define EPIC_EX_INTx_DES_REG(x)		(EPIC_EX_INT0_DES_REG + (x) * 0x20)

#define EPIC_SR_INT0_VEC_REG	(EPIC_EUMBBAR + 0x10200)/* Sr. Int. Sr0 Des */
#define EPIC_SR_INT0_DES_REG	(EPIC_EUMBBAR + 0x10210)/* Sr. Int. Sr0 Vect */
#define EPIC_SR_INT1_VEC_REG	(EPIC_EUMBBAR + 0x10220)/* Sr. Int. Sr1 Des */
#define EPIC_SR_INT1_DES_REG	(EPIC_EUMBBAR + 0x10230)/* Sr. Int. Sr1 Vect.*/
#define EPIC_SR_INT2_VEC_REG	(EPIC_EUMBBAR + 0x10240)/* Sr. Int. Sr2 Des */
#define EPIC_SR_INT2_DES_REG	(EPIC_EUMBBAR + 0x10250)/* Sr. Int. Sr2 Vect.*/
#define EPIC_SR_INT3_VEC_REG	(EPIC_EUMBBAR + 0x10260)/* Sr. Int. Sr3 Des */
#define EPIC_SR_INT3_DES_REG	(EPIC_EUMBBAR + 0x10270)/* Sr. Int. Sr3 Vect.*/
#define EPIC_SR_INT4_VEC_REG	(EPIC_EUMBBAR + 0x10280)/* Sr. Int. Sr4 Des */
#define EPIC_SR_INT4_DES_REG	(EPIC_EUMBBAR + 0x10290)/* Sr. Int. Sr4 Vect.*/

#define EPIC_SR_INT5_VEC_REG	(EPIC_EUMBBAR + 0x102a0)/* Sr. Int. Sr5 Des */
#define EPIC_SR_INT5_DES_REG	(EPIC_EUMBBAR + 0x102b0)/* Sr. Int. Sr5 Vect.*/
#define EPIC_SR_INT6_VEC_REG	(EPIC_EUMBBAR + 0x102c0)/* Sr. Int. Sr6 Des */
#define EPIC_SR_INT6_DES_REG	(EPIC_EUMBBAR + 0x102d0)/* Sr. Int. Sr6 Vect.*/
#define EPIC_SR_INT7_VEC_REG	(EPIC_EUMBBAR + 0x102e0)/* Sr. Int. Sr7 Des */
#define EPIC_SR_INT7_DES_REG	(EPIC_EUMBBAR + 0x102f0)/* Sr. Int. Sr7 Vect.*/
#define EPIC_SR_INT8_VEC_REG	(EPIC_EUMBBAR + 0x10300)/* Sr. Int. Sr8 Des */
#define EPIC_SR_INT8_DES_REG	(EPIC_EUMBBAR + 0x10310)/* Sr. Int. Sr8 Vect.*/
#define EPIC_SR_INT9_VEC_REG	(EPIC_EUMBBAR + 0x10320)/* Sr. Int. Sr9 Des */
#define EPIC_SR_INT9_DES_REG	(EPIC_EUMBBAR + 0x10330)/* Sr. Int. Sr9 Vect.*/

#define EPIC_SR_INT10_VEC_REG	(EPIC_EUMBBAR + 0x10340)/* Sr. Int. Sr10 Des */
#define EPIC_SR_INT10_DES_REG	(EPIC_EUMBBAR + 0x10350)/* Sr. Int. Sr10 Vect*/
#define EPIC_SR_INT11_VEC_REG	(EPIC_EUMBBAR + 0x10360)/* Sr. Int. Sr11 Des */
#define EPIC_SR_INT11_DES_REG	(EPIC_EUMBBAR + 0x10370)/* Sr. Int. Sr11 Vect*/
#define EPIC_SR_INT12_VEC_REG	(EPIC_EUMBBAR + 0x10380)/* Sr. Int. Sr12 Des */
#define EPIC_SR_INT12_DES_REG	(EPIC_EUMBBAR + 0x10390)/* Sr. Int. Sr12 Vect*/
#define EPIC_SR_INT13_VEC_REG	(EPIC_EUMBBAR + 0x103a0)/* Sr. Int. Sr13 Des */
#define EPIC_SR_INT13_DES_REG	(EPIC_EUMBBAR + 0x103b0)/* Sr. Int. Sr13 Vect*/
#define EPIC_SR_INT14_VEC_REG	(EPIC_EUMBBAR + 0x103c0)/* Sr. Int. Sr14 Des */
#define EPIC_SR_INT14_DES_REG	(EPIC_EUMBBAR + 0x103d0)/* Sr. Int. Sr14 Vect*/
#define EPIC_SR_INT15_VEC_REG	(EPIC_EUMBBAR + 0x103e0)/* Sr. Int. Sr15 Des */
#define EPIC_SR_INT15_DES_REG	(EPIC_EUMBBAR + 0x103f0)/* Sr. Int. Sr15 Vect*/

#define EPIC_SR_INTx_VEC_REG(x)		(EPIC_SR_INT0_VEC_REG + (x) * 0x20)
#define EPIC_SR_INTx_DES_REG(x)		(EPIC_SR_INT0_DES_REG + (x) * 0x20)

#define EPIC_I2C_INT_VEC_REG	(EPIC_EUMBBAR + 0x11020)/* I2C Int. Vect Pri.*/
#define EPIC_I2C_INT_DES_REG	(EPIC_EUMBBAR + 0x11030)/* I2C Int. Dest */
#define EPIC_DMA0_INT_VEC_REG	(EPIC_EUMBBAR + 0x11040)/* DMA0 Int. Vect Pri*/
#define EPIC_DMA0_INT_DES_REG	(EPIC_EUMBBAR + 0x11050)/* DMA0 Int. Dest */
#define EPIC_DMA1_INT_VEC_REG	(EPIC_EUMBBAR + 0x11060)/* DMA1 Int. Vect Pri*/
#define EPIC_DMA1_INT_DES_REG	(EPIC_EUMBBAR + 0x11070)/* DMA1 Int. Dest */
#define EPIC_MSG_INT_VEC_REG	(EPIC_EUMBBAR + 0x110c0)/* Msg Int. Vect Pri*/
#define EPIC_MSG_INT_DES_REG	(EPIC_EUMBBAR + 0x110d0)/* Msg Int. Dest  */

#define	EPIC_VECREG_PRIO_SHFT	16
#define	EPIC_VECREG_PRIO_MASK	(0xf << EPIC_EIS_PRIO_SHFT)
#define	EPIC_VECREG_VEC_SHFT	0
#define	EPIC_VECREG_VEC_MASK	(0xff << EPIC_EIS_VEC_SHFT)
#define	EPIC_VECREG_M		(1<<31)	/* MASK bit */
#define	EPIC_VECREG_A		(1<<30)	/* Activity  */
#define	EPIC_VECREG_P		(1<<23)	/* Polarity */
#define	EPIC_VECREG_S		(1<<22)	/* Sense */

#define EPIC_VECTOR_EXT0	0
#define EPIC_VECTOR_EXT1	1
#define EPIC_VECTOR_EXT2	2
#define EPIC_VECTOR_EXT3	3
#define EPIC_VECTOR_EXT4	4
#define EPIC_VECTOR_TM0		16
#define EPIC_VECTOR_TM1		17
#define EPIC_VECTOR_TM2		18
#define EPIC_VECTOR_TM3		19
#define EPIC_VECTOR_I2C		20
#define EPIC_VECTOR_DMA0	21
#define EPIC_VECTOR_DMA1	22
#define EPIC_VECTOR_I2O		23

#define	EPIC_VECTOR_CNT		0x100
#define EPIC_VECTOR_USED	24

#define	EPIC_GCR_RESET		(1<<31)
#define	EPIC_GCR_M		(1<<29)

#define	EPIC_ICR_R_SHFT		28
#define	EPIC_ICR_R_MASK		(7<<EPIC_ICR_R_SHFT)
#define	EPIC_ICR_SIE		(1<<27)


#define EPIC_PROC_CTASK_PRI_REG	(EPIC_EUMBBAR + 0x20080)/* Proc. current task*/
#define EPIC_PROC_INT_ACK_REG	(EPIC_EUMBBAR + 0x200a0)/* Int. acknowledge */
#define EPIC_PROC_EOI_REG	(EPIC_EUMBBAR + 0x200b0)/* End of interrupt */


#define EPIC_DIRECT_IRQ		0
#define EPIC_VEC_REG_INTERVAL	0x20	/* Distance between int. vector regs */

/*
 * Public interface
 */

#ifndef _ASMLANGUAGE
extern	void	epic_init(void);
extern	STATUS	epic_int_enable(int vec);
extern	STATUS	epic_int_disable(int vec);
#endif /* !_ASMLANGUAGE */

#endif /* defined(EPIC_H) */

^ permalink raw reply	[flat|nested] 8+ messages in thread
* RE: ppc-linux EPIC (OpenPIC) and Interrupts on MPC8240
@ 2001-07-10  7:34 Neil Wilson
  0 siblings, 0 replies; 8+ messages in thread
From: Neil Wilson @ 2001-07-10  7:34 UTC (permalink / raw)
  To: 'Dan Malek', James F Dougherty; +Cc: linuxppc-embedded, cort


If anyone has those patches are to hand I wouldn't mind them for my
Sandpoint X3 7450, thanks.

Neil

> -----Original Message-----
> From:	Dan Malek [SMTP:dan@mvista.com]
> Sent:	Monday, July 09, 2001 6:58 PM
> To:	James F Dougherty
> Cc:	linuxppc-embedded@lists.linuxppc.org; cort@cs.nmt.edu
> Subject:	Re: ppc-linux EPIC (OpenPIC) and Interrupts on MPC8240
>
>
> James F Dougherty wrote:
>
> > The board is essentially a Motorola Sandpoint design variant, so
> > I have started with the MontaVista Sandpoint port of linux-2.3.1
>
> What is linux-2.3.1?  Which version of the Sandpoint?
>
> If it is the old Sandpoint X2, and you are using the EPIC with
> discrete interrups (IRQ0 - IRQ4) the latest MontaVista HHL 2.0
> should be used (it should be used in any case).  The code in
> the public BK trees should also match this release.  If you are
> using a Sandpoint X3 with the serial mode interrupt EPIC, there
> are some patches I'll have to send you.
>
>
> 	-- Dan
>

** Sent via the linuxppc-embedded mail list. See http://lists.linuxppc.org/

^ permalink raw reply	[flat|nested] 8+ messages in thread
* Re: ppc-linux EPIC (OpenPIC) and Interrupts on MPC8240
@ 2001-07-12 18:03 James F Dougherty
  0 siblings, 0 replies; 8+ messages in thread
From: James F Dougherty @ 2001-07-12 18:03 UTC (permalink / raw)
  To: dan, linuxppc-embedded, cort; +Cc: jfd


Hi Guys,

I installed hhl-host-kernel-2.4.2_hhl20-hhl2.0.1.noarch.rpm which has the
sandpoint lsp for any arch, and then I made the following mods to
open_pic.c and sandpoint_setup.c for my board which does not use the 8259
and rather, uses the EPIC in direct mode (IRQ0-4).


1) On OpenPIC discrete interrupt mode, in MPC8240-UM and from my working
   vxworks BSP, here is the call I added to openpic_init()

#define OPENPIC_CONFIG_SERIAL_INTS              (1<<27)
#define OPENPIC_CONFIG_DISCRETE_INTS            (1<<29)
#define OPENPIC_CONFIG_IN_RESET                 (1<<31)


static void openpic_discrete_mode(void)
{
  u_int t;

  if ( ppc_md.progress ) ppc_md.progress("openpic discrete mode\n",0x122);

  /* Reset and wait till done ... */
  openpic_reset();

  while ((t = openpic_read(&OpenPIC->Global.Global_Configuration0)) &
	 OPENPIC_CONFIG_IN_RESET)
    ;

  /* Discrete ints please */
  openpic_write(&OpenPIC->Global.Global_Configuration0,
                OPENPIC_CONFIG_DISCRETE_INTS);

  /* Set direct interrupts (disable serial interrupts) */
  t = openpic_read(&OpenPIC->Global.Global_Configuration1);
  openpic_write(&OpenPIC->Global.Global_Configuration1,
                t & ~OPENPIC_CONFIG_SERIAL_INTS);

  /* Clear all pending interrupts */
  while((t = openpic_readfield(&OpenPIC->THIS_CPU.Interrupt_Acknowledge,
			       OPENPIC_VECTOR_MASK)) != 0xff)
    ;
}


2) In openpic_get_irq(), comment out the chrp_int_ack stuff (like yours).

3) In sandpoint_init:

        /* ppc_md.irq_cannonicalize = NULL; */
        ppc_md.init_IRQ = sandpoint_init_IRQ;
        ppc_md.get_irq = openpic_get_irq;
        /* ppc_md.post_irq = NULL; */

4) In sandpoint_init_IRQ()

	OpenPIC_InitSenses = sandpoint_openpic_initsenses;
	OpenPIC_NumInitSenses = sizeof(sandpoint_openpic_initsenses);

	openpic_init(1, 0, NULL, -1);

5) Define:

static u_char sandpoint_openpic_initsenses[] __initdata = {
	0,	/* 0-15 not used by EPCI but by 8259 (std PC-type IRQs) */
	0,	/* 1 */
	0,	/* 2 */
	0,	/* 3 */
	0,	/* 4 */
	0,	/* 5 */
	0,	/* 6 */
	0,	/* 7 */
	0,	/* 8 */
	0,	/* 9 */
	0,	/* 10 */
	0,	/* 11 */
	0,	/* 12 */
	0,	/* 13 */
	0,	/* 14 */
	0,	/* 15 */
	/* MPC8240/EPIC in Direct mode (5 external interrupts) */
	1,	/* 16: EPIC IRQ 0: Unused */
	1,	/* 17: EPIC IRQ 1: DEC 21143 onboard 10/100 Enet */
	1,	/* 18: EPIC IRQ 2: CPCI IntA */
	1,	/* 19: EPIC IRQ 3: Local PCI Slot (Int{A,B,C,D} */
        0,	/* 20: EPIC IRQ 4: NS16550 UART COM1 */
	0,      /* 21: EPIC IRQ 5: Unused*/
	0,      /* 22: Unused */
	0,      /* 23: Unused */
	0,      /* 24: Unused */
	0,      /* 25: Unused */
	0,	/* 26: Unused */
	0,      /* 27: Unused */
	0,      /* 28: Unused */
	0,      /* 29: Unused */
	0,      /* 30: Unused */
	0,      /* 31: Unused */
};

Now, on the console, I edited drivers/char/serial.c and added:


static struct serial_state rs_table[RS_TABLE_SIZE] = {
        { 0, 9600, 0xffe08080, 20, ASYNC_BOOT_AUTOCONF,0,
	  PORT_16550, /* chip */
	  0, /*line*/
	  0, /*rev*/
	  0, /*tx fifo sz*/
	  0, /* custom div */
	  0, /* count */
	  0xffe08080, /* IO base */
	  0, /* shift */
	  0,0,0,0,0,
	  SERIAL_IO_MEM
	} /* ttyS0 */
};

Since my ns16550 UART is mapped (through a PLD) into PortX I/O space
at 0xffe08080.

Finally, I hacked up init/main.c with some PIO printf() routines (the
progress routine which does PIO on the 16550 for output) to tell me
where I am.

Alas, no luck. I see that init/main.c runs all the way to the idle loop,
but that damn openpic is not working, otherwise, I would be getting
interrupts. Is there some other way to debug this? Perhaps the init_senses
array is still wrong. I am not sure how to proceed. How would people
debug this? I am considering simply writing my own interrupt driver
based on code which I know works.



Many thanks in advance.

						-James


## Booting image at 00100000 ...
   Image Name:   vmlinux.bin.gz
   Image Type:   PowerPC Linux Kernel Image (gzip compressed)
   Data Size:    658739 Bytes = 643 kB = 0 MB
   Load Address: 00000000
   Entry Point:  00000000
   Verifying Checksum ... OK
   Uncompressing Kernel Image ... OK
id mach(): doneMMU:enterMMU:hash inithash:enterhash:find
piecehash:doneMMU:mapinMMU:setbatMMU:exitsetup_arch: entersetup_arch:
bootmemmpc10x:entermpc10x:exitarch: exitopenpic enteropenpic discrete mode
openpic timeropenpic extopenpic spuriousopenpic exitconsole_init

serial_out(ffe08083,00000093)

serial_out(ffe08080,00000001)

serial_out(ffe08081,00000000)

serial_out(ffe08083,00000013)

serial_out(ffe08081,00000000)

serial_out(ffe08084,00000003)

serial_in(ffe08085)
BogoMIPS:00000d6a
                 idle task started

serial_in(ffe08084)

serial_in(ffe08083)

serial_out(ffe08084,0000001a)

serial_in(ffe08086)

serial_out(ffe08084,000000ff)


** Sent via the linuxppc-embedded mail list. See http://lists.linuxppc.org/

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2001-07-12 18:03 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2001-07-06 21:39 ppc-linux EPIC (OpenPIC) and Interrupts on MPC8240 James F Dougherty
2001-07-09 17:57 ` Dan Malek
2001-07-09 20:00   ` Andrew Johnson
  -- strict thread matches above, loose matches on Subject: below --
2001-07-09 21:57 James F Dougherty
2001-07-09 22:27 ` Andrew Johnson
2001-07-09 23:46 ` Tom Rini
2001-07-10  7:34 Neil Wilson
2001-07-12 18:03 James F Dougherty

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).