void __iomem * __ioremap_caller(phys_addr_t addr, unsigned long size, unsigned long flags, void *caller) { phys_addr_t paligned; void __iomem *ret; /* * Choose an address to map it to. * Once the imalloc system is running, we use it. * Before that, we map using addresses going * up from ioremap_bot. imalloc will use * the addresses from ioremap_bot through * IMALLOC_END * */ paligned = addr & PAGE_MASK; size = PAGE_ALIGN(addr + size) - paligned; if ((size == 0) || (paligned == 0)) return NULL; if (slab_is_available()) { struct vm_struct *area; area = __get_vm_area_caller(size, VM_IOREMAP, ioremap_bot, IOREMAP_END, caller); if (area == NULL) return NULL; area->phys_addr = paligned; ret = __ioremap_at(paligned, area->addr, size, flags); if (!ret) vunmap(area->addr); } else { ret = __ioremap_at(paligned, (void *)ioremap_bot, size, flags); if (ret) ioremap_bot += size; } if (ret) ret += addr & ~PAGE_MASK; return ret; }
static int __devinit electra_cf_probe(struct of_device *ofdev, const struct of_device_id *match) { struct device *device = &ofdev->dev; struct device_node *np = ofdev->node; struct electra_cf_socket *cf; struct resource mem, io; int status; const unsigned int *prop; int err; struct vm_struct *area; err = of_address_to_resource(np, 0, &mem); if (err) return -EINVAL; err = of_address_to_resource(np, 1, &io); if (err) return -EINVAL; cf = kzalloc(sizeof *cf, GFP_KERNEL); if (!cf) return -ENOMEM; setup_timer(&cf->timer, electra_cf_timer, (unsigned long)cf); cf->irq = NO_IRQ; cf->ofdev = ofdev; cf->mem_phys = mem.start; cf->mem_size = PAGE_ALIGN(mem.end - mem.start); cf->mem_base = ioremap(cf->mem_phys, cf->mem_size); cf->io_size = PAGE_ALIGN(io.end - io.start); area = __get_vm_area(cf->io_size, 0, PHB_IO_BASE, PHB_IO_END); if (area == NULL) return -ENOMEM; cf->io_virt = (void __iomem *)(area->addr); cf->gpio_base = ioremap(0xfc103000, 0x1000); dev_set_drvdata(device, cf); if (!cf->mem_base || !cf->io_virt || !cf->gpio_base || (__ioremap_at(io.start, cf->io_virt, cf->io_size, _PAGE_NO_CACHE | _PAGE_GUARDED) == NULL)) { dev_err(device, "can't ioremap ranges\n"); status = -ENOMEM; goto fail1; } cf->io_base = (unsigned long)cf->io_virt - VMALLOC_END; cf->iomem.start = (unsigned long)cf->mem_base; cf->iomem.end = (unsigned long)cf->mem_base + (mem.end - mem.start); cf->iomem.flags = IORESOURCE_MEM; cf->irq = irq_of_parse_and_map(np, 0); status = request_irq(cf->irq, electra_cf_irq, IRQF_SHARED, driver_name, cf); if (status < 0) { dev_err(device, "request_irq failed\n"); goto fail1; } cf->socket.pci_irq = cf->irq; prop = of_get_property(np, "card-detect-gpio", NULL); if (!prop) goto fail1; cf->gpio_detect = *prop; prop = of_get_property(np, "card-vsense-gpio", NULL); if (!prop) goto fail1; cf->gpio_vsense = *prop; prop = of_get_property(np, "card-3v-gpio", NULL); if (!prop) goto fail1; cf->gpio_3v = *prop; prop = of_get_property(np, "card-5v-gpio", NULL); if (!prop) goto fail1; cf->gpio_5v = *prop; cf->socket.io_offset = cf->io_base; /* reserve chip-select regions */ if (!request_mem_region(cf->mem_phys, cf->mem_size, driver_name)) { status = -ENXIO; dev_err(device, "Can't claim memory region\n"); goto fail1; } if (!request_region(cf->io_base, cf->io_size, driver_name)) { status = -ENXIO; dev_err(device, "Can't claim I/O region\n"); goto fail2; } cf->socket.owner = THIS_MODULE; cf->socket.dev.parent = &ofdev->dev; cf->socket.ops = &electra_cf_ops; cf->socket.resource_ops = &pccard_static_ops; cf->socket.features = SS_CAP_PCCARD | SS_CAP_STATIC_MAP | SS_CAP_MEM_ALIGN; cf->socket.map_size = 0x800; status = pcmcia_register_socket(&cf->socket); if (status < 0) { dev_err(device, "pcmcia_register_socket failed\n"); goto fail3; } dev_info(device, "at mem 0x%lx io 0x%llx irq %d\n", cf->mem_phys, io.start, cf->irq); cf->active = 1; electra_cf_timer((unsigned long)cf); return 0; fail3: release_region(cf->io_base, cf->io_size); fail2: release_mem_region(cf->mem_phys, cf->mem_size); fail1: if (cf->irq != NO_IRQ) free_irq(cf->irq, cf); if (cf->io_virt) __iounmap_at(cf->io_virt, cf->io_size); if (cf->mem_base) iounmap(cf->mem_base); if (cf->gpio_base) iounmap(cf->gpio_base); device_init_wakeup(&ofdev->dev, 0); kfree(cf); return status; }