static int myri_do_handshake(struct myri_eth *mp) { struct myri_shmem __iomem *shmem = mp->shmem; void __iomem *cregs = mp->cregs; struct myri_channel __iomem *chan = &shmem->channel; int tick = 0; DET(("myri_do_handshake: ")); if (sbus_readl(&chan->state) == STATE_READY) { DET(("Already STATE_READY, failed.\n")); return -1; /* We're hosed... */ } myri_disable_irq(mp->lregs, cregs); while (tick++ < 25) { u32 softstate; /* Wake it up. */ DET(("shakedown, CONTROL_WON, ")); sbus_writel(1, &shmem->shakedown); sbus_writel(CONTROL_WON, cregs + MYRICTRL_CTRL); softstate = sbus_readl(&chan->state); DET(("chanstate[%08x] ", softstate)); if (softstate == STATE_READY) { DET(("wakeup successful, ")); break; } if (softstate != STATE_WFN) { DET(("not WFN setting that, ")); sbus_writel(STATE_WFN, &chan->state); } udelay(20); } myri_enable_irq(mp->lregs, cregs); if (tick > 25) { DET(("25 ticks we lose, failure.\n")); return -1; } DET(("success\n")); return 0; }
void sun4m_unmask_profile_irq(void) { unsigned long flags; local_irq_save(flags); sbus_writel(sun4m_imask[SUN4M_PROFILE_IRQ], &sun4m_irq_global->mask_clear); local_irq_restore(flags); }
static void sun4m_unmask_irq(struct irq_data *data) { struct sun4m_handler_data *handler_data = data->handler_data; int cpu = smp_processor_id(); if (handler_data->mask) { unsigned long flags; local_irq_save(flags); if (handler_data->percpu) { sbus_writel(handler_data->mask, &sun4m_irq_percpu[cpu]->clear); } else { sbus_writel(handler_data->mask, &sun4m_irq_global->mask_clear); } local_irq_restore(flags); } }
static void parport_sunbpp_enable_irq(struct parport *p) { struct bpp_regs __iomem *regs = (struct bpp_regs __iomem *)p->base; u32 tmp; tmp = sbus_readl(®s->p_csr); tmp |= DMA_INT_ENAB; sbus_writel(tmp, ®s->p_csr); }
static void parport_sunbpp_disable_irq(struct parport *p) { struct bpp_regs *regs = (struct bpp_regs *)p->base; u32 tmp; tmp = sbus_readl(®s->p_csr); tmp &= ~DMA_INT_ENAB; sbus_writel(tmp, ®s->p_csr); }
static void leo_setcursormap (struct fb_info_sbusfb *fb, u8 *red, u8 *green, u8 *blue) { struct leo_cursor *l = fb->s.leo.cursor; unsigned long flags; int i; spin_lock_irqsave(&fb->lock, flags); for (i = 0; (sbus_readl(&l->cur_misc) & LEO_CUR_PROGRESS) && i < 300000; i++) udelay (1); /* Busy wait at most 0.3 sec */ if (i == 300000) goto out; /* Timed out - should we print some message? */ sbus_writel(LEO_CUR_TYPE_CMAP, &l->cur_type); sbus_writel((red[0] | (green[0]<<8) | (blue[0]<<16)), &l->cur_data); sbus_writel((red[1] | (green[1]<<8) | (blue[1]<<16)), &l->cur_data); sbus_writel(LEO_CUR_UPDATECMAP, &l->cur_misc); out: spin_unlock_irqrestore(&fb->lock, flags); }
void __init sun4m_init_IRQ(void) { struct device_node *dp = of_find_node_by_name(NULL, "interrupt"); int len, i, mid, num_cpu_iregs; const u32 *addr; if (!dp) { printk(KERN_ERR "sun4m_init_IRQ: No 'interrupt' node.\n"); return; } addr = of_get_property(dp, "address", &len); of_node_put(dp); if (!addr) { printk(KERN_ERR "sun4m_init_IRQ: No 'address' prop.\n"); return; } num_cpu_iregs = (len / sizeof(u32)) - 1; for (i = 0; i < num_cpu_iregs; i++) { sun4m_irq_percpu[i] = (void __iomem *) (unsigned long) addr[i]; } sun4m_irq_global = (void __iomem *) (unsigned long) addr[num_cpu_iregs]; local_irq_disable(); sbus_writel(~SUN4M_INT_MASKALL, &sun4m_irq_global->mask_set); for (i = 0; !cpu_find_by_instance(i, NULL, &mid); i++) sbus_writel(~0x17fff, &sun4m_irq_percpu[mid]->clear); if (num_cpu_iregs == 4) sbus_writel(0, &sun4m_irq_global->interrupt_target); sparc_config.init_timers = sun4m_init_timers; sparc_config.build_device_irq = sun4m_build_device_irq; sparc_config.clock_rate = SBUS_CLOCK_RATE; sparc_config.clear_clock_irq = sun4m_clear_clock_irq; sparc_config.load_profile_irq = sun4m_load_profile_irq; /* Cannot enable interrupts until OBP ticker is disabled. */ }
static int __devinit uctrl_probe(struct of_device *op, const struct of_device_id *match) { struct uctrl_driver *p; int err = -ENOMEM; p = kzalloc(sizeof(*p), GFP_KERNEL); if (!p) { printk(KERN_ERR "uctrl: Unable to allocate device struct.\n"); goto out; } p->regs = of_ioremap(&op->resource[0], 0, resource_size(&op->resource[0]), "uctrl"); if (!p->regs) { printk(KERN_ERR "uctrl: Unable to map registers.\n"); goto out_free; } p->irq = op->irqs[0]; err = request_irq(p->irq, uctrl_interrupt, 0, "uctrl", p); if (err) { printk(KERN_ERR "uctrl: Unable to register irq.\n"); goto out_iounmap; } err = misc_register(&uctrl_dev); if (err) { printk(KERN_ERR "uctrl: Unable to register misc device.\n"); goto out_free_irq; } sbus_writel(UCTRL_INTR_RXNE_REQ|UCTRL_INTR_RXNE_MSK, &p->regs->uctrl_intr); printk(KERN_INFO "%s: uctrl regs[0x%p] (irq %d)\n", op->dev.of_node->full_name, p->regs, p->irq); uctrl_get_event_status(p); uctrl_get_external_status(p); dev_set_drvdata(&op->dev, p); global_driver = p; out: return err; out_free_irq: free_irq(p->irq, p); out_iounmap: of_iounmap(&op->resource[0], p->regs, resource_size(&op->resource[0])); out_free: kfree(p); goto out; }
static void leo_restore_palette (struct fb_info_sbusfb *fb) { u32 tmp; unsigned long flags; spin_lock_irqsave(&fb->lock, flags); tmp = sbus_readl(&fb->s.leo.ld_ss1->ss1_misc); tmp &= ~(LEO_SS1_MISC_ENABLE); sbus_writel(tmp, &fb->s.leo.ld_ss1->ss1_misc); spin_unlock_irqrestore(&fb->lock, flags); }
static void leo_init_hw(struct fb_info *info) { struct leo_par *par = (struct leo_par *) info->par; u32 val; val = sbus_readl(&par->ld_ss1->ss1_misc); val |= LEO_SS1_MISC_ENABLE; sbus_writel(val, &par->ld_ss1->ss1_misc); leo_switch_from_graph(info); }
int vfc_csr_init(struct vfc_dev *dev) { dev->control_reg = 0x80000000; sbus_writel(dev->control_reg, &dev->regs->control); udelay(200); dev->control_reg &= ~0x80000000; sbus_writel(dev->control_reg, &dev->regs->control); udelay(100); sbus_writel(0x0f000000, &dev->regs->i2c_magic2); vfc_memptr_reset(dev); dev->control_reg &= ~VFC_CONTROL_DIAGMODE; dev->control_reg &= ~VFC_CONTROL_CAPTURE; dev->control_reg |= 0x40000000; sbus_writel(dev->control_reg, &dev->regs->control); vfc_captstat_reset(dev); return 0; }
int vfc_capture_start(struct vfc_dev *dev) { vfc_captstat_reset(dev); dev->control_reg = sbus_readl(&dev->regs->control); if((dev->control_reg & VFC_STATUS_CAPTURE)) { printk(KERN_ERR "vfc%d: vfc capture status not reset\n", dev->instance); return -EIO; } vfc_lock_device(dev); dev->control_reg &= ~VFC_CONTROL_CAPTURE; sbus_writel(dev->control_reg, &dev->regs->control); dev->control_reg |= VFC_CONTROL_CAPTURE; sbus_writel(dev->control_reg, &dev->regs->control); dev->control_reg &= ~VFC_CONTROL_CAPTURE; sbus_writel(dev->control_reg, &dev->regs->control); vfc_unlock_device(dev); return 0; }
static void bigmac_get_counters(struct bigmac *bp, void __iomem *bregs) { struct net_device_stats *stats = &bp->enet_stats; stats->rx_crc_errors += sbus_readl(bregs + BMAC_RCRCECTR); sbus_writel(0, bregs + BMAC_RCRCECTR); stats->rx_frame_errors += sbus_readl(bregs + BMAC_UNALECTR); sbus_writel(0, bregs + BMAC_UNALECTR); stats->rx_length_errors += sbus_readl(bregs + BMAC_GLECTR); sbus_writel(0, bregs + BMAC_GLECTR); stats->tx_aborted_errors += sbus_readl(bregs + BMAC_EXCTR); stats->collisions += (sbus_readl(bregs + BMAC_EXCTR) + sbus_readl(bregs + BMAC_LTCTR)); sbus_writel(0, bregs + BMAC_EXCTR); sbus_writel(0, bregs + BMAC_LTCTR); }
static void myri_init_rings(struct myri_eth *mp, int from_irq) { struct recvq __iomem *rq = mp->rq; struct myri_rxd __iomem *rxd = &rq->myri_rxd[0]; struct net_device *dev = mp->dev; gfp_t gfp_flags = GFP_KERNEL; int i; if (from_irq || in_interrupt()) gfp_flags = GFP_ATOMIC; myri_clean_rings(mp); for (i = 0; i < RX_RING_SIZE; i++) { struct sk_buff *skb = myri_alloc_skb(RX_ALLOC_SIZE, gfp_flags); u32 dma_addr; if (!skb) continue; mp->rx_skbs[i] = skb; skb->dev = dev; skb_put(skb, RX_ALLOC_SIZE); dma_addr = dma_map_single(&mp->myri_op->dev, skb->data, RX_ALLOC_SIZE, DMA_FROM_DEVICE); sbus_writel(dma_addr, &rxd[i].myri_scatters[0].addr); sbus_writel(RX_ALLOC_SIZE, &rxd[i].myri_scatters[0].len); sbus_writel(i, &rxd[i].ctx); sbus_writel(1, &rxd[i].num_sg); } sbus_writel(0, &rq->head); sbus_writel(RX_RING_SIZE, &rq->tail); }
static void leo_switch_from_graph (struct fb_info_sbusfb *fb) { register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr; register struct leo_ld *ss = (struct leo_ld *) fb->s.leo.ld_ss0; unsigned long flags; spin_lock_irqsave(&fb->lock, flags); sbus_writel(0xffffffff, &ss->wid); sbus_writel(0xffff, &ss->wmask); sbus_writel(0, &ss->vclipmin); sbus_writel(fb->s.leo.extent, &ss->vclipmax); sbus_writel(0xff000000, &ss->planemask); sbus_writel(0x310850, &ss->rop); sbus_writel(0, &ss->widclip); sbus_writel(4, &us->addrspace); sbus_writel(0, &us->fontt); spin_unlock_irqrestore(&fb->lock, flags); }
static void write_tcvr_bit(struct bigmac *bp, void __iomem *tregs, int bit) { if (bp->tcvr_type == internal) { bit = (bit & 1) << 3; sbus_writel(bit | (MGMT_PAL_OENAB | MGMT_PAL_EXT_MDIO), tregs + TCVR_MPAL); sbus_readl(tregs + TCVR_MPAL); sbus_writel(bit | MGMT_PAL_OENAB | MGMT_PAL_EXT_MDIO | MGMT_PAL_DCLOCK, tregs + TCVR_MPAL); sbus_readl(tregs + TCVR_MPAL); } else if (bp->tcvr_type == external) { bit = (bit & 1) << 2; sbus_writel(bit | MGMT_PAL_INT_MDIO | MGMT_PAL_OENAB, tregs + TCVR_MPAL); sbus_readl(tregs + TCVR_MPAL); sbus_writel(bit | MGMT_PAL_INT_MDIO | MGMT_PAL_OENAB | MGMT_PAL_DCLOCK, tregs + TCVR_MPAL); sbus_readl(tregs + TCVR_MPAL); } else { printk(KERN_ERR "write_tcvr_bit: No transceiver type known!\n"); } }
static void myri_clean_rings(struct myri_eth *mp) { struct sendq __iomem *sq = mp->sq; struct recvq __iomem *rq = mp->rq; int i; sbus_writel(0, &rq->tail); sbus_writel(0, &rq->head); for (i = 0; i < (RX_RING_SIZE+1); i++) { if (mp->rx_skbs[i] != NULL) { struct myri_rxd __iomem *rxd = &rq->myri_rxd[i]; u32 dma_addr; dma_addr = sbus_readl(&rxd->myri_scatters[0].addr); dma_unmap_single(&mp->myri_op->dev, dma_addr, RX_ALLOC_SIZE, DMA_FROM_DEVICE); dev_kfree_skb(mp->rx_skbs[i]); mp->rx_skbs[i] = NULL; } } mp->tx_old = 0; sbus_writel(0, &sq->tail); sbus_writel(0, &sq->head); for (i = 0; i < TX_RING_SIZE; i++) { if (mp->tx_skbs[i] != NULL) { struct sk_buff *skb = mp->tx_skbs[i]; struct myri_txd __iomem *txd = &sq->myri_txd[i]; u32 dma_addr; dma_addr = sbus_readl(&txd->myri_gathers[0].addr); dma_unmap_single(&mp->myri_op->dev, dma_addr, (skb->len + 3) & ~3, DMA_TO_DEVICE); dev_kfree_skb(mp->tx_skbs[i]); mp->tx_skbs[i] = NULL; } } }
/* Load cursor information */ static void leo_setcursor (struct fb_info_sbusfb *fb) { struct cg_cursor *c = &fb->cursor; struct leo_cursor *l = fb->s.leo.cursor; unsigned long flags; u32 tmp; spin_lock_irqsave(&fb->lock, flags); tmp = sbus_readl(&l->cur_misc); tmp &= ~LEO_CUR_ENABLE; sbus_writel(tmp, &l->cur_misc); sbus_writel(((c->cpos.fbx - c->chot.fbx) & 0x7ff) | (((c->cpos.fby - c->chot.fby) & 0x7ff) << 11), &l->cur_cursxy); tmp = sbus_readl(&l->cur_misc); tmp |= LEO_CUR_UPDATE; if (c->enable) tmp |= LEO_CUR_ENABLE; sbus_writel(tmp, &l->cur_misc); spin_unlock_irqrestore(&fb->lock, flags); }
static void sun4m_enable_irq(unsigned int irq_nr) { unsigned long mask, flags; int cpu = smp_processor_id(); /* Dreadful floppy hack. When we use 0x2b instead of * 0x0b the system blows (it starts to whistle!). * So we continue to use 0x0b. Fixme ASAP. --P3 */ if (irq_nr != 0x0b) { mask = sun4m_get_irqmask(irq_nr); local_irq_save(flags); if (irq_nr > 15) sbus_writel(mask, &sun4m_irq_global->mask_clear); else sbus_writel(mask, &sun4m_irq_percpu[cpu]->clear); local_irq_restore(flags); } else { local_irq_save(flags); sbus_writel(SUN4M_INT_FLOPPY, &sun4m_irq_global->mask_clear); local_irq_restore(flags); } }
static void leo_fill(struct fb_info_sbusfb *fb, struct display *p, int s, int count, unsigned short *boxes) { int i; register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr; register struct leo_ld *ss = (struct leo_ld *) fb->s.leo.ld_ss0; unsigned long flags; spin_lock_irqsave(&fb->lock, flags); sbus_writel((attr_bgcol(p,s)<<24), &ss->fg); while (count-- > 0) { do { i = sbus_readl(&us->csr); } while (i & 0x20000000); sbus_writel((boxes[2] - boxes[0] - 1) | ((boxes[3] - boxes[1] - 1) << 11), &us->extent); sbus_writel(boxes[0] | (boxes[1] << 11) | 0x80000000, &us->fill); boxes += 4; } spin_unlock_irqrestore(&fb->lock, flags); }
static void bigmac_rx_reset(void __iomem *bregs) { int tries = RX_RESET_TRIES; sbus_writel(0, bregs + BMAC_RXCFG); while (sbus_readl(bregs + BMAC_RXCFG) && --tries) udelay(20); if (!tries) { printk(KERN_ERR "BIGMAC: Receiver will not reset.\n"); printk(KERN_ERR "BIGMAC: rx_cfg is %08x\n", sbus_readl(bregs + BMAC_RXCFG)); } }
static void leo_wid_put(struct fb_info *info, struct fb_wid_list *wl) { struct leo_par *par = (struct leo_par *) info->par; struct leo_lx_krn __iomem *lx_krn = par->lx_krn; struct fb_wid_item *wi; unsigned long flags; u32 val; int i, j; spin_lock_irqsave(&par->lock, flags); leo_wait(lx_krn); for (i = 0, wi = wl->wl_list; i < wl->wl_count; i++, wi++) { switch(wi->wi_type) { case FB_WID_DBL_8: j = (wi->wi_index & 0xf) + 0x40; break; case FB_WID_DBL_24: j = wi->wi_index & 0x3f; break; default: continue; }; sbus_writel(0x5800 + j, &lx_krn->krn_type); sbus_writel(wi->wi_values[0], &lx_krn->krn_value); } sbus_writel(LEO_KRN_TYPE_WID, &lx_krn->krn_type); val = sbus_readl(&lx_krn->krn_csr); val |= (LEO_KRN_CSR_UNK | LEO_KRN_CSR_UNK2); sbus_writel(val, &lx_krn->krn_csr); spin_unlock_irqrestore(&par->lock, flags); }
static int __init leo_wid_put (struct fb_info_sbusfb *fb, struct fb_wid_list *wl) { struct leo_lx_krn *lx_krn = fb->s.leo.lx_krn; struct fb_wid_item *wi; int i, j; sbus_writel(LEO_KRN_TYPE_WID, &lx_krn->krn_type); i = leo_wait (lx_krn); if (i) return i; for (i = 0, wi = wl->wl_list; i < wl->wl_count; i++, wi++) { switch (wi->wi_type) { case FB_WID_DBL_8: j = (wi->wi_index & 0xf) + 0x40; break; case FB_WID_DBL_24: j = wi->wi_index & 0x3f; break; default: return -EINVAL; } sbus_writel(0x5800 + j, &lx_krn->krn_type); sbus_writel(wi->wi_values[0], &lx_krn->krn_value); } sbus_writel(LEO_KRN_TYPE_WID, &lx_krn->krn_type); sbus_writel(3, &lx_krn->krn_csr); return 0; }
/** * leo_setcolreg - Optional function. Sets a color register. * @regno: boolean, 0 copy local, 1 get_user() function * @red: frame buffer colormap structure * @green: The green value which can be up to 16 bits wide * @blue: The blue value which can be up to 16 bits wide. * @transp: If supported the alpha value which can be up to 16 bits wide. * @info: frame buffer info structure */ static int leo_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *info) { struct leo_par *par = (struct leo_par *) info->par; struct leo_lx_krn __iomem *lx_krn = par->lx_krn; unsigned long flags; u32 val; int i; if (regno >= 256) return 1; red >>= 8; green >>= 8; blue >>= 8; par->clut_data[regno] = red | (green << 8) | (blue << 16); spin_lock_irqsave(&par->lock, flags); leo_wait(lx_krn); sbus_writel(LEO_KRN_TYPE_CLUTDATA, &lx_krn->krn_type); for (i = 0; i < 256; i++) sbus_writel(par->clut_data[i], &lx_krn->krn_value); sbus_writel(LEO_KRN_TYPE_CLUT0, &lx_krn->krn_type); val = sbus_readl(&lx_krn->krn_csr); val |= (LEO_KRN_CSR_UNK | LEO_KRN_CSR_UNK2); sbus_writel(val, &lx_krn->krn_csr); spin_unlock_irqrestore(&par->lock, flags); return 0; }
static void __init sun4c_init_timers(irq_handler_t counter_fn) { const struct linux_prom_irqs *prom_irqs; struct device_node *dp; unsigned int irq; const u32 *addr; int err; dp = of_find_node_by_name(NULL, "counter-timer"); if (!dp) { prom_printf("sun4c_init_timers: Unable to find counter-timer\n"); prom_halt(); } addr = of_get_property(dp, "address", NULL); if (!addr) { prom_printf("sun4c_init_timers: No address property\n"); prom_halt(); } sun4c_timers = (void __iomem *) (unsigned long) addr[0]; prom_irqs = of_get_property(dp, "intr", NULL); of_node_put(dp); if (!prom_irqs) { prom_printf("sun4c_init_timers: No intr property\n"); prom_halt(); } /* Have the level 10 timer tick at 100HZ. We don't touch the * level 14 timer limit since we are letting the prom handle * them until we have a real console driver so L1-A works. */ sbus_writel((((1000000/HZ) + 1) << 10), &sun4c_timers->l10_limit); master_l10_counter = &sun4c_timers->l10_count; irq = sun4c_build_device_irq(NULL, prom_irqs[0].pri); err = request_irq(irq, counter_fn, IRQF_TIMER, "timer", NULL); if (err) { prom_printf("sun4c_init_timers: request_irq() fails with %d\n", err); prom_halt(); } /* disable timer interrupt */ sun4c_mask_irq(irq_get_irq_data(irq)); }
static int qec_global_reset(void __iomem *gregs) { int tries = QEC_RESET_TRIES; sbus_writel(GLOB_CTRL_RESET, gregs + GLOB_CTRL); while (--tries) { if (sbus_readl(gregs + GLOB_CTRL) & GLOB_CTRL_RESET) { udelay(20); continue; } break; } if (tries) return 0; printk(KERN_ERR "BigMAC: Cannot reset the QEC.\n"); return -1; }
/* Reset control plane so that WID is 8-bit plane. */ static void __tcx_set_control_plane (struct tcx_par *par) { u32 __iomem *p, *pend; if (par->lowdepth) return; p = par->cplane; if (p == NULL) return; for (pend = p + par->fbsize; p < pend; p++) { u32 tmp = sbus_readl(p); tmp &= 0xffffff; sbus_writel(tmp, p); } }
static int __init leo_rasterimg (struct fb_info *info, int start) { struct fb_info_sbusfb *fb = sbusfbinfo(info); register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr; register struct leo_ld *ss = (struct leo_ld *) fb->s.leo.ld_ss0; if (start) { sbus_writel(1, &ss->wid); sbus_writel(0xffffff, &ss->planemask); sbus_writel(0x310b90, &ss->rop); sbus_writel(0, &us->addrspace); } else { sbus_writel(0xffffffff, &ss->wid); sbus_writel(0xff000000, &ss->planemask); sbus_writel(0x310850, &ss->rop); sbus_writel(4, &us->addrspace); } return 0; }
static void __init sun4c_init_timers(irq_handler_t counter_fn) { const struct linux_prom_irqs *irq; struct device_node *dp; const u32 *addr; int err; dp = of_find_node_by_name(NULL, "counter-timer"); if (!dp) { prom_printf("sun4c_init_timers: Unable to find counter-timer\n"); prom_halt(); } addr = of_get_property(dp, "address", NULL); if (!addr) { prom_printf("sun4c_init_timers: No address property\n"); prom_halt(); } sun4c_timers = (void __iomem *) (unsigned long) addr[0]; irq = of_get_property(dp, "intr", NULL); if (!irq) { prom_printf("sun4c_init_timers: No intr property\n"); prom_halt(); } /* Have the level 10 timer tick at 100HZ. We don't touch the * level 14 timer limit since we are letting the prom handle * them until we have a real console driver so L1-A works. */ sbus_writel((((1000000/HZ) + 1) << 10), &sun4c_timers->l10_limit); master_l10_counter = &sun4c_timers->l10_count; err = request_irq(irq[0].pri, counter_fn, (IRQF_DISABLED | SA_STATIC_ALLOC), "timer", NULL); if (err) { prom_printf("sun4c_init_timers: request_irq() fails with %d\n", err); prom_halt(); } sun4c_disable_irq(irq[1].pri); }
static inline int qec_global_reset(void __iomem *gregs) { int tries = QEC_RESET_TRIES; sbus_writel(GLOB_CTRL_RESET, gregs + GLOB_CTRL); while (--tries) { u32 tmp = sbus_readl(gregs + GLOB_CTRL); if (tmp & GLOB_CTRL_RESET) { udelay(20); continue; } break; } if (tries) return 0; printk(KERN_ERR "QuadEther: AIEEE cannot reset the QEC!\n"); return -1; }