Merge branch 'linus' into core/locking
[cascardo/linux.git] / drivers / clk / clk-max77686.c
index b4a1a97..3d7e8dd 100644 (file)
@@ -66,7 +66,7 @@ static void max77686_clk_unprepare(struct clk_hw *hw)
                MAX77686_REG_32KHZ, max77686->mask, ~max77686->mask);
 }
 
-static int max77686_clk_is_enabled(struct clk_hw *hw)
+static int max77686_clk_is_prepared(struct clk_hw *hw)
 {
        struct max77686_clk *max77686 = to_max77686_clk(hw);
        int ret;
@@ -81,10 +81,17 @@ static int max77686_clk_is_enabled(struct clk_hw *hw)
        return val & max77686->mask;
 }
 
+static unsigned long max77686_recalc_rate(struct clk_hw *hw,
+                                         unsigned long parent_rate)
+{
+       return 32768;
+}
+
 static struct clk_ops max77686_clk_ops = {
        .prepare        = max77686_clk_prepare,
        .unprepare      = max77686_clk_unprepare,
-       .is_enabled     = max77686_clk_is_enabled,
+       .is_prepared    = max77686_clk_is_prepared,
+       .recalc_rate    = max77686_recalc_rate,
 };
 
 static struct clk_init_data max77686_clks_init[MAX77686_CLKS_NUM] = {
@@ -105,38 +112,38 @@ static struct clk_init_data max77686_clks_init[MAX77686_CLKS_NUM] = {
        },
 };
 
-static int max77686_clk_register(struct device *dev,
+static struct clk *max77686_clk_register(struct device *dev,
                                struct max77686_clk *max77686)
 {
        struct clk *clk;
        struct clk_hw *hw = &max77686->hw;
 
        clk = clk_register(dev, hw);
-
        if (IS_ERR(clk))
-               return -ENOMEM;
+               return clk;
 
        max77686->lookup = kzalloc(sizeof(struct clk_lookup), GFP_KERNEL);
        if (!max77686->lookup)
-               return -ENOMEM;
+               return ERR_PTR(-ENOMEM);
 
        max77686->lookup->con_id = hw->init->name;
        max77686->lookup->clk = clk;
 
        clkdev_add(max77686->lookup);
 
-       return 0;
+       return clk;
 }
 
 static int max77686_clk_probe(struct platform_device *pdev)
 {
        struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent);
-       struct max77686_clk **max77686_clks;
+       struct max77686_clk *max77686_clks[MAX77686_CLKS_NUM];
+       struct clk **clocks;
        int i, ret;
 
-       max77686_clks = devm_kzalloc(&pdev->dev, sizeof(struct max77686_clk *)
+       clocks = devm_kzalloc(&pdev->dev, sizeof(struct clk *)
                                        * MAX77686_CLKS_NUM, GFP_KERNEL);
-       if (!max77686_clks)
+       if (!clocks)
                return -ENOMEM;
 
        for (i = 0; i < MAX77686_CLKS_NUM; i++) {
@@ -151,45 +158,63 @@ static int max77686_clk_probe(struct platform_device *pdev)
                max77686_clks[i]->mask = 1 << i;
                max77686_clks[i]->hw.init = &max77686_clks_init[i];
 
-               ret = max77686_clk_register(&pdev->dev, max77686_clks[i]);
+               clocks[i] = max77686_clk_register(&pdev->dev, max77686_clks[i]);
+               if (IS_ERR(clocks[i])) {
+                       ret = PTR_ERR(clocks[i]);
+                       dev_err(&pdev->dev, "failed to register %s\n",
+                               max77686_clks[i]->hw.init->name);
+                       goto err_clocks;
+               }
+       }
+
+       platform_set_drvdata(pdev, clocks);
+
+       if (iodev->dev->of_node) {
+               struct clk_onecell_data *of_data;
+
+               of_data = devm_kzalloc(&pdev->dev,
+                                       sizeof(*of_data), GFP_KERNEL);
+               if (!of_data) {
+                       ret = -ENOMEM;
+                       goto err_clocks;
+               }
+
+               of_data->clks = clocks;
+               of_data->clk_num = MAX77686_CLKS_NUM;
+               ret = of_clk_add_provider(iodev->dev->of_node,
+                                       of_clk_src_onecell_get, of_data);
                if (ret) {
-                       switch (i) {
-                       case MAX77686_CLK_AP:
-                               dev_err(&pdev->dev, "Fail to register CLK_AP\n");
-                               goto err_clk_ap;
-                       case MAX77686_CLK_CP:
-                               dev_err(&pdev->dev, "Fail to register CLK_CP\n");
-                               goto err_clk_cp;
-                       case MAX77686_CLK_PMIC:
-                               dev_err(&pdev->dev, "Fail to register CLK_PMIC\n");
-                               goto err_clk_pmic;
-                       }
+                       dev_err(&pdev->dev, "failed to register OF clock provider\n");
+                       goto err_clocks;
                }
        }
 
-       platform_set_drvdata(pdev, max77686_clks);
+       return 0;
 
-       goto out;
+err_clocks:
+       for (--i; i >= 0; --i) {
+               clkdev_drop(max77686_clks[i]->lookup);
+               clk_unregister(max77686_clks[i]->hw.clk);
+       }
 
-err_clk_pmic:
-       clkdev_drop(max77686_clks[MAX77686_CLK_CP]->lookup);
-       kfree(max77686_clks[MAX77686_CLK_CP]->hw.clk);
-err_clk_cp:
-       clkdev_drop(max77686_clks[MAX77686_CLK_AP]->lookup);
-       kfree(max77686_clks[MAX77686_CLK_AP]->hw.clk);
-err_clk_ap:
-out:
        return ret;
 }
 
 static int max77686_clk_remove(struct platform_device *pdev)
 {
-       struct max77686_clk **max77686_clks = platform_get_drvdata(pdev);
+       struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent);
+       struct clk **clocks = platform_get_drvdata(pdev);
        int i;
 
+       if (iodev->dev->of_node)
+               of_clk_del_provider(iodev->dev->of_node);
+
        for (i = 0; i < MAX77686_CLKS_NUM; i++) {
-               clkdev_drop(max77686_clks[i]->lookup);
-               kfree(max77686_clks[i]->hw.clk);
+               struct clk_hw *hw = __clk_get_hw(clocks[i]);
+               struct max77686_clk *max77686 = to_max77686_clk(hw);
+
+               clkdev_drop(max77686->lookup);
+               clk_unregister(clocks[i]);
        }
        return 0;
 }