]> Pileus Git - ~andy/linux/blobdiff - drivers/bus/imx-weim.c
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
[~andy/linux] / drivers / bus / imx-weim.c
index 349f14e886b7b50d8a599c953b1a7f553904a081..3ef58c8dbf1143cb555a1be8cf121d4d456dd854 100644 (file)
 #include <linux/io.h>
 #include <linux/of_device.h>
 
-struct imx_weim {
-       void __iomem *base;
-       struct clk *clk;
+struct imx_weim_devtype {
+       unsigned int    cs_count;
+       unsigned int    cs_regs_count;
+       unsigned int    cs_stride;
+};
+
+static const struct imx_weim_devtype imx1_weim_devtype = {
+       .cs_count       = 6,
+       .cs_regs_count  = 2,
+       .cs_stride      = 0x08,
+};
+
+static const struct imx_weim_devtype imx27_weim_devtype = {
+       .cs_count       = 6,
+       .cs_regs_count  = 3,
+       .cs_stride      = 0x10,
+};
+
+static const struct imx_weim_devtype imx50_weim_devtype = {
+       .cs_count       = 4,
+       .cs_regs_count  = 6,
+       .cs_stride      = 0x18,
+};
+
+static const struct imx_weim_devtype imx51_weim_devtype = {
+       .cs_count       = 6,
+       .cs_regs_count  = 6,
+       .cs_stride      = 0x18,
 };
 
 static const struct of_device_id weim_id_table[] = {
-       { .compatible = "fsl,imx6q-weim", },
-       {}
+       /* i.MX1/21 */
+       { .compatible = "fsl,imx1-weim", .data = &imx1_weim_devtype, },
+       /* i.MX25/27/31/35 */
+       { .compatible = "fsl,imx27-weim", .data = &imx27_weim_devtype, },
+       /* i.MX50/53/6Q */
+       { .compatible = "fsl,imx50-weim", .data = &imx50_weim_devtype, },
+       { .compatible = "fsl,imx6q-weim", .data = &imx50_weim_devtype, },
+       /* i.MX51 */
+       { .compatible = "fsl,imx51-weim", .data = &imx51_weim_devtype, },
+       { }
 };
 MODULE_DEVICE_TABLE(of, weim_id_table);
 
-#define CS_TIMING_LEN 6
-#define CS_REG_RANGE  0x18
-
 /* Parse and set the timing for this device. */
-static int
-weim_timing_setup(struct platform_device *pdev, struct device_node *np)
+static int __init weim_timing_setup(struct device_node *np, void __iomem *base,
+                                   const struct imx_weim_devtype *devtype)
 {
-       struct imx_weim *weim = platform_get_drvdata(pdev);
-       u32 value[CS_TIMING_LEN];
-       u32 cs_idx;
-       int ret;
-       int i;
+       u32 cs_idx, value[devtype->cs_regs_count];
+       int i, ret;
 
        /* get the CS index from this child node's "reg" property. */
        ret = of_property_read_u32(np, "reg", &cs_idx);
        if (ret)
                return ret;
 
-       /* The weim has four chip selects. */
-       if (cs_idx > 3)
+       if (cs_idx >= devtype->cs_count)
                return -EINVAL;
 
        ret = of_property_read_u32_array(np, "fsl,weim-cs-timing",
-                                       value, CS_TIMING_LEN);
+                                        value, devtype->cs_regs_count);
        if (ret)
                return ret;
 
        /* set the timing for WEIM */
-       for (i = 0; i < CS_TIMING_LEN; i++)
-               writel(value[i], weim->base + cs_idx * CS_REG_RANGE + i * 4);
+       for (i = 0; i < devtype->cs_regs_count; i++)
+               writel(value[i], base + cs_idx * devtype->cs_stride + i * 4);
+
        return 0;
 }
 
-static int weim_parse_dt(struct platform_device *pdev)
+static int __init weim_parse_dt(struct platform_device *pdev,
+                               void __iomem *base)
 {
+       const struct of_device_id *of_id = of_match_device(weim_id_table,
+                                                          &pdev->dev);
+       const struct imx_weim_devtype *devtype = of_id->data;
        struct device_node *child;
        int ret;
 
@@ -65,7 +96,7 @@ static int weim_parse_dt(struct platform_device *pdev)
                if (!child->name)
                        continue;
 
-               ret = weim_timing_setup(pdev, child);
+               ret = weim_timing_setup(child, base, devtype);
                if (ret) {
                        dev_err(&pdev->dev, "%s set timing failed.\n",
                                child->full_name);
@@ -80,59 +111,47 @@ static int weim_parse_dt(struct platform_device *pdev)
        return ret;
 }
 
-static int weim_probe(struct platform_device *pdev)
+static int __init weim_probe(struct platform_device *pdev)
 {
-       struct imx_weim *weim;
        struct resource *res;
-       int ret = -EINVAL;
-
-       weim = devm_kzalloc(&pdev->dev, sizeof(*weim), GFP_KERNEL);
-       if (!weim) {
-               ret = -ENOMEM;
-               goto weim_err;
-       }
-       platform_set_drvdata(pdev, weim);
+       struct clk *clk;
+       void __iomem *base;
+       int ret;
 
        /* get the resource */
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       weim->base = devm_ioremap_resource(&pdev->dev, res);
-       if (IS_ERR(weim->base)) {
-               ret = PTR_ERR(weim->base);
-               goto weim_err;
-       }
+       base = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(base))
+               return PTR_ERR(base);
 
        /* get the clock */
-       weim->clk = devm_clk_get(&pdev->dev, NULL);
-       if (IS_ERR(weim->clk))
-               goto weim_err;
+       clk = devm_clk_get(&pdev->dev, NULL);
+       if (IS_ERR(clk))
+               return PTR_ERR(clk);
 
-       ret = clk_prepare_enable(weim->clk);
+       ret = clk_prepare_enable(clk);
        if (ret)
-               goto weim_err;
+               return ret;
 
        /* parse the device node */
-       ret = weim_parse_dt(pdev);
-       if (ret) {
-               clk_disable_unprepare(weim->clk);
-               goto weim_err;
-       }
-
-       dev_info(&pdev->dev, "WEIM driver registered.\n");
-       return 0;
+       ret = weim_parse_dt(pdev, base);
+       if (ret)
+               clk_disable_unprepare(clk);
+       else
+               dev_info(&pdev->dev, "Driver registered.\n");
 
-weim_err:
        return ret;
 }
 
 static struct platform_driver weim_driver = {
        .driver = {
-               .name = "imx-weim",
-               .of_match_table = weim_id_table,
+               .name           = "imx-weim",
+               .owner          = THIS_MODULE,
+               .of_match_table = weim_id_table,
        },
-       .probe   = weim_probe,
 };
+module_platform_driver_probe(weim_driver, weim_probe);
 
-module_platform_driver(weim_driver);
 MODULE_AUTHOR("Freescale Semiconductor Inc.");
 MODULE_DESCRIPTION("i.MX EIM Controller Driver");
 MODULE_LICENSE("GPL");