From ab13446616118dc61c00ea50cc49919400717dd0 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Mon, 3 Jul 2006 17:19:48 +1000 Subject: [POWERPC] Fix various offb and BootX-related issues This patch fixes various issues with offb (the default fbdev used on powerpc when no proper fbdev is supported). It was broken when using BootX under some circumstances and would fail to properly get the framebuffer base address in others. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras --- drivers/video/offb.c | 284 +++++++++++++++++++++------------------------------ 1 file changed, 118 insertions(+), 166 deletions(-) (limited to 'drivers') diff --git a/drivers/video/offb.c b/drivers/video/offb.c index bfeb11bd471..71ce1fa45cf 100644 --- a/drivers/video/offb.c +++ b/drivers/video/offb.c @@ -97,14 +97,43 @@ static int offb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, u_int transp, struct fb_info *info) { struct offb_par *par = (struct offb_par *) info->par; + int i, depth; + u32 *pal = info->pseudo_palette; - if (!par->cmap_adr || regno > 255) + depth = info->var.bits_per_pixel; + if (depth == 16) + depth = (info->var.green.length == 5) ? 15 : 16; + + if (regno > 255 || + (depth == 16 && regno > 63) || + (depth == 15 && regno > 31)) return 1; + if (regno < 16) { + switch (depth) { + case 15: + pal[regno] = (regno << 10) | (regno << 5) | regno; + break; + case 16: + pal[regno] = (regno << 11) | (regno << 5) | regno; + break; + case 24: + pal[regno] = (regno << 16) | (regno << 8) | regno; + break; + case 32: + i = (regno << 8) | regno; + pal[regno] = (i << 16) | i; + break; + } + } + red >>= 8; green >>= 8; blue >>= 8; + if (!par->cmap_adr) + return 0; + switch (par->cmap_type) { case cmap_m64: writeb(regno, par->cmap_adr); @@ -141,20 +170,6 @@ static int offb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, break; } - if (regno < 16) - switch (info->var.bits_per_pixel) { - case 16: - ((u16 *) (info->pseudo_palette))[regno] = - (regno << 10) | (regno << 5) | regno; - break; - case 32: - { - int i = (regno << 8) | regno; - ((u32 *) (info->pseudo_palette))[regno] = - (i << 16) | i; - break; - } - } return 0; } @@ -223,81 +238,9 @@ int __init offb_init(void) { struct device_node *dp = NULL, *boot_disp = NULL; -#if defined(CONFIG_BOOTX_TEXT) && defined(CONFIG_PPC32) - struct device_node *macos_display = NULL; -#endif if (fb_get_options("offb", NULL)) return -ENODEV; -#if defined(CONFIG_BOOTX_TEXT) && defined(CONFIG_PPC32) - /* If we're booted from BootX... */ - if (boot_infos != 0) { - unsigned long addr = - (unsigned long) boot_infos->dispDeviceBase; - u32 *addrp; - u64 daddr, dsize; - unsigned int flags; - - /* find the device node corresponding to the macos display */ - while ((dp = of_find_node_by_type(dp, "display"))) { - int i; - - /* - * Look for an AAPL,address property first. - */ - unsigned int na; - unsigned int *ap = - (unsigned int *)get_property(dp, "AAPL,address", - &na); - if (ap != 0) { - for (na /= sizeof(unsigned int); na > 0; - --na, ++ap) - if (*ap <= addr && - addr < *ap + 0x1000000) { - macos_display = dp; - goto foundit; - } - } - - /* - * See if the display address is in one of the address - * ranges for this display. - */ - i = 0; - for (;;) { - addrp = of_get_address(dp, i++, &dsize, &flags); - if (addrp == NULL) - break; - if (!(flags & IORESOURCE_MEM)) - continue; - daddr = of_translate_address(dp, addrp); - if (daddr == OF_BAD_ADDR) - continue; - if (daddr <= addr && addr < (daddr + dsize)) { - macos_display = dp; - goto foundit; - } - } - foundit: - if (macos_display) { - printk(KERN_INFO "MacOS display is %s\n", - dp->full_name); - break; - } - } - - /* initialize it */ - offb_init_fb(macos_display ? macos_display-> - name : "MacOS display", - macos_display ? macos_display-> - full_name : "MacOS display", - boot_infos->dispDeviceRect[2], - boot_infos->dispDeviceRect[3], - boot_infos->dispDeviceDepth, - boot_infos->dispDeviceRowBytes, addr, NULL); - } -#endif /* defined(CONFIG_BOOTX_TEXT) && defined(CONFIG_PPC32) */ - for (dp = NULL; (dp = of_find_node_by_type(dp, "display"));) { if (get_property(dp, "linux,opened", NULL) && get_property(dp, "linux,boot-display", NULL)) { @@ -317,94 +260,93 @@ int __init offb_init(void) static void __init offb_init_nodriver(struct device_node *dp) { - int *pp, i; unsigned int len; - int width = 640, height = 480, depth = 8, pitch; - unsigned int flags, rsize, *up; - u64 address = OF_BAD_ADDR; - u32 *addrp; + int i, width = 640, height = 480, depth = 8, pitch = 640; + unsigned int flags, rsize, addr_prop = 0; + unsigned long max_size = 0; + u64 rstart, address = OF_BAD_ADDR; + u32 *pp, *addrp, *up; u64 asize; - if ((pp = (int *) get_property(dp, "depth", &len)) != NULL - && len == sizeof(int)) + pp = (u32 *)get_property(dp, "linux,bootx-depth", &len); + if (pp == NULL) + pp = (u32 *)get_property(dp, "depth", &len); + if (pp && len == sizeof(u32)) depth = *pp; - if ((pp = (int *) get_property(dp, "width", &len)) != NULL - && len == sizeof(int)) + + pp = (u32 *)get_property(dp, "linux,bootx-width", &len); + if (pp == NULL) + pp = (u32 *)get_property(dp, "width", &len); + if (pp && len == sizeof(u32)) width = *pp; - if ((pp = (int *) get_property(dp, "height", &len)) != NULL - && len == sizeof(int)) + + pp = (u32 *)get_property(dp, "linux,bootx-height", &len); + if (pp == NULL) + pp = (u32 *)get_property(dp, "height", &len); + if (pp && len == sizeof(u32)) height = *pp; - if ((pp = (int *) get_property(dp, "linebytes", &len)) != NULL - && len == sizeof(int)) { + + pp = (u32 *)get_property(dp, "linux,bootx-linebytes", &len); + if (pp == NULL) + pp = (u32 *)get_property(dp, "linebytes", &len); + if (pp && len == sizeof(u32)) pitch = *pp; - if (pitch == 1) - pitch = 0x1000; - } else - pitch = width; - - rsize = (unsigned long)pitch * (unsigned long)height * - (unsigned long)(depth / 8); - - /* Try to match device to a PCI device in order to get a properly - * translated address rather then trying to decode the open firmware - * stuff in various incorrect ways - */ -#ifdef CONFIG_PCI - /* First try to locate the PCI device if any */ - { - struct pci_dev *pdev = NULL; - - for_each_pci_dev(pdev) { - if (dp == pci_device_to_OF_node(pdev)) - break; - } - if (pdev) { - for (i = 0; i < 6 && address == OF_BAD_ADDR; i++) { - if ((pci_resource_flags(pdev, i) & - IORESOURCE_MEM) && - (pci_resource_len(pdev, i) >= rsize)) - address = pci_resource_start(pdev, i); - } - pci_dev_put(pdev); - } - } -#endif /* CONFIG_PCI */ - - /* This one is dodgy, we may drop it ... */ - if (address == OF_BAD_ADDR && - (up = (unsigned *) get_property(dp, "address", &len)) != NULL && - len == sizeof(unsigned int)) - address = (u64) * up; - - if (address == OF_BAD_ADDR) { - for (i = 0; (addrp = of_get_address(dp, i, &asize, &flags)) - != NULL; i++) { - if (!(flags & IORESOURCE_MEM)) - continue; - if (asize >= pitch * height * depth / 8) - break; - } - if (addrp == NULL) { - printk(KERN_ERR - "no framebuffer address found for %s\n", - dp->full_name); - return; - } - address = of_translate_address(dp, addrp); - if (address == OF_BAD_ADDR) { - printk(KERN_ERR - "can't translate framebuffer address for %s\n", - dp->full_name); - return; + else + pitch = width * ((depth + 7) / 8); + + rsize = (unsigned long)pitch * (unsigned long)height; + + /* Ok, now we try to figure out the address of the framebuffer. + * + * Unfortunately, Open Firmware doesn't provide a standard way to do + * so. All we can do is a dodgy heuristic that happens to work in + * practice. On most machines, the "address" property contains what + * we need, though not on Matrox cards found in IBM machines. What I've + * found that appears to give good results is to go through the PCI + * ranges and pick one that is both big enough and if possible encloses + * the "address" property. If none match, we pick the biggest + */ + up = (u32 *)get_property(dp, "linux,bootx-addr", &len); + if (up == NULL) + up = (u32 *)get_property(dp, "address", &len); + if (up && len == sizeof(u32)) + addr_prop = *up; + + for (i = 0; (addrp = of_get_address(dp, i, &asize, &flags)) + != NULL; i++) { + int match_addrp = 0; + + if (!(flags & IORESOURCE_MEM)) + continue; + if (asize < rsize) + continue; + rstart = of_translate_address(dp, addrp); + if (rstart == OF_BAD_ADDR) + continue; + if (addr_prop && (rstart <= addr_prop) && + ((rstart + asize) >= (addr_prop + rsize))) + match_addrp = 1; + if (match_addrp) { + address = addr_prop; + break; } + if (rsize > max_size) { + max_size = rsize; + address = OF_BAD_ADDR; + } + if (address == OF_BAD_ADDR) + address = rstart; + } + if (address == OF_BAD_ADDR && addr_prop) + address = (u64)addr_prop; + if (address != OF_BAD_ADDR) { /* kludge for valkyrie */ if (strcmp(dp->name, "valkyrie") == 0) address += 0x1000; + offb_init_fb(dp->name, dp->full_name, width, height, depth, + pitch, address, dp); } - offb_init_fb(dp->name, dp->full_name, width, height, depth, - pitch, address, dp); - } static void __init offb_init_fb(const char *name, const char *full_name, @@ -412,7 +354,7 @@ static void __init offb_init_fb(const char *name, const char *full_name, int pitch, unsigned long address, struct device_node *dp) { - unsigned long res_size = pitch * height * depth / 8; + unsigned long res_size = pitch * height * (depth + 7) / 8; struct offb_par *par = &default_par; unsigned long res_start = address; struct fb_fix_screeninfo *fix; @@ -426,7 +368,7 @@ static void __init offb_init_fb(const char *name, const char *full_name, printk(KERN_INFO "Using unsupported %dx%d %s at %lx, depth=%d, pitch=%d\n", width, height, name, address, depth, pitch); - if (depth != 8 && depth != 16 && depth != 32) { + if (depth != 8 && depth != 15 && depth != 16 && depth != 32) { printk(KERN_ERR "%s: can't use depth = %d\n", full_name, depth); release_mem_region(res_start, res_size); @@ -502,7 +444,6 @@ static void __init offb_init_fb(const char *name, const char *full_name, : */ FB_VISUAL_TRUECOLOR; var->xoffset = var->yoffset = 0; - var->bits_per_pixel = depth; switch (depth) { case 8: var->bits_per_pixel = 8; @@ -515,7 +456,7 @@ static void __init offb_init_fb(const char *name, const char *full_name, var->transp.offset = 0; var->transp.length = 0; break; - case 16: /* RGB 555 */ + case 15: /* RGB 555 */ var->bits_per_pixel = 16; var->red.offset = 10; var->red.length = 5; @@ -526,6 +467,17 @@ static void __init offb_init_fb(const char *name, const char *full_name, var->transp.offset = 0; var->transp.length = 0; break; + case 16: /* RGB 565 */ + var->bits_per_pixel = 16; + var->red.offset = 11; + var->red.length = 5; + var->green.offset = 5; + var->green.length = 6; + var->blue.offset = 0; + var->blue.length = 5; + var->transp.offset = 0; + var->transp.length = 0; + break; case 32: /* RGB 888 */ var->bits_per_pixel = 32; var->red.offset = 16; -- cgit v1.2.3 From 3e9a69275f23baec86b54febc5dad0b2fc7fb200 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Mon, 3 Jul 2006 17:25:26 +1000 Subject: [POWERPC] Update the SWIM3 (powermac) floppy driver Port the PowerMac floppy driver (swim3) to use the macio device infrastructure. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras --- drivers/block/swim3.c | 230 ++++++++++++++++++++++++++++---------------------- 1 file changed, 130 insertions(+), 100 deletions(-) (limited to 'drivers') diff --git a/drivers/block/swim3.c b/drivers/block/swim3.c index 3721e12135d..cc42e762396 100644 --- a/drivers/block/swim3.c +++ b/drivers/block/swim3.c @@ -250,8 +250,6 @@ static int floppy_open(struct inode *inode, struct file *filp); static int floppy_release(struct inode *inode, struct file *filp); static int floppy_check_change(struct gendisk *disk); static int floppy_revalidate(struct gendisk *disk); -static int swim3_add_device(struct device_node *swims); -int swim3_init(void); #ifndef CONFIG_PMAC_MEDIABAY #define check_media_bay(which, what) 1 @@ -1011,114 +1009,63 @@ static struct block_device_operations floppy_fops = { .revalidate_disk= floppy_revalidate, }; -int swim3_init(void) -{ - struct device_node *swim; - int err = -ENOMEM; - int i; - - swim = find_devices("floppy"); - while (swim && (floppy_count < MAX_FLOPPIES)) - { - swim3_add_device(swim); - swim = swim->next; - } - - swim = find_devices("swim3"); - while (swim && (floppy_count < MAX_FLOPPIES)) - { - swim3_add_device(swim); - swim = swim->next; - } - - if (!floppy_count) - return -ENODEV; - - for (i = 0; i < floppy_count; i++) { - disks[i] = alloc_disk(1); - if (!disks[i]) - goto out; - } - - if (register_blkdev(FLOPPY_MAJOR, "fd")) { - err = -EBUSY; - goto out; - } - - swim3_queue = blk_init_queue(do_fd_request, &swim3_lock); - if (!swim3_queue) { - err = -ENOMEM; - goto out_queue; - } - - for (i = 0; i < floppy_count; i++) { - struct gendisk *disk = disks[i]; - disk->major = FLOPPY_MAJOR; - disk->first_minor = i; - disk->fops = &floppy_fops; - disk->private_data = &floppy_states[i]; - disk->queue = swim3_queue; - disk->flags |= GENHD_FL_REMOVABLE; - sprintf(disk->disk_name, "fd%d", i); - set_capacity(disk, 2880); - add_disk(disk); - } - return 0; - -out_queue: - unregister_blkdev(FLOPPY_MAJOR, "fd"); -out: - while (i--) - put_disk(disks[i]); - /* shouldn't we do something with results of swim_add_device()? */ - return err; -} - -static int swim3_add_device(struct device_node *swim) +static int swim3_add_device(struct macio_dev *mdev, int index) { + struct device_node *swim = mdev->ofdev.node; struct device_node *mediabay; - struct floppy_state *fs = &floppy_states[floppy_count]; - struct resource res_reg, res_dma; + struct floppy_state *fs = &floppy_states[index]; + int rc = -EBUSY; - if (of_address_to_resource(swim, 0, &res_reg) || - of_address_to_resource(swim, 1, &res_dma)) { - printk(KERN_ERR "swim3: Can't get addresses\n"); - return -EINVAL; + /* Check & Request resources */ + if (macio_resource_count(mdev) < 2) { + printk(KERN_WARNING "ifd%d: no address for %s\n", + index, swim->full_name); + return -ENXIO; } - if (request_mem_region(res_reg.start, res_reg.end - res_reg.start + 1, - " (reg)") == NULL) { - printk(KERN_ERR "swim3: Can't request register space\n"); - return -EINVAL; + if (macio_irq_count(mdev) < 2) { + printk(KERN_WARNING "fd%d: no intrs for device %s\n", + index, swim->full_name); } - if (request_mem_region(res_dma.start, res_dma.end - res_dma.start + 1, - " (dma)") == NULL) { - release_mem_region(res_reg.start, - res_reg.end - res_reg.start + 1); - printk(KERN_ERR "swim3: Can't request DMA space\n"); - return -EINVAL; + if (macio_request_resource(mdev, 0, "swim3 (mmio)")) { + printk(KERN_ERR "fd%d: can't request mmio resource for %s\n", + index, swim->full_name); + return -EBUSY; } - - if (swim->n_intrs < 2) { - printk(KERN_INFO "swim3: expecting 2 intrs (n_intrs:%d)\n", - swim->n_intrs); - release_mem_region(res_reg.start, - res_reg.end - res_reg.start + 1); - release_mem_region(res_dma.start, - res_dma.end - res_dma.start + 1); - return -EINVAL; + if (macio_request_resource(mdev, 1, "swim3 (dma)")) { + printk(KERN_ERR "fd%d: can't request dma resource for %s\n", + index, swim->full_name); + macio_release_resource(mdev, 0); + return -EBUSY; } + dev_set_drvdata(&mdev->ofdev.dev, fs); - mediabay = (strcasecmp(swim->parent->type, "media-bay") == 0) ? swim->parent : NULL; + mediabay = (strcasecmp(swim->parent->type, "media-bay") == 0) ? + swim->parent : NULL; if (mediabay == NULL) pmac_call_feature(PMAC_FTR_SWIM3_ENABLE, swim, 0, 1); memset(fs, 0, sizeof(*fs)); spin_lock_init(&fs->lock); fs->state = idle; - fs->swim3 = (struct swim3 __iomem *)ioremap(res_reg.start, 0x200); - fs->dma = (struct dbdma_regs __iomem *)ioremap(res_dma.start, 0x200); - fs->swim3_intr = swim->intrs[0].line; - fs->dma_intr = swim->intrs[1].line; + fs->swim3 = (struct swim3 __iomem *) + ioremap(macio_resource_start(mdev, 0), 0x200); + if (fs->swim3 == NULL) { + printk("fd%d: couldn't map registers for %s\n", + index, swim->full_name); + rc = -ENOMEM; + goto out_release; + } + fs->dma = (struct dbdma_regs __iomem *) + ioremap(macio_resource_start(mdev, 1), 0x200); + if (fs->dma == NULL) { + printk("fd%d: couldn't map DMA for %s\n", + index, swim->full_name); + iounmap(fs->swim3); + rc = -ENOMEM; + goto out_release; + } + fs->swim3_intr = macio_irq(mdev, 0); + fs->dma_intr = macio_irq(mdev, 1);; fs->cur_cyl = -1; fs->cur_sector = -1; fs->secpercyl = 36; @@ -1132,15 +1079,16 @@ static int swim3_add_device(struct device_node *swim) st_le16(&fs->dma_cmd[1].command, DBDMA_STOP); if (request_irq(fs->swim3_intr, swim3_interrupt, 0, "SWIM3", fs)) { - printk(KERN_ERR "Couldn't get irq %d for SWIM3\n", fs->swim3_intr); + printk(KERN_ERR "fd%d: couldn't request irq %d for %s\n", + index, fs->swim3_intr, swim->full_name); pmac_call_feature(PMAC_FTR_SWIM3_ENABLE, swim, 0, 0); + goto out_unmap; return -EBUSY; } /* if (request_irq(fs->dma_intr, fd_dma_interrupt, 0, "SWIM3-dma", fs)) { printk(KERN_ERR "Couldn't get irq %d for SWIM3 DMA", fs->dma_intr); - pmac_call_feature(PMAC_FTR_SWIM3_ENABLE, swim, 0, 0); return -EBUSY; } */ @@ -1150,8 +1098,90 @@ static int swim3_add_device(struct device_node *swim) printk(KERN_INFO "fd%d: SWIM3 floppy controller %s\n", floppy_count, mediabay ? "in media bay" : ""); - floppy_count++; - + return 0; + + out_unmap: + iounmap(fs->dma); + iounmap(fs->swim3); + + out_release: + macio_release_resource(mdev, 0); + macio_release_resource(mdev, 1); + + return rc; +} + +static int __devinit swim3_attach(struct macio_dev *mdev, const struct of_device_id *match) +{ + int i, rc; + struct gendisk *disk; + + /* Add the drive */ + rc = swim3_add_device(mdev, floppy_count); + if (rc) + return rc; + + /* Now create the queue if not there yet */ + if (swim3_queue == NULL) { + /* If we failed, there isn't much we can do as the driver is still + * too dumb to remove the device, just bail out + */ + if (register_blkdev(FLOPPY_MAJOR, "fd")) + return 0; + swim3_queue = blk_init_queue(do_fd_request, &swim3_lock); + if (swim3_queue == NULL) { + unregister_blkdev(FLOPPY_MAJOR, "fd"); + return 0; + } + } + + /* Now register that disk. Same comment about failure handling */ + i = floppy_count++; + disk = disks[i] = alloc_disk(1); + if (disk == NULL) + return 0; + + disk->major = FLOPPY_MAJOR; + disk->first_minor = i; + disk->fops = &floppy_fops; + disk->private_data = &floppy_states[i]; + disk->queue = swim3_queue; + disk->flags |= GENHD_FL_REMOVABLE; + sprintf(disk->disk_name, "fd%d", i); + set_capacity(disk, 2880); + add_disk(disk); + + return 0; +} + +static struct of_device_id swim3_match[] = +{ + { + .name = "swim3", + }, + { + .compatible = "ohare-swim3" + }, + { + .compatible = "swim3" + }, +}; + +static struct macio_driver swim3_driver = +{ + .name = "swim3", + .match_table = swim3_match, + .probe = swim3_attach, +#if 0 + .suspend = swim3_suspend, + .resume = swim3_resume, +#endif +}; + + +int swim3_init(void) +{ + macio_register_driver(&swim3_driver); return 0; } -- cgit v1.2.3 From 0ebfff1491ef85d41ddf9c633834838be144f69f Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Mon, 3 Jul 2006 21:36:01 +1000 Subject: [POWERPC] Add new interrupt mapping core and change platforms to use it This adds the new irq remapper core and removes the old one. Because there are some fundamental conflicts with the old code, like the value of NO_IRQ which I'm now setting to 0 (as per discussions with Linus), etc..., this commit also changes the relevant platform and driver code over to use the new remapper (so as not to cause difficulties later in bisecting). This patch removes the old pre-parsing of the open firmware interrupt tree along with all the bogus assumptions it made to try to renumber interrupts according to the platform. This is all to be handled by the new code now. For the pSeries XICS interrupt controller, a single remapper host is created for the whole machine regardless of how many interrupt presentation and source controllers are found, and it's set to match any device node that isn't a 8259. That works fine on pSeries and avoids having to deal with some of the complexities of split source controllers vs. presentation controllers in the pSeries device trees. The powerpc i8259 PIC driver now always requests the legacy interrupt range. It also has the feature of being able to match any device node (including NULL) if passed no device node as an input. That will help porting over platforms with broken device-trees like Pegasos who don't have a proper interrupt tree. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras --- drivers/char/hvsi.c | 7 +- drivers/macintosh/macio-adb.c | 19 ++---- drivers/macintosh/macio_asic.c | 152 ++++++++++++++++++++++++++++------------- drivers/macintosh/smu.c | 6 +- drivers/macintosh/via-cuda.c | 24 ++++--- drivers/macintosh/via-pmu.c | 33 ++++----- drivers/net/mace.c | 4 +- drivers/serial/pmac_zilog.c | 6 +- 8 files changed, 146 insertions(+), 105 deletions(-) (limited to 'drivers') diff --git a/drivers/char/hvsi.c b/drivers/char/hvsi.c index 8dc205b275e..56612a2dca6 100644 --- a/drivers/char/hvsi.c +++ b/drivers/char/hvsi.c @@ -1299,13 +1299,12 @@ static int __init hvsi_console_init(void) hp->inbuf_end = hp->inbuf; hp->state = HVSI_CLOSED; hp->vtermno = *vtermno; - hp->virq = virt_irq_create_mapping(irq[0]); + hp->virq = irq_create_mapping(NULL, irq[0], 0); if (hp->virq == NO_IRQ) { printk(KERN_ERR "%s: couldn't create irq mapping for 0x%x\n", - __FUNCTION__, hp->virq); + __FUNCTION__, irq[0]); continue; - } else - hp->virq = irq_offset_up(hp->virq); + } hvsi_count++; } diff --git a/drivers/macintosh/macio-adb.c b/drivers/macintosh/macio-adb.c index 314fc0830d9..4b08852c35e 100644 --- a/drivers/macintosh/macio-adb.c +++ b/drivers/macintosh/macio-adb.c @@ -90,22 +90,12 @@ int macio_init(void) { struct device_node *adbs; struct resource r; + unsigned int irq; adbs = find_compatible_devices("adb", "chrp,adb0"); if (adbs == 0) return -ENXIO; -#if 0 - { int i = 0; - - printk("macio_adb_init: node = %p, addrs =", adbs->node); - while(!of_address_to_resource(adbs, i, &r)) - printk(" %x(%x)", r.start, r.end - r.start); - printk(", intrs ="); - for (i = 0; i < adbs->n_intrs; ++i) - printk(" %x", adbs->intrs[i].line); - printk("\n"); } -#endif if (of_address_to_resource(adbs, 0, &r)) return -ENXIO; adb = ioremap(r.start, sizeof(struct adb_regs)); @@ -117,10 +107,9 @@ int macio_init(void) out_8(&adb->active_lo.r, 0xff); out_8(&adb->autopoll.r, APE); - if (request_irq(adbs->intrs[0].line, macio_adb_interrupt, - 0, "ADB", (void *)0)) { - printk(KERN_ERR "ADB: can't get irq %d\n", - adbs->intrs[0].line); + irq = irq_of_parse_and_map(adbs, 0); + if (request_irq(irq, macio_adb_interrupt, 0, "ADB", (void *)0)) { + printk(KERN_ERR "ADB: can't get irq %d\n", irq); return -EAGAIN; } out_8(&adb->intr_enb.r, DFB | TAG); diff --git a/drivers/macintosh/macio_asic.c b/drivers/macintosh/macio_asic.c index 40ae7b6a939..80c0c665b5f 100644 --- a/drivers/macintosh/macio_asic.c +++ b/drivers/macintosh/macio_asic.c @@ -280,75 +280,128 @@ static void macio_release_dev(struct device *dev) static int macio_resource_quirks(struct device_node *np, struct resource *res, int index) { - if (res->flags & IORESOURCE_MEM) { - /* Grand Central has too large resource 0 on some machines */ - if (index == 0 && !strcmp(np->name, "gc")) - res->end = res->start + 0x1ffff; + /* Only quirks for memory resources for now */ + if ((res->flags & IORESOURCE_MEM) == 0) + return 0; + + /* Grand Central has too large resource 0 on some machines */ + if (index == 0 && !strcmp(np->name, "gc")) + res->end = res->start + 0x1ffff; - /* Airport has bogus resource 2 */ - if (index >= 2 && !strcmp(np->name, "radio")) - return 1; + /* Airport has bogus resource 2 */ + if (index >= 2 && !strcmp(np->name, "radio")) + return 1; #ifndef CONFIG_PPC64 - /* DBDMAs may have bogus sizes */ - if ((res->start & 0x0001f000) == 0x00008000) - res->end = res->start + 0xff; + /* DBDMAs may have bogus sizes */ + if ((res->start & 0x0001f000) == 0x00008000) + res->end = res->start + 0xff; #endif /* CONFIG_PPC64 */ - /* ESCC parent eats child resources. We could have added a - * level of hierarchy, but I don't really feel the need - * for it - */ - if (!strcmp(np->name, "escc")) - return 1; - - /* ESCC has bogus resources >= 3 */ - if (index >= 3 && !(strcmp(np->name, "ch-a") && - strcmp(np->name, "ch-b"))) - return 1; - - /* Media bay has too many resources, keep only first one */ - if (index > 0 && !strcmp(np->name, "media-bay")) - return 1; - - /* Some older IDE resources have bogus sizes */ - if (!(strcmp(np->name, "IDE") && strcmp(np->name, "ATA") && - strcmp(np->type, "ide") && strcmp(np->type, "ata"))) { - if (index == 0 && (res->end - res->start) > 0xfff) - res->end = res->start + 0xfff; - if (index == 1 && (res->end - res->start) > 0xff) - res->end = res->start + 0xff; - } + /* ESCC parent eats child resources. We could have added a + * level of hierarchy, but I don't really feel the need + * for it + */ + if (!strcmp(np->name, "escc")) + return 1; + + /* ESCC has bogus resources >= 3 */ + if (index >= 3 && !(strcmp(np->name, "ch-a") && + strcmp(np->name, "ch-b"))) + return 1; + + /* Media bay has too many resources, keep only first one */ + if (index > 0 && !strcmp(np->name, "media-bay")) + return 1; + + /* Some older IDE resources have bogus sizes */ + if (!(strcmp(np->name, "IDE") && strcmp(np->name, "ATA") && + strcmp(np->type, "ide") && strcmp(np->type, "ata"))) { + if (index == 0 && (res->end - res->start) > 0xfff) + res->end = res->start + 0xfff; + if (index == 1 && (res->end - res->start) > 0xff) + res->end = res->start + 0xff; } return 0; } +static void macio_create_fixup_irq(struct macio_dev *dev, int index, + unsigned int line) +{ + unsigned int irq; -static void macio_setup_interrupts(struct macio_dev *dev) + irq = irq_create_mapping(NULL, line, 0); + if (irq != NO_IRQ) { + dev->interrupt[index].start = irq; + dev->interrupt[index].flags = IORESOURCE_IRQ; + dev->interrupt[index].name = dev->ofdev.dev.bus_id; + } + if (dev->n_interrupts <= index) + dev->n_interrupts = index + 1; +} + +static void macio_add_missing_resources(struct macio_dev *dev) { struct device_node *np = dev->ofdev.node; - int i,j; + unsigned int irq_base; + + /* Gatwick has some missing interrupts on child nodes */ + if (dev->bus->chip->type != macio_gatwick) + return; - /* For now, we use pre-parsed entries in the device-tree for - * interrupt routing and addresses, but we should change that - * to dynamically parsed entries and so get rid of most of the - * clutter in struct device_node + /* irq_base is always 64 on gatwick. I have no cleaner way to get + * that value from here at this point */ - for (i = j = 0; i < np->n_intrs; i++) { + irq_base = 64; + + /* Fix SCC */ + if (strcmp(np->name, "ch-a") == 0) { + macio_create_fixup_irq(dev, 0, 15 + irq_base); + macio_create_fixup_irq(dev, 1, 4 + irq_base); + macio_create_fixup_irq(dev, 2, 5 + irq_base); + printk(KERN_INFO "macio: fixed SCC irqs on gatwick\n"); + } + + /* Fix media-bay */ + if (strcmp(np->name, "media-bay") == 0) { + macio_create_fixup_irq(dev, 0, 29 + irq_base); + printk(KERN_INFO "macio: fixed media-bay irq on gatwick\n"); + } + + /* Fix left media bay childs */ + if (dev->media_bay != NULL && strcmp(np->name, "floppy") == 0) { + macio_create_fixup_irq(dev, 0, 19 + irq_base); + macio_create_fixup_irq(dev, 1, 1 + irq_base); + printk(KERN_INFO "macio: fixed left floppy irqs\n"); + } + if (dev->media_bay != NULL && strcasecmp(np->name, "ata4") == 0) { + macio_create_fixup_irq(dev, 0, 14 + irq_base); + macio_create_fixup_irq(dev, 0, 3 + irq_base); + printk(KERN_INFO "macio: fixed left ide irqs\n"); + } +} + +static void macio_setup_interrupts(struct macio_dev *dev) +{ + struct device_node *np = dev->ofdev.node; + unsigned int irq; + int i = 0, j = 0; + + for (;;) { struct resource *res = &dev->interrupt[j]; if (j >= MACIO_DEV_COUNT_IRQS) break; - res->start = np->intrs[i].line; - res->flags = IORESOURCE_IO; - if (np->intrs[j].sense) - res->flags |= IORESOURCE_IRQ_LOWLEVEL; - else - res->flags |= IORESOURCE_IRQ_HIGHEDGE; + irq = irq_of_parse_and_map(np, i++); + if (irq == NO_IRQ) + break; + res->start = irq; + res->flags = IORESOURCE_IRQ; res->name = dev->ofdev.dev.bus_id; - if (macio_resource_quirks(np, res, i)) + if (macio_resource_quirks(np, res, i - 1)) { memset(res, 0, sizeof(struct resource)); - else + continue; + } else j++; } dev->n_interrupts = j; @@ -445,6 +498,7 @@ static struct macio_dev * macio_add_one_device(struct macio_chip *chip, /* Setup interrupts & resources */ macio_setup_interrupts(dev); macio_setup_resources(dev, parent_res); + macio_add_missing_resources(dev); /* Register with core */ if (of_device_register(&dev->ofdev) != 0) { diff --git a/drivers/macintosh/smu.c b/drivers/macintosh/smu.c index ff6d9bfdc3d..f139a74696f 100644 --- a/drivers/macintosh/smu.c +++ b/drivers/macintosh/smu.c @@ -497,8 +497,7 @@ int __init smu_init (void) smu->doorbell = *data; if (smu->doorbell < 0x50) smu->doorbell += 0x50; - if (np->n_intrs > 0) - smu->db_irq = np->intrs[0].line; + smu->db_irq = irq_of_parse_and_map(np, 0); of_node_put(np); @@ -515,8 +514,7 @@ int __init smu_init (void) smu->msg = *data; if (smu->msg < 0x50) smu->msg += 0x50; - if (np->n_intrs > 0) - smu->msg_irq = np->intrs[0].line; + smu->msg_irq = irq_of_parse_and_map(np, 0); of_node_put(np); } while(0); diff --git a/drivers/macintosh/via-cuda.c b/drivers/macintosh/via-cuda.c index 6501db50fb8..69d5452fd22 100644 --- a/drivers/macintosh/via-cuda.c +++ b/drivers/macintosh/via-cuda.c @@ -34,13 +34,6 @@ static volatile unsigned char __iomem *via; static DEFINE_SPINLOCK(cuda_lock); -#ifdef CONFIG_MAC -#define CUDA_IRQ IRQ_MAC_ADB -#define eieio() -#else -#define CUDA_IRQ vias->intrs[0].line -#endif - /* VIA registers - spaced 0x200 bytes apart */ #define RS 0x200 /* skip between registers */ #define B 0 /* B-side data */ @@ -189,11 +182,24 @@ int __init find_via_cuda(void) static int __init via_cuda_start(void) { + unsigned int irq; + if (via == NULL) return -ENODEV; - if (request_irq(CUDA_IRQ, cuda_interrupt, 0, "ADB", cuda_interrupt)) { - printk(KERN_ERR "cuda_init: can't get irq %d\n", CUDA_IRQ); +#ifdef CONFIG_MAC + irq = IRQ_MAC_ADB; +#else /* CONFIG_MAC */ + irq = irq_of_parse_and_map(vias, 0); + if (irq == NO_IRQ) { + printk(KERN_ERR "via-cuda: can't map interrupts for %s\n", + vias->full_name); + return -ENODEV; + } +#endif /* CONFIG_MAP */ + + if (request_irq(irq, cuda_interrupt, 0, "ADB", cuda_interrupt)) { + printk(KERN_ERR "via-cuda: can't request irq %d\n", irq); return -EAGAIN; } diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c index c1193d34ec9..06ca80bfd6b 100644 --- a/drivers/macintosh/via-pmu.c +++ b/drivers/macintosh/via-pmu.c @@ -64,10 +64,6 @@ #include #endif -#ifdef CONFIG_PPC32 -#include -#endif - #include "via-pmu-event.h" /* Some compile options */ @@ -151,7 +147,7 @@ static int pmu_fully_inited = 0; static int pmu_has_adb; static struct device_node *gpio_node; static unsigned char __iomem *gpio_reg = NULL; -static int gpio_irq = -1; +static int gpio_irq = NO_IRQ; static int gpio_irq_enabled = -1; static volatile int pmu_suspended = 0; static spinlock_t pmu_lock; @@ -403,22 +399,21 @@ static int __init pmu_init(void) */ static int __init via_pmu_start(void) { + unsigned int irq; + if (vias == NULL) return -ENODEV; batt_req.complete = 1; -#ifndef CONFIG_PPC_MERGE - if (pmu_kind == PMU_KEYLARGO_BASED) - openpic_set_irq_priority(vias->intrs[0].line, - OPENPIC_PRIORITY_DEFAULT + 1); -#endif - - if (request_irq(vias->intrs[0].line, via_pmu_interrupt, 0, "VIA-PMU", - (void *)0)) { - printk(KERN_ERR "VIA-PMU: can't get irq %d\n", - vias->intrs[0].line); - return -EAGAIN; + irq = irq_of_parse_and_map(vias, 0); + if (irq == NO_IRQ) { + printk(KERN_ERR "via-pmu: can't map interruptn"); + return -ENODEV; + } + if (request_irq(irq, via_pmu_interrupt, 0, "VIA-PMU", (void *)0)) { + printk(KERN_ERR "via-pmu: can't request irq %d\n", irq); + return -ENODEV; } if (pmu_kind == PMU_KEYLARGO_BASED) { @@ -426,10 +421,10 @@ static int __init via_pmu_start(void) if (gpio_node == NULL) gpio_node = of_find_node_by_name(NULL, "pmu-interrupt"); - if (gpio_node && gpio_node->n_intrs > 0) - gpio_irq = gpio_node->intrs[0].line; + if (gpio_node) + gpio_irq = irq_of_parse_and_map(gpio_node, 0); - if (gpio_irq != -1) { + if (gpio_irq != NO_IRQ) { if (request_irq(gpio_irq, gpio1_interrupt, 0, "GPIO1 ADB", (void *)0)) printk(KERN_ERR "pmu: can't get irq %d" diff --git a/drivers/net/mace.c b/drivers/net/mace.c index f2c0bf89f0c..29e4b5aa6ea 100644 --- a/drivers/net/mace.c +++ b/drivers/net/mace.c @@ -242,12 +242,12 @@ static int __devinit mace_probe(struct macio_dev *mdev, const struct of_device_i } rc = request_irq(mp->tx_dma_intr, mace_txdma_intr, 0, "MACE-txdma", dev); if (rc) { - printk(KERN_ERR "MACE: can't get irq %d\n", mace->intrs[1].line); + printk(KERN_ERR "MACE: can't get irq %d\n", mp->tx_dma_intr); goto err_free_irq; } rc = request_irq(mp->rx_dma_intr, mace_rxdma_intr, 0, "MACE-rxdma", dev); if (rc) { - printk(KERN_ERR "MACE: can't get irq %d\n", mace->intrs[2].line); + printk(KERN_ERR "MACE: can't get irq %d\n", mp->rx_dma_intr); goto err_free_tx_irq; } diff --git a/drivers/serial/pmac_zilog.c b/drivers/serial/pmac_zilog.c index 459c0231aef..bfd2a22759e 100644 --- a/drivers/serial/pmac_zilog.c +++ b/drivers/serial/pmac_zilog.c @@ -1443,8 +1443,8 @@ static int __init pmz_init_port(struct uart_pmac_port *uap) uap->flags &= ~PMACZILOG_FLAG_HAS_DMA; goto no_dma; } - uap->tx_dma_irq = np->intrs[1].line; - uap->rx_dma_irq = np->intrs[2].line; + uap->tx_dma_irq = irq_of_parse_and_map(np, 1); + uap->rx_dma_irq = irq_of_parse_and_map(np, 2); } no_dma: @@ -1491,7 +1491,7 @@ no_dma: * Init remaining bits of "port" structure */ uap->port.iotype = UPIO_MEM; - uap->port.irq = np->intrs[0].line; + uap->port.irq = irq_of_parse_and_map(np, 0); uap->port.uartclk = ZS_CLOCK; uap->port.fifosize = 1; uap->port.ops = &pmz_pops; -- cgit v1.2.3