Commit dd243518 authored by Pete Zaitcev's avatar Pete Zaitcev Committed by David S. Miller

[SPARC]: Eric Browers sbus interrupts decoders.

parent 8b6975d3
......@@ -34,6 +34,7 @@
#include <asm/sun4paddr.h>
#include <asm/idprom.h>
#include <asm/machines.h>
#include <asm/sbus.h>
#if 0
static struct resource sun4c_timer_eb = { "sun4c_timer" };
......@@ -51,6 +52,17 @@ static struct resource sun4c_intr_eb = { "sun4c_intr" };
*/
unsigned char *interrupt_enable = 0;
static int sun4c_pil_map[] = { 0, 1, 2, 3, 5, 7, 8, 9 };
unsigned int sun4c_sbint_to_irq(struct sbus_dev *sdev, unsigned int sbint)
{
if (sbint >= sizeof(sun4c_pil_map)) {
printk(KERN_ERR "%s: bogus SBINT %d\n", sdev->prom_name, sbint);
BUG();
}
return sun4c_pil_map[sbint];
}
static void sun4c_disable_irq(unsigned int irq_nr)
{
unsigned long flags;
......@@ -213,6 +225,7 @@ void __init sun4c_init_IRQ(void)
int_regs[0].reg_size, "sun4c_intr");
}
BTFIXUPSET_CALL(sbint_to_irq, sun4c_sbint_to_irq, BTFIXUPCALL_NORM);
BTFIXUPSET_CALL(enable_irq, sun4c_enable_irq, BTFIXUPCALL_NORM);
BTFIXUPSET_CALL(disable_irq, sun4c_disable_irq, BTFIXUPCALL_NORM);
BTFIXUPSET_CALL(enable_pil_irq, sun4c_enable_irq, BTFIXUPCALL_NORM);
......
......@@ -252,6 +252,15 @@ unsigned int sun4d_build_irq(struct sbus_dev *sdev, int irq)
return irq;
}
unsigned int sun4d_sbint_to_irq(struct sbus_dev *sdev, unsigned int sbint)
{
if (sbint >= sizeof(sbus_to_pil)) {
printk(KERN_ERR "%s: bogus SBINT %d\n", sdev->prom_name, sbint);
BUG();
}
return sun4d_build_irq(sdev, sbus_to_pil[sbint]);
}
int sun4d_request_irq(unsigned int irq,
void (*handler)(int, void *, struct pt_regs *),
unsigned long irqflags, const char * devname, void *dev_id)
......@@ -541,6 +550,7 @@ void __init sun4d_init_IRQ(void)
{
local_irq_disable();
BTFIXUPSET_CALL(sbint_to_irq, sun4d_sbint_to_irq, BTFIXUPCALL_NORM);
BTFIXUPSET_CALL(enable_irq, sun4d_enable_irq, BTFIXUPCALL_NORM);
BTFIXUPSET_CALL(disable_irq, sun4d_disable_irq, BTFIXUPCALL_NORM);
BTFIXUPSET_CALL(clear_clock_irq, sun4d_clear_clock_irq, BTFIXUPCALL_NORM);
......
......@@ -36,6 +36,7 @@
#include <asm/smp.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/sbus.h>
static unsigned long dummy;
......@@ -77,6 +78,17 @@ static unsigned long irq_mask[] = {
SUN4M_INT_SBUS(6) /* 14 irq 13 */
};
static int sun4m_pil_map[] = { 0, 2, 3, 5, 7, 9, 11, 13 };
unsigned int sun4m_sbint_to_irq(struct sbus_dev *sdev, unsigned int sbint)
{
if (sbint >= sizeof(sun4m_pil_map)) {
printk(KERN_ERR "%s: bogus SBINT %d\n", sdev->prom_name, sbint);
BUG();
}
return sun4m_pil_map[sbint] | 0x30;
}
inline unsigned long sun4m_get_irqmask(unsigned int irq)
{
unsigned long mask;
......@@ -366,6 +378,7 @@ void __init sun4m_init_IRQ(void)
&sun4m_interrupts->undirected_target;
sun4m_interrupts->undirected_target = 0;
}
BTFIXUPSET_CALL(sbint_to_irq, sun4m_sbint_to_irq, BTFIXUPCALL_NORM);
BTFIXUPSET_CALL(enable_irq, sun4m_enable_irq, BTFIXUPCALL_NORM);
BTFIXUPSET_CALL(disable_irq, sun4m_disable_irq, BTFIXUPCALL_NORM);
BTFIXUPSET_CALL(enable_pil_irq, sun4m_enable_pil_irq, BTFIXUPCALL_NORM);
......
......@@ -20,6 +20,7 @@
struct sbus_bus *sbus_root = NULL;
static struct linux_prom_irqs irqs[PROMINTR_MAX] __initdata = { { 0 } };
static int interrupts[PROMINTR_MAX] __initdata = { 0 };
#ifdef CONFIG_PCI
extern int pcic_present(void);
......@@ -126,20 +127,37 @@ static void __init fill_sbus_device(int prom_node, struct sbus_dev *sdev)
#else
len = prom_getproperty(prom_node, "intr",
(char *)irqs, sizeof(irqs));
if (len == -1)
len = 0;
sdev->num_irqs = len / 8;
if (sdev->num_irqs == 0) {
sdev->irqs[0] = 0;
} else if (sparc_cpu_model == sun4d) {
extern unsigned int sun4d_build_irq(struct sbus_dev *sdev, int irq);
for (len = 0; len < sdev->num_irqs; len++)
sdev->irqs[len] = sun4d_build_irq(sdev, irqs[len].pri);
if (len != -1) {
sdev->num_irqs = len / 8;
if (sdev->num_irqs == 0) {
sdev->irqs[0] = 0;
} else if (sparc_cpu_model == sun4d) {
extern unsigned int sun4d_build_irq(struct sbus_dev *sdev, int irq);
for (len = 0; len < sdev->num_irqs; len++)
sdev->irqs[len] = sun4d_build_irq(sdev, irqs[len].pri);
} else {
for (len = 0; len < sdev->num_irqs; len++)
sdev->irqs[len] = irqs[len].pri;
}
} else {
for (len = 0; len < sdev->num_irqs; len++)
sdev->irqs[len] = irqs[len].pri;
}
/* No "intr" node found-- check for "interrupts" node.
* This node contains SBus interrupt levels, not IPLs
* as in "intr", and no vector values. We convert
* SBus interrupt levels to PILs (platform specific).
*/
len = prom_getproperty(prom_node, "interrupts",
(char *)interrupts, sizeof(interrupts));
if (len == -1) {
sdev->irqs[0] = 0;
sdev->num_irqs = 0;
} else {
sdev->num_irqs = len / sizeof(int);
for (len = 0; len < sdev->num_irqs; len++) {
sdev->irqs[len] = sbint_to_irq(sdev, interrupts[len]);
}
}
}
#endif /* !__sparc_v9__ */
}
......
......@@ -121,4 +121,15 @@ extern void sbus_unmap_sg(struct sbus_dev *, struct scatterlist *, int, int);
extern void sbus_dma_sync_single(struct sbus_dev *, dma_addr_t, size_t, int);
extern void sbus_dma_sync_sg(struct sbus_dev *, struct scatterlist *, int, int);
/* Eric Brower (ebrower@usa.net)
* Translate SBus interrupt levels to ino values--
* this is used when converting sbus "interrupts" OBP
* node values to "intr" node values, and is platform
* dependent. If only we could call OBP with
* "sbus-intr>cpu (sbint -- ino)" from kernel...
* See .../drivers/sbus/sbus.c for details.
*/
BTFIXUPDEF_CALL(unsigned int, sbint_to_irq, struct sbus_dev *sdev, unsigned int)
#define sbint_to_irq(sdev, sbint) BTFIXUP_CALL(sbint_to_irq)(sdev, sbint)
#endif /* !(_SPARC_SBUS_H) */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment