diff options
author | Andre Przywara <andre.przywara@arm.com> | 2016-02-16 05:46:07 -0500 |
---|---|---|
committer | Maxime Ripard <maxime.ripard@free-electrons.com> | 2016-02-21 22:44:38 -0500 |
commit | b26803ebfba8d81e2e8fb392c1248df2ebd1ba83 (patch) | |
tree | 426d3015823bb16f790aa6e94fc08a0914480de2 /drivers/clk/sunxi | |
parent | 72360b91164aa35753942e5310ae1e1d16e28611 (diff) |
clk: sunxi: improve divider_clk error handling and reporting
We now report a failing ioremap, failing output names parsing,
failures in table registration and in the final step.
Also there was a bug where clk_register_divider_table() would return
an ERR_PTR value instead of NULL, which we were checking for.
We now implement proper rollback in case of an error.
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Diffstat (limited to 'drivers/clk/sunxi')
-rw-r--r-- | drivers/clk/sunxi/clk-sunxi.c | 36 |
1 files changed, 33 insertions, 3 deletions
diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c index 775e13776f84..4bd09179a401 100644 --- a/drivers/clk/sunxi/clk-sunxi.c +++ b/drivers/clk/sunxi/clk-sunxi.c | |||
@@ -805,17 +805,47 @@ static void __init sunxi_divider_clk_setup(struct device_node *node, | |||
805 | void __iomem *reg; | 805 | void __iomem *reg; |
806 | 806 | ||
807 | reg = of_iomap(node, 0); | 807 | reg = of_iomap(node, 0); |
808 | if (!reg) { | ||
809 | pr_err("Could not map registers for mux-clk: %s\n", | ||
810 | of_node_full_name(node)); | ||
811 | return; | ||
812 | } | ||
808 | 813 | ||
809 | clk_parent = of_clk_get_parent_name(node, 0); | 814 | clk_parent = of_clk_get_parent_name(node, 0); |
810 | 815 | ||
811 | of_property_read_string(node, "clock-output-names", &clk_name); | 816 | if (of_property_read_string(node, "clock-output-names", &clk_name)) { |
817 | pr_err("%s: could not read clock-output-names from \"%s\"\n", | ||
818 | __func__, of_node_full_name(node)); | ||
819 | goto out_unmap; | ||
820 | } | ||
812 | 821 | ||
813 | clk = clk_register_divider_table(NULL, clk_name, clk_parent, 0, | 822 | clk = clk_register_divider_table(NULL, clk_name, clk_parent, 0, |
814 | reg, data->shift, data->width, | 823 | reg, data->shift, data->width, |
815 | data->pow ? CLK_DIVIDER_POWER_OF_TWO : 0, | 824 | data->pow ? CLK_DIVIDER_POWER_OF_TWO : 0, |
816 | data->table, &clk_lock); | 825 | data->table, &clk_lock); |
817 | if (clk) | 826 | if (IS_ERR(clk)) { |
818 | of_clk_add_provider(node, of_clk_src_simple_get, clk); | 827 | pr_err("%s: failed to register divider clock %s: %ld\n", |
828 | __func__, clk_name, PTR_ERR(clk)); | ||
829 | goto out_unmap; | ||
830 | } | ||
831 | |||
832 | if (of_clk_add_provider(node, of_clk_src_simple_get, clk)) { | ||
833 | pr_err("%s: failed to add clock provider for %s\n", | ||
834 | __func__, clk_name); | ||
835 | goto out_unregister; | ||
836 | } | ||
837 | |||
838 | if (clk_register_clkdev(clk, clk_name, NULL)) { | ||
839 | of_clk_del_provider(node); | ||
840 | goto out_unregister; | ||
841 | } | ||
842 | |||
843 | return; | ||
844 | out_unregister: | ||
845 | clk_unregister_divider(clk); | ||
846 | |||
847 | out_unmap: | ||
848 | iounmap(reg); | ||
819 | } | 849 | } |
820 | 850 | ||
821 | static void __init sun4i_ahb_clk_setup(struct device_node *node) | 851 | static void __init sun4i_ahb_clk_setup(struct device_node *node) |