* git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc: powerpc: add defconfig for Freescale MPC8349E-mITX board powerpc: Add base support for the Freescale MPC8349E-mITX eval board Documentation: correct values in MPC8548E SEC example node [POWERPC] Actually copy over i8259.c to arch/ppc/syslib this time [POWERPC] Add new interrupt mapping core and change platforms to use it [POWERPC] Copy i8259 code back to arch/ppc [POWERPC] New device-tree interrupt parsing code [POWERPC] Use the genirq framework [PATCH] genirq: Allow fasteoi handler to retrigger disabled interrupts [POWERPC] Update the SWIM3 (powermac) floppy driver [POWERPC] Fix error handling in detecting legacy serial ports [POWERPC] Fix booting on Momentum "Apache" board (a Maple derivative) [POWERPC] Fix various offb and BootX-related issues [POWERPC] Add a default config for 32-bit CHRP machines [POWERPC] fix implicit declaration on cell. [POWERPC] change get_property to return void *tirimbino
commit
912b2539e1
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,156 @@ |
||||
/*
|
||||
* arch/powerpc/platforms/83xx/mpc834x_itx.c |
||||
* |
||||
* MPC834x ITX board specific routines |
||||
* |
||||
* Maintainer: Kumar Gala <galak@kernel.crashing.org> |
||||
* |
||||
* 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. |
||||
*/ |
||||
|
||||
#include <linux/config.h> |
||||
#include <linux/stddef.h> |
||||
#include <linux/kernel.h> |
||||
#include <linux/init.h> |
||||
#include <linux/errno.h> |
||||
#include <linux/reboot.h> |
||||
#include <linux/pci.h> |
||||
#include <linux/kdev_t.h> |
||||
#include <linux/major.h> |
||||
#include <linux/console.h> |
||||
#include <linux/delay.h> |
||||
#include <linux/seq_file.h> |
||||
#include <linux/root_dev.h> |
||||
|
||||
#include <asm/system.h> |
||||
#include <asm/atomic.h> |
||||
#include <asm/time.h> |
||||
#include <asm/io.h> |
||||
#include <asm/machdep.h> |
||||
#include <asm/ipic.h> |
||||
#include <asm/bootinfo.h> |
||||
#include <asm/irq.h> |
||||
#include <asm/prom.h> |
||||
#include <asm/udbg.h> |
||||
#include <sysdev/fsl_soc.h> |
||||
|
||||
#include "mpc83xx.h" |
||||
|
||||
#include <platforms/83xx/mpc834x_sys.h> |
||||
|
||||
#ifndef CONFIG_PCI |
||||
unsigned long isa_io_base = 0; |
||||
unsigned long isa_mem_base = 0; |
||||
#endif |
||||
|
||||
#ifdef CONFIG_PCI |
||||
static int |
||||
mpc83xx_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) |
||||
{ |
||||
static char pci_irq_table[][4] = |
||||
/*
|
||||
* PCI IDSEL/INTPIN->INTLINE |
||||
* A B C D |
||||
*/ |
||||
{ |
||||
{PIRQB, PIRQC, PIRQD, PIRQA}, /* idsel 0x0e */ |
||||
{PIRQA, PIRQB, PIRQC, PIRQD}, /* idsel 0x0f */ |
||||
{PIRQC, PIRQD, PIRQA, PIRQB}, /* idsel 0x10 */ |
||||
}; |
||||
|
||||
const long min_idsel = 0x0e, max_idsel = 0x10, irqs_per_slot = 4; |
||||
return PCI_IRQ_TABLE_LOOKUP; |
||||
} |
||||
#endif /* CONFIG_PCI */ |
||||
|
||||
/* ************************************************************************
|
||||
* |
||||
* Setup the architecture |
||||
* |
||||
*/ |
||||
static void __init mpc834x_itx_setup_arch(void) |
||||
{ |
||||
struct device_node *np; |
||||
|
||||
if (ppc_md.progress) |
||||
ppc_md.progress("mpc834x_itx_setup_arch()", 0); |
||||
|
||||
np = of_find_node_by_type(NULL, "cpu"); |
||||
if (np != 0) { |
||||
unsigned int *fp = |
||||
(int *)get_property(np, "clock-frequency", NULL); |
||||
if (fp != 0) |
||||
loops_per_jiffy = *fp / HZ; |
||||
else |
||||
loops_per_jiffy = 50000000 / HZ; |
||||
of_node_put(np); |
||||
} |
||||
#ifdef CONFIG_PCI |
||||
for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) |
||||
add_bridge(np); |
||||
|
||||
ppc_md.pci_swizzle = common_swizzle; |
||||
ppc_md.pci_map_irq = mpc83xx_map_irq; |
||||
ppc_md.pci_exclude_device = mpc83xx_exclude_device; |
||||
#endif |
||||
|
||||
#ifdef CONFIG_ROOT_NFS |
||||
ROOT_DEV = Root_NFS; |
||||
#else |
||||
ROOT_DEV = Root_HDA1; |
||||
#endif |
||||
} |
||||
|
||||
void __init mpc834x_itx_init_IRQ(void) |
||||
{ |
||||
u8 senses[8] = { |
||||
0, /* EXT 0 */ |
||||
IRQ_SENSE_LEVEL, /* EXT 1 */ |
||||
IRQ_SENSE_LEVEL, /* EXT 2 */ |
||||
0, /* EXT 3 */ |
||||
#ifdef CONFIG_PCI |
||||
IRQ_SENSE_LEVEL, /* EXT 4 */ |
||||
IRQ_SENSE_LEVEL, /* EXT 5 */ |
||||
IRQ_SENSE_LEVEL, /* EXT 6 */ |
||||
IRQ_SENSE_LEVEL, /* EXT 7 */ |
||||
#else |
||||
0, /* EXT 4 */ |
||||
0, /* EXT 5 */ |
||||
0, /* EXT 6 */ |
||||
0, /* EXT 7 */ |
||||
#endif |
||||
}; |
||||
|
||||
ipic_init(get_immrbase() + 0x00700, 0, 0, senses, 8); |
||||
|
||||
/* Initialize the default interrupt mapping priorities,
|
||||
* in case the boot rom changed something on us. |
||||
*/ |
||||
ipic_set_default_priority(); |
||||
} |
||||
|
||||
/*
|
||||
* Called very early, MMU is off, device-tree isn't unflattened |
||||
*/ |
||||
static int __init mpc834x_itx_probe(void) |
||||
{ |
||||
/* We always match for now, eventually we should look at the flat
|
||||
dev tree to ensure this is the board we are suppose to run on |
||||
*/ |
||||
return 1; |
||||
} |
||||
|
||||
define_machine(mpc834x_itx) { |
||||
.name = "MPC834x ITX", |
||||
.probe = mpc834x_itx_probe, |
||||
.setup_arch = mpc834x_itx_setup_arch, |
||||
.init_IRQ = mpc834x_itx_init_IRQ, |
||||
.get_irq = ipic_get_irq, |
||||
.restart = mpc83xx_restart, |
||||
.time_init = mpc83xx_time_init, |
||||
.calibrate_decr = generic_calibrate_decr, |
||||
.progress = udbg_progress, |
||||
}; |
@ -0,0 +1,23 @@ |
||||
/*
|
||||
* arch/powerpc/platforms/83xx/mpc834x_itx.h |
||||
* |
||||
* MPC834X ITX common board definitions |
||||
* |
||||
* Maintainer: Kumar Gala <galak@kernel.crashing.org> |
||||
* |
||||
* 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 __MACH_MPC83XX_ITX_H__ |
||||
#define __MACH_MPC83XX_ITX_H__ |
||||
|
||||
#define PIRQA MPC83xx_IRQ_EXT4 |
||||
#define PIRQB MPC83xx_IRQ_EXT5 |
||||
#define PIRQC MPC83xx_IRQ_EXT6 |
||||
#define PIRQD MPC83xx_IRQ_EXT7 |
||||
|
||||
#endif /* __MACH_MPC83XX_ITX_H__ */ |
@ -0,0 +1,212 @@ |
||||
/*
|
||||
* i8259 interrupt controller driver. |
||||
* |
||||
* 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. |
||||
*/ |
||||
#include <linux/init.h> |
||||
#include <linux/ioport.h> |
||||
#include <linux/interrupt.h> |
||||
#include <asm/io.h> |
||||
#include <asm/i8259.h> |
||||
|
||||
static volatile void __iomem *pci_intack; /* RO, gives us the irq vector */ |
||||
|
||||
static unsigned char cached_8259[2] = { 0xff, 0xff }; |
||||
#define cached_A1 (cached_8259[0]) |
||||
#define cached_21 (cached_8259[1]) |
||||
|
||||
static DEFINE_SPINLOCK(i8259_lock); |
||||
|
||||
static int i8259_pic_irq_offset; |
||||
|
||||
/*
|
||||
* Acknowledge the IRQ using either the PCI host bridge's interrupt |
||||
* acknowledge feature or poll. How i8259_init() is called determines |
||||
* which is called. It should be noted that polling is broken on some |
||||
* IBM and Motorola PReP boxes so we must use the int-ack feature on them. |
||||
*/ |
||||
int i8259_irq(struct pt_regs *regs) |
||||
{ |
||||
int irq; |
||||
|
||||
spin_lock(&i8259_lock); |
||||
|
||||
/* Either int-ack or poll for the IRQ */ |
||||
if (pci_intack) |
||||
irq = readb(pci_intack); |
||||
else { |
||||
/* Perform an interrupt acknowledge cycle on controller 1. */ |
||||
outb(0x0C, 0x20); /* prepare for poll */ |
||||
irq = inb(0x20) & 7; |
||||
if (irq == 2 ) { |
||||
/*
|
||||
* Interrupt is cascaded so perform interrupt |
||||
* acknowledge on controller 2. |
||||
*/ |
||||
outb(0x0C, 0xA0); /* prepare for poll */ |
||||
irq = (inb(0xA0) & 7) + 8; |
||||
} |
||||
} |
||||
|
||||
if (irq == 7) { |
||||
/*
|
||||
* This may be a spurious interrupt. |
||||
* |
||||
* Read the interrupt status register (ISR). If the most |
||||
* significant bit is not set then there is no valid |
||||
* interrupt. |
||||
*/ |
||||
if (!pci_intack) |
||||
outb(0x0B, 0x20); /* ISR register */ |
||||
if(~inb(0x20) & 0x80) |
||||
irq = -1; |
||||
} |
||||
|
||||
spin_unlock(&i8259_lock); |
||||
return irq + i8259_pic_irq_offset; |
||||
} |
||||
|
||||
static void i8259_mask_and_ack_irq(unsigned int irq_nr) |
||||
{ |
||||
unsigned long flags; |
||||
|
||||
spin_lock_irqsave(&i8259_lock, flags); |
||||
irq_nr -= i8259_pic_irq_offset; |
||||
if (irq_nr > 7) { |
||||
cached_A1 |= 1 << (irq_nr-8); |
||||
inb(0xA1); /* DUMMY */ |
||||
outb(cached_A1, 0xA1); |
||||
outb(0x20, 0xA0); /* Non-specific EOI */ |
||||
outb(0x20, 0x20); /* Non-specific EOI to cascade */ |
||||
} else { |
||||
cached_21 |= 1 << irq_nr; |
||||
inb(0x21); /* DUMMY */ |
||||
outb(cached_21, 0x21); |
||||
outb(0x20, 0x20); /* Non-specific EOI */ |
||||
} |
||||
spin_unlock_irqrestore(&i8259_lock, flags); |
||||
} |
||||
|
||||
static void i8259_set_irq_mask(int irq_nr) |
||||
{ |
||||
outb(cached_A1,0xA1); |
||||
outb(cached_21,0x21); |
||||
} |
||||
|
||||
static void i8259_mask_irq(unsigned int irq_nr) |
||||
{ |
||||
unsigned long flags; |
||||
|
||||
spin_lock_irqsave(&i8259_lock, flags); |
||||
irq_nr -= i8259_pic_irq_offset; |
||||
if (irq_nr < 8) |
||||
cached_21 |= 1 << irq_nr; |
||||
else |
||||
cached_A1 |= 1 << (irq_nr-8); |
||||
i8259_set_irq_mask(irq_nr); |
||||
spin_unlock_irqrestore(&i8259_lock, flags); |
||||
} |
||||
|
||||
static void i8259_unmask_irq(unsigned int irq_nr) |
||||
{ |
||||
unsigned long flags; |
||||
|
||||
spin_lock_irqsave(&i8259_lock, flags); |
||||
irq_nr -= i8259_pic_irq_offset; |
||||
if (irq_nr < 8) |
||||
cached_21 &= ~(1 << irq_nr); |
||||
else |
||||
cached_A1 &= ~(1 << (irq_nr-8)); |
||||
i8259_set_irq_mask(irq_nr); |
||||
spin_unlock_irqrestore(&i8259_lock, flags); |
||||
} |
||||
|
||||
static struct irq_chip i8259_pic = { |
||||
.typename = " i8259 ", |
||||
.mask = i8259_mask_irq, |
||||
.unmask = i8259_unmask_irq, |
||||
.mask_ack = i8259_mask_and_ack_irq, |
||||
}; |
||||
|
||||
static struct resource pic1_iores = { |
||||
.name = "8259 (master)", |
||||
.start = 0x20, |
||||
.end = 0x21, |
||||
.flags = IORESOURCE_BUSY, |
||||
}; |
||||
|
||||
static struct resource pic2_iores = { |
||||
.name = "8259 (slave)", |
||||
.start = 0xa0, |
||||
.end = 0xa1, |
||||
.flags = IORESOURCE_BUSY, |
||||
}; |
||||
|
||||
static struct resource pic_edgectrl_iores = { |
||||
.name = "8259 edge control", |
||||
.start = 0x4d0, |
||||
.end = 0x4d1, |
||||
.flags = IORESOURCE_BUSY, |
||||
}; |
||||
|
||||
static struct irqaction i8259_irqaction = { |
||||
.handler = no_action, |
||||
.flags = SA_INTERRUPT, |
||||
.mask = CPU_MASK_NONE, |
||||
.name = "82c59 secondary cascade", |
||||
}; |
||||
|
||||
/*
|
||||
* i8259_init() |
||||
* intack_addr - PCI interrupt acknowledge (real) address which will return |
||||
* the active irq from the 8259 |
||||
*/ |
||||
void __init i8259_init(unsigned long intack_addr, int offset) |
||||
{ |
||||
unsigned long flags; |
||||
int i; |
||||
|
||||
spin_lock_irqsave(&i8259_lock, flags); |
||||
i8259_pic_irq_offset = offset; |
||||
|
||||
/* init master interrupt controller */ |
||||
outb(0x11, 0x20); /* Start init sequence */ |
||||
outb(0x00, 0x21); /* Vector base */ |
||||
outb(0x04, 0x21); /* edge tiggered, Cascade (slave) on IRQ2 */ |
||||
outb(0x01, 0x21); /* Select 8086 mode */ |
||||
|
||||
/* init slave interrupt controller */ |
||||
outb(0x11, 0xA0); /* Start init sequence */ |
||||
outb(0x08, 0xA1); /* Vector base */ |
||||
outb(0x02, 0xA1); /* edge triggered, Cascade (slave) on IRQ2 */ |
||||
outb(0x01, 0xA1); /* Select 8086 mode */ |
||||
|
||||
/* always read ISR */ |
||||
outb(0x0B, 0x20); |
||||
outb(0x0B, 0xA0); |
||||
|
||||
/* Mask all interrupts */ |
||||
outb(cached_A1, 0xA1); |
||||
outb(cached_21, 0x21); |
||||
|
||||
spin_unlock_irqrestore(&i8259_lock, flags); |
||||
|
||||
for (i = 0; i < NUM_ISA_INTERRUPTS; ++i) { |
||||
set_irq_chip_and_handler(offset + i, &i8259_pic, |
||||
handle_level_irq); |
||||
irq_desc[offset + i].status |= IRQ_LEVEL; |
||||
} |
||||
|
||||
/* reserve our resources */ |
||||
setup_irq(offset + 2, &i8259_irqaction); |
||||
request_resource(&ioport_resource, &pic1_iores); |
||||
request_resource(&ioport_resource, &pic2_iores); |
||||
request_resource(&ioport_resource, &pic_edgectrl_iores); |
||||
|
||||
if (intack_addr != 0) |
||||
pci_intack = ioremap(intack_addr, 1); |
||||
|
||||
} |
Loading…
Reference in new issue