[POWERPC] Update mpc7448hpc2 board irq support using device tree

The patch rewrites mpc7448hpc2 board irq support according to the new
mpic device tree interface.

Signed-off-by: Roy Zang	<tie-fei.zang@freescale.com>
Signed-off-by: Paul Mackerras <paulus@samba.org>
This commit is contained in:
Zang Roy-r61911 2006-08-23 10:19:50 +08:00 committed by Paul Mackerras
parent 6cdd2bdfb9
commit c4342ff92b
5 changed files with 174 additions and 68 deletions

View File

@ -1,7 +1,7 @@
/* /*
* mpc7448_hpc2.c * mpc7448_hpc2.c
* *
* Board setup routines for the Freescale Taiga platform * Board setup routines for the Freescale mpc7448hpc2(taiga) platform
* *
* Author: Jacob Pan * Author: Jacob Pan
* jacob.pan@freescale.com * jacob.pan@freescale.com
@ -12,10 +12,10 @@
* *
* Copyright 2004-2006 Freescale Semiconductor, Inc. * Copyright 2004-2006 Freescale Semiconductor, Inc.
* *
* This file is licensed under * This program is free software; you can redistribute it and/or
* the terms of the GNU General Public License version 2. This program * modify it under the terms of the GNU General Public License
* is licensed "as is" without any warranty of any kind, whether express * as published by the Free Software Foundation; either version
* or implied. * 2 of the License, or (at your option) any later version.
*/ */
#include <linux/config.h> #include <linux/config.h>
@ -62,43 +62,8 @@ pci_dram_offset = MPC7448_HPC2_PCI_MEM_OFFSET;
extern int tsi108_setup_pci(struct device_node *dev); extern int tsi108_setup_pci(struct device_node *dev);
extern void _nmask_and_or_msr(unsigned long nmask, unsigned long or_val); extern void _nmask_and_or_msr(unsigned long nmask, unsigned long or_val);
extern void tsi108_pci_int_init(void); extern void tsi108_pci_int_init(void);
extern int tsi108_irq_cascade(struct pt_regs *regs, void *unused); extern void tsi108_irq_cascade(unsigned int irq, struct irq_desc *desc,
struct pt_regs *regs);
/*
* Define all of the IRQ senses and polarities. Taken from the
* mpc7448hpc manual.
* Note: Likely, this table and the following function should be
* obtained and derived from the OF Device Tree.
*/
static u_char mpc7448_hpc2_pic_initsenses[] __initdata = {
/* External on-board sources */
(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* INT[0] XINT0 from FPGA */
(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* INT[1] XINT1 from FPGA */
(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* INT[2] PHY_INT from both GIGE */
(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* INT[3] RESERVED */
/* Internal Tsi108/109 interrupt sources */
(IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* Reserved IRQ */
(IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* Reserved IRQ */
(IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* Reserved IRQ */
(IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* Reserved IRQ */
(IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* DMA0 */
(IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* DMA1 */
(IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* DMA2 */
(IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* DMA3 */
(IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* UART0 */
(IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* UART1 */
(IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* I2C */
(IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* GPIO */
(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* GIGE0 */
(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* GIGE1 */
(IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* Reserved IRQ */
(IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* HLP */
(IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* SDC */
(IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* Processor IF */
(IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* Reserved IRQ */
(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* PCI/X block */
};
int mpc7448_hpc2_exclude_device(u_char bus, u_char devfn) int mpc7448_hpc2_exclude_device(u_char bus, u_char devfn)
{ {
@ -229,6 +194,8 @@ static void __init mpc7448_hpc2_init_IRQ(void)
{ {
struct mpic *mpic; struct mpic *mpic;
phys_addr_t mpic_paddr = 0; phys_addr_t mpic_paddr = 0;
unsigned int cascade_pci_irq;
struct device_node *tsi_pci;
struct device_node *tsi_pic; struct device_node *tsi_pic;
tsi_pic = of_find_node_by_type(NULL, "open-pic"); tsi_pic = of_find_node_by_type(NULL, "open-pic");
@ -246,24 +213,31 @@ static void __init mpc7448_hpc2_init_IRQ(void)
DBG("%s: tsi108pic phys_addr = 0x%x\n", __FUNCTION__, DBG("%s: tsi108pic phys_addr = 0x%x\n", __FUNCTION__,
(u32) mpic_paddr); (u32) mpic_paddr);
mpic = mpic_alloc(mpic_paddr, mpic = mpic_alloc(tsi_pic, mpic_paddr,
MPIC_PRIMARY | MPIC_BIG_ENDIAN | MPIC_WANTS_RESET | MPIC_PRIMARY | MPIC_BIG_ENDIAN | MPIC_WANTS_RESET |
MPIC_SPV_EOI | MPIC_MOD_ID(MPIC_ID_TSI108), MPIC_SPV_EOI | MPIC_MOD_ID(MPIC_ID_TSI108),
0, /* num_sources used */ 0, /* num_sources used */
TSI108_IRQ_BASE,
0, /* num_sources used */ 0, /* num_sources used */
NR_IRQS - 4 /* XXXX */, "Tsi108_PIC");
mpc7448_hpc2_pic_initsenses,
sizeof(mpc7448_hpc2_pic_initsenses), "Tsi108_PIC");
BUG_ON(mpic == NULL); /* XXXX */ BUG_ON(mpic == NULL); /* XXXX */
mpic_init(mpic); mpic_init(mpic);
mpic_setup_cascade(IRQ_TSI108_PCI, tsi108_irq_cascade, mpic);
tsi_pci = of_find_node_by_type(NULL, "pci");
if (tsi_pci == 0) {
printk("%s: No tsi108 pci node found !\n", __FUNCTION__);
return;
}
cascade_pci_irq = irq_of_parse_and_map(tsi_pci, 0);
set_irq_data(cascade_pci_irq, mpic);
set_irq_chained_handler(cascade_pci_irq, tsi108_irq_cascade);
tsi108_pci_int_init(); tsi108_pci_int_init();
/* Configure MPIC outputs to CPU0 */ /* Configure MPIC outputs to CPU0 */
tsi108_write_reg(TSI108_MPIC_OFFSET + 0x30c, 0); tsi108_write_reg(TSI108_MPIC_OFFSET + 0x30c, 0);
of_node_put(tsi_pic);
} }
void mpc7448_hpc2_show_cpuinfo(struct seq_file *m) void mpc7448_hpc2_show_cpuinfo(struct seq_file *m)
@ -320,6 +294,7 @@ static int mpc7448_machine_check_exception(struct pt_regs *regs)
return 0; return 0;
} }
define_machine(mpc7448_hpc2){ define_machine(mpc7448_hpc2){
.name = "MPC7448 HPC2", .name = "MPC7448 HPC2",
.probe = mpc7448_hpc2_probe, .probe = mpc7448_hpc2_probe,

View File

@ -93,13 +93,15 @@ static int __init tsi108_eth_of_init(void)
goto err; goto err;
r[1].name = "tx"; r[1].name = "tx";
r[1].start = np->intrs[0].line; r[1].start = irq_of_parse_and_map(np, 0);
r[1].end = np->intrs[0].line; r[1].end = irq_of_parse_and_map(np, 0);
r[1].flags = IORESOURCE_IRQ; r[1].flags = IORESOURCE_IRQ;
DBG("%s: name:start->end = %s:0x%lx-> 0x%lx\n",
__FUNCTION__,r[1].name, r[1].start, r[1].end);
tsi_eth_dev = tsi_eth_dev =
platform_device_register_simple("tsi-ethernet", i, &r[0], platform_device_register_simple("tsi-ethernet", i, &r[0],
np->n_intrs + 1); 1);
if (IS_ERR(tsi_eth_dev)) { if (IS_ERR(tsi_eth_dev)) {
ret = PTR_ERR(tsi_eth_dev); ret = PTR_ERR(tsi_eth_dev);
@ -127,7 +129,7 @@ static int __init tsi108_eth_of_init(void)
tsi_eth_data.regs = r[0].start; tsi_eth_data.regs = r[0].start;
tsi_eth_data.phyregs = res.start; tsi_eth_data.phyregs = res.start;
tsi_eth_data.phy = *phy_id; tsi_eth_data.phy = *phy_id;
tsi_eth_data.irq_num = np->intrs[0].line; tsi_eth_data.irq_num = irq_of_parse_and_map(np, 0);
of_node_put(phy); of_node_put(phy);
ret = ret =
platform_device_add_data(tsi_eth_dev, &tsi_eth_data, platform_device_add_data(tsi_eth_dev, &tsi_eth_data,

View File

@ -26,7 +26,6 @@
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <asm/byteorder.h> #include <asm/byteorder.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/irq.h> #include <asm/irq.h>
@ -228,7 +227,7 @@ int __init tsi108_setup_pci(struct device_node *dev)
(hose)->ops = &tsi108_direct_pci_ops; (hose)->ops = &tsi108_direct_pci_ops;
printk(KERN_INFO "Found tsi108 PCI host bridge at 0x%08lx. " printk(KERN_INFO "Found tsi108 PCI host bridge at 0x%08x. "
"Firmware bus number: %d->%d\n", "Firmware bus number: %d->%d\n",
rsrc.start, hose->first_busno, hose->last_busno); rsrc.start, hose->first_busno, hose->last_busno);
@ -278,7 +277,7 @@ static void init_pci_source(void)
mb(); mb();
} }
static inline int get_pci_source(void) static inline unsigned int get_pci_source(void)
{ {
u_int temp = 0; u_int temp = 0;
int irq = -1; int irq = -1;
@ -371,12 +370,12 @@ static void tsi108_pci_irq_end(u_int irq)
* Interrupt controller descriptor for cascaded PCI interrupt controller. * Interrupt controller descriptor for cascaded PCI interrupt controller.
*/ */
struct hw_interrupt_type tsi108_pci_irq = { static struct irq_chip tsi108_pci_irq = {
.typename = "tsi108_PCI_int", .typename = "tsi108_PCI_int",
.enable = tsi108_pci_irq_enable, .mask = tsi108_pci_irq_disable,
.disable = tsi108_pci_irq_disable,
.ack = tsi108_pci_irq_ack, .ack = tsi108_pci_irq_ack,
.end = tsi108_pci_irq_end, .end = tsi108_pci_irq_end,
.unmask = tsi108_pci_irq_enable,
}; };
/* /*
@ -399,14 +398,18 @@ void __init tsi108_pci_int_init(void)
DBG("Tsi108_pci_int_init: initializing PCI interrupts\n"); DBG("Tsi108_pci_int_init: initializing PCI interrupts\n");
for (i = 0; i < NUM_PCI_IRQS; i++) { for (i = 0; i < NUM_PCI_IRQS; i++) {
irq_desc[i + IRQ_PCI_INTAD_BASE].handler = &tsi108_pci_irq; irq_desc[i + IRQ_PCI_INTAD_BASE].chip = &tsi108_pci_irq;
irq_desc[i + IRQ_PCI_INTAD_BASE].status |= IRQ_LEVEL; irq_desc[i + IRQ_PCI_INTAD_BASE].status |= IRQ_LEVEL;
} }
init_pci_source(); init_pci_source();
} }
int tsi108_irq_cascade(struct pt_regs *regs, void *unused) void tsi108_irq_cascade(unsigned int irq, struct irq_desc *desc,
struct pt_regs *regs)
{ {
return get_pci_source(); unsigned int cascade_irq = get_pci_source();
if (cascade_irq != NO_IRQ)
generic_handle_irq(cascade_irq, regs);
desc->chip->eoi(irq);
} }

View File

@ -1,16 +1,18 @@
/* /*
* include/asm-ppc/tsi108.h
*
* common routine and memory layout for Tundra TSI108(Grendel) host bridge * common routine and memory layout for Tundra TSI108(Grendel) host bridge
* memory controller. * memory controller.
* *
* Author: Jacob Pan (jacob.pan@freescale.com) * Author: Jacob Pan (jacob.pan@freescale.com)
* Alex Bounine (alexandreb@tundra.com) * Alex Bounine (alexandreb@tundra.com)
* 2004 (c) Freescale Semiconductor Inc. This file is licensed under *
* the terms of the GNU General Public License version 2. This program * Copyright 2004-2006 Freescale Semiconductor, Inc.
* is licensed "as is" without any warranty of any kind, whether express *
* or implied. * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/ */
#ifndef __PPC_KERNEL_TSI108_H #ifndef __PPC_KERNEL_TSI108_H
#define __PPC_KERNEL_TSI108_H #define __PPC_KERNEL_TSI108_H

View File

@ -0,0 +1,124 @@
/*
* (C) Copyright 2005 Tundra Semiconductor Corp.
* Alex Bounine, <alexandreb at tundra.com).
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that 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
*/
/*
* definitions for interrupt controller initialization and external interrupt
* demultiplexing on TSI108EMU/SVB boards.
*/
#ifndef _ASM_PPC_TSI108_IRQ_H
#define _ASM_PPC_TSI108_IRQ_H
/*
* Tsi108 interrupts
*/
#ifndef TSI108_IRQ_REG_BASE
#define TSI108_IRQ_REG_BASE 0
#endif
#define TSI108_IRQ(x) (TSI108_IRQ_REG_BASE + (x))
#define TSI108_MAX_VECTORS (36 + 4) /* 36 sources + PCI INT demux */
#define MAX_TASK_PRIO 0xF
#define TSI108_IRQ_SPURIOUS (TSI108_MAX_VECTORS)
#define DEFAULT_PRIO_LVL 10 /* initial priority level */
/* Interrupt vectors assignment to external and internal
* sources of requests. */
/* EXTERNAL INTERRUPT SOURCES */
#define IRQ_TSI108_EXT_INT0 TSI108_IRQ(0) /* External Source at INT[0] */
#define IRQ_TSI108_EXT_INT1 TSI108_IRQ(1) /* External Source at INT[1] */
#define IRQ_TSI108_EXT_INT2 TSI108_IRQ(2) /* External Source at INT[2] */
#define IRQ_TSI108_EXT_INT3 TSI108_IRQ(3) /* External Source at INT[3] */
/* INTERNAL INTERRUPT SOURCES */
#define IRQ_TSI108_RESERVED0 TSI108_IRQ(4) /* Reserved IRQ */
#define IRQ_TSI108_RESERVED1 TSI108_IRQ(5) /* Reserved IRQ */
#define IRQ_TSI108_RESERVED2 TSI108_IRQ(6) /* Reserved IRQ */
#define IRQ_TSI108_RESERVED3 TSI108_IRQ(7) /* Reserved IRQ */
#define IRQ_TSI108_DMA0 TSI108_IRQ(8) /* DMA0 */
#define IRQ_TSI108_DMA1 TSI108_IRQ(9) /* DMA1 */
#define IRQ_TSI108_DMA2 TSI108_IRQ(10) /* DMA2 */
#define IRQ_TSI108_DMA3 TSI108_IRQ(11) /* DMA3 */
#define IRQ_TSI108_UART0 TSI108_IRQ(12) /* UART0 */
#define IRQ_TSI108_UART1 TSI108_IRQ(13) /* UART1 */
#define IRQ_TSI108_I2C TSI108_IRQ(14) /* I2C */
#define IRQ_TSI108_GPIO TSI108_IRQ(15) /* GPIO */
#define IRQ_TSI108_GIGE0 TSI108_IRQ(16) /* GIGE0 */
#define IRQ_TSI108_GIGE1 TSI108_IRQ(17) /* GIGE1 */
#define IRQ_TSI108_RESERVED4 TSI108_IRQ(18) /* Reserved IRQ */
#define IRQ_TSI108_HLP TSI108_IRQ(19) /* HLP */
#define IRQ_TSI108_SDRAM TSI108_IRQ(20) /* SDC */
#define IRQ_TSI108_PROC_IF TSI108_IRQ(21) /* Processor IF */
#define IRQ_TSI108_RESERVED5 TSI108_IRQ(22) /* Reserved IRQ */
#define IRQ_TSI108_PCI TSI108_IRQ(23) /* PCI/X block */
#define IRQ_TSI108_MBOX0 TSI108_IRQ(24) /* Mailbox 0 register */
#define IRQ_TSI108_MBOX1 TSI108_IRQ(25) /* Mailbox 1 register */
#define IRQ_TSI108_MBOX2 TSI108_IRQ(26) /* Mailbox 2 register */
#define IRQ_TSI108_MBOX3 TSI108_IRQ(27) /* Mailbox 3 register */
#define IRQ_TSI108_DBELL0 TSI108_IRQ(28) /* Doorbell 0 */
#define IRQ_TSI108_DBELL1 TSI108_IRQ(29) /* Doorbell 1 */
#define IRQ_TSI108_DBELL2 TSI108_IRQ(30) /* Doorbell 2 */
#define IRQ_TSI108_DBELL3 TSI108_IRQ(31) /* Doorbell 3 */
#define IRQ_TSI108_TIMER0 TSI108_IRQ(32) /* Global Timer 0 */
#define IRQ_TSI108_TIMER1 TSI108_IRQ(33) /* Global Timer 1 */
#define IRQ_TSI108_TIMER2 TSI108_IRQ(34) /* Global Timer 2 */
#define IRQ_TSI108_TIMER3 TSI108_IRQ(35) /* Global Timer 3 */
/*
* PCI bus INTA# - INTD# lines demultiplexor
*/
#define IRQ_PCI_INTAD_BASE TSI108_IRQ(36)
#define IRQ_PCI_INTA (IRQ_PCI_INTAD_BASE + 0)
#define IRQ_PCI_INTB (IRQ_PCI_INTAD_BASE + 1)
#define IRQ_PCI_INTC (IRQ_PCI_INTAD_BASE + 2)
#define IRQ_PCI_INTD (IRQ_PCI_INTAD_BASE + 3)
#define NUM_PCI_IRQS (4)
/* number of entries in vector dispatch table */
#define IRQ_TSI108_TAB_SIZE (TSI108_MAX_VECTORS + 1)
/* Mapping of MPIC outputs to processors' interrupt pins */
#define IDIR_INT_OUT0 0x1
#define IDIR_INT_OUT1 0x2
#define IDIR_INT_OUT2 0x4
#define IDIR_INT_OUT3 0x8
/*---------------------------------------------------------------
* IRQ line configuration parameters */
/* Interrupt delivery modes */
typedef enum {
TSI108_IRQ_DIRECTED,
TSI108_IRQ_DISTRIBUTED,
} TSI108_IRQ_MODE;
#endif /* _ASM_PPC_TSI108_IRQ_H */