Commit 57848f98 authored by David S. Miller's avatar David S. Miller

Init FHC controller registers earlier so that

Zilog interrupt mappings are not clobbered on
Sun Enterprise servers.
Fix some FHC register offsets.
Sometimes IPIs can allow BHs to run with interrupts
disabled, fix that by rescheduling them to normal
PIL based interrupts.
parent 50f253e8
...@@ -247,6 +247,55 @@ static void probe_clock_board(struct linux_central *central, ...@@ -247,6 +247,55 @@ static void probe_clock_board(struct linux_central *central,
(central->clkver ? upa_readb(central->clkver) : 0x00)); (central->clkver ? upa_readb(central->clkver) : 0x00));
} }
static void init_all_fhc_hw(void)
{
struct linux_fhc *fhc;
for(fhc = fhc_list; fhc != NULL; fhc = fhc->next) {
u32 tmp;
/* Clear all of the interrupt mapping registers
* just in case OBP left them in a foul state.
*/
#define ZAP(ICLR, IMAP) \
do { u32 imap_tmp; \
upa_writel(0, (ICLR)); \
upa_readl(ICLR); \
imap_tmp = upa_readl(IMAP); \
imap_tmp &= ~(0x80000000); \
upa_writel(imap_tmp, (IMAP)); \
upa_readl(IMAP); \
} while (0)
ZAP(fhc->fhc_regs.ffregs + FHC_FFREGS_ICLR,
fhc->fhc_regs.ffregs + FHC_FFREGS_IMAP);
ZAP(fhc->fhc_regs.sregs + FHC_SREGS_ICLR,
fhc->fhc_regs.sregs + FHC_SREGS_IMAP);
ZAP(fhc->fhc_regs.uregs + FHC_UREGS_ICLR,
fhc->fhc_regs.uregs + FHC_UREGS_IMAP);
ZAP(fhc->fhc_regs.tregs + FHC_TREGS_ICLR,
fhc->fhc_regs.tregs + FHC_TREGS_IMAP);
#undef ZAP
/* Setup FHC control register. */
tmp = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_CTRL);
/* All non-central boards have this bit set. */
if(! IS_CENTRAL_FHC(fhc))
tmp |= FHC_CONTROL_IXIST;
/* For all FHCs, clear the firmware synchronization
* line and both low power mode enables.
*/
tmp &= ~(FHC_CONTROL_AOFF | FHC_CONTROL_BOFF | FHC_CONTROL_SLINE);
upa_writel(tmp, fhc->fhc_regs.pregs + FHC_PREGS_CTRL);
upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_CTRL);
}
}
void central_probe(void) void central_probe(void)
{ {
struct linux_prom_registers fpregs[6]; struct linux_prom_registers fpregs[6];
...@@ -341,6 +390,8 @@ void central_probe(void) ...@@ -341,6 +390,8 @@ void central_probe(void)
((err & FHC_ID_MANUF) >> 1)); ((err & FHC_ID_MANUF) >> 1));
probe_other_fhcs(); probe_other_fhcs();
init_all_fhc_hw();
} }
static __inline__ void fhc_ledblink(struct linux_fhc *fhc, int on) static __inline__ void fhc_ledblink(struct linux_fhc *fhc, int on)
...@@ -398,56 +449,12 @@ static void sunfire_timer(unsigned long __ignored) ...@@ -398,56 +449,12 @@ static void sunfire_timer(unsigned long __ignored)
void firetruck_init(void) void firetruck_init(void)
{ {
struct linux_central *central = central_bus; struct linux_central *central = central_bus;
struct linux_fhc *fhc;
u8 ctrl; u8 ctrl;
/* No central bus, nothing to do. */ /* No central bus, nothing to do. */
if (central == NULL) if (central == NULL)
return; return;
for(fhc = fhc_list; fhc != NULL; fhc = fhc->next) {
u32 tmp;
/* Clear all of the interrupt mapping registers
* just in case OBP left them in a foul state.
*/
#define ZAP(ICLR, IMAP) \
do { u32 imap_tmp; \
upa_writel(0, (ICLR)); \
upa_readl(ICLR); \
imap_tmp = upa_readl(IMAP); \
imap_tmp &= ~(0x80000000); \
upa_writel(imap_tmp, (IMAP)); \
upa_readl(IMAP); \
} while (0)
ZAP(fhc->fhc_regs.ffregs + FHC_FFREGS_ICLR,
fhc->fhc_regs.ffregs + FHC_FFREGS_IMAP);
ZAP(fhc->fhc_regs.sregs + FHC_SREGS_ICLR,
fhc->fhc_regs.sregs + FHC_SREGS_IMAP);
ZAP(fhc->fhc_regs.uregs + FHC_UREGS_ICLR,
fhc->fhc_regs.uregs + FHC_UREGS_IMAP);
ZAP(fhc->fhc_regs.tregs + FHC_TREGS_ICLR,
fhc->fhc_regs.tregs + FHC_TREGS_IMAP);
#undef ZAP
/* Setup FHC control register. */
tmp = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_CTRL);
/* All non-central boards have this bit set. */
if(! IS_CENTRAL_FHC(fhc))
tmp |= FHC_CONTROL_IXIST;
/* For all FHCs, clear the firmware synchronization
* line and both low power mode enables.
*/
tmp &= ~(FHC_CONTROL_AOFF | FHC_CONTROL_BOFF | FHC_CONTROL_SLINE);
upa_writel(tmp, fhc->fhc_regs.pregs + FHC_PREGS_CTRL);
upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_CTRL);
}
/* OBP leaves it on, turn it off so clock board timer LED /* OBP leaves it on, turn it off so clock board timer LED
* is in sync with FHC ones. * is in sync with FHC ones.
*/ */
......
...@@ -326,15 +326,15 @@ static unsigned char psycho_pil_table[] = { ...@@ -326,15 +326,15 @@ static unsigned char psycho_pil_table[] = {
/*0x14*/0, 0, 0, 0, /* PCI B slot 1 Int A, B, C, D */ /*0x14*/0, 0, 0, 0, /* PCI B slot 1 Int A, B, C, D */
/*0x18*/0, 0, 0, 0, /* PCI B slot 2 Int A, B, C, D */ /*0x18*/0, 0, 0, 0, /* PCI B slot 2 Int A, B, C, D */
/*0x1c*/0, 0, 0, 0, /* PCI B slot 3 Int A, B, C, D */ /*0x1c*/0, 0, 0, 0, /* PCI B slot 3 Int A, B, C, D */
/*0x20*/3, /* SCSI */ /*0x20*/4, /* SCSI */
/*0x21*/5, /* Ethernet */ /*0x21*/5, /* Ethernet */
/*0x22*/8, /* Parallel Port */ /*0x22*/8, /* Parallel Port */
/*0x23*/13, /* Audio Record */ /*0x23*/13, /* Audio Record */
/*0x24*/14, /* Audio Playback */ /*0x24*/14, /* Audio Playback */
/*0x25*/15, /* PowerFail */ /*0x25*/15, /* PowerFail */
/*0x26*/3, /* second SCSI */ /*0x26*/4, /* second SCSI */
/*0x27*/11, /* Floppy */ /*0x27*/11, /* Floppy */
/*0x28*/2, /* Spare Hardware */ /*0x28*/4, /* Spare Hardware */
/*0x29*/9, /* Keyboard */ /*0x29*/9, /* Keyboard */
/*0x2a*/4, /* Mouse */ /*0x2a*/4, /* Mouse */
/*0x2b*/12, /* Serial */ /*0x2b*/12, /* Serial */
...@@ -353,7 +353,7 @@ static int __init psycho_ino_to_pil(struct pci_dev *pdev, unsigned int ino) ...@@ -353,7 +353,7 @@ static int __init psycho_ino_to_pil(struct pci_dev *pdev, unsigned int ino)
ret = psycho_pil_table[ino]; ret = psycho_pil_table[ino];
if (ret == 0 && pdev == NULL) { if (ret == 0 && pdev == NULL) {
ret = 2; ret = 4;
} else if (ret == 0) { } else if (ret == 0) {
switch ((pdev->class >> 16) & 0xff) { switch ((pdev->class >> 16) & 0xff) {
case PCI_BASE_CLASS_STORAGE: case PCI_BASE_CLASS_STORAGE:
...@@ -376,7 +376,7 @@ static int __init psycho_ino_to_pil(struct pci_dev *pdev, unsigned int ino) ...@@ -376,7 +376,7 @@ static int __init psycho_ino_to_pil(struct pci_dev *pdev, unsigned int ino)
break; break;
default: default:
ret = 2; ret = 4;
break; break;
}; };
} }
......
...@@ -564,15 +564,15 @@ static unsigned char sabre_pil_table[] = { ...@@ -564,15 +564,15 @@ static unsigned char sabre_pil_table[] = {
/*0x14*/0, 0, 0, 0, /* PCI B slot 1 Int A, B, C, D */ /*0x14*/0, 0, 0, 0, /* PCI B slot 1 Int A, B, C, D */
/*0x18*/0, 0, 0, 0, /* PCI B slot 2 Int A, B, C, D */ /*0x18*/0, 0, 0, 0, /* PCI B slot 2 Int A, B, C, D */
/*0x1c*/0, 0, 0, 0, /* PCI B slot 3 Int A, B, C, D */ /*0x1c*/0, 0, 0, 0, /* PCI B slot 3 Int A, B, C, D */
/*0x20*/3, /* SCSI */ /*0x20*/4, /* SCSI */
/*0x21*/5, /* Ethernet */ /*0x21*/5, /* Ethernet */
/*0x22*/8, /* Parallel Port */ /*0x22*/8, /* Parallel Port */
/*0x23*/13, /* Audio Record */ /*0x23*/13, /* Audio Record */
/*0x24*/14, /* Audio Playback */ /*0x24*/14, /* Audio Playback */
/*0x25*/15, /* PowerFail */ /*0x25*/15, /* PowerFail */
/*0x26*/3, /* second SCSI */ /*0x26*/4, /* second SCSI */
/*0x27*/11, /* Floppy */ /*0x27*/11, /* Floppy */
/*0x28*/2, /* Spare Hardware */ /*0x28*/4, /* Spare Hardware */
/*0x29*/9, /* Keyboard */ /*0x29*/9, /* Keyboard */
/*0x2a*/4, /* Mouse */ /*0x2a*/4, /* Mouse */
/*0x2b*/12, /* Serial */ /*0x2b*/12, /* Serial */
...@@ -596,7 +596,7 @@ static int __init sabre_ino_to_pil(struct pci_dev *pdev, unsigned int ino) ...@@ -596,7 +596,7 @@ static int __init sabre_ino_to_pil(struct pci_dev *pdev, unsigned int ino)
ret = sabre_pil_table[ino]; ret = sabre_pil_table[ino];
if (ret == 0 && pdev == NULL) { if (ret == 0 && pdev == NULL) {
ret = 2; ret = 4;
} else if (ret == 0) { } else if (ret == 0) {
switch ((pdev->class >> 16) & 0xff) { switch ((pdev->class >> 16) & 0xff) {
case PCI_BASE_CLASS_STORAGE: case PCI_BASE_CLASS_STORAGE:
...@@ -619,7 +619,7 @@ static int __init sabre_ino_to_pil(struct pci_dev *pdev, unsigned int ino) ...@@ -619,7 +619,7 @@ static int __init sabre_ino_to_pil(struct pci_dev *pdev, unsigned int ino)
break; break;
default: default:
ret = 2; ret = 4;
break; break;
}; };
} }
......
...@@ -291,8 +291,8 @@ static unsigned char schizo_pil_table[] = { ...@@ -291,8 +291,8 @@ static unsigned char schizo_pil_table[] = {
/*0x0c*/0, 0, 0, 0, /* PCI slot 3 Int A, B, C, D */ /*0x0c*/0, 0, 0, 0, /* PCI slot 3 Int A, B, C, D */
/*0x10*/0, 0, 0, 0, /* PCI slot 4 Int A, B, C, D */ /*0x10*/0, 0, 0, 0, /* PCI slot 4 Int A, B, C, D */
/*0x14*/0, 0, 0, 0, /* PCI slot 5 Int A, B, C, D */ /*0x14*/0, 0, 0, 0, /* PCI slot 5 Int A, B, C, D */
/*0x18*/3, /* SCSI */ /*0x18*/4, /* SCSI */
/*0x19*/3, /* second SCSI */ /*0x19*/4, /* second SCSI */
/*0x1a*/0, /* UNKNOWN */ /*0x1a*/0, /* UNKNOWN */
/*0x1b*/0, /* UNKNOWN */ /*0x1b*/0, /* UNKNOWN */
/*0x1c*/8, /* Parallel */ /*0x1c*/8, /* Parallel */
...@@ -302,7 +302,7 @@ static unsigned char schizo_pil_table[] = { ...@@ -302,7 +302,7 @@ static unsigned char schizo_pil_table[] = {
/*0x20*/13, /* Audio Record */ /*0x20*/13, /* Audio Record */
/*0x21*/14, /* Audio Playback */ /*0x21*/14, /* Audio Playback */
/*0x22*/12, /* Serial */ /*0x22*/12, /* Serial */
/*0x23*/2, /* EBUS I2C */ /*0x23*/4, /* EBUS I2C */
/*0x24*/10, /* RTC Clock */ /*0x24*/10, /* RTC Clock */
/*0x25*/11, /* Floppy */ /*0x25*/11, /* Floppy */
/*0x26*/0, /* UNKNOWN */ /*0x26*/0, /* UNKNOWN */
...@@ -344,7 +344,7 @@ static int __init schizo_ino_to_pil(struct pci_dev *pdev, unsigned int ino) ...@@ -344,7 +344,7 @@ static int __init schizo_ino_to_pil(struct pci_dev *pdev, unsigned int ino)
ret = schizo_pil_table[ino]; ret = schizo_pil_table[ino];
if (ret == 0 && pdev == NULL) { if (ret == 0 && pdev == NULL) {
ret = 2; ret = 4;
} else if (ret == 0) { } else if (ret == 0) {
switch ((pdev->class >> 16) & 0xff) { switch ((pdev->class >> 16) & 0xff) {
case PCI_BASE_CLASS_STORAGE: case PCI_BASE_CLASS_STORAGE:
...@@ -367,7 +367,7 @@ static int __init schizo_ino_to_pil(struct pci_dev *pdev, unsigned int ino) ...@@ -367,7 +367,7 @@ static int __init schizo_ino_to_pil(struct pci_dev *pdev, unsigned int ino)
break; break;
default: default:
ret = 2; ret = 4;
break; break;
}; };
} }
......
...@@ -15,7 +15,6 @@ ...@@ -15,7 +15,6 @@
#include <asm/visasm.h> #include <asm/visasm.h>
#include <asm/processor.h> #include <asm/processor.h>
#define PTREGS_OFF (STACK_BIAS + REGWIN_SZ)
#define RTRAP_PSTATE (PSTATE_RMO|PSTATE_PEF|PSTATE_PRIV|PSTATE_IE) #define RTRAP_PSTATE (PSTATE_RMO|PSTATE_PEF|PSTATE_PRIV|PSTATE_IE)
#define RTRAP_PSTATE_IRQOFF (PSTATE_RMO|PSTATE_PEF|PSTATE_PRIV) #define RTRAP_PSTATE_IRQOFF (PSTATE_RMO|PSTATE_PEF|PSTATE_PRIV)
#define RTRAP_PSTATE_AG_IRQOFF (PSTATE_RMO|PSTATE_PEF|PSTATE_PRIV|PSTATE_AG) #define RTRAP_PSTATE_AG_IRQOFF (PSTATE_RMO|PSTATE_PEF|PSTATE_PRIV|PSTATE_AG)
...@@ -150,7 +149,7 @@ __handle_signal: ...@@ -150,7 +149,7 @@ __handle_signal:
andn %l1, %l4, %l1 andn %l1, %l4, %l1
.align 64 .align 64
.globl rtrap_irq, rtrap_clr_l6, rtrap, irqsz_patchme .globl rtrap_irq, rtrap_clr_l6, rtrap, irqsz_patchme, rtrap_xcall
rtrap_irq: rtrap_irq:
#ifdef CONFIG_PREEMPT #ifdef CONFIG_PREEMPT
ldsw [%g6 + TI_PRE_COUNT], %l0 ldsw [%g6 + TI_PRE_COUNT], %l0
...@@ -165,9 +164,11 @@ irqsz_patchme: sllx %l0, 0, %l0 ...@@ -165,9 +164,11 @@ irqsz_patchme: sllx %l0, 0, %l0
lduw [%l2 + %l0], %l1 ! softirq_pending lduw [%l2 + %l0], %l1 ! softirq_pending
cmp %l1, 0 cmp %l1, 0
/* mm/ultra.S:xcall_report_regs KNOWS about this load. */
bne,pn %icc, __handle_softirq bne,pn %icc, __handle_softirq
ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %l1 ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %l1
__handle_softirq_continue: __handle_softirq_continue:
rtrap_xcall:
sethi %hi(0xf << 20), %l4 sethi %hi(0xf << 20), %l4
andcc %l1, TSTATE_PRIV, %l3 andcc %l1, TSTATE_PRIV, %l3
and %l1, %l4, %l4 and %l1, %l4, %l4
...@@ -331,5 +332,3 @@ kern_fpucheck: ldub [%g6 + TI_FPDEPTH], %l5 ...@@ -331,5 +332,3 @@ kern_fpucheck: ldub [%g6 + TI_FPDEPTH], %l5
wr %g0, FPRS_DU, %fprs wr %g0, FPRS_DU, %fprs
ba,pt %xcc, rt_continue ba,pt %xcc, rt_continue
stb %l5, [%g6 + TI_FPDEPTH] stb %l5, [%g6 + TI_FPDEPTH]
#undef PTREGS_OFF
...@@ -628,11 +628,11 @@ void sbus_set_sbus64(struct sbus_dev *sdev, int bursts) ...@@ -628,11 +628,11 @@ void sbus_set_sbus64(struct sbus_dev *sdev, int bursts)
/* SBUS SYSIO INO number to Sparc PIL level. */ /* SBUS SYSIO INO number to Sparc PIL level. */
static unsigned char sysio_ino_to_pil[] = { static unsigned char sysio_ino_to_pil[] = {
0, 2, 2, 7, 5, 7, 8, 9, /* SBUS slot 0 */ 0, 4, 4, 7, 5, 7, 8, 9, /* SBUS slot 0 */
0, 2, 2, 7, 5, 7, 8, 9, /* SBUS slot 1 */ 0, 4, 4, 7, 5, 7, 8, 9, /* SBUS slot 1 */
0, 2, 2, 7, 5, 7, 8, 9, /* SBUS slot 2 */ 0, 4, 4, 7, 5, 7, 8, 9, /* SBUS slot 2 */
0, 2, 2, 7, 5, 7, 8, 9, /* SBUS slot 3 */ 0, 4, 4, 7, 5, 7, 8, 9, /* SBUS slot 3 */
3, /* Onboard SCSI */ 4, /* Onboard SCSI */
5, /* Onboard Ethernet */ 5, /* Onboard Ethernet */
/*XXX*/ 8, /* Onboard BPP */ /*XXX*/ 8, /* Onboard BPP */
0, /* Bogon */ 0, /* Bogon */
......
...@@ -594,11 +594,12 @@ int smp_call_function(void (*func)(void *info), void *info, ...@@ -594,11 +594,12 @@ int smp_call_function(void (*func)(void *info), void *info,
return 0; return 0;
} }
void smp_call_function_client(void) void smp_call_function_client(int irq, struct pt_regs *regs)
{ {
void (*func) (void *info) = call_data->func; void (*func) (void *info) = call_data->func;
void *info = call_data->info; void *info = call_data->info;
clear_softint(1 << irq);
if (call_data->wait) { if (call_data->wait) {
/* let initiator proceed only after completion */ /* let initiator proceed only after completion */
func(info); func(info);
...@@ -722,6 +723,12 @@ void smp_receive_signal(int cpu) ...@@ -722,6 +723,12 @@ void smp_receive_signal(int cpu)
} }
} }
void smp_receive_signal_client(int irq, struct pt_regs *regs)
{
/* Just return, rtrap takes care of the rest. */
clear_softint(1 << irq);
}
void smp_report_regs(void) void smp_report_regs(void)
{ {
smp_cross_call(&xcall_report_regs, 0, 0, 0); smp_cross_call(&xcall_report_regs, 0, 0, 0);
...@@ -940,10 +947,14 @@ void smp_release(void) ...@@ -940,10 +947,14 @@ void smp_release(void)
extern void prom_world(int); extern void prom_world(int);
extern void save_alternate_globals(unsigned long *); extern void save_alternate_globals(unsigned long *);
extern void restore_alternate_globals(unsigned long *); extern void restore_alternate_globals(unsigned long *);
void smp_penguin_jailcell(void) void smp_penguin_jailcell(int irq, struct pt_regs *regs)
{ {
unsigned long global_save[24]; unsigned long global_save[24];
clear_softint(1 << irq);
preempt_disable();
__asm__ __volatile__("flushw"); __asm__ __volatile__("flushw");
save_alternate_globals(global_save); save_alternate_globals(global_save);
prom_world(1); prom_world(1);
...@@ -954,6 +965,8 @@ void smp_penguin_jailcell(void) ...@@ -954,6 +965,8 @@ void smp_penguin_jailcell(void)
restore_alternate_globals(global_save); restore_alternate_globals(global_save);
atomic_dec(&smp_capture_registry); atomic_dec(&smp_capture_registry);
prom_world(0); prom_world(0);
preempt_enable();
} }
extern unsigned long xcall_promstop; extern unsigned long xcall_promstop;
......
...@@ -405,6 +405,7 @@ void __init clock_probe(void) ...@@ -405,6 +405,7 @@ void __init clock_probe(void)
char model[128]; char model[128];
int node, busnd = -1, err; int node, busnd = -1, err;
unsigned long flags; unsigned long flags;
struct linux_central *cbus;
#ifdef CONFIG_PCI #ifdef CONFIG_PCI
struct linux_ebus *ebus = NULL; struct linux_ebus *ebus = NULL;
struct isa_bridge *isa_br = NULL; struct isa_bridge *isa_br = NULL;
...@@ -431,21 +432,30 @@ void __init clock_probe(void) ...@@ -431,21 +432,30 @@ void __init clock_probe(void)
__save_and_cli(flags); __save_and_cli(flags);
if(central_bus != NULL) { cbus = central_bus;
if (cbus != NULL)
busnd = central_bus->child->prom_node; busnd = central_bus->child->prom_node;
}
/* Check FHC Central then EBUSs then ISA bridges then SBUSs.
* That way we handle the presence of multiple properly.
*
* As a special case, machines with Central must provide the
* timer chip there.
*/
#ifdef CONFIG_PCI #ifdef CONFIG_PCI
else if (ebus_chain != NULL) { if (ebus_chain != NULL) {
ebus = ebus_chain; ebus = ebus_chain;
busnd = ebus->prom_node; if (busnd == -1)
} else if (isa_chain != NULL) { busnd = ebus->prom_node;
}
if (isa_chain != NULL) {
isa_br = isa_chain; isa_br = isa_chain;
busnd = isa_br->prom_node; if (busnd == -1)
busnd = isa_br->prom_node;
} }
#endif #endif
else if (sbus_root != NULL) { if (sbus_root != NULL && busnd == -1)
busnd = sbus_root->prom_node; busnd = sbus_root->prom_node;
}
if (busnd == -1) { if (busnd == -1) {
prom_printf("clock_probe: problem, cannot find bus to search.\n"); prom_printf("clock_probe: problem, cannot find bus to search.\n");
...@@ -464,7 +474,12 @@ void __init clock_probe(void) ...@@ -464,7 +474,12 @@ void __init clock_probe(void)
strcmp(model, "mk48t59") && strcmp(model, "mk48t59") &&
strcmp(model, "m5819") && strcmp(model, "m5819") &&
strcmp(model, "ds1287")) { strcmp(model, "ds1287")) {
if (node) if (cbus != NULL) {
prom_printf("clock_probe: Central bus lacks timer chip.\n");
prom_halt();
}
if (node != 0)
node = prom_getsibling(node); node = prom_getsibling(node);
#ifdef CONFIG_PCI #ifdef CONFIG_PCI
while ((node == 0) && ebus != NULL) { while ((node == 0) && ebus != NULL) {
...@@ -496,12 +511,12 @@ void __init clock_probe(void) ...@@ -496,12 +511,12 @@ void __init clock_probe(void)
prom_halt(); prom_halt();
} }
if(central_bus) { if (cbus != NULL) {
apply_fhc_ranges(central_bus->child, clk_reg, 1); apply_fhc_ranges(central_bus->child, clk_reg, 1);
apply_central_ranges(central_bus, clk_reg, 1); apply_central_ranges(central_bus, clk_reg, 1);
} }
#ifdef CONFIG_PCI #ifdef CONFIG_PCI
else if (ebus_chain != NULL) { else if (ebus != NULL) {
struct linux_ebus_device *edev; struct linux_ebus_device *edev;
for_each_ebusdev(edev, ebus) for_each_ebusdev(edev, ebus)
...@@ -523,7 +538,8 @@ void __init clock_probe(void) ...@@ -523,7 +538,8 @@ void __init clock_probe(void)
mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02; mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02;
} }
break; break;
} else if (isa_chain != NULL) { }
else if (isa_br != NULL) {
struct isa_device *isadev; struct isa_device *isadev;
try_isa_clock: try_isa_clock:
......
...@@ -44,9 +44,16 @@ tl0_stdfmna: TRAP_NOSAVE(do_stdfmna) ...@@ -44,9 +44,16 @@ tl0_stdfmna: TRAP_NOSAVE(do_stdfmna)
tl0_privact: TRAP_NOSAVE(__do_privact) tl0_privact: TRAP_NOSAVE(__do_privact)
tl0_resv038: BTRAP(0x38) BTRAP(0x39) BTRAP(0x3a) BTRAP(0x3b) BTRAP(0x3c) BTRAP(0x3d) tl0_resv038: BTRAP(0x38) BTRAP(0x39) BTRAP(0x3a) BTRAP(0x3b) BTRAP(0x3c) BTRAP(0x3d)
tl0_resv03e: BTRAP(0x3e) BTRAP(0x3f) BTRAP(0x40) tl0_resv03e: BTRAP(0x3e) BTRAP(0x3f) BTRAP(0x40)
#ifdef CONFIG_SMP
tl0_irq1: TRAP_IRQ(smp_call_function_client, 1)
tl0_irq2: TRAP_IRQ(smp_receive_signal_client, 2)
tl0_irq3: TRAP_IRQ(smp_penguin_jailcell, 3)
#else
tl0_irq1: BTRAP(0x41) tl0_irq1: BTRAP(0x41)
tl0_irq2: TRAP_IRQ(handler_irq, 2) tl0_irq2: BTRAP(0x42)
tl0_irq3: TRAP_IRQ(handler_irq, 3) TRAP_IRQ(handler_irq, 4) tl0_irq3: BTRAP(0x43)
#endif
tl0_irq4: TRAP_IRQ(handler_irq, 4)
tl0_irq5: TRAP_IRQ(handler_irq, 5) TRAP_IRQ(handler_irq, 6) tl0_irq5: TRAP_IRQ(handler_irq, 5) TRAP_IRQ(handler_irq, 6)
tl0_irq7: TRAP_IRQ(handler_irq, 7) TRAP_IRQ(handler_irq, 8) tl0_irq7: TRAP_IRQ(handler_irq, 7) TRAP_IRQ(handler_irq, 8)
tl0_irq9: TRAP_IRQ(handler_irq, 9) TRAP_IRQ(handler_irq, 10) tl0_irq9: TRAP_IRQ(handler_irq, 9) TRAP_IRQ(handler_irq, 10)
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include <asm/spitfire.h> #include <asm/spitfire.h>
#include <asm/mmu_context.h> #include <asm/mmu_context.h>
#include <asm/pil.h> #include <asm/pil.h>
#include <asm/head.h>
/* Basically, all this madness has to do with the /* Basically, all this madness has to do with the
* fact that Cheetah does not support IMMU flushes * fact that Cheetah does not support IMMU flushes
...@@ -482,6 +483,15 @@ xcall_flush_tlb_range: ...@@ -482,6 +483,15 @@ xcall_flush_tlb_range:
nop nop
nop nop
/* NOTE: This is SPECIAL!! We do etrap/rtrap however
* we choose to deal with the "BH's run with
* %pil==15" problem (described in asm/pil.h)
* by just invoking rtrap directly past where
* BH's are checked for.
*
* We do it like this because we do not want %pil==15
* lockups to prevent regs being reported.
*/
.globl xcall_report_regs .globl xcall_report_regs
xcall_report_regs: xcall_report_regs:
rdpr %pstate, %g2 rdpr %pstate, %g2
...@@ -489,12 +499,14 @@ xcall_report_regs: ...@@ -489,12 +499,14 @@ xcall_report_regs:
rdpr %pil, %g2 rdpr %pil, %g2
wrpr %g0, 15, %pil wrpr %g0, 15, %pil
sethi %hi(109f), %g7 sethi %hi(109f), %g7
b,pt %xcc, etrap_irq b,pt %xcc, etrap
109: or %g7, %lo(109b), %g7 109: or %g7, %lo(109b), %g7
call __show_regs call __show_regs
add %sp, STACK_BIAS + REGWIN_SZ, %o0 add %sp, STACK_BIAS + REGWIN_SZ, %o0
b,pt %xcc, rtrap_irq clr %l6
nop /* Has to be a non-v9 branch due to the large distance. */
b rtrap_xcall
ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %l1
.align 32 .align 32
.globl xcall_flush_dcache_page_cheetah .globl xcall_flush_dcache_page_cheetah
...@@ -543,20 +555,6 @@ xcall_flush_dcache_page_spitfire: /* %g1 == physical page address ...@@ -543,20 +555,6 @@ xcall_flush_dcache_page_spitfire: /* %g1 == physical page address
nop nop
nop nop
.globl xcall_capture
xcall_capture:
rdpr %pstate, %g2
wrpr %g2, PSTATE_IG | PSTATE_AG, %pstate
rdpr %pil, %g2
wrpr %g0, 15, %pil
sethi %hi(109f), %g7
b,pt %xcc, etrap_irq
109: or %g7, %lo(109b), %g7
call smp_penguin_jailcell
nop
b,pt %xcc, rtrap_irq
nop
.globl xcall_promstop .globl xcall_promstop
xcall_promstop: xcall_promstop:
rdpr %pstate, %g2 rdpr %pstate, %g2
...@@ -564,7 +562,7 @@ xcall_promstop: ...@@ -564,7 +562,7 @@ xcall_promstop:
rdpr %pil, %g2 rdpr %pil, %g2
wrpr %g0, 15, %pil wrpr %g0, 15, %pil
sethi %hi(109f), %g7 sethi %hi(109f), %g7
b,pt %xcc, etrap_irq b,pt %xcc, etrap
109: or %g7, %lo(109b), %g7 109: or %g7, %lo(109b), %g7
flushw flushw
call prom_stopself call prom_stopself
...@@ -573,21 +571,6 @@ xcall_promstop: ...@@ -573,21 +571,6 @@ xcall_promstop:
1: b,a,pt %xcc, 1b 1: b,a,pt %xcc, 1b
nop nop
.globl xcall_receive_signal
xcall_receive_signal:
rdpr %pstate, %g2
wrpr %g2, PSTATE_IG | PSTATE_AG, %pstate
rdpr %tstate, %g1
andcc %g1, TSTATE_PRIV, %g0
/* If we did not trap from user space, just ignore. */
bne,pn %xcc, 99f
sethi %hi(109f), %g7
b,pt %xcc, etrap
109: or %g7, %lo(109b), %g7
b,pt %xcc, rtrap
clr %l6
99: retry
.data .data
errata32_hwbug: errata32_hwbug:
...@@ -670,18 +653,20 @@ __spitfire_xcall_flush_cache_all: ...@@ -670,18 +653,20 @@ __spitfire_xcall_flush_cache_all:
__cheetah_xcall_flush_cache_all: __cheetah_xcall_flush_cache_all:
retry retry
/* These just get rescheduled to PIL vectors. */
.globl xcall_call_function .globl xcall_call_function
xcall_call_function: xcall_call_function:
rdpr %pstate, %g2 wr %g0, (1 << PIL_SMP_CALL_FUNC), %set_softint
wrpr %g2, PSTATE_IG | PSTATE_AG, %pstate retry
rdpr %pil, %g2
wrpr %g0, 15, %pil .globl xcall_receive_signal
sethi %hi(109f), %g7 xcall_receive_signal:
b,pt %xcc, etrap_irq wr %g0, (1 << PIL_SMP_RECEIVE_SIGNAL), %set_softint
109: or %g7, %lo(109b), %g7 retry
call smp_call_function_client
nop .globl xcall_capture
b,pt %xcc, rtrap_irq xcall_capture:
nop wr %g0, (1 << PIL_SMP_CAPTURE), %set_softint
retry
#endif /* CONFIG_SMP */ #endif /* CONFIG_SMP */
...@@ -86,10 +86,10 @@ struct fhc_regs { ...@@ -86,10 +86,10 @@ struct fhc_regs {
#define FHC_BSR_NIA 0x0000001c /* Jumper, bit 18 in PROM space */ #define FHC_BSR_NIA 0x0000001c /* Jumper, bit 18 in PROM space */
#define FHC_BSR_SI 0x00000001 /* Spare input pin value */ #define FHC_BSR_SI 0x00000001 /* Spare input pin value */
#define FHC_PREGS_ECC 0x40UL /* FHC ECC Control Register (16 bits) */ #define FHC_PREGS_ECC 0x40UL /* FHC ECC Control Register (16 bits) */
#define FHC_PREGS_JCTRL 0x50UL /* FHC JTAG Control Register */ #define FHC_PREGS_JCTRL 0xf0UL /* FHC JTAG Control Register */
#define FHC_JTAG_CTRL_MENAB 0x80000000 /* Indicates this is JTAG Master */ #define FHC_JTAG_CTRL_MENAB 0x80000000 /* Indicates this is JTAG Master */
#define FHC_JTAG_CTRL_MNONE 0x40000000 /* Indicates no JTAG Master present */ #define FHC_JTAG_CTRL_MNONE 0x40000000 /* Indicates no JTAG Master present */
#define FHC_PREGS_JCMD 0x60UL /* FHC JTAG Command Register */ #define FHC_PREGS_JCMD 0x100UL /* FHC JTAG Command Register */
unsigned long ireg; /* FHC IGN reg */ unsigned long ireg; /* FHC IGN reg */
#define FHC_IREG_IGN 0x00UL /* This FHC's IGN */ #define FHC_IREG_IGN 0x00UL /* This FHC's IGN */
unsigned long ffregs; /* FHC fanfail regs */ unsigned long ffregs; /* FHC fanfail regs */
......
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
#include <asm/pstate.h> #include <asm/pstate.h>
#define KERNBASE 0x400000 #define KERNBASE 0x400000
#define PTREGS_OFF (STACK_BIAS + REGWIN_SZ)
#endif /* !(_SPARC64_HEAD_H) */ #endif /* !(_SPARC64_HEAD_H) */
...@@ -3,20 +3,24 @@ ...@@ -3,20 +3,24 @@
#define _SPARC64_PIL_H #define _SPARC64_PIL_H
/* To avoid some locking problems, we hard allocate certain PILs /* To avoid some locking problems, we hard allocate certain PILs
* for SMP cross call messages. cli() does not block the cross * for SMP cross call messages that must do a etrap/rtrap.
* call delivery, so when SMP locking is an issue we reschedule
* the event into a PIL interrupt which is blocked by cli().
* *
* XXX In fact the whole set of PILs used for hardware interrupts * A cli() does not block the cross call delivery, so when SMP
* XXX may be allocated in this manner. All of the devices can * locking is an issue we reschedule the event into a PIL interrupt
* XXX happily sit at the same PIL. We would then need only two * which is blocked by cli().
* XXX PILs, one for devices and one for the CPU local timer tick. *
* In fact any XCALL which has to etrap/rtrap has a problem because
* it is difficult to prevent rtrap from running BH's, and that would
* need to be done if the XCALL arrived while %pil==15.
*/ */
/* None currently allocated, '1' is available for use. */ #define PIL_SMP_CALL_FUNC 1
#define PIL_SMP_1 1 #define PIL_SMP_RECEIVE_SIGNAL 2
#define PIL_SMP_CAPTURE 3
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
#define PIL_RESERVED(PIL) ((PIL) == PIL_SMP_1) #define PIL_RESERVED(PIL) ((PIL) == PIL_SMP_CALL_FUNC || \
(PIL) == PIL_SMP_RECEIVE_SIGNAL || \
(PIL) == PIL_SMP_CAPTURE)
#endif #endif
#endif /* !(_SPARC64_PIL_H) */ #endif /* !(_SPARC64_PIL_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