static int __devinit hilscher_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) { struct uio_info *info; info = kzalloc(sizeof(struct uio_info), GFP_KERNEL); if (!info) return -ENOMEM; if (pci_enable_device(dev)) goto out_free; if (pci_request_regions(dev, "hilscher")) goto out_disable; info->mem[0].addr = pci_resource_start(dev, 0); if (!info->mem[0].addr) goto out_release; info->mem[0].internal_addr = ioremap(pci_resource_start(dev, 0), pci_resource_len(dev, 0)); if (!info->mem[0].internal_addr) goto out_release; info->mem[0].size = pci_resource_len(dev, 0); info->mem[0].memtype = UIO_MEM_PHYS; info->mem[1].addr = pci_resource_start(dev, 2); info->mem[1].size = pci_resource_len(dev, 2); info->mem[1].memtype = UIO_MEM_PHYS; switch (id->subdevice) { case CIF_SUBDEVICE_PROFIBUS: info->name = "CIF_Profibus"; break; case CIF_SUBDEVICE_DEVICENET: info->name = "CIF_Devicenet"; break; default: info->name = "CIF_???"; } info->version = "0.0.1"; info->irq = dev->irq; info->irq_flags = IRQF_DISABLED | IRQF_SHARED; info->handler = hilscher_handler; if (uio_register_device(&dev->dev, info)) goto out_unmap; pci_set_drvdata(dev, info); return 0; out_unmap: iounmap(info->mem[0].internal_addr); out_release: pci_release_regions(dev); out_disable: pci_disable_device(dev); out_free: kfree (info); return -ENODEV; }
static int __devinit probe(struct pci_dev *pdev, const struct pci_device_id *id) { struct uio_info *info; int ret; info = kzalloc(sizeof(struct uio_info), GFP_KERNEL); if (!info) return -ENOMEM; if (pci_enable_device(pdev)) goto out_free; if (pci_request_regions(pdev, "aectc")) goto out_disable; info->name = "aectc"; info->port[0].start = pci_resource_start(pdev, 0); if (!info->port[0].start) goto out_release; info->priv = pci_iomap(pdev, 0, 0); if (!info->priv) goto out_release; info->port[0].size = pci_resource_len(pdev, 0); info->port[0].porttype = UIO_PORT_GPIO; info->version = "0.0.1"; info->irq = pdev->irq; info->irq_flags = IRQF_SHARED; info->handler = aectc_irq; print_board_data(pdev, info); ret = uio_register_device(&pdev->dev, info); if (ret) goto out_unmap; iowrite32(INT_ENABLE, info->priv + INT_ENABLE_ADDR); iowrite8(INT_MASK_ALL, info->priv + INT_MASK_ADDR); if (!(ioread8(info->priv + INTA_DRVR_ADDR) & INTA_ENABLED_FLAG)) dev_err(&pdev->dev, "aectc: interrupts not enabled\n"); pci_set_drvdata(pdev, info); return 0; out_unmap: pci_iounmap(pdev, info->priv); out_release: pci_release_regions(pdev); out_disable: pci_disable_device(pdev); out_free: kfree(info); return -ENODEV; }
static int drv_kpart_probe(struct device *dev) { printk("drv_kpart_probe(%p)\n",dev); kpart_info.mem[0].addr = (unsigned long)kmalloc(1024,GFP_KERNEL); if(kpart_info.mem[0].addr == 0) return -ENOMEM; kpart_info.mem[0].memtype = UIO_MEM_LOGICAL; kpart_info.mem[0].size = 1024; if(uio_register_device(dev,&kpart_info)) return -ENODEV; return 0; }
static int probe(struct pci_dev *const pci_dev, const struct pci_device_id *const did) { struct uio_info *info; int ret; ret = pci_enable_device(pci_dev); if (ret) goto return_; ret = pci_request_regions(pci_dev, DRIVER_TAG); if (ret) goto return_disable; info = kzalloc(sizeof(struct uio_info), GFP_KERNEL); if (!info) { ret = -ENOMEM; goto return_release; } info->name = DRIVER_TAG; info->version = DRIVER_VERSION; info->mem[0].name = "EHCI MMIO area"; info->mem[0].addr = pci_resource_start(pci_dev, 0); if (!info->mem[0].addr) { ret = -ENODEV; goto return_free; } info->mem[0].size = pci_resource_len(pci_dev, 0); info->mem[0].memtype = UIO_MEM_PHYS; ret = uio_register_device(&pci_dev->dev, info); if (ret) goto return_free; pci_set_drvdata(pci_dev, info); return 0; return_free: kfree(info); return_release: pci_release_regions(pci_dev); return_disable: pci_disable_device(pci_dev); return_: return ret; }
// 完成了uio_info的初始化和uio设备的注册 static int drv_kpart_probe(struct device *dev) { // 初始化设备相关的 uio_info结构 printk(KERN_ERR "drv_kpart_probe( %p)\n", dev); // 这是内存映射必须要设置的 kpart_info.mem[0].addr = (unsigned long)kmalloc(1024,GFP_KERNEL); if(kpart_info.mem[0].addr == 0) return -ENOMEM; /* memtype可以是 UIO_MEM_PHYS,那么被映射到用户空间的是你 设备的物理内存。也可以是UIO_MEM_LOGICAL,那么被映射到用户空间的是逻辑内存 (比如使用 kmalloc分配的内存)。还可以是UIO_MEM_VIRTUAL,那么被映射到用户空间的是 虚拟内存(比如用vmalloc分配的内存) */ kpart_info.mem[0].memtype = UIO_MEM_LOGICAL; kpart_info.mem[0].size = 1024; // 调用uio_register_device 分配并注册一个uio设备 if( uio_register_device(dev, &kpart_info)) return -ENODEV; return 0; }
static int #if(LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0)) __devinit #endif ivshmem_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) { struct uio_info *info; struct ivshmem_info * ivshmem_info; #ifdef IRQ_SUPPORT int nvectors = 4; #endif info = kzalloc(sizeof(struct uio_info), GFP_KERNEL); if (!info) return -ENOMEM; ivshmem_info = kzalloc(sizeof(struct ivshmem_info), GFP_KERNEL); if (!ivshmem_info) { kfree(info); return -ENOMEM; } if (pci_enable_device(dev)) goto out_free; if (pci_request_regions(dev, "ivshmem")) goto out_disable; info->mem[0].addr = pci_resource_start(dev, 0); if (!info->mem[0].addr) goto out_release; info->mem[0].size = pci_resource_len(dev, 0); info->mem[0].internal_addr = pci_ioremap_bar(dev, 0); if (!info->mem[0].internal_addr) { goto out_release; } info->mem[0].memtype = UIO_MEM_PHYS; info->mem[1].addr = pci_resource_start(dev, 2); if (!info->mem[1].addr) goto out_unmap; info->mem[1].internal_addr = ioremap_cache(pci_resource_start(dev, 2), pci_resource_len(dev, 2)); if (!info->mem[1].internal_addr) goto out_unmap; #if 0 info->mem[1].internal_addr = pci_ioremap_bar(dev, 2); if (!info->mem[1].internal_addr) goto out_unmap; #endif info->mem[1].size = pci_resource_len(dev, 2); info->mem[1].memtype = UIO_MEM_PHYS; ivshmem_info->uio = info; ivshmem_info->dev = dev; #ifdef IRQ_SUPPORT if (request_msix_vectors(ivshmem_info, nvectors) != 0) { printk(KERN_INFO "regular IRQs\n"); info->irq = dev->irq; info->irq_flags = IRQF_SHARED; info->handler = ivshmem_handler; writel(0xffffffff, info->mem[0].internal_addr + IntrMask); } else { printk(KERN_INFO "MSI-X enabled\n"); info->irq = -1; } #else info->irq = -1; #endif info->name = "ivshmem"; info->version = "0.0.1"; if (uio_register_device(&dev->dev, info)) goto out_unmap2; pci_set_drvdata(dev, info); return 0; out_unmap2: iounmap(info->mem[2].internal_addr); out_unmap: iounmap(info->mem[0].internal_addr); out_release: pci_release_regions(dev); out_disable: pci_disable_device(dev); out_free: kfree (info); return -ENODEV; }
static int __devinit sercos3_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) { struct uio_info *info; struct sercos3_priv *priv; int i; info = kzalloc(sizeof(struct uio_info), GFP_KERNEL); if (!info) return -ENOMEM; priv = kzalloc(sizeof(struct sercos3_priv), GFP_KERNEL); if (!priv) goto out_free; if (pci_enable_device(dev)) goto out_free_priv; if (pci_request_regions(dev, "sercos3")) goto out_disable; /* we only need PCI BAR's 0, 2, 3, 4, 5 */ if (sercos3_setup_iomem(dev, info, 0, 0)) goto out_unmap; if (sercos3_setup_iomem(dev, info, 1, 2)) goto out_unmap; if (sercos3_setup_iomem(dev, info, 2, 3)) goto out_unmap; if (sercos3_setup_iomem(dev, info, 3, 4)) goto out_unmap; if (sercos3_setup_iomem(dev, info, 4, 5)) goto out_unmap; spin_lock_init(&priv->ier0_cache_lock); info->priv = priv; info->name = "Sercos_III_PCI"; info->version = "0.0.1"; info->irq = dev->irq; info->irq_flags = IRQF_DISABLED | IRQF_SHARED; info->handler = sercos3_handler; info->irqcontrol = sercos3_irqcontrol; pci_set_drvdata(dev, info); if (uio_register_device(&dev->dev, info)) goto out_unmap; return 0; out_unmap: for (i = 0; i < 5; i++) { if (info->mem[i].internal_addr) iounmap(info->mem[i].internal_addr); } pci_release_regions(dev); out_disable: pci_disable_device(dev); out_free_priv: kfree(priv); out_free: kfree(info); return -ENODEV; }
static int uio_pdrv_probe(struct platform_device *pdev) { struct uio_info *uioinfo = pdev->dev.platform_data; struct uio_platdata *pdata; struct uio_mem *uiomem; int ret = -ENODEV; int i; if (!uioinfo || !uioinfo->name || !uioinfo->version) { dev_dbg(&pdev->dev, "%s: err_uioinfo\n", __func__); goto err_uioinfo; } pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); if (!pdata) { ret = -ENOMEM; dev_dbg(&pdev->dev, "%s: err_alloc_pdata\n", __func__); goto err_alloc_pdata; } pdata->uioinfo = uioinfo; uiomem = &uioinfo->mem[0]; for (i = 0; i < pdev->num_resources; ++i) { struct resource *r = &pdev->resource[i]; if (r->flags != IORESOURCE_MEM) continue; if (uiomem >= &uioinfo->mem[MAX_UIO_MAPS]) { dev_warn(&pdev->dev, "device has more than " __stringify(MAX_UIO_MAPS) " I/O memory resources.\n"); break; } uiomem->memtype = UIO_MEM_PHYS; uiomem->addr = r->start; uiomem->size = r->end - r->start + 1; ++uiomem; } while (uiomem < &uioinfo->mem[MAX_UIO_MAPS]) { uiomem->size = 0; ++uiomem; } pdata->uioinfo->priv = pdata; ret = uio_register_device(&pdev->dev, pdata->uioinfo); if (ret) { kfree(pdata); err_alloc_pdata: err_uioinfo: return ret; } platform_set_drvdata(pdev, pdata); return 0; }
static int __devinit pruss_probe(struct platform_device *dev) { int ret = -ENODEV; int count = 0; struct resource *regs_pruram, *regs_l3ram, *regs_ddr; char *string; /* Power on PRU in case its not done as part of boot-loader */ pruss_clk = clk_get(&dev->dev, "pruss"); if (IS_ERR(pruss_clk)) { dev_err(&dev->dev, "no pruss clock available\n"); ret = PTR_ERR(pruss_clk); pruss_clk = NULL; return ret; } else { clk_enable (pruss_clk); } ecap0_clk = clk_get(&dev->dev, "ecap0"); if (IS_ERR(ecap0_clk)) { dev_err(&dev->dev, "no ecap0 clock available\n"); ret = PTR_ERR(ecap0_clk); ecap0_clk = NULL; return ret; } else { clk_enable (ecap0_clk); } for (count = 0; count < PRUSS_INSTANCE; count ++) { info[count] = (struct uio_info *)kzalloc(sizeof (struct uio_info), GFP_KERNEL); if (!info[count]) return -ENOMEM; } regs_pruram = platform_get_resource(dev, IORESOURCE_MEM, 0); if (!regs_pruram) { dev_err(&dev->dev, "No memory resource specified\n"); goto out_free; } regs_l3ram = platform_get_resource(dev, IORESOURCE_MEM, 1); if (!regs_l3ram) { dev_err(&dev->dev, "No memory resource specified\n"); goto out_free; } regs_ddr = platform_get_resource(dev, IORESOURCE_MEM, 2); if (!regs_ddr) { dev_err(&dev->dev, "No memory resource specified\n"); goto out_free; } ddr_virt_addr = dma_alloc_coherent (&dev->dev, regs_ddr->end-regs_ddr->start+1, &ddr_phy_addr, GFP_KERNEL|GFP_DMA); for (count = 0; count < PRUSS_INSTANCE; count ++) { info[count]->mem[0].addr = regs_pruram->start; if (!info[count]->mem[0].addr) { dev_err(&dev->dev, "Invalid memory resource\n"); break; } info[count]->mem[0].size = regs_pruram->end - regs_pruram->start + 1; info[count]->mem[0].internal_addr = ioremap(regs_pruram->start, info[count]->mem[0].size); if (!info[count]->mem[0].internal_addr) { dev_err(&dev->dev, "Can't remap memory address range\n"); break; } info[count]->mem[0].memtype = UIO_MEM_PHYS; info[count]->mem[1].addr = regs_l3ram->start; if (!info[count]->mem[1].addr) { dev_err(&dev->dev, "Invalid memory resource\n"); break; } info[count]->mem[1].size = regs_l3ram->end - regs_l3ram->start + 1; info[count]->mem[1].internal_addr = ioremap(regs_l3ram->start, info[count]->mem[1].size); if (!info[count]->mem[1].internal_addr) { dev_err(&dev->dev, "Can't remap memory address range\n"); break; } info[count]->mem[1].memtype = UIO_MEM_PHYS; info[count]->mem[2].size = regs_ddr->end - regs_ddr->start + 1; if (!(info[count]->mem[2].size-1)) { dev_err(&dev->dev, "Invalid memory resource\n"); break; } info[count]->mem[2].internal_addr = ddr_virt_addr; if (!info[count]->mem[2].internal_addr) { dev_err(&dev->dev, "Can't remap memory address range\n"); break; } info[count]->mem[2].addr = ddr_phy_addr; info[count]->mem[2].memtype = UIO_MEM_PHYS; string = kzalloc(20, GFP_KERNEL); sprintf (string, "pruss_evt%d", count); info[count]->name = string; info[count]->version = "0.01"; /* Register PRUSS IRQ lines */ info[count]->irq = IRQ_DA8XX_EVTOUT0+count; info[count]->irq_flags = IRQF_SHARED; info[count]->handler = pruss_handler; ret = uio_register_device(&dev->dev, info[count]); if (ret < 0) break; } platform_set_drvdata(dev, info); if (ret < 0) { if (ddr_virt_addr) dma_free_coherent (&dev->dev, regs_ddr->end - regs_ddr->start + 1, ddr_virt_addr, ddr_phy_addr); while (count --) { uio_unregister_device (info[count]); if (info[count]->name) kfree (info[count]->name); iounmap(info[count]->mem[0].internal_addr); } } else { return 0; } out_free: for (count = 0; count < PRUSS_INSTANCE; count ++) { if (info[count]) kfree(info[count]); } if(pruss_clk != NULL) clk_put(pruss_clk); if (ecap0_clk != NULL) clk_put (ecap0_clk); return ret; }
static int uio_dmem_genirq_probe(struct platform_device *pdev) { struct uio_dmem_genirq_pdata *pdata = dev_get_platdata(&pdev->dev); struct uio_info *uioinfo = &pdata->uioinfo; struct uio_dmem_genirq_platdata *priv; struct uio_mem *uiomem; int ret = -EINVAL; int i; if (pdev->dev.of_node) { int irq; /* alloc uioinfo for one device */ uioinfo = kzalloc(sizeof(*uioinfo), GFP_KERNEL); if (!uioinfo) { ret = -ENOMEM; dev_err(&pdev->dev, "unable to kmalloc\n"); goto bad2; } uioinfo->name = pdev->dev.of_node->name; uioinfo->version = "devicetree"; /* Multiple IRQs are not supported */ irq = platform_get_irq(pdev, 0); if (irq == -ENXIO) uioinfo->irq = UIO_IRQ_NONE; else uioinfo->irq = irq; } if (!uioinfo || !uioinfo->name || !uioinfo->version) { dev_err(&pdev->dev, "missing platform_data\n"); goto bad0; } if (uioinfo->handler || uioinfo->irqcontrol || uioinfo->irq_flags & IRQF_SHARED) { dev_err(&pdev->dev, "interrupt configuration error\n"); goto bad0; } priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) { ret = -ENOMEM; dev_err(&pdev->dev, "unable to kmalloc\n"); goto bad0; } dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); priv->uioinfo = uioinfo; spin_lock_init(&priv->lock); priv->flags = 0; /* interrupt is enabled to begin with */ priv->pdev = pdev; mutex_init(&priv->alloc_lock); if (!uioinfo->irq) { ret = platform_get_irq(pdev, 0); if (ret < 0) { dev_err(&pdev->dev, "failed to get IRQ\n"); goto bad1; } uioinfo->irq = ret; } uiomem = &uioinfo->mem[0]; for (i = 0; i < pdev->num_resources; ++i) { struct resource *r = &pdev->resource[i]; if (r->flags != IORESOURCE_MEM) continue; if (uiomem >= &uioinfo->mem[MAX_UIO_MAPS]) { dev_warn(&pdev->dev, "device has more than " __stringify(MAX_UIO_MAPS) " I/O memory resources.\n"); break; } uiomem->memtype = UIO_MEM_PHYS; uiomem->addr = r->start; uiomem->size = resource_size(r); ++uiomem; } priv->dmem_region_start = i; priv->num_dmem_regions = pdata->num_dynamic_regions; for (i = 0; i < pdata->num_dynamic_regions; ++i) { if (uiomem >= &uioinfo->mem[MAX_UIO_MAPS]) { dev_warn(&pdev->dev, "device has more than " __stringify(MAX_UIO_MAPS) " dynamic and fixed memory regions.\n"); break; } uiomem->memtype = UIO_MEM_PHYS; uiomem->addr = DMEM_MAP_ERROR; uiomem->size = pdata->dynamic_region_sizes[i]; ++uiomem; } while (uiomem < &uioinfo->mem[MAX_UIO_MAPS]) { uiomem->size = 0; ++uiomem; } /* This driver requires no hardware specific kernel code to handle * interrupts. Instead, the interrupt handler simply disables the * interrupt in the interrupt controller. User space is responsible * for performing hardware specific acknowledge and re-enabling of * the interrupt in the interrupt controller. * * Interrupt sharing is not supported. */ uioinfo->handler = uio_dmem_genirq_handler; uioinfo->irqcontrol = uio_dmem_genirq_irqcontrol; uioinfo->open = uio_dmem_genirq_open; uioinfo->release = uio_dmem_genirq_release; uioinfo->priv = priv; /* Enable Runtime PM for this device: * The device starts in suspended state to allow the hardware to be * turned off by default. The Runtime PM bus code should power on the * hardware and enable clocks at open(). */ pm_runtime_enable(&pdev->dev); ret = uio_register_device(&pdev->dev, priv->uioinfo); if (ret) { dev_err(&pdev->dev, "unable to register uio device\n"); pm_runtime_disable(&pdev->dev); goto bad1; } platform_set_drvdata(pdev, priv); return 0; bad1: kfree(priv); bad0: /* kfree uioinfo for OF */ if (pdev->dev.of_node) kfree(uioinfo); bad2: return ret; }
static int uio_ubicom32ring_probe(struct platform_device *pdev) { struct uio_info *uioinfo; struct uio_mem *uiomem; struct uio_ubicom32ring_data *priv; struct uio_ubicom32ring_regs *regs; struct resource *mem_resource; struct resource *irqtx_resource; struct resource *irqrx_resource; int ret = -EINVAL; int i; uioinfo = kzalloc(sizeof(struct uio_info), GFP_KERNEL); if (!uioinfo) { dev_err(&pdev->dev, "unable to kmalloc\n"); return -ENOMEM; } /* * Allocate private data with some string space after */ i = sizeof(DRIVER_NAME) + 1; i += pdev->dev.platform_data ? strlen(pdev->dev.platform_data) : 0; priv = kzalloc(sizeof(struct uio_ubicom32ring_data) + i, GFP_KERNEL); if (!priv) { dev_err(&pdev->dev, "unable to kmalloc\n"); kfree(uioinfo); return -ENOMEM; } strcpy(priv->name, DRIVER_NAME ":"); if (pdev->dev.platform_data) { strcat(priv->name, pdev->dev.platform_data); } uioinfo->priv = priv; uioinfo->name = priv->name; uioinfo->version = "0.1"; priv->uioinfo = uioinfo; spin_lock_init(&priv->lock); priv->flags = 0; /* interrupt is enabled to begin with */ /* * Get our resources, the IRQ_TX and IRQ_RX are optional. */ priv->irq_tx = 0xFF; irqtx_resource = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (irqtx_resource) { priv->irq_tx = irqtx_resource->start; } uioinfo->irq = -1; priv->irq_rx = 0xFF; irqrx_resource = platform_get_resource(pdev, IORESOURCE_IRQ, 1); if (irqrx_resource) { priv->irq_rx = irqrx_resource->start; uioinfo->irq = priv->irq_rx; uioinfo->handler = uio_ubicom32ring_handler; } mem_resource = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!mem_resource || !mem_resource->start) { dev_err(&pdev->dev, "No valid memory resource found\n"); ret = -ENODEV; goto fail; } regs = (struct uio_ubicom32ring_regs *)mem_resource->start; priv->regs = regs; if (regs->version != UIO_UBICOM32RING_REG_VERSION) { dev_err(&pdev->dev, "version %d not supported\n", regs->version); ret = -ENODEV; goto fail; } /* * First range is the shared register space, if we have any */ uiomem = &uioinfo->mem[0]; if (regs->regs_size) { uiomem->memtype = UIO_MEM_PHYS; uiomem->addr = (u32_t)regs->regs; uiomem->size = regs->regs_size; ++uiomem; dev_info(&pdev->dev, "regs:%p (%u) / rings: %d found\n", regs->regs, regs->regs_size, regs->num_rings); } else { dev_info(&pdev->dev, "rings: %d found\n", regs->num_rings); } /* * The rest of the range correspond to the rings */ for (i = 0; i < regs->num_rings; i++) { dev_info(&pdev->dev, "\t%d: entries:%d ring:%p\n", i, regs->rings[i]->entries, &(regs->rings[i]->ring)); if (uiomem >= &uioinfo->mem[MAX_UIO_MAPS]) { dev_warn(&pdev->dev, "device has more than " __stringify(MAX_UIO_MAPS) " I/O memory resources.\n"); break; } uiomem->memtype = UIO_MEM_PHYS; uiomem->addr = (u32_t)&(regs->rings[i]->head); uiomem->size = (regs->rings[i]->entries * sizeof(u32_t)) + sizeof(struct uio_ubicom32ring_desc); ++uiomem; } while (uiomem < &uioinfo->mem[MAX_UIO_MAPS]) { uiomem->size = 0; ++uiomem; } /* This driver requires no hardware specific kernel code to handle * interrupts. Instead, the interrupt handler simply disables the * interrupt in the interrupt controller. User space is responsible * for performing hardware specific acknowledge and re-enabling of * the interrupt in the interrupt controller. * * Interrupt sharing is not supported. */ uioinfo->irq_flags = IRQF_DISABLED; uioinfo->irqcontrol = uio_ubicom32ring_irqcontrol; ret = uio_register_device(&pdev->dev, priv->uioinfo); if (ret) { dev_err(&pdev->dev, "unable to register uio device\n"); goto fail; } platform_set_drvdata(pdev, priv); dev_info(&pdev->dev, "'%s' using irq: rx %d tx %d, regs %p\n", priv->name, priv->irq_rx, priv->irq_tx, priv->regs); return 0; fail: kfree(uioinfo); kfree(priv); return ret; }
static int __devinit mbref_uio_probe(struct platform_device *pdev) { struct uio_info *uioinfo = pdev->dev.platform_data; struct uio_mem *uiomem; struct mbref_uio_platdata *priv; int i, ret = -EINVAL; if (!uioinfo) { int irq; /* alloc uioinfo for one device */ uioinfo = kzalloc(sizeof(*uioinfo), GFP_KERNEL); if (!uioinfo) { ret = -ENOMEM; dev_err(&pdev->dev, "unable to kmalloc uioinfo\n"); goto err; } uioinfo->name = DRIVER_NAME; /* or: pdev->dev.of_node->name */ uioinfo->version = DRIVER_VERS; /* Multiple IRQs are not supported */ irq = platform_get_irq(pdev, 0); if (irq == -ENXIO) uioinfo->irq = UIO_IRQ_NONE; else uioinfo->irq = irq; } if (!uioinfo || !uioinfo->name || !uioinfo->version) { dev_err(&pdev->dev, "missing platform_data\n"); goto err_cleanup0; } if (uioinfo->handler || uioinfo->irqcontrol || uioinfo->irq_flags & IRQF_SHARED) { dev_err(&pdev->dev, "interrupt configuration error\n"); goto err_cleanup0; } priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) { ret = -ENOMEM; dev_err(&pdev->dev, "unable to kmalloc\n"); goto err_cleanup0; } priv->uioinfo = uioinfo; spin_lock_init(&priv->lock); priv->flags = 0; /* interrupt is enabled to begin with */ priv->pdev = pdev; uiomem = &uioinfo->mem[0]; for (i = 0; i < pdev->num_resources; ++i) { struct resource *r = &pdev->resource[i]; if (r->flags != IORESOURCE_MEM) continue; if (uiomem >= &uioinfo->mem[MAX_UIO_MAPS]) { dev_warn(&pdev->dev, "device has more than " __stringify(MAX_UIO_MAPS) " I/O memory resources.\n"); break; } dev_info(&pdev->dev, "0x%08X-0x%08X\n", r->start, r->end); uiomem->memtype = UIO_MEM_PHYS; uiomem->addr = r->start; uiomem->size = resource_size(r); ++uiomem; } while (uiomem < &uioinfo->mem[MAX_UIO_MAPS]) { uiomem->size = 0; ++uiomem; } if (uioinfo->irq != UIO_IRQ_NONE) dev_info(&pdev->dev, "IRQ%li\n", uioinfo->irq); else dev_info(&pdev->dev, "no IRQ\n"); /* This driver requires no hardware specific kernel code to handle * interrupts. Instead, the interrupt handler simply disables the * interrupt in the interrupt controller. User space is responsible * for performing hardware specific acknowledge and re-enabling of * the interrupt in the interrupt controller. * * Interrupt sharing is not supported. */ uioinfo->handler = mbref_uio_handler; uioinfo->irqcontrol = mbref_uio_irqcontrol; uioinfo->open = mbref_uio_open; uioinfo->release = mbref_uio_release; uioinfo->priv = priv; /* Enable Runtime PM for this device: * The device starts in suspended state to allow the hardware to be * turned off by default. The Runtime PM bus code should power on the * hardware and enable clocks at open(). */ pm_runtime_enable(&pdev->dev); ret = uio_register_device(&pdev->dev, priv->uioinfo); if (ret) { dev_err(&pdev->dev, "unable to register uio device\n"); goto err_cleanup1; } platform_set_drvdata(pdev, priv); dev_info(&pdev->dev, "registered\n"); return 0; err_cleanup1: kfree(priv); pm_runtime_disable(&pdev->dev); err_cleanup0: /* kfree uioinfo for OF */ if (pdev->dev.of_node) kfree(uioinfo); err: return ret; }
static int __devinit mrf_probe(struct pci_dev *dev, const struct pci_device_id *id) { int ret = -ENODEV; struct mrf_priv *priv; struct uio_info *info; priv = kzalloc(sizeof(struct mrf_priv), GFP_KERNEL); if (!priv) return -ENOMEM; info = &priv->uio; priv->pdev = dev; ret = pci_enable_device(dev); if (ret) { dev_err(&dev->dev, "pci_enable_device failed with %d\n",ret); goto err_free; } if (!dev->irq) { dev_warn(&dev->dev, "Device not configured with IRQ!\n"); ret=-ENODEV; goto err_disable; } if (pci_request_regions(dev, DRV_NAME)) goto err_disable; /* BAR 0 is the PLX bridge */ info->mem[0].addr = pci_resource_start(dev, 0); info->mem[0].size = pci_resource_len(dev,0); info->mem[0].internal_addr =pci_ioremap_bar(dev,0); info->mem[0].memtype = UIO_MEM_PHYS; /* Not used */ info->mem[1].memtype = UIO_MEM_NONE; info->mem[1].size = 1; /* Otherwise UIO will stop searching... */ /* BAR 2 is the EVR */ info->mem[2].addr = pci_resource_start(dev, 2); info->mem[2].size = pci_resource_len(dev,2); info->mem[2].internal_addr =pci_ioremap_bar(dev,2); info->mem[2].memtype = UIO_MEM_PHYS; if (!info->mem[0].internal_addr || !info->mem[0].addr || !info->mem[2].internal_addr || !info->mem[2].addr) { dev_err(&dev->dev, "Failed to map BARS!\n"); ret=-ENODEV; goto err_release; } info->irq = dev->irq; info->irq_flags = IRQF_SHARED; info->handler = mrf_handler; info->irqcontrol = mrf_irqcontrol; #ifdef USE_CUSTOM_MMAP info->mmap = mrf_mmap_physical; #endif info->name = DRV_NAME; info->version = DRV_VERSION; info->priv = dev; pci_set_drvdata(dev, info); ret = uio_register_device(&dev->dev, info); if (ret) goto err_unmap; #if defined(CONFIG_GENERIC_GPIO) || defined(CONFIG_PARPORT_NOT_PC) spin_lock_init(&priv->lock); if (dev->device==PCI_DEVICE_ID_PLX_9030) { u32 val; void __iomem *plx = info->mem[0].internal_addr; /* GPIO Bits 0-3 are used as GPIO for JTAG. * Bits 4-7 must be left to their normal functions. * The device is expected to configure bits 4-7 * itself when initialized, and not change them * afterward. So we just avoid changes. * * Power up value observed in a PMC-EVR-230 * GPIOC = 0x00249924 * is consistent with the default given in the * PLX 9030 data book. */ val = ioread32(plx + GPIOC); /* clear everything for GPIO 0-3 (aka first 12 bits). * Preserve current settings for GPIO 4-7. * This will setup these as inputs (which float high) * * Each GPIO bit has 3 register bits (function, direction, and value) */ val &= 0xfffff000; // Enable output drivers for TCLK, TMS, and TDI val |= GPIOC_pin_dir(0); val |= GPIOC_pin_dir(1); val |= GPIOC_pin_dir(3); dev_info(&dev->dev, "GPIOC %08x\n", val); iowrite32(val, plx + GPIOC); #ifdef CONFIG_GENERIC_GPIO mrf_gpio_setup(priv); #endif #ifdef CONFIG_PARPORT_NOT_PC mrf_pp_setup(priv); #endif } #else if (dev->device==PCI_DEVICE_ID_PLX_9030) dev_info(&dev->dev, "GPIO support not built, JTAG unavailable\n"); #endif /* defined(CONFIG_GENERIC_GPIO) || defined(CONFIG_PARPORT_NOT_PC) */ dev_info(&dev->dev, "MRF Setup complete\n"); return 0; //err_unreg: // uio_unregister_device(info); // pci_set_drvdata(dev, NULL); err_unmap: iounmap(info->mem[0].internal_addr); iounmap(info->mem[2].internal_addr); err_release: pci_release_regions(dev); err_disable: pci_disable_device(dev); err_free: kzfree(priv); return ret; }
static int uio_mvisp_probe(struct platform_device *pdev) { struct resource *res; struct uio_mvisp_dev *cdev; int ret = 0; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { dev_err(&pdev->dev, "no memory resources given\n"); return -ENODEV; } cdev = devm_kzalloc(&pdev->dev, sizeof(*cdev), GFP_KERNEL); if (!cdev) { dev_err(&pdev->dev, "uio_mvisp_dev: out of memory\n"); return -ENOMEM; } cdev->clk = clk_get(&pdev->dev, "ISP-CLK"); if (IS_ERR(cdev->clk)) { dev_err(&pdev->dev, "cannot get mvisp clock\n"); ret = PTR_ERR(cdev->clk); goto err_clk; } cdev->reg_base = (void *)ioremap(res->start, res->end - res->start + 1); if (!cdev->reg_base) { dev_err(&pdev->dev, "can't remap register area\n"); ret = -ENOMEM; goto err_reg_base; } platform_set_drvdata(pdev, cdev); cdev->uio_info.name = UIO_MVISP_NAME; cdev->uio_info.version = UIO_MVISP_VERSION; cdev->uio_info.mem[0].internal_addr = (void __iomem *)cdev->reg_base; cdev->uio_info.mem[0].addr = res->start; cdev->uio_info.mem[0].memtype = UIO_MEM_PHYS; cdev->uio_info.mem[0].size = res->end - res->start + 1; cdev->uio_info.priv = cdev; cdev->uio_info.open = mvisp_open; cdev->uio_info.release = mvisp_release; cdev->uio_info.ioctl = mvisp_ioctl; cdev->uio_info.mmap = NULL; mutex_init(&(cdev->mutex)); cdev->filehandle_ins_num = 0; ret = uio_register_device(&pdev->dev, &cdev->uio_info); if (ret) { dev_err(&pdev->dev, "failed to register uio device\n"); goto err_uio_register; } return 0; err_uio_register: free_pages((unsigned long)cdev->uio_info.mem[1].internal_addr, get_order(VDEC_WORKING_BUFFER_SIZE)); err_reg_base: clk_put(cdev->clk); err_clk: devm_kfree(&pdev->dev, cdev); return ret; }
static int xillybus_lite_of_probe(struct platform_device *op) { struct device *dev = &op->dev; struct xillybus_lite_info *myinfo; struct uio_info *info; int rc; int irq; /* Allocate the driver data region */ myinfo = kzalloc(sizeof(*myinfo), GFP_KERNEL); if (!myinfo) { dev_err(dev, "Couldn't allocate device private record\n"); return -ENOMEM; } rc = of_address_to_resource(dev->of_node, 0, &myinfo->res); if (rc) { dev_err(dev, "Failed to obtain device tree resource\n"); goto noresource; } if (!request_mem_region(myinfo->res.start, resource_size(&myinfo->res), DRIVER_NAME)) { dev_err(dev, "request_mem_region failed. Aborting.\n"); rc = -EBUSY; goto noresource; } irq = irq_of_parse_and_map(dev->of_node, 0); info = &myinfo->info; info->name = DRIVER_NAME; info->version = "1.00"; info->mem[0].addr = myinfo->res.start; info->mem[0].size = resource_size(&myinfo->res); info->mem[0].memtype = UIO_MEM_PHYS; info->handler = xillybus_lite_handler; if ((irq == NO_IRQ) || !irq) info->irq = UIO_IRQ_NONE; else info->irq = irq; if (uio_register_device(dev, info)) goto failed_register; dev_set_drvdata(dev, myinfo); return 0; /* Success */ failed_register: release_mem_region(myinfo->res.start, resource_size(&myinfo->res)); noresource: kfree(myinfo); return rc; }
static int uio_pdrv_genirq_probe(struct platform_device *pdev) { struct uio_info *uioinfo = pdev->dev.platform_data; struct uio_pdrv_genirq_platdata *priv; struct uio_mem *uiomem; int ret = -EINVAL; int i; if (!uioinfo || !uioinfo->name || !uioinfo->version) { dev_err(&pdev->dev, "missing platform_data\n"); goto bad0; } if (uioinfo->handler || uioinfo->irqcontrol || uioinfo->irq_flags & IRQF_SHARED) { dev_err(&pdev->dev, "interrupt configuration error\n"); goto bad0; } priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) { ret = -ENOMEM; dev_err(&pdev->dev, "unable to kmalloc\n"); goto bad0; } priv->uioinfo = uioinfo; spin_lock_init(&priv->lock); priv->flags = 0; /* interrupt is enabled to begin with */ priv->pdev = pdev; uiomem = &uioinfo->mem[0]; for (i = 0; i < pdev->num_resources; ++i) { struct resource *r = &pdev->resource[i]; if (r->flags != IORESOURCE_MEM) continue; if (uiomem >= &uioinfo->mem[MAX_UIO_MAPS]) { dev_warn(&pdev->dev, "device has more than " __stringify(MAX_UIO_MAPS) " I/O memory resources.\n"); break; } uiomem->memtype = UIO_MEM_PHYS; uiomem->addr = r->start; uiomem->size = r->end - r->start + 1; ++uiomem; } while (uiomem < &uioinfo->mem[MAX_UIO_MAPS]) { uiomem->size = 0; ++uiomem; } /* This driver requires no hardware specific kernel code to handle * interrupts. Instead, the interrupt handler simply disables the * interrupt in the interrupt controller. User space is responsible * for performing hardware specific acknowledge and re-enabling of * the interrupt in the interrupt controller. * * Interrupt sharing is not supported. */ uioinfo->irq_flags |= IRQF_DISABLED; uioinfo->handler = uio_pdrv_genirq_handler; uioinfo->irqcontrol = uio_pdrv_genirq_irqcontrol; uioinfo->open = uio_pdrv_genirq_open; uioinfo->release = uio_pdrv_genirq_release; uioinfo->priv = priv; /* Enable Runtime PM for this device: * The device starts in suspended state to allow the hardware to be * turned off by default. The Runtime PM bus code should power on the * hardware and enable clocks at open(). */ pm_runtime_enable(&pdev->dev); ret = uio_register_device(&pdev->dev, priv->uioinfo); if (ret) { dev_err(&pdev->dev, "unable to register uio device\n"); goto bad1; } platform_set_drvdata(pdev, priv); return 0; bad1: kfree(priv); pm_runtime_disable(&pdev->dev); bad0: return ret; }
static int hv_uio_probe(struct hv_device *dev, const struct hv_vmbus_device_id *dev_id) { struct hv_uio_private_data *pdata; int ret; pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); if (!pdata) return -ENOMEM; ret = vmbus_open(dev->channel, HV_RING_SIZE * PAGE_SIZE, HV_RING_SIZE * PAGE_SIZE, NULL, 0, hv_uio_channel_cb, pdata); if (ret) goto fail; /* Communicating with host has to be via shared memory not hypercall */ if (!dev->channel->offermsg.monitor_allocated) { dev_err(&dev->device, "vmbus channel requires hypercall\n"); ret = -ENOTSUPP; goto fail_close; } dev->channel->inbound.ring_buffer->interrupt_mask = 1; set_channel_read_mode(dev->channel, HV_CALL_ISR); /* Fill general uio info */ pdata->info.name = "uio_hv_generic"; pdata->info.version = DRIVER_VERSION; pdata->info.irqcontrol = hv_uio_irqcontrol; pdata->info.irq = UIO_IRQ_CUSTOM; /* mem resources */ pdata->info.mem[TXRX_RING_MAP].name = "txrx_rings"; pdata->info.mem[TXRX_RING_MAP].addr = (phys_addr_t)dev->channel->ringbuffer_pages; pdata->info.mem[TXRX_RING_MAP].size = dev->channel->ringbuffer_pagecount << PAGE_SHIFT; pdata->info.mem[TXRX_RING_MAP].memtype = UIO_MEM_LOGICAL; pdata->info.mem[INT_PAGE_MAP].name = "int_page"; pdata->info.mem[INT_PAGE_MAP].addr = (phys_addr_t)vmbus_connection.int_page; pdata->info.mem[INT_PAGE_MAP].size = PAGE_SIZE; pdata->info.mem[INT_PAGE_MAP].memtype = UIO_MEM_LOGICAL; pdata->info.mem[MON_PAGE_MAP].name = "monitor_page"; pdata->info.mem[MON_PAGE_MAP].addr = (phys_addr_t)vmbus_connection.monitor_pages[1]; pdata->info.mem[MON_PAGE_MAP].size = PAGE_SIZE; pdata->info.mem[MON_PAGE_MAP].memtype = UIO_MEM_LOGICAL; pdata->recv_buf = vzalloc(RECV_BUFFER_SIZE); if (pdata->recv_buf == NULL) { ret = -ENOMEM; goto fail_close; } ret = vmbus_establish_gpadl(dev->channel, pdata->recv_buf, RECV_BUFFER_SIZE, &pdata->recv_gpadl); if (ret) goto fail_close; /* put Global Physical Address Label in name */ snprintf(pdata->recv_name, sizeof(pdata->recv_name), "recv:%u", pdata->recv_gpadl); pdata->info.mem[RECV_BUF_MAP].name = pdata->recv_name; pdata->info.mem[RECV_BUF_MAP].addr = (phys_addr_t)pdata->recv_buf; pdata->info.mem[RECV_BUF_MAP].size = RECV_BUFFER_SIZE; pdata->info.mem[RECV_BUF_MAP].memtype = UIO_MEM_VIRTUAL; pdata->send_buf = vzalloc(SEND_BUFFER_SIZE); if (pdata->send_buf == NULL) { ret = -ENOMEM; goto fail_close; } ret = vmbus_establish_gpadl(dev->channel, pdata->send_buf, SEND_BUFFER_SIZE, &pdata->send_gpadl); if (ret) goto fail_close; snprintf(pdata->send_name, sizeof(pdata->send_name), "send:%u", pdata->send_gpadl); pdata->info.mem[SEND_BUF_MAP].name = pdata->send_name; pdata->info.mem[SEND_BUF_MAP].addr = (phys_addr_t)pdata->send_buf; pdata->info.mem[SEND_BUF_MAP].size = SEND_BUFFER_SIZE; pdata->info.mem[SEND_BUF_MAP].memtype = UIO_MEM_VIRTUAL; pdata->info.priv = pdata; pdata->device = dev; ret = uio_register_device(&dev->device, &pdata->info); if (ret) { dev_err(&dev->device, "hv_uio register failed\n"); goto fail_close; } vmbus_set_chn_rescind_callback(dev->channel, hv_uio_rescind); hv_set_drvdata(dev, pdata); return 0; fail_close: hv_uio_cleanup(dev, pdata); vmbus_close(dev->channel); fail: kfree(pdata); return ret; }
static int __devinit #else static int #endif igbuio_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) { struct rte_uio_pci_dev *udev; struct msix_entry msix_entry; int err; /* essential vars for configuring the device with net_device */ struct net_device *netdev; struct net_adapter *adapter = NULL; struct ixgbe_hw *hw_i = NULL; struct e1000_hw *hw_e = NULL; udev = kzalloc(sizeof(struct rte_uio_pci_dev), GFP_KERNEL); if (!udev) return -ENOMEM; /* * enable device: ask low-level code to enable I/O and * memory */ err = pci_enable_device(dev); if (err != 0) { dev_err(&dev->dev, "Cannot enable PCI device\n"); goto fail_free; } /* * reserve device's PCI memory regions for use by this * module */ err = pci_request_regions(dev, "igb_uio"); if (err != 0) { dev_err(&dev->dev, "Cannot request regions\n"); goto fail_disable; } /* enable bus mastering on the device */ pci_set_master(dev); /* remap IO memory */ err = igbuio_setup_bars(dev, &udev->info); if (err != 0) goto fail_release_iomem; /* set 64-bit DMA mask */ err = pci_set_dma_mask(dev, DMA_BIT_MASK(64)); if (err != 0) { dev_err(&dev->dev, "Cannot set DMA mask\n"); goto fail_release_iomem; } err = pci_set_consistent_dma_mask(dev, DMA_BIT_MASK(64)); if (err != 0) { dev_err(&dev->dev, "Cannot set consistent DMA mask\n"); goto fail_release_iomem; } /* fill uio infos */ udev->info.name = "igb_uio"; udev->info.version = "0.1"; udev->info.handler = igbuio_pci_irqhandler; udev->info.irqcontrol = igbuio_pci_irqcontrol; #ifdef CONFIG_XEN_DOM0 /* check if the driver run on Xen Dom0 */ if (xen_initial_domain()) udev->info.mmap = igbuio_dom0_pci_mmap; #endif udev->info.priv = udev; udev->pdev = dev; switch (igbuio_intr_mode_preferred) { case RTE_INTR_MODE_MSIX: /* Only 1 msi-x vector needed */ msix_entry.entry = 0; if (pci_enable_msix(dev, &msix_entry, 1) == 0) { dev_dbg(&dev->dev, "using MSI-X"); udev->info.irq = msix_entry.vector; udev->mode = RTE_INTR_MODE_MSIX; break; } /* fall back to INTX */ case RTE_INTR_MODE_LEGACY: if (pci_intx_mask_supported(dev)) { dev_dbg(&dev->dev, "using INTX"); udev->info.irq_flags = IRQF_SHARED; udev->info.irq = dev->irq; udev->mode = RTE_INTR_MODE_LEGACY; break; } dev_notice(&dev->dev, "PCI INTX mask not supported\n"); /* fall back to no IRQ */ case RTE_INTR_MODE_NONE: udev->mode = RTE_INTR_MODE_NONE; udev->info.irq = 0; break; default: dev_err(&dev->dev, "invalid IRQ mode %u", igbuio_intr_mode_preferred); err = -EINVAL; goto fail_release_iomem; } err = sysfs_create_group(&dev->dev.kobj, &dev_attr_grp); if (err != 0) goto fail_release_iomem; /* initialize the corresponding netdev */ netdev = alloc_etherdev(sizeof(struct net_adapter)); if (!netdev) { err = -ENOMEM; goto fail_alloc_etherdev; } SET_NETDEV_DEV(netdev, pci_dev_to_dev(dev)); adapter = netdev_priv(netdev); adapter->netdev = netdev; adapter->pdev = dev; udev->adapter = adapter; adapter->type = retrieve_dev_specs(id); /* recover device-specific mac address */ switch (adapter->type) { case IXGBE: hw_i = &adapter->hw._ixgbe_hw; hw_i->back = adapter; hw_i->hw_addr = ioremap(pci_resource_start(dev, 0), pci_resource_len(dev, 0)); if (!hw_i->hw_addr) { err = -EIO; goto fail_ioremap; } break; case IGB: hw_e = &adapter->hw._e1000_hw; hw_e->back = adapter; hw_e->hw_addr = ioremap(pci_resource_start(dev, 0), pci_resource_len(dev, 0)); if (!hw_e->hw_addr) { err = -EIO; goto fail_ioremap; } break; } netdev_assign_netdev_ops(netdev); strncpy(netdev->name, pci_name(dev), sizeof(netdev->name) - 1); retrieve_dev_addr(netdev, adapter); strcpy(netdev->name, "dpdk%d"); err = register_netdev(netdev); if (err) goto fail_ioremap; adapter->netdev_registered = true; if (sscanf(netdev->name, "dpdk%hu", &adapter->bd_number) <= 0) goto fail_bdnumber; //printk(KERN_DEBUG "ifindex picked: %hu\n", adapter->bd_number); dev_info(&dev->dev, "ifindex picked: %hu\n", adapter->bd_number); /* register uio driver */ err = uio_register_device(&dev->dev, &udev->info); if (err != 0) goto fail_remove_group; pci_set_drvdata(dev, udev); dev_info(&dev->dev, "uio device registered with irq %lx\n", udev->info.irq); /* reset nstats */ memset(&adapter->nstats, 0, sizeof(struct net_device_stats)); return 0; fail_bdnumber: fail_ioremap: free_netdev(netdev); fail_alloc_etherdev: pci_release_selected_regions(dev, pci_select_bars(dev, IORESOURCE_MEM)); fail_remove_group: sysfs_remove_group(&dev->dev.kobj, &dev_attr_grp); fail_release_iomem: igbuio_pci_release_iomem(&udev->info); if (udev->mode == RTE_INTR_MODE_MSIX) pci_disable_msix(udev->pdev); pci_release_regions(dev); fail_disable: pci_disable_device(dev); fail_free: kfree(udev); return err; }
static int ivshmem_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) { struct uio_info *info; struct ivshmem_info *ivshmem_info; int nvectors = 4; info = kzalloc(sizeof(struct uio_info), GFP_KERNEL); if (!info) return -ENOMEM; ivshmem_info = kzalloc(sizeof(struct ivshmem_info), GFP_KERNEL); if (!ivshmem_info) { kfree(info); return -ENOMEM; } if (pci_enable_device(dev)) goto out_free; if (pci_request_regions(dev, "ivshmem")) goto out_disable; info->mem[0].addr = pci_resource_start(dev, 0); if (!info->mem[0].addr) goto out_release; info->mem[0].size = (pci_resource_len(dev, 0) + PAGE_SIZE - 1) & PAGE_MASK; info->mem[0].internal_addr = pci_ioremap_bar(dev, 0); if (!info->mem[0].internal_addr) goto out_release; info->mem[0].memtype = UIO_MEM_PHYS; info->mem[0].name = "registers"; info->mem[1].addr = pci_resource_start(dev, 2); if (!info->mem[1].addr) goto out_unmap; info->mem[1].size = pci_resource_len(dev, 2); info->mem[1].memtype = UIO_MEM_PHYS; info->mem[1].name = "shmem"; ivshmem_info->uio = info; ivshmem_info->dev = dev; if (request_msix_vectors(ivshmem_info, nvectors) != 0) { dev_info(&ivshmem_info->dev->dev, "regular IRQs\n"); info->irq = dev->irq; info->irq_flags = IRQF_SHARED; info->handler = ivshmem_handler; writel(0xffffffff, info->mem[0].internal_addr + IntrMask); } else { dev_info(&ivshmem_info->dev->dev, "MSI-X enabled\n"); pci_set_master(dev); info->irq = -1; } info->name = "ivshmem"; info->version = "0.0.1"; if (uio_register_device(&dev->dev, info)) goto out_unmap; pci_set_drvdata(dev, ivshmem_info); return 0; out_unmap: iounmap(info->mem[0].internal_addr); out_release: pci_release_regions(dev); out_disable: pci_disable_device(dev); out_free: kfree(ivshmem_info); kfree(info); return -ENODEV; }
static int __devinit #else static int #endif igbuio_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) { struct rte_uio_pci_dev *udev; dma_addr_t map_dma_addr; void *map_addr; int err; udev = kzalloc(sizeof(struct rte_uio_pci_dev), GFP_KERNEL); if (!udev) return -ENOMEM; mutex_init(&udev->lock); /* * enable device: ask low-level code to enable I/O and * memory */ err = pci_enable_device(dev); if (err != 0) { dev_err(&dev->dev, "Cannot enable PCI device\n"); goto fail_free; } /* enable bus mastering on the device */ pci_set_master(dev); /* remap IO memory */ err = igbuio_setup_bars(dev, &udev->info); if (err != 0) goto fail_release_iomem; /* set 64-bit DMA mask */ err = pci_set_dma_mask(dev, DMA_BIT_MASK(64)); if (err != 0) { dev_err(&dev->dev, "Cannot set DMA mask\n"); goto fail_release_iomem; } err = pci_set_consistent_dma_mask(dev, DMA_BIT_MASK(64)); if (err != 0) { dev_err(&dev->dev, "Cannot set consistent DMA mask\n"); goto fail_release_iomem; } /* fill uio infos */ udev->info.name = "igb_uio"; udev->info.version = "0.1"; udev->info.irqcontrol = igbuio_pci_irqcontrol; udev->info.open = igbuio_pci_open; udev->info.release = igbuio_pci_release; udev->info.priv = udev; udev->pdev = dev; err = sysfs_create_group(&dev->dev.kobj, &dev_attr_grp); if (err != 0) goto fail_release_iomem; /* register uio driver */ err = uio_register_device(&dev->dev, &udev->info); if (err != 0) goto fail_remove_group; pci_set_drvdata(dev, udev); /* * Doing a harmless dma mapping for attaching the device to * the iommu identity mapping if kernel boots with iommu=pt. * Note this is not a problem if no IOMMU at all. */ map_addr = dma_alloc_coherent(&dev->dev, 1024, &map_dma_addr, GFP_KERNEL); if (map_addr) memset(map_addr, 0, 1024); if (!map_addr) dev_info(&dev->dev, "dma mapping failed\n"); else { dev_info(&dev->dev, "mapping 1K dma=%#llx host=%p\n", (unsigned long long)map_dma_addr, map_addr); dma_free_coherent(&dev->dev, 1024, map_addr, map_dma_addr); dev_info(&dev->dev, "unmapping 1K dma=%#llx host=%p\n", (unsigned long long)map_dma_addr, map_addr); } return 0; fail_remove_group: sysfs_remove_group(&dev->dev.kobj, &dev_attr_grp); fail_release_iomem: igbuio_pci_release_iomem(&udev->info); pci_disable_device(dev); fail_free: kfree(udev); return err; }
static int sch_gpio_probe(struct platform_device *pdev) { struct resource *res; struct sch_gpio *chip; int err, id; chip = kzalloc(sizeof(*chip), GFP_KERNEL); if (chip == NULL) return -ENOMEM; chip_ptr = chip; sch_gpio_core_save_state(&(chip->initial_core)); sch_gpio_resume_save_state(&(chip->initial_resume)); id = pdev->id; if (!id) return -ENODEV; /* Get UIO memory */ info = kzalloc(sizeof(struct uio_info), GFP_KERNEL); if (!info) return -ENOMEM; res = platform_get_resource(pdev, IORESOURCE_IO, 0); if (!res) return -EBUSY; if (!request_region(res->start, resource_size(res), pdev->name)) return -EBUSY; gpio_ba = res->start; irq_num = RESOURCE_IRQ; switch (id) { case PCI_DEVICE_ID_INTEL_SCH_LPC: sch_gpio_core.base = 0; sch_gpio_core.ngpio = 10; sch_gpio_resume.base = 10; sch_gpio_resume.ngpio = 4; /* * GPIO[6:0] enabled by default * GPIO7 is configured by the CMC as SLPIOVR * Enable GPIO[9:8] core powered gpios explicitly */ outb(0x3, gpio_ba + CGEN + 1); /* * SUS_GPIO[2:0] enabled by default * Enable SUS_GPIO3 resume powered gpio explicitly */ outb(0x8, gpio_ba + RGEN); break; case PCI_DEVICE_ID_INTEL_ITC_LPC: sch_gpio_core.base = 0; sch_gpio_core.ngpio = 5; sch_gpio_resume.base = 5; sch_gpio_resume.ngpio = 9; break; case PCI_DEVICE_ID_INTEL_CENTERTON_ILB: sch_gpio_core.base = 0; sch_gpio_core.ngpio = 21; sch_gpio_resume.base = 21; sch_gpio_resume.ngpio = 9; break; case PCI_DEVICE_ID_INTEL_QUARK_ILB: sch_gpio_core.base = 0; sch_gpio_core.ngpio = 2; sch_gpio_resume.base = 2; sch_gpio_resume.ngpio = 6; break; default: err = -ENODEV; goto err_sch_gpio_core; } sch_gpio_core.dev = &pdev->dev; sch_gpio_resume.dev = &pdev->dev; err = gpiochip_add(&sch_gpio_core); if (err < 0) goto err_sch_gpio_core; err = gpiochip_add(&sch_gpio_resume); if (err < 0) goto err_sch_gpio_resume; chip->irq_base_core = irq_alloc_descs(-1, 0, sch_gpio_core.ngpio, NUMA_NO_NODE); if (chip->irq_base_core < 0) { dev_err(&pdev->dev, "failure adding GPIO core IRQ descs\n"); chip->irq_base_core = -1; goto err_sch_intr_core; } chip->irq_base_resume = irq_alloc_descs(-1, 0, sch_gpio_resume.ngpio, NUMA_NO_NODE); if (chip->irq_base_resume < 0) { dev_err(&pdev->dev, "failure adding GPIO resume IRQ descs\n"); chip->irq_base_resume = -1; goto err_sch_intr_resume; } platform_set_drvdata(pdev, chip); err = platform_device_register(&qrk_gpio_restrict_pdev); if (err < 0) goto err_sch_gpio_device_register; /* disable interrupts */ sch_gpio_core_irq_disable_all(chip, sch_gpio_core.ngpio); sch_gpio_resume_irq_disable_all(chip, sch_gpio_resume.ngpio); err = request_irq(irq_num, sch_gpio_irq_handler, IRQF_SHARED, KBUILD_MODNAME, chip); if (err != 0) { dev_err(&pdev->dev, "%s request_irq failed\n", __func__); goto err_sch_request_irq; } sch_gpio_core_irqs_init(chip, sch_gpio_core.ngpio); sch_gpio_resume_irqs_init(chip, sch_gpio_resume.ngpio); /* UIO */ info->port[0].name = "gpio_regs"; info->port[0].start = res->start; info->port[0].size = resource_size(res); info->port[0].porttype = UIO_PORT_X86; info->name = "sch_gpio"; info->version = "0.0.1"; if (uio_register_device(&pdev->dev, info)) goto err_sch_uio_register; pr_info("%s UIO port addr 0x%04x size %lu porttype %d\n", __func__, (unsigned int)info->port[0].start, info->port[0].size, info->port[0].porttype); return 0; err_sch_uio_register: free_irq(irq_num, chip); err_sch_request_irq: platform_device_unregister(&qrk_gpio_restrict_pdev); err_sch_gpio_device_register: irq_free_descs(chip->irq_base_resume, sch_gpio_resume.ngpio); err_sch_intr_resume: irq_free_descs(chip->irq_base_core, sch_gpio_core.ngpio); err_sch_intr_core: gpiochip_remove(&sch_gpio_resume); err_sch_gpio_resume: gpiochip_remove(&sch_gpio_core); err_sch_gpio_core: release_region(res->start, resource_size(res)); gpio_ba = 0; sch_gpio_resume_restore_state(&(chip->initial_resume)); sch_gpio_core_restore_state(&(chip->initial_core)); kfree(chip); chip_ptr = 0; if (info != NULL) kfree(info); return err; }
int __mbref_uio_pdrv_probe(struct device *dev, struct uio_info *uioinfo, struct resource *resources, unsigned int num_resources) { struct mbref_uio_platdata *priv; struct uio_mem *uiomem; unsigned int i; int ret; priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) { ret = -ENOMEM; dev_err(dev, "unable to kmalloc priv\n"); goto bad0; } priv->uioinfo = uioinfo; spin_lock_init(&priv->lock); priv->flags = 0; /* interrupt is enabled to begin with */ uiomem = &uioinfo->mem[0]; for (i = 0; i < num_resources; ++i) { struct resource *r = resources + i; if (r->flags != IORESOURCE_MEM) continue; if (uiomem >= &uioinfo->mem[MAX_UIO_MAPS]) { dev_warn(dev, "device has more than " __stringify(MAX_UIO_MAPS) " I/O memory resources.\n"); break; } uiomem->memtype = UIO_MEM_PHYS; uiomem->addr = r->start; uiomem->size = r->end - r->start + 1; ++uiomem; } while (uiomem < &uioinfo->mem[MAX_UIO_MAPS]) { uiomem->size = 0; ++uiomem; } /* This driver requires no hardware specific kernel code to handle * interrupts. Instead, the interrupt handler simply disables the * interrupt in the interrupt controller. User space is responsible * for performing hardware specific acknowledge and re-enabling of * the interrupt in the interrupt controller. * * Interrupt sharing is not supported. */ uioinfo->irq_flags |= IRQF_DISABLED; uioinfo->handler = mbref_uio_handler; uioinfo->irqcontrol = mbref_uio_irqcontrol; uioinfo->priv = priv; ret = uio_register_device(dev, priv->uioinfo); if (ret) { dev_err(dev, "unable to register uio device\n"); goto bad1; } dev_set_drvdata(dev, priv); return 0; bad1: kfree(priv); bad0: return ret; }
static int __devinit netx_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) { struct uio_info *info; int bar; info = kzalloc(sizeof(struct uio_info), GFP_KERNEL); if (!info) return -ENOMEM; if (pci_enable_device(dev)) goto out_free; if (pci_request_regions(dev, "netx")) goto out_disable; switch (id->device) { case PCI_DEVICE_ID_HILSCHER_NETX: bar = 0; info->name = "netx"; break; default: bar = 2; info->name = "netx_plx"; } /* BAR0 or 2 points to the card's dual port memory */ info->mem[0].addr = pci_resource_start(dev, bar); if (!info->mem[0].addr) goto out_release; info->mem[0].internal_addr = ioremap(pci_resource_start(dev, bar), pci_resource_len(dev, bar)); if (!info->mem[0].internal_addr) goto out_release; info->mem[0].size = pci_resource_len(dev, bar); info->mem[0].memtype = UIO_MEM_PHYS; info->irq = dev->irq; info->irq_flags = IRQF_SHARED; info->handler = netx_handler; info->version = "0.0.1"; /* Make sure all interrupts are disabled */ iowrite32(0, info->mem[0].internal_addr + DPM_HOST_INT_EN0); if (uio_register_device(&dev->dev, info)) goto out_unmap; pci_set_drvdata(dev, info); dev_info(&dev->dev, "Found %s card, registered UIO device.\n", info->name); return 0; out_unmap: iounmap(info->mem[0].internal_addr); out_release: pci_release_regions(dev); out_disable: pci_disable_device(dev); out_free: kfree(info); return -ENODEV; }
static int __devinit #else static int #endif igbuio_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) { struct rte_uio_pci_dev *udev; struct msix_entry msix_entry; int err; udev = kzalloc(sizeof(struct rte_uio_pci_dev), GFP_KERNEL); if (!udev) return -ENOMEM; /* * enable device: ask low-level code to enable I/O and * memory */ err = pci_enable_device(dev); if (err != 0) { dev_err(&dev->dev, "Cannot enable PCI device\n"); goto fail_free; } /* * reserve device's PCI memory regions for use by this * module */ err = pci_request_regions(dev, "igb_uio"); if (err != 0) { dev_err(&dev->dev, "Cannot request regions\n"); goto fail_disable; } /* enable bus mastering on the device */ pci_set_master(dev); /* remap IO memory */ err = igbuio_setup_bars(dev, &udev->info); if (err != 0) goto fail_release_iomem; /* set 64-bit DMA mask */ err = pci_set_dma_mask(dev, DMA_BIT_MASK(64)); if (err != 0) { dev_err(&dev->dev, "Cannot set DMA mask\n"); goto fail_release_iomem; } err = pci_set_consistent_dma_mask(dev, DMA_BIT_MASK(64)); if (err != 0) { dev_err(&dev->dev, "Cannot set consistent DMA mask\n"); goto fail_release_iomem; } /* fill uio infos */ udev->info.name = "igb_uio"; udev->info.version = "0.1"; udev->info.handler = igbuio_pci_irqhandler; udev->info.irqcontrol = igbuio_pci_irqcontrol; #ifdef CONFIG_XEN_DOM0 /* check if the driver run on Xen Dom0 */ if (xen_initial_domain()) udev->info.mmap = igbuio_dom0_pci_mmap; #endif udev->info.priv = udev; udev->pdev = dev; switch (igbuio_intr_mode_preferred) { case RTE_INTR_MODE_MSIX: /* Only 1 msi-x vector needed */ msix_entry.entry = 0; if (pci_enable_msix(dev, &msix_entry, 1) == 0) { dev_dbg(&dev->dev, "using MSI-X"); udev->info.irq = msix_entry.vector; udev->mode = RTE_INTR_MODE_MSIX; break; } /* fall back to INTX */ case RTE_INTR_MODE_LEGACY: if (pci_intx_mask_supported(dev)) { dev_dbg(&dev->dev, "using INTX"); udev->info.irq_flags = IRQF_SHARED; udev->info.irq = dev->irq; udev->mode = RTE_INTR_MODE_LEGACY; break; } dev_notice(&dev->dev, "PCI INTX mask not supported\n"); /* fall back to no IRQ */ case RTE_INTR_MODE_NONE: udev->mode = RTE_INTR_MODE_NONE; udev->info.irq = 0; break; default: dev_err(&dev->dev, "invalid IRQ mode %u", igbuio_intr_mode_preferred); err = -EINVAL; goto fail_release_iomem; } err = sysfs_create_group(&dev->dev.kobj, &dev_attr_grp); if (err != 0) goto fail_release_iomem; /* register uio driver */ err = uio_register_device(&dev->dev, &udev->info); if (err != 0) goto fail_remove_group; pci_set_drvdata(dev, udev); dev_info(&dev->dev, "uio device registered with irq %lx\n", udev->info.irq); return 0; fail_remove_group: sysfs_remove_group(&dev->dev.kobj, &dev_attr_grp); fail_release_iomem: igbuio_pci_release_iomem(&udev->info); if (udev->mode == RTE_INTR_MODE_MSIX) pci_disable_msix(udev->pdev); pci_release_regions(dev); fail_disable: pci_disable_device(dev); fail_free: kfree(udev); return err; }
static int hv_uio_probe(struct hv_device *dev, const struct hv_vmbus_device_id *dev_id) { struct vmbus_channel *channel = dev->channel; struct hv_uio_private_data *pdata; void *ring_buffer; int ret; /* Communicating with host has to be via shared memory not hypercall */ if (!channel->offermsg.monitor_allocated) { dev_err(&dev->device, "vmbus channel requires hypercall\n"); return -ENOTSUPP; } pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); if (!pdata) return -ENOMEM; ret = vmbus_alloc_ring(channel, HV_RING_SIZE * PAGE_SIZE, HV_RING_SIZE * PAGE_SIZE); if (ret) goto fail; set_channel_read_mode(channel, HV_CALL_ISR); /* Fill general uio info */ pdata->info.name = "uio_hv_generic"; pdata->info.version = DRIVER_VERSION; pdata->info.irqcontrol = hv_uio_irqcontrol; pdata->info.open = hv_uio_open; pdata->info.release = hv_uio_release; pdata->info.irq = UIO_IRQ_CUSTOM; atomic_set(&pdata->refcnt, 0); /* mem resources */ pdata->info.mem[TXRX_RING_MAP].name = "txrx_rings"; ring_buffer = page_address(channel->ringbuffer_page); pdata->info.mem[TXRX_RING_MAP].addr = (uintptr_t)virt_to_phys(ring_buffer); pdata->info.mem[TXRX_RING_MAP].size = channel->ringbuffer_pagecount << PAGE_SHIFT; pdata->info.mem[TXRX_RING_MAP].memtype = UIO_MEM_IOVA; pdata->info.mem[INT_PAGE_MAP].name = "int_page"; pdata->info.mem[INT_PAGE_MAP].addr = (uintptr_t)vmbus_connection.int_page; pdata->info.mem[INT_PAGE_MAP].size = PAGE_SIZE; pdata->info.mem[INT_PAGE_MAP].memtype = UIO_MEM_LOGICAL; pdata->info.mem[MON_PAGE_MAP].name = "monitor_page"; pdata->info.mem[MON_PAGE_MAP].addr = (uintptr_t)vmbus_connection.monitor_pages[1]; pdata->info.mem[MON_PAGE_MAP].size = PAGE_SIZE; pdata->info.mem[MON_PAGE_MAP].memtype = UIO_MEM_LOGICAL; pdata->recv_buf = vzalloc(RECV_BUFFER_SIZE); if (pdata->recv_buf == NULL) { ret = -ENOMEM; goto fail_close; } ret = vmbus_establish_gpadl(channel, pdata->recv_buf, RECV_BUFFER_SIZE, &pdata->recv_gpadl); if (ret) goto fail_close; /* put Global Physical Address Label in name */ snprintf(pdata->recv_name, sizeof(pdata->recv_name), "recv:%u", pdata->recv_gpadl); pdata->info.mem[RECV_BUF_MAP].name = pdata->recv_name; pdata->info.mem[RECV_BUF_MAP].addr = (uintptr_t)pdata->recv_buf; pdata->info.mem[RECV_BUF_MAP].size = RECV_BUFFER_SIZE; pdata->info.mem[RECV_BUF_MAP].memtype = UIO_MEM_VIRTUAL; pdata->send_buf = vzalloc(SEND_BUFFER_SIZE); if (pdata->send_buf == NULL) { ret = -ENOMEM; goto fail_close; } ret = vmbus_establish_gpadl(channel, pdata->send_buf, SEND_BUFFER_SIZE, &pdata->send_gpadl); if (ret) goto fail_close; snprintf(pdata->send_name, sizeof(pdata->send_name), "send:%u", pdata->send_gpadl); pdata->info.mem[SEND_BUF_MAP].name = pdata->send_name; pdata->info.mem[SEND_BUF_MAP].addr = (uintptr_t)pdata->send_buf; pdata->info.mem[SEND_BUF_MAP].size = SEND_BUFFER_SIZE; pdata->info.mem[SEND_BUF_MAP].memtype = UIO_MEM_VIRTUAL; pdata->info.priv = pdata; pdata->device = dev; ret = uio_register_device(&dev->device, &pdata->info); if (ret) { dev_err(&dev->device, "hv_uio register failed\n"); goto fail_close; } ret = sysfs_create_bin_file(&channel->kobj, &ring_buffer_bin_attr); if (ret) dev_notice(&dev->device, "sysfs create ring bin file failed; %d\n", ret); hv_set_drvdata(dev, pdata); return 0; fail_close: hv_uio_cleanup(dev, pdata); fail: kfree(pdata); return ret; }
static int xapm_probe(struct platform_device *pdev) { struct xapm_dev *xapm; struct resource *res; int irq; int ret; void *ptr; xapm = devm_kzalloc(&pdev->dev, (sizeof(struct xapm_dev)), GFP_KERNEL); if (!xapm) return -ENOMEM; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); xapm->regs = devm_ioremap_resource(&pdev->dev, res); if (!xapm->regs) { dev_err(&pdev->dev, "unable to iomap registers\n"); return -ENOMEM; } /* Initialize mode as Advanced so that if no mode in dts, default * is Advanced */ xapm->param.mode = XAPM_MODE_ADVANCED; ret = xapm_getprop(pdev, &xapm->param); if (ret < 0) return ret; xapm->info.mem[0].name = "xilinx_apm"; xapm->info.mem[0].addr = res->start; xapm->info.mem[0].size = resource_size(res); xapm->info.mem[0].memtype = UIO_MEM_PHYS; xapm->info.mem[1].addr = (unsigned long)kzalloc(UIO_DUMMY_MEMSIZE, GFP_KERNEL); ptr = (unsigned long *)xapm->info.mem[1].addr; xapm->info.mem[1].size = UIO_DUMMY_MEMSIZE; xapm->info.mem[1].memtype = UIO_MEM_LOGICAL; xapm->info.name = "axi-pmon"; xapm->info.version = DRV_VERSION; irq = platform_get_irq(pdev, 0); if (irq < 0) { dev_err(&pdev->dev, "unable to get irq\n"); return irq; } xapm->info.irq = irq; xapm->info.handler = xapm_handler; xapm->info.priv = xapm; memcpy(ptr, &xapm->param, sizeof(struct xapm_param)); ret = uio_register_device(&pdev->dev, &xapm->info); if (ret < 0) { dev_err(&pdev->dev, "unable to register to UIO\n"); return ret; } platform_set_drvdata(pdev, xapm); dev_info(&pdev->dev, "Probed Xilinx APM\n"); return 0; }
static int __devinit smx_ce_probe(struct platform_device *dev) { int ret = -ENODEV; struct uio_info *info; struct resource *regs; info = kzalloc(sizeof(struct uio_info), GFP_KERNEL); if (!info) return -ENOMEM; regs = platform_get_resource(dev, IORESOURCE_MEM, 0); if (!regs) { dev_err(&dev->dev, "No memory resource specified\n"); goto out_free; } info->mem[0].addr = regs->start; if (!info->mem[0].addr) { dev_err(&dev->dev, "Invalid memory resource\n"); goto out_free; } info->mem[0].size = regs->end - regs->start + 1; info->mem[0].internal_addr = ioremap(regs->start, info->mem[0].size); if (!info->mem[0].internal_addr) { dev_err(&dev->dev, "Can't remap memory address range\n"); goto out_free; } info->mem[0].memtype = UIO_MEM_PHYS; info->name = "smx-ce"; info->version = "0.03"; info->irq = platform_get_irq(dev, 0); if (info->irq < 0) { ret = info->irq; dev_err(&dev->dev, "No (or invalid) IRQ resource specified\n"); goto out_unmap; } info->irq_flags = IRQF_SHARED; info->handler = smx_handler; platform_set_drvdata(dev, info); ret = uio_register_device(&dev->dev, info); if (ret) goto out_unmap; return 0; out_unmap: iounmap(info->mem[0].internal_addr); out_free: kfree(info); return ret; }
static int mf624_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) { struct uio_info *info; info = kzalloc(sizeof(struct uio_info), GFP_KERNEL); if (!info) return -ENOMEM; if (pci_enable_device(dev)) goto out_free; if (pci_request_regions(dev, "mf624")) goto out_disable; info->name = "mf624"; info->version = "0.0.1"; /* Note: Datasheet says device uses BAR0, BAR1, BAR2 -- do not trust it */ /* BAR0 */ info->mem[0].name = "PCI chipset, interrupts, status " "bits, special functions"; info->mem[0].addr = pci_resource_start(dev, 0); if (!info->mem[0].addr) goto out_release; info->mem[0].size = pci_resource_len(dev, 0); info->mem[0].memtype = UIO_MEM_PHYS; info->mem[0].internal_addr = pci_ioremap_bar(dev, 0); if (!info->mem[0].internal_addr) goto out_release; /* BAR2 */ info->mem[1].name = "ADC, DAC, DIO"; info->mem[1].addr = pci_resource_start(dev, 2); if (!info->mem[1].addr) goto out_unmap0; info->mem[1].size = pci_resource_len(dev, 2); info->mem[1].memtype = UIO_MEM_PHYS; info->mem[1].internal_addr = pci_ioremap_bar(dev, 2); if (!info->mem[1].internal_addr) goto out_unmap0; /* BAR4 */ info->mem[2].name = "Counter/timer chip"; info->mem[2].addr = pci_resource_start(dev, 4); if (!info->mem[2].addr) goto out_unmap1; info->mem[2].size = pci_resource_len(dev, 4); info->mem[2].memtype = UIO_MEM_PHYS; info->mem[2].internal_addr = pci_ioremap_bar(dev, 4); if (!info->mem[2].internal_addr) goto out_unmap1; info->irq = dev->irq; info->irq_flags = IRQF_SHARED; info->handler = mf624_irq_handler; info->irqcontrol = mf624_irqcontrol; if (uio_register_device(&dev->dev, info)) goto out_unmap2; pci_set_drvdata(dev, info); return 0; out_unmap2: iounmap(info->mem[2].internal_addr); out_unmap1: iounmap(info->mem[1].internal_addr); out_unmap0: iounmap(info->mem[0].internal_addr); out_release: pci_release_regions(dev); out_disable: pci_disable_device(dev); out_free: kfree(info); return -ENODEV; }
static int __devinit pruss_probe(struct platform_device *dev) { struct uio_info *p; struct uio_pruss_dev *gdev; struct resource *regs_prussio; int ret = -ENODEV, cnt = 0, len; struct uio_pruss_pdata *pdata = dev->dev.platform_data; gdev = kzalloc(sizeof(struct uio_pruss_dev), GFP_KERNEL); if (!gdev) return -ENOMEM; gdev->info = kzalloc(sizeof(*p) * MAX_PRUSS_EVT, GFP_KERNEL); if (!gdev->info) { kfree(gdev); return -ENOMEM; } /* Power on PRU in case its not done as part of boot-loader */ gdev->pruss_clk = clk_get(&dev->dev, "pruss"); if (IS_ERR(gdev->pruss_clk)) { dev_err(&dev->dev, "Failed to get clock\n"); kfree(gdev->info); kfree(gdev); ret = PTR_ERR(gdev->pruss_clk); return ret; } else { clk_enable(gdev->pruss_clk); } regs_prussio = platform_get_resource(dev, IORESOURCE_MEM, 0); if (!regs_prussio) { dev_err(&dev->dev, "No PRUSS I/O resource specified\n"); goto out_free; } if (!regs_prussio->start) { dev_err(&dev->dev, "Invalid memory resource\n"); goto out_free; } gdev->sram_vaddr = (void *)gen_pool_alloc(davinci_gen_pool, sram_pool_sz); if (!gdev->sram_vaddr) { dev_err(&dev->dev, "Could not allocate SRAM pool\n"); goto out_free; } gdev->sram_paddr = gen_pool_virt_to_phys(davinci_gen_pool, (unsigned long)gdev->sram_vaddr); gdev->ddr_vaddr = dma_alloc_coherent(&dev->dev, extram_pool_sz, &(gdev->ddr_paddr), GFP_KERNEL | GFP_DMA); if (!gdev->ddr_vaddr) { dev_err(&dev->dev, "Could not allocate external memory\n"); goto out_free; } len = resource_size(regs_prussio); gdev->prussio_vaddr = ioremap(regs_prussio->start, len); if (!gdev->prussio_vaddr) { dev_err(&dev->dev, "Can't remap PRUSS I/O address range\n"); goto out_free; } gdev->pintc_base = pdata->pintc_base; gdev->hostirq_start = platform_get_irq(dev, 0); for (cnt = 0, p = gdev->info; cnt < MAX_PRUSS_EVT; cnt++, p++) { p->mem[0].addr = regs_prussio->start; p->mem[0].size = resource_size(regs_prussio); p->mem[0].memtype = UIO_MEM_PHYS; p->mem[1].addr = gdev->sram_paddr; p->mem[1].size = sram_pool_sz; p->mem[1].memtype = UIO_MEM_PHYS; p->mem[2].addr = gdev->ddr_paddr; p->mem[2].size = extram_pool_sz; p->mem[2].memtype = UIO_MEM_PHYS; p->name = kasprintf(GFP_KERNEL, "pruss_evt%d", cnt); p->version = DRV_VERSION; /* Register PRUSS IRQ lines */ p->irq = gdev->hostirq_start + cnt; p->handler = pruss_handler; p->priv = gdev; ret = uio_register_device(&dev->dev, p); if (ret < 0) goto out_free; } platform_set_drvdata(dev, gdev); return 0; out_free: pruss_cleanup(dev, gdev); return ret; }
static int uio_fsl_elbc_gpcm_probe(struct platform_device *pdev) { struct device_node *node = pdev->dev.of_node; struct fsl_elbc_gpcm *priv; struct uio_info *info; char *uio_name = NULL; struct resource res; unsigned int irq; u32 reg_br_cur; u32 reg_or_cur; u32 reg_br_new; u32 reg_or_new; int ret; if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs) return -ENODEV; /* allocate private data */ priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; priv->dev = &pdev->dev; priv->lbc = fsl_lbc_ctrl_dev->regs; /* get device tree data */ ret = get_of_data(priv, node, &res, ®_br_new, ®_or_new, &irq, &uio_name); if (ret) goto out_err0; /* allocate UIO structure */ info = kzalloc(sizeof(*info), GFP_KERNEL); if (!info) { ret = -ENOMEM; goto out_err0; } /* get current BR/OR values */ reg_br_cur = in_be32(&priv->lbc->bank[priv->bank].br); reg_or_cur = in_be32(&priv->lbc->bank[priv->bank].or); /* if bank already configured, make sure it matches */ if ((reg_br_cur & BR_V)) { if ((reg_br_cur & BR_MSEL) != BR_MS_GPCM || (reg_br_cur & reg_or_cur & BR_BA) != fsl_lbc_addr(res.start)) { dev_err(priv->dev, "bank in use by another peripheral\n"); ret = -ENODEV; goto out_err1; } /* warn if behavior settings changing */ if ((reg_br_cur & ~(BR_BA | BR_V)) != (reg_br_new & ~(BR_BA | BR_V))) { dev_warn(priv->dev, "modifying BR settings: 0x%08x -> 0x%08x", reg_br_cur, reg_br_new); } if ((reg_or_cur & ~OR_GPCM_AM) != (reg_or_new & ~OR_GPCM_AM)) { dev_warn(priv->dev, "modifying OR settings: 0x%08x -> 0x%08x", reg_or_cur, reg_or_new); } } /* configure the bank (force base address and GPCM) */ reg_br_new &= ~(BR_BA | BR_MSEL); reg_br_new |= fsl_lbc_addr(res.start) | BR_MS_GPCM | BR_V; out_be32(&priv->lbc->bank[priv->bank].or, reg_or_new); out_be32(&priv->lbc->bank[priv->bank].br, reg_br_new); /* map the memory resource */ info->mem[0].internal_addr = ioremap(res.start, resource_size(&res)); if (!info->mem[0].internal_addr) { dev_err(priv->dev, "failed to map chip region\n"); ret = -ENODEV; goto out_err1; } /* set all UIO data */ if (node->name) info->mem[0].name = kstrdup(node->name, GFP_KERNEL); info->mem[0].addr = res.start; info->mem[0].size = resource_size(&res); info->mem[0].memtype = UIO_MEM_PHYS; info->priv = priv; info->name = uio_name; info->version = "0.0.1"; if (irq != NO_IRQ) { if (priv->irq_handler) { info->irq = irq; info->irq_flags = IRQF_SHARED; info->handler = priv->irq_handler; } else { irq = NO_IRQ; dev_warn(priv->dev, "ignoring irq, no handler\n"); } } if (priv->init) priv->init(info); /* register UIO device */ if (uio_register_device(priv->dev, info) != 0) { dev_err(priv->dev, "UIO registration failed\n"); ret = -ENODEV; goto out_err2; } /* store private data */ platform_set_drvdata(pdev, info); /* create sysfs files */ ret = device_create_file(priv->dev, &dev_attr_reg_br); if (ret) goto out_err3; ret = device_create_file(priv->dev, &dev_attr_reg_or); if (ret) goto out_err4; dev_info(priv->dev, "eLBC/GPCM device (%s) at 0x%llx, bank %d, irq=%d\n", priv->name, (unsigned long long)res.start, priv->bank, irq != NO_IRQ ? irq : -1); return 0; out_err4: device_remove_file(priv->dev, &dev_attr_reg_br); out_err3: platform_set_drvdata(pdev, NULL); uio_unregister_device(info); out_err2: if (priv->shutdown) priv->shutdown(info, true); iounmap(info->mem[0].internal_addr); out_err1: kfree(info->mem[0].name); kfree(info); out_err0: kfree(uio_name); kfree(priv); return ret; }