static void __init lasi_init_irq(struct gsc_asic *this_lasi) { unsigned long lasi_base = this_lasi->hpa; /* Stop LASI barking for a bit */ gsc_writel(0x00000000, lasi_base+OFFSET_IMR); /* clear pending interrupts */ gsc_readl(lasi_base+OFFSET_IRR); /* We're not really convinced we want to reset the onboard * devices. Firmware does it for us... */ /* Resets */ /* gsc_writel(0xFFFFFFFF, lasi_base+0x2000);*/ /* Parallel */ if(pdc_add_valid(lasi_base+0x4004) == PDC_OK) gsc_writel(0xFFFFFFFF, lasi_base+0x4004); /* Audio */ /* gsc_writel(0xFFFFFFFF, lasi_base+0x5000);*/ /* Serial */ /* gsc_writel(0xFFFFFFFF, lasi_base+0x6000);*/ /* SCSI */ gsc_writel(0xFFFFFFFF, lasi_base+0x7000); /* LAN */ gsc_writel(0xFFFFFFFF, lasi_base+0x8000); /* Keyboard */ gsc_writel(0xFFFFFFFF, lasi_base+0xA000); /* FDC */ /* Ok we hit it on the head with a hammer, our Dog is now ** comatose and muzzled. Devices will now unmask LASI ** interrupts as they are registered as irq's in the LASI range. */ /* XXX: I thought it was `awks that got `it on the `ead with an * `ammer. -- willy */ }
static int __init lasi_init_chip(struct parisc_device *dev) { extern void (*chassis_power_off)(void); struct gsc_asic *lasi; struct gsc_irq gsc_irq; int ret; lasi = kzalloc(sizeof(*lasi), GFP_KERNEL); if (!lasi) return -ENOMEM; lasi->name = "Lasi"; lasi->hpa = dev->hpa.start; lasi->version = gsc_readl(lasi->hpa + LASI_VER) & 0xf; printk(KERN_INFO "%s version %d at 0x%lx found.\n", lasi->name, lasi->version, lasi->hpa); lasi_led_init(lasi->hpa); lasi_init_irq(lasi); dev->irq = gsc_alloc_irq(&gsc_irq); if (dev->irq < 0) { printk(KERN_ERR "%s(): cannot get GSC irq\n", __func__); kfree(lasi); return -EBUSY; } lasi->eim = ((u32) gsc_irq.txn_addr) | gsc_irq.txn_data; ret = request_irq(gsc_irq.irq, gsc_asic_intr, 0, "lasi", lasi); if (ret < 0) { kfree(lasi); return ret; } gsc_writel(lasi->eim, lasi->hpa + OFFSET_IAR); ret = gsc_common_setup(dev, lasi); if (ret) { kfree(lasi); return ret; } gsc_fixup_irqs(dev, lasi, lasi_choose_irq); lasi_power_off_hpa = lasi->hpa; chassis_power_off = lasi_power_off; return ret; }
/* ** The Wright Brothers and Gecko systems have a H/W problem ** (Lasi...'nuf said) may cause a broadcast reset to lockup ** the system. An HVERSION dependent PDC call was developed ** to perform a "safe", platform specific broadcast reset instead ** of kludging up all the code. ** ** Older machines which do not implement PDC_BROADCAST_RESET will ** return (with an error) and the regular broadcast reset can be ** issued. Obviously, if the PDC does implement PDC_BROADCAST_RESET ** the PDC call will not return (the system will be reset). */ void machine_restart(char *cmd) { #ifdef FASTBOOT_SELFTEST_SUPPORT /* ** If user has modified the Firmware Selftest Bitmap, ** run the tests specified in the bitmap after the ** system is rebooted w/PDC_DO_RESET. ** ** ftc_bitmap = 0x1AUL "Skip destructive memory tests" ** ** Using "directed resets" at each processor with the MEM_TOC ** vector cleared will also avoid running destructive ** memory self tests. (Not implemented yet) */ if (ftc_bitmap) { pdc_do_firm_test_reset(ftc_bitmap); } #endif /* set up a new led state on systems shipped with a LED State panel */ pdc_chassis_send_status(PDC_CHASSIS_DIRECT_SHUTDOWN); /* "Normal" system reset */ pdc_do_reset(); /* Nope...box should reset with just CMD_RESET now */ gsc_writel(CMD_RESET, COMMAND_GLOBAL); /* Wait for RESET to lay us to rest. */ while (1) ; }
static int __init lasi_init_chip(struct parisc_device *dev) { extern void (*chassis_power_off)(void); struct gsc_asic *lasi; struct gsc_irq gsc_irq; int ret; lasi = kzalloc(sizeof(*lasi), GFP_KERNEL); if (!lasi) return -ENOMEM; lasi->name = "Lasi"; lasi->hpa = dev->hpa.start; /* Check the 4-bit (yes, only 4) version register */ lasi->version = gsc_readl(lasi->hpa + LASI_VER) & 0xf; printk(KERN_INFO "%s version %d at 0x%lx found.\n", lasi->name, lasi->version, lasi->hpa); /* initialize the chassis LEDs really early */ lasi_led_init(lasi->hpa); /* Stop LASI barking for a bit */ lasi_init_irq(lasi); /* the IRQ lasi should use */ dev->irq = gsc_alloc_irq(&gsc_irq); if (dev->irq < 0) { printk(KERN_ERR "%s(): cannot get GSC irq\n", __func__); kfree(lasi); return -EBUSY; } lasi->eim = ((u32) gsc_irq.txn_addr) | gsc_irq.txn_data; ret = request_irq(gsc_irq.irq, gsc_asic_intr, 0, "lasi", lasi); if (ret < 0) { kfree(lasi); return ret; } /* enable IRQ's for devices below LASI */ gsc_writel(lasi->eim, lasi->hpa + OFFSET_IAR); /* Done init'ing, register this driver */ ret = gsc_common_setup(dev, lasi); if (ret) { kfree(lasi); return ret; } gsc_fixup_irqs(dev, lasi, lasi_choose_irq); /* initialize the power off function */ lasi_power_off_hpa = lasi->hpa; chassis_power_off = lasi_power_off; return ret; }
int __init asp_init_chip(struct parisc_device *dev) { struct busdevice *asp; struct gsc_irq gsc_irq; int irq, ret; asp = kmalloc(sizeof(struct busdevice), GFP_KERNEL); if(!asp) return -ENOMEM; asp->version = gsc_readb(dev->hpa + ASP_VER_OFFSET) & 0xf; asp->name = (asp->version == 1) ? "Asp" : "Cutoff"; asp->hpa = ASP_INTERRUPT_ADDR; printk(KERN_INFO "%s version %d at 0x%lx found.\n", asp->name, asp->version, dev->hpa); /* the IRQ ASP should use */ ret = -EBUSY; irq = gsc_claim_irq(&gsc_irq, ASP_GSC_IRQ); if (irq < 0) { printk(KERN_ERR "%s(): cannot get GSC irq\n", __FUNCTION__); goto out; } ret = request_irq(gsc_irq.irq, busdev_barked, 0, "asp", asp); if (ret < 0) goto out; /* Save this for debugging later */ asp->parent_irq = gsc_irq.irq; asp->eim = ((u32) gsc_irq.txn_addr) | gsc_irq.txn_data; /* Program VIPER to interrupt on the ASP irq */ gsc_writel((1 << (31 - ASP_GSC_IRQ)),VIPER_INT_WORD); /* Done init'ing, register this driver */ ret = gsc_common_irqsetup(dev, asp); if (ret) goto out; fixup_child_irqs(dev, asp->busdev_region->data.irqbase, asp_choose_irq); /* Mongoose is a sibling of Asp, not a child... */ fixup_child_irqs(dev->parent, asp->busdev_region->data.irqbase, asp_choose_irq); /* initialize the chassis LEDs */ #ifdef CONFIG_CHASSIS_LCD_LED register_led_driver(DISPLAY_MODEL_OLD_ASP, LED_CMD_REG_NONE, (char *)ASP_LED_ADDR); #endif return 0; out: kfree(asp); return ret; }
/* * Bring one cpu online. */ int smp_boot_one_cpu(int cpuid, struct task_struct *idle) { const struct cpuinfo_parisc *p = &per_cpu(cpu_data, cpuid); long timeout; task_thread_info(idle)->cpu = cpuid; /* Let _start know what logical CPU we're booting ** (offset into init_tasks[],cpu_data[]) */ cpu_now_booting = cpuid; /* ** boot strap code needs to know the task address since ** it also contains the process stack. */ smp_init_current_idle_task = idle ; mb(); printk(KERN_INFO "Releasing cpu %d now, hpa=%lx\n", cpuid, p->hpa); /* ** This gets PDC to release the CPU from a very tight loop. ** ** From the PA-RISC 2.0 Firmware Architecture Reference Specification: ** "The MEM_RENDEZ vector specifies the location of OS_RENDEZ which ** is executed after receiving the rendezvous signal (an interrupt to ** EIR{0}). MEM_RENDEZ is valid only when it is nonzero and the ** contents of memory are valid." */ gsc_writel(TIMER_IRQ - CPU_IRQ_BASE, p->hpa); mb(); /* * OK, wait a bit for that CPU to finish staggering about. * Slave will set a bit when it reaches smp_cpu_init(). * Once the "monarch CPU" sees the bit change, it can move on. */ for (timeout = 0; timeout < 10000; timeout++) { if(cpu_online(cpuid)) { /* Which implies Slave has started up */ cpu_now_booting = 0; smp_init_current_idle_task = NULL; goto alive ; } udelay(100); barrier(); } printk(KERN_CRIT "SMP: CPU:%d is stuck.\n", cpuid); return -1; alive: /* Remember the Slave data */ smp_debug(100, KERN_DEBUG "SMP: CPU:%d came alive after %ld _us\n", cpuid, timeout * 100); return 0; }
int __init wax_init_chip(struct parisc_device *dev) { struct gsc_asic *wax; struct parisc_device *parent; struct gsc_irq gsc_irq; int ret; wax = kzalloc(sizeof(*wax), GFP_KERNEL); if (!wax) return -ENOMEM; wax->name = "wax"; wax->hpa = dev->hpa.start; wax->version = 0; /* gsc_readb(wax->hpa+WAX_VER); */ printk(KERN_INFO "%s at 0x%lx found.\n", wax->name, wax->hpa); /* Stop wax hissing for a bit */ wax_init_irq(wax); /* the IRQ wax should use */ dev->irq = gsc_claim_irq(&gsc_irq, WAX_GSC_IRQ); if (dev->irq < 0) { printk(KERN_ERR "%s(): cannot get GSC irq\n", __func__); kfree(wax); return -EBUSY; } wax->eim = ((u32) gsc_irq.txn_addr) | gsc_irq.txn_data; ret = request_irq(gsc_irq.irq, gsc_asic_intr, 0, "wax", wax); if (ret < 0) { kfree(wax); return ret; } /* enable IRQ's for devices below WAX */ gsc_writel(wax->eim, wax->hpa + OFFSET_IAR); /* Done init'ing, register this driver */ ret = gsc_common_setup(dev, wax); if (ret) { kfree(wax); return ret; } gsc_fixup_irqs(dev, wax, wax_choose_irq); /* On 715-class machines, Wax EISA is a sibling of Wax, not a child. */ parent = parisc_parent(dev); if (parent->id.hw_type != HPHW_IOA) { gsc_fixup_irqs(parent, wax, wax_choose_irq); } return ret; }
static int __init wax_init_chip(struct parisc_device *dev) { struct gsc_asic *wax; struct parisc_device *parent; struct gsc_irq gsc_irq; int ret; wax = kzalloc(sizeof(*wax), GFP_KERNEL); if (!wax) return -ENOMEM; wax->name = "wax"; wax->hpa = dev->hpa.start; wax->version = 0; /* */ printk(KERN_INFO "%s at 0x%lx found.\n", wax->name, wax->hpa); /* */ wax_init_irq(wax); /* */ dev->irq = gsc_claim_irq(&gsc_irq, WAX_GSC_IRQ); if (dev->irq < 0) { printk(KERN_ERR "%s(): cannot get GSC irq\n", __func__); kfree(wax); return -EBUSY; } wax->eim = ((u32) gsc_irq.txn_addr) | gsc_irq.txn_data; ret = request_irq(gsc_irq.irq, gsc_asic_intr, 0, "wax", wax); if (ret < 0) { kfree(wax); return ret; } /* */ gsc_writel(wax->eim, wax->hpa + OFFSET_IAR); /* */ ret = gsc_common_setup(dev, wax); if (ret) { kfree(wax); return ret; } gsc_fixup_irqs(dev, wax, wax_choose_irq); /* */ parent = parisc_parent(dev); if (parent->id.hw_type != HPHW_IOA) { gsc_fixup_irqs(parent, wax, wax_choose_irq); } return ret; }
static void lasi_power_off(void) { unsigned long datareg; datareg = lasi_power_off_hpa + 0x0000C000; gsc_writel(0x02, datareg); }
static void lasi_power_off(void) { unsigned long datareg; /* calculate addr of the Power Control Register */ datareg = lasi_power_off_hpa + 0x0000C000; /* Power down the machine */ gsc_writel(0x02, datareg); }
static inline void ipi_send(int cpu, enum ipi_message_type op) { struct cpuinfo_parisc *p = &cpu_data[cpu]; unsigned long flags; spin_lock_irqsave(&(p->lock),flags); p->pending_ipi |= 1 << op; gsc_writel(IPI_IRQ - CPU_IRQ_BASE, cpu_data[cpu].hpa); spin_unlock_irqrestore(&(p->lock),flags); }
static inline void ipi_send(int cpu, enum ipi_message_type op) { struct cpuinfo_parisc *p = &per_cpu(cpu_data, cpu); spinlock_t *lock = &per_cpu(ipi_lock, cpu); unsigned long flags; spin_lock_irqsave(lock, flags); p->pending_ipi |= 1 << op; gsc_writel(IPI_IRQ - CPU_IRQ_BASE, p->hpa); spin_unlock_irqrestore(lock, flags); }
static int __init asp_init_chip(struct parisc_device *dev) { struct gsc_irq gsc_irq; int ret; asp.version = gsc_readb(dev->hpa.start + ASP_VER_OFFSET) & 0xf; asp.name = (asp.version == 1) ? "Asp" : "Cutoff"; asp.hpa = ASP_INTERRUPT_ADDR; #ifdef CONFIG_DEBUG_PRINTK printk(KERN_INFO "%s version %d at 0x%lx found.\n", asp.name, asp.version, (unsigned long)dev->hpa.start); #else ; #endif /* the IRQ ASP should use */ ret = -EBUSY; dev->irq = gsc_claim_irq(&gsc_irq, ASP_GSC_IRQ); if (dev->irq < 0) { printk(KERN_ERR "%s(): cannot get GSC irq\n", __func__); goto out; } asp.eim = ((u32) gsc_irq.txn_addr) | gsc_irq.txn_data; ret = request_irq(gsc_irq.irq, gsc_asic_intr, 0, "asp", &asp); if (ret < 0) goto out; /* Program VIPER to interrupt on the ASP irq */ gsc_writel((1 << (31 - ASP_GSC_IRQ)),VIPER_INT_WORD); /* Done init'ing, register this driver */ ret = gsc_common_setup(dev, &asp); if (ret) goto out; gsc_fixup_irqs(dev, &asp, asp_choose_irq); /* Mongoose is a sibling of Asp, not a child... */ gsc_fixup_irqs(parisc_parent(dev), &asp, asp_choose_irq); /* initialize the chassis LEDs */ #ifdef CONFIG_CHASSIS_LCD_LED register_led_driver(DISPLAY_MODEL_OLD_ASP, LED_CMD_REG_NONE, ASP_LED_ADDR); #endif out: return ret; }
static void __init lasi_init_irq(struct gsc_asic *this_lasi) { unsigned long lasi_base = this_lasi->hpa; gsc_writel(0x00000000, lasi_base+OFFSET_IMR); gsc_readl(lasi_base+OFFSET_IRR); if(pdc_add_valid(lasi_base+0x4004) == PDC_OK) gsc_writel(0xFFFFFFFF, lasi_base+0x4004); gsc_writel(0xFFFFFFFF, lasi_base+0x7000); gsc_writel(0xFFFFFFFF, lasi_base+0x8000); gsc_writel(0xFFFFFFFF, lasi_base+0xA000); }
/* ONLY called from entry.S:intr_extint() */ void do_cpu_irq_mask(struct pt_regs *regs) { struct pt_regs *old_regs; unsigned long eirr_val; int irq, cpu = smp_processor_id(); #ifdef CONFIG_SMP struct irq_desc *desc; cpumask_t dest; #endif old_regs = set_irq_regs(regs); local_irq_disable(); irq_enter(); eirr_val = mfctl(23) & cpu_eiem & per_cpu(local_ack_eiem, cpu); if (!eirr_val) goto set_out; irq = eirr_to_irq(eirr_val); #ifdef CONFIG_SMP desc = irq_to_desc(irq); cpumask_copy(&dest, desc->irq_data.affinity); if (irqd_is_per_cpu(&desc->irq_data) && !cpu_isset(smp_processor_id(), dest)) { int cpu = first_cpu(dest); printk(KERN_DEBUG "redirecting irq %d from CPU %d to %d\n", irq, smp_processor_id(), cpu); gsc_writel(irq + CPU_IRQ_BASE, per_cpu(cpu_data, cpu).hpa); goto set_out; } #endif stack_overflow_check(regs); #ifdef CONFIG_IRQSTACKS execute_on_irq_stack(&generic_handle_irq, irq); #else generic_handle_irq(irq); #endif /* CONFIG_IRQSTACKS */ out: irq_exit(); set_irq_regs(old_regs); return; set_out: set_eiem(cpu_eiem & per_cpu(local_ack_eiem, cpu)); goto out; }
static void gsc_asic_mask_irq(unsigned int irq) { struct gsc_asic *irq_dev = get_irq_chip_data(irq); int local_irq = gsc_find_local_irq(irq, irq_dev->global_irq, 32); u32 imr; DEBPRINTK(KERN_DEBUG "%s(%d) %s: IMR 0x%x\n", __func__, irq, irq_dev->name, imr); /* Disable the IRQ line by clearing the bit in the IMR */ imr = gsc_readl(irq_dev->hpa + OFFSET_IMR); imr &= ~(1 << local_irq); gsc_writel(imr, irq_dev->hpa + OFFSET_IMR); }
static void memset_tohp(void *dest, u32 word, int count) { unsigned long d = ram2log(dest); count += 3; count &= ~3; while(count) { count--; gsc_writel(word, d); d += 32; } }
static void gsc_asic_enable_irq(unsigned int irq) { struct irq_desc *desc = irq_to_desc(irq); struct gsc_asic *irq_dev = desc->chip_data; int local_irq = gsc_find_local_irq(irq, irq_dev->global_irq, 32); u32 imr; DEBPRINTK(KERN_DEBUG "%s(%d) %s: IMR 0x%x\n", __func__, irq, irq_dev->name, imr); /* Enable the IRQ line by setting the bit in the IMR */ imr = gsc_readl(irq_dev->hpa + OFFSET_IMR); imr |= 1 << local_irq; gsc_writel(imr, irq_dev->hpa + OFFSET_IMR); }
static void memcpy_fromhp_tohp(void *dest, void *src, int count) { unsigned long d = ram2log(dest); unsigned long s = ram2log(src); count += 3; count &= ~3; /* XXX */ while(count) { count --; gsc_writel(~gsc_readl(s), d); d += 32*4; s += 32*4; } }
static int __init asp_init_chip(struct parisc_device *dev) { struct gsc_irq gsc_irq; int ret; asp.version = gsc_readb(dev->hpa.start + ASP_VER_OFFSET) & 0xf; asp.name = (asp.version == 1) ? "Asp" : "Cutoff"; asp.hpa = ASP_INTERRUPT_ADDR; printk(KERN_INFO "%s version %d at 0x%lx found.\n", asp.name, asp.version, (unsigned long)dev->hpa.start); ret = -EBUSY; dev->irq = gsc_claim_irq(&gsc_irq, ASP_GSC_IRQ); if (dev->irq < 0) { printk(KERN_ERR "%s(): cannot get GSC irq\n", __func__); goto out; } asp.eim = ((u32) gsc_irq.txn_addr) | gsc_irq.txn_data; ret = request_irq(gsc_irq.irq, gsc_asic_intr, 0, "asp", &asp); if (ret < 0) goto out; gsc_writel((1 << (31 - ASP_GSC_IRQ)),VIPER_INT_WORD); ret = gsc_common_setup(dev, &asp); if (ret) goto out; gsc_fixup_irqs(dev, &asp, asp_choose_irq); gsc_fixup_irqs(parisc_parent(dev), &asp, asp_choose_irq); #ifdef CONFIG_CHASSIS_LCD_LED register_led_driver(DISPLAY_MODEL_OLD_ASP, LED_CMD_REG_NONE, ASP_LED_ADDR); #endif out: return ret; }
static void gsc_asic_unmask_irq(unsigned int irq) { struct gsc_asic *irq_dev = get_irq_chip_data(irq); int local_irq = gsc_find_local_irq(irq, irq_dev->global_irq, 32); u32 imr; DEBPRINTK(KERN_DEBUG "%s(%d) %s: IMR 0x%x\n", __func__, irq, irq_dev->name, imr); /* Enable the IRQ line by setting the bit in the IMR */ imr = gsc_readl(irq_dev->hpa + OFFSET_IMR); imr |= 1 << local_irq; gsc_writel(imr, irq_dev->hpa + OFFSET_IMR); /* * FIXME: read IPR to make sure the IRQ isn't already pending. * If so, we need to read IRR and manually call do_irq(). */ }
static void __init wax_init_irq(struct gsc_asic *wax) { unsigned long base = wax->hpa; /* */ gsc_writel(0x00000000, base+OFFSET_IMR); /* */ gsc_readl(base+OFFSET_IRR); /* */ /* */ // // }
static void __init wax_init_irq(struct gsc_asic *wax) { unsigned long base = wax->hpa; /* Wax-off */ gsc_writel(0x00000000, base+OFFSET_IMR); /* clear pending interrupts */ gsc_readl(base+OFFSET_IRR); /* We're not really convinced we want to reset the onboard * devices. Firmware does it for us... */ /* Resets */ // gsc_writel(0xFFFFFFFF, base+0x1000); /* HIL */ // gsc_writel(0xFFFFFFFF, base+0x2000); /* RS232-B on Wax */ }
/* ONLY called from entry.S:intr_extint() */ void do_cpu_irq_mask(struct pt_regs *regs) { struct pt_regs *old_regs; unsigned long eirr_val; int irq, cpu = smp_processor_id(); #ifdef CONFIG_SMP cpumask_t dest; #endif old_regs = set_irq_regs(regs); local_irq_disable(); irq_enter(); eirr_val = mfctl(23) & cpu_eiem & per_cpu(local_ack_eiem, cpu); if (!eirr_val) goto set_out; irq = eirr_to_irq(eirr_val); #ifdef CONFIG_SMP cpumask_copy(&dest, irq_desc[irq].affinity); if (CHECK_IRQ_PER_CPU(irq_desc[irq].status) && !cpu_isset(smp_processor_id(), dest)) { int cpu = first_cpu(dest); printk(KERN_DEBUG "redirecting irq %d from CPU %d to %d\n", irq, smp_processor_id(), cpu); gsc_writel(irq + CPU_IRQ_BASE, per_cpu(cpu_data, cpu).hpa); goto set_out; } #endif __do_IRQ(irq); out: irq_exit(); set_irq_regs(old_regs); return; set_out: set_eiem(cpu_eiem & per_cpu(local_ack_eiem, cpu)); goto out; }
static inline void ca(struct net_device *dev) { gsc_writel(0, dev->base_addr + PA_CHANNEL_ATTENTION); }
/* * Bring one cpu online. */ int smp_boot_one_cpu(int cpuid) { const struct cpuinfo_parisc *p = &per_cpu(cpu_data, cpuid); struct task_struct *idle; long timeout; /* * Create an idle task for this CPU. Note the address wed* give * to kernel_thread is irrelevant -- it's going to start * where OS_BOOT_RENDEVZ vector in SAL says to start. But * this gets all the other task-y sort of data structures set * up like we wish. We need to pull the just created idle task * off the run queue and stuff it into the init_tasks[] array. * Sheesh . . . */ idle = fork_idle(cpuid); if (IS_ERR(idle)) panic("SMP: fork failed for CPU:%d", cpuid); task_thread_info(idle)->cpu = cpuid; /* Let _start know what logical CPU we're booting ** (offset into init_tasks[],cpu_data[]) */ cpu_now_booting = cpuid; /* ** boot strap code needs to know the task address since ** it also contains the process stack. */ smp_init_current_idle_task = idle ; mb(); printk(KERN_INFO "Releasing cpu %d now, hpa=%lx\n", cpuid, p->hpa); /* ** This gets PDC to release the CPU from a very tight loop. ** ** From the PA-RISC 2.0 Firmware Architecture Reference Specification: ** "The MEM_RENDEZ vector specifies the location of OS_RENDEZ which ** is executed after receiving the rendezvous signal (an interrupt to ** EIR{0}). MEM_RENDEZ is valid only when it is nonzero and the ** contents of memory are valid." */ gsc_writel(TIMER_IRQ - CPU_IRQ_BASE, p->hpa); mb(); /* * OK, wait a bit for that CPU to finish staggering about. * Slave will set a bit when it reaches smp_cpu_init(). * Once the "monarch CPU" sees the bit change, it can move on. */ for (timeout = 0; timeout < 10000; timeout++) { if(cpu_online(cpuid)) { /* Which implies Slave has started up */ cpu_now_booting = 0; smp_init_current_idle_task = NULL; goto alive ; } udelay(100); barrier(); } put_task_struct(idle); idle = NULL; printk(KERN_CRIT "SMP: CPU:%d is stuck.\n", cpuid); return -1; alive: /* Remember the Slave data */ smp_debug(100, KERN_DEBUG "SMP: CPU:%d came alive after %ld _us\n", cpuid, timeout * 100); return 0; }
int __init lasi_init_chip(struct parisc_device *dev) { struct busdevice *lasi; struct gsc_irq gsc_irq; int irq, ret; lasi = kmalloc(sizeof(struct busdevice), GFP_KERNEL); if (!lasi) return -ENOMEM; lasi->name = "Lasi"; lasi->hpa = dev->hpa; /* Check the 4-bit (yes, only 4) version register */ lasi->version = gsc_readl(lasi->hpa + LASI_VER) & 0xf; printk(KERN_INFO "%s version %d at 0x%lx found.\n", lasi->name, lasi->version, lasi->hpa); /* initialize the chassis LEDs really early */ lasi_led_init(lasi->hpa); /* Stop LASI barking for a bit */ lasi_init_irq(lasi); /* the IRQ lasi should use */ irq = gsc_alloc_irq(&gsc_irq); if (irq < 0) { printk(KERN_ERR "%s(): cannot get GSC irq\n", __FUNCTION__); kfree(lasi); return -EBUSY; } ret = request_irq(gsc_irq.irq, busdev_barked, 0, "lasi", lasi); if (ret < 0) { kfree(lasi); return ret; } /* Save this for debugging later */ lasi->parent_irq = gsc_irq.irq; lasi->eim = ((u32) gsc_irq.txn_addr) | gsc_irq.txn_data; /* enable IRQ's for devices below LASI */ gsc_writel(lasi->eim, lasi->hpa + OFFSET_IAR); /* Done init'ing, register this driver */ ret = gsc_common_irqsetup(dev, lasi); if (ret) { kfree(lasi); return ret; } fixup_child_irqs(dev, lasi->busdev_region->data.irqbase, lasi_choose_irq); /* initialize the power off function */ /* FIXME: Record the LASI HPA for the power off function. This should * ensure that only the first LASI (the one controlling the power off) * should set the HPA here */ lasi_power_off_hpa = lasi->hpa; pm_power_off = lasi_power_off; return ret; }