The uio_dmem_genirq works in a similar way as uio_pdrv_genirq now. It accepts the of_id module parameter to bind to a specific device. The information about dynamic memory is obtained from OF. This patch implements the two OF bindings: * uio,number-of-dynamic-regions * uio,dynamic-regions-sizes Signed-off-by: Jan Viktorin <viktorin@xxxxxxxxxxxxxx> --- drivers/uio/uio_dmem_genirq.c | 76 +++++++++++++++++++++++++++++++++---------- 1 file changed, 58 insertions(+), 18 deletions(-) diff --git a/drivers/uio/uio_dmem_genirq.c b/drivers/uio/uio_dmem_genirq.c index 945515d..ade650a 100644 --- a/drivers/uio/uio_dmem_genirq.c +++ b/drivers/uio/uio_dmem_genirq.c @@ -144,29 +144,70 @@ static int uio_dmem_genirq_irqcontrol(struct uio_info *dev_info, s32 irq_on) return 0; } +static int uio_dmem_genirq_alloc_platdata(struct platform_device *pdev) +{ + struct uio_dmem_genirq_pdata pdata; + u32 regions; + u32 sizes[MAX_UIO_MAPS]; + int ret; + + memset(&pdata, 0, sizeof(pdata)); + + ret = of_property_read_u32(pdev->dev.of_node, + "uio,number-of-dynamic-regions", ®ions); + if (ret) { + dev_err(&pdev->dev, + "Missing property uio,number-of-dynamic-regions\n"); + return ret; + } + + regions = min_t(u32, regions, MAX_UIO_MAPS); + + ret = of_property_read_u32_array(pdev->dev.of_node, + "uio,dynamic-regions-sizes", sizes, regions); + if (ret) { + dev_err(&pdev->dev, "Missing or invalid property " + "uio,dynamic-regions-sizes\n"); + return ret; + } + + pdata.dynamic_region_sizes = devm_kzalloc(&pdev->dev, + sizeof(*pdata.dynamic_region_sizes) * + pdata.num_dynamic_regions, GFP_KERNEL); + if (!pdata.dynamic_region_sizes) { + dev_err(&pdev->dev, "Unable to alloc dynamic_region_sizes\n"); + ret = -ENOMEM; + return ret; + } + + pdata.num_dynamic_regions = regions; + while (regions--) + pdata.dynamic_region_sizes[regions] = sizes[regions]; + + pdata.uioinfo.name = pdev->dev.of_node->name; + pdata.uioinfo.version = "devicetree"; + + return platform_device_add_data(pdev, &pdata, sizeof(pdata)); +} + 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_pdata *pdata; + struct uio_info *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"); + ret = uio_dmem_genirq_alloc_platdata(pdev); + if (ret) goto bad2; - } - uioinfo->name = pdev->dev.of_node->name; - uioinfo->version = "devicetree"; } + pdata = dev_get_platdata(&pdev->dev); + uioinfo = &pdata->uioinfo; + if (!uioinfo || !uioinfo->name || !uioinfo->version) { dev_err(&pdev->dev, "missing platform_data\n"); goto bad0; @@ -298,10 +339,6 @@ static int uio_dmem_genirq_remove(struct platform_device *pdev) priv->uioinfo->handler = NULL; priv->uioinfo->irqcontrol = NULL; - /* kfree uioinfo for OF */ - if (pdev->dev.of_node) - kfree(priv->uioinfo); - kfree(priv); return 0; } @@ -329,10 +366,13 @@ static const struct dev_pm_ops uio_dmem_genirq_dev_pm_ops = { }; #ifdef CONFIG_OF -static const struct of_device_id uio_of_genirq_match[] = { - { /* empty for now */ }, +static struct of_device_id uio_of_genirq_match[] = { + { /* This is filled with module_parm */ }, + { /* end of list */ }, }; MODULE_DEVICE_TABLE(of, uio_of_genirq_match); +module_param_string(of_id, uio_of_genirq_match[0].compatible, 128, 0); +MODULE_PARM_DESC(of_id, "Openfirmware id of the device to be handled by uio"); #endif static struct platform_driver uio_dmem_genirq = { -- 2.8.0 -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html