Merge branch 'misc.namei' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
[linux-2.6-microblaze.git] / drivers / remoteproc / qcom_wcnss_iris.c
index 169acd3..09720dd 100644 (file)
@@ -17,7 +17,7 @@
 #include "qcom_wcnss.h"
 
 struct qcom_iris {
-       struct device *dev;
+       struct device dev;
 
        struct clk *xo_clk;
 
@@ -75,7 +75,7 @@ int qcom_iris_enable(struct qcom_iris *iris)
 
        ret = clk_prepare_enable(iris->xo_clk);
        if (ret) {
-               dev_err(iris->dev, "failed to enable xo clk\n");
+               dev_err(&iris->dev, "failed to enable xo clk\n");
                goto disable_regulators;
        }
 
@@ -93,43 +93,90 @@ void qcom_iris_disable(struct qcom_iris *iris)
        regulator_bulk_disable(iris->num_vregs, iris->vregs);
 }
 
-static int qcom_iris_probe(struct platform_device *pdev)
+static const struct of_device_id iris_of_match[] = {
+       { .compatible = "qcom,wcn3620", .data = &wcn3620_data },
+       { .compatible = "qcom,wcn3660", .data = &wcn3660_data },
+       { .compatible = "qcom,wcn3660b", .data = &wcn3680_data },
+       { .compatible = "qcom,wcn3680", .data = &wcn3680_data },
+       {}
+};
+
+static void qcom_iris_release(struct device *dev)
+{
+       struct qcom_iris *iris = container_of(dev, struct qcom_iris, dev);
+
+       of_node_put(iris->dev.of_node);
+       kfree(iris);
+}
+
+struct qcom_iris *qcom_iris_probe(struct device *parent, bool *use_48mhz_xo)
 {
+       const struct of_device_id *match;
        const struct iris_data *data;
-       struct qcom_wcnss *wcnss;
+       struct device_node *of_node;
        struct qcom_iris *iris;
        int ret;
        int i;
 
-       iris = devm_kzalloc(&pdev->dev, sizeof(struct qcom_iris), GFP_KERNEL);
-       if (!iris)
-               return -ENOMEM;
+       of_node = of_get_child_by_name(parent->of_node, "iris");
+       if (!of_node) {
+               dev_err(parent, "No child node \"iris\" found\n");
+               return ERR_PTR(-EINVAL);
+       }
+
+       iris = kzalloc(sizeof(*iris), GFP_KERNEL);
+       if (!iris) {
+               of_node_put(of_node);
+               return ERR_PTR(-ENOMEM);
+       }
+
+       device_initialize(&iris->dev);
+       iris->dev.parent = parent;
+       iris->dev.release = qcom_iris_release;
+       iris->dev.of_node = of_node;
+
+       dev_set_name(&iris->dev, "%s.iris", dev_name(parent));
+
+       ret = device_add(&iris->dev);
+       if (ret) {
+               put_device(&iris->dev);
+               return ERR_PTR(ret);
+       }
+
+       match = of_match_device(iris_of_match, &iris->dev);
+       if (!match) {
+               dev_err(&iris->dev, "no matching compatible for iris\n");
+               ret = -EINVAL;
+               goto err_device_del;
+       }
 
-       data = of_device_get_match_data(&pdev->dev);
-       wcnss = dev_get_drvdata(pdev->dev.parent);
+       data = match->data;
 
-       iris->xo_clk = devm_clk_get(&pdev->dev, "xo");
+       iris->xo_clk = devm_clk_get(&iris->dev, "xo");
        if (IS_ERR(iris->xo_clk)) {
-               if (PTR_ERR(iris->xo_clk) != -EPROBE_DEFER)
-                       dev_err(&pdev->dev, "failed to acquire xo clk\n");
-               return PTR_ERR(iris->xo_clk);
+               ret = PTR_ERR(iris->xo_clk);
+               if (ret != -EPROBE_DEFER)
+                       dev_err(&iris->dev, "failed to acquire xo clk\n");
+               goto err_device_del;
        }
 
        iris->num_vregs = data->num_vregs;
-       iris->vregs = devm_kcalloc(&pdev->dev,
+       iris->vregs = devm_kcalloc(&iris->dev,
                                   iris->num_vregs,
                                   sizeof(struct regulator_bulk_data),
                                   GFP_KERNEL);
-       if (!iris->vregs)
-               return -ENOMEM;
+       if (!iris->vregs) {
+               ret = -ENOMEM;
+               goto err_device_del;
+       }
 
        for (i = 0; i < iris->num_vregs; i++)
                iris->vregs[i].supply = data->vregs[i].name;
 
-       ret = devm_regulator_bulk_get(&pdev->dev, iris->num_vregs, iris->vregs);
+       ret = devm_regulator_bulk_get(&iris->dev, iris->num_vregs, iris->vregs);
        if (ret) {
-               dev_err(&pdev->dev, "failed to get regulators\n");
-               return ret;
+               dev_err(&iris->dev, "failed to get regulators\n");
+               goto err_device_del;
        }
 
        for (i = 0; i < iris->num_vregs; i++) {
@@ -143,34 +190,17 @@ static int qcom_iris_probe(struct platform_device *pdev)
                                           data->vregs[i].load_uA);
        }
 
-       qcom_wcnss_assign_iris(wcnss, iris, data->use_48mhz_xo);
-
-       return 0;
-}
+       *use_48mhz_xo = data->use_48mhz_xo;
 
-static int qcom_iris_remove(struct platform_device *pdev)
-{
-       struct qcom_wcnss *wcnss = dev_get_drvdata(pdev->dev.parent);
+       return iris;
 
-       qcom_wcnss_assign_iris(wcnss, NULL, false);
+err_device_del:
+       device_del(&iris->dev);
 
-       return 0;
+       return ERR_PTR(ret);
 }
 
-static const struct of_device_id iris_of_match[] = {
-       { .compatible = "qcom,wcn3620", .data = &wcn3620_data },
-       { .compatible = "qcom,wcn3660", .data = &wcn3660_data },
-       { .compatible = "qcom,wcn3660b", .data = &wcn3680_data },
-       { .compatible = "qcom,wcn3680", .data = &wcn3680_data },
-       {}
-};
-MODULE_DEVICE_TABLE(of, iris_of_match);
-
-struct platform_driver qcom_iris_driver = {
-       .probe = qcom_iris_probe,
-       .remove = qcom_iris_remove,
-       .driver = {
-               .name = "qcom-iris",
-               .of_match_table = iris_of_match,
-       },
-};
+void qcom_iris_remove(struct qcom_iris *iris)
+{
+       device_del(&iris->dev);
+}