diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-01-23 18:56:08 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-01-23 18:56:08 -0800 |
commit | 7e21774db5cc9cf8fe93a64a2f0c6cf47db8ab24 (patch) | |
tree | 460812792bc3b23789a83968b7bad840cc3eb047 /drivers/clk/clk-max77686.c | |
parent | 0ba3307a8ec35252f7b1e222e32889a6f3d9ceb3 (diff) | |
parent | 2e84d75116c17c2034e917b411250d2d11755435 (diff) | |
download | linux-7e21774db5cc9cf8fe93a64a2f0c6cf47db8ab24.tar.gz linux-7e21774db5cc9cf8fe93a64a2f0c6cf47db8ab24.tar.bz2 linux-7e21774db5cc9cf8fe93a64a2f0c6cf47db8ab24.zip |
Merge tag 'clk-for-linus-3.14-part1' of git://git.linaro.org/people/mike.turquette/linux
Pull clk framework changes from Mike Turquette:
"The first half of the clk framework pull request is made up almost
entirely of new platform/driver support. There are some conversions
of existing drivers to the common-clock Device Tree binding, and a few
non-critical fixes to the framework.
Due to an entirely unnecessary cyclical dependency with the arm-soc
tree this pull request is broken into two pieces. The second piece
will be sent out after arm-soc sends you the pull request that merged
in core support for the HiSilicon 3620 platform. That same pull
request from arm-soc depends on this pull request to merge in those
HiSilicon bits without causing build failures"
[ Just did the ARM SoC merges, so getting ready for the second clk tree
pull request - Linus ]
* tag 'clk-for-linus-3.14-part1' of git://git.linaro.org/people/mike.turquette/linux: (97 commits)
devicetree: bindings: Document qcom,mmcc
devicetree: bindings: Document qcom,gcc
clk: qcom: Add support for MSM8660's global clock controller (GCC)
clk: qcom: Add support for MSM8974's multimedia clock controller (MMCC)
clk: qcom: Add support for MSM8974's global clock controller (GCC)
clk: qcom: Add support for MSM8960's multimedia clock controller (MMCC)
clk: qcom: Add support for MSM8960's global clock controller (GCC)
clk: qcom: Add reset controller support
clk: qcom: Add support for branches/gate clocks
clk: qcom: Add support for root clock generators (RCGs)
clk: qcom: Add support for phase locked loops (PLLs)
clk: qcom: Add a regmap type clock struct
clk: Add set_rate_and_parent() op
reset: Silence warning in reset-controller.h
clk: sirf: re-arch to make the codes support both prima2 and atlas6
clk: composite: pass mux_hw into determine_rate
clk: shmobile: Fix MSTP clock array initialization
clk: shmobile: Fix MSTP clock index
ARM: dts: Add clock provider specific properties to max77686 node
clk: max77686: Register OF clock provider
...
Diffstat (limited to 'drivers/clk/clk-max77686.c')
-rw-r--r-- | drivers/clk/clk-max77686.c | 97 |
1 files changed, 60 insertions, 37 deletions
diff --git a/drivers/clk/clk-max77686.c b/drivers/clk/clk-max77686.c index 9f57bc37cd60..3d7e8dd8fd58 100644 --- a/drivers/clk/clk-max77686.c +++ b/drivers/clk/clk-max77686.c @@ -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,47 +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; - break; - case MAX77686_CLK_CP: - dev_err(&pdev->dev, "Fail to register CLK_CP\n"); - goto err_clk_cp; - break; - 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; } |