diff options
author | Jiancheng Xue <xuejiancheng@hisilicon.com> | 2016-06-15 02:26:38 -0400 |
---|---|---|
committer | Stephen Boyd <sboyd@codeaurora.org> | 2016-06-30 15:35:20 -0400 |
commit | 224b3b262c52ef3b13ec62cd879b48d2611c2c10 (patch) | |
tree | 08ed88e6c84465ae452bb42370410ade5a92c095 | |
parent | fbf0410ed5f96ae63fcb221ab785e746871a4e62 (diff) |
clk: hisilicon: hi3519: add driver remove path and fix some issues
1. Add driver remove path.
2. Fix some issues.
-Fix the ordering issue about clock provider being published.
-Add error checking upon registering clocks.
Signed-off-by: Jiancheng Xue <xuejiancheng@hisilicon.com>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
-rw-r--r-- | drivers/clk/hisilicon/clk-hi3519.c | 116 |
1 files changed, 100 insertions, 16 deletions
diff --git a/drivers/clk/hisilicon/clk-hi3519.c b/drivers/clk/hisilicon/clk-hi3519.c index 8d12700d0cff..51b173ef1dda 100644 --- a/drivers/clk/hisilicon/clk-hi3519.c +++ b/drivers/clk/hisilicon/clk-hi3519.c | |||
@@ -38,6 +38,11 @@ | |||
38 | 38 | ||
39 | #define HI3519_NR_CLKS 128 | 39 | #define HI3519_NR_CLKS 128 |
40 | 40 | ||
41 | struct hi3519_crg_data { | ||
42 | struct hisi_clock_data *clk_data; | ||
43 | struct hisi_reset_controller *rstc; | ||
44 | }; | ||
45 | |||
41 | static const struct hisi_fixed_rate_clock hi3519_fixed_rate_clks[] = { | 46 | static const struct hisi_fixed_rate_clock hi3519_fixed_rate_clks[] = { |
42 | { HI3519_FIXED_24M, "24m", NULL, 0, 24000000, }, | 47 | { HI3519_FIXED_24M, "24m", NULL, 0, 24000000, }, |
43 | { HI3519_FIXED_50M, "50m", NULL, 0, 50000000, }, | 48 | { HI3519_FIXED_50M, "50m", NULL, 0, 50000000, }, |
@@ -80,33 +85,105 @@ static const struct hisi_gate_clock hi3519_gate_clks[] = { | |||
80 | CLK_SET_RATE_PARENT, 0xe4, 18, 0, }, | 85 | CLK_SET_RATE_PARENT, 0xe4, 18, 0, }, |
81 | }; | 86 | }; |
82 | 87 | ||
83 | static int hi3519_clk_probe(struct platform_device *pdev) | 88 | static struct hisi_clock_data *hi3519_clk_register(struct platform_device *pdev) |
84 | { | 89 | { |
85 | struct device_node *np = pdev->dev.of_node; | ||
86 | struct hisi_clock_data *clk_data; | 90 | struct hisi_clock_data *clk_data; |
87 | struct hisi_reset_controller *rstc; | 91 | int ret; |
88 | 92 | ||
89 | rstc = hisi_reset_init(pdev); | 93 | clk_data = hisi_clk_alloc(pdev, HI3519_NR_CLKS); |
90 | if (!rstc) | 94 | if (!clk_data) |
95 | return ERR_PTR(-ENOMEM); | ||
96 | |||
97 | ret = hisi_clk_register_fixed_rate(hi3519_fixed_rate_clks, | ||
98 | ARRAY_SIZE(hi3519_fixed_rate_clks), | ||
99 | clk_data); | ||
100 | if (ret) | ||
101 | return ERR_PTR(ret); | ||
102 | |||
103 | ret = hisi_clk_register_mux(hi3519_mux_clks, | ||
104 | ARRAY_SIZE(hi3519_mux_clks), | ||
105 | clk_data); | ||
106 | if (ret) | ||
107 | goto unregister_fixed_rate; | ||
108 | |||
109 | ret = hisi_clk_register_gate(hi3519_gate_clks, | ||
110 | ARRAY_SIZE(hi3519_gate_clks), | ||
111 | clk_data); | ||
112 | if (ret) | ||
113 | goto unregister_mux; | ||
114 | |||
115 | ret = of_clk_add_provider(pdev->dev.of_node, | ||
116 | of_clk_src_onecell_get, &clk_data->clk_data); | ||
117 | if (ret) | ||
118 | goto unregister_gate; | ||
119 | |||
120 | return clk_data; | ||
121 | |||
122 | unregister_fixed_rate: | ||
123 | hisi_clk_unregister_fixed_rate(hi3519_fixed_rate_clks, | ||
124 | ARRAY_SIZE(hi3519_fixed_rate_clks), | ||
125 | clk_data); | ||
126 | |||
127 | unregister_mux: | ||
128 | hisi_clk_unregister_mux(hi3519_mux_clks, | ||
129 | ARRAY_SIZE(hi3519_mux_clks), | ||
130 | clk_data); | ||
131 | unregister_gate: | ||
132 | hisi_clk_unregister_gate(hi3519_gate_clks, | ||
133 | ARRAY_SIZE(hi3519_gate_clks), | ||
134 | clk_data); | ||
135 | return ERR_PTR(ret); | ||
136 | } | ||
137 | |||
138 | static void hi3519_clk_unregister(struct platform_device *pdev) | ||
139 | { | ||
140 | struct hi3519_crg_data *crg = platform_get_drvdata(pdev); | ||
141 | |||
142 | of_clk_del_provider(pdev->dev.of_node); | ||
143 | |||
144 | hisi_clk_unregister_gate(hi3519_gate_clks, | ||
145 | ARRAY_SIZE(hi3519_mux_clks), | ||
146 | crg->clk_data); | ||
147 | hisi_clk_unregister_mux(hi3519_mux_clks, | ||
148 | ARRAY_SIZE(hi3519_mux_clks), | ||
149 | crg->clk_data); | ||
150 | hisi_clk_unregister_fixed_rate(hi3519_fixed_rate_clks, | ||
151 | ARRAY_SIZE(hi3519_fixed_rate_clks), | ||
152 | crg->clk_data); | ||
153 | } | ||
154 | |||
155 | static int hi3519_clk_probe(struct platform_device *pdev) | ||
156 | { | ||
157 | struct hi3519_crg_data *crg; | ||
158 | |||
159 | crg = devm_kmalloc(&pdev->dev, sizeof(*crg), GFP_KERNEL); | ||
160 | if (!crg) | ||
161 | return -ENOMEM; | ||
162 | |||
163 | crg->rstc = hisi_reset_init(pdev); | ||
164 | if (!crg->rstc) | ||
91 | return -ENOMEM; | 165 | return -ENOMEM; |
92 | 166 | ||
93 | clk_data = hisi_clk_init(np, HI3519_NR_CLKS); | 167 | crg->clk_data = hi3519_clk_register(pdev); |
94 | if (!clk_data) { | 168 | if (IS_ERR(crg->clk_data)) { |
95 | hisi_reset_exit(rstc); | 169 | hisi_reset_exit(crg->rstc); |
96 | return -ENODEV; | 170 | return PTR_ERR(crg->clk_data); |
97 | } | 171 | } |
98 | 172 | ||
99 | hisi_clk_register_fixed_rate(hi3519_fixed_rate_clks, | 173 | platform_set_drvdata(pdev, crg); |
100 | ARRAY_SIZE(hi3519_fixed_rate_clks), | 174 | return 0; |
101 | clk_data); | 175 | } |
102 | hisi_clk_register_mux(hi3519_mux_clks, ARRAY_SIZE(hi3519_mux_clks), | 176 | |
103 | clk_data); | 177 | static int hi3519_clk_remove(struct platform_device *pdev) |
104 | hisi_clk_register_gate(hi3519_gate_clks, | 178 | { |
105 | ARRAY_SIZE(hi3519_gate_clks), clk_data); | 179 | struct hi3519_crg_data *crg = platform_get_drvdata(pdev); |
106 | 180 | ||
181 | hisi_reset_exit(crg->rstc); | ||
182 | hi3519_clk_unregister(pdev); | ||
107 | return 0; | 183 | return 0; |
108 | } | 184 | } |
109 | 185 | ||
186 | |||
110 | static const struct of_device_id hi3519_clk_match_table[] = { | 187 | static const struct of_device_id hi3519_clk_match_table[] = { |
111 | { .compatible = "hisilicon,hi3519-crg" }, | 188 | { .compatible = "hisilicon,hi3519-crg" }, |
112 | { } | 189 | { } |
@@ -115,6 +192,7 @@ MODULE_DEVICE_TABLE(of, hi3519_clk_match_table); | |||
115 | 192 | ||
116 | static struct platform_driver hi3519_clk_driver = { | 193 | static struct platform_driver hi3519_clk_driver = { |
117 | .probe = hi3519_clk_probe, | 194 | .probe = hi3519_clk_probe, |
195 | .remove = hi3519_clk_remove, | ||
118 | .driver = { | 196 | .driver = { |
119 | .name = "hi3519-clk", | 197 | .name = "hi3519-clk", |
120 | .of_match_table = hi3519_clk_match_table, | 198 | .of_match_table = hi3519_clk_match_table, |
@@ -127,5 +205,11 @@ static int __init hi3519_clk_init(void) | |||
127 | } | 205 | } |
128 | core_initcall(hi3519_clk_init); | 206 | core_initcall(hi3519_clk_init); |
129 | 207 | ||
208 | static void __exit hi3519_clk_exit(void) | ||
209 | { | ||
210 | platform_driver_unregister(&hi3519_clk_driver); | ||
211 | } | ||
212 | module_exit(hi3519_clk_exit); | ||
213 | |||
130 | MODULE_LICENSE("GPL v2"); | 214 | MODULE_LICENSE("GPL v2"); |
131 | MODULE_DESCRIPTION("HiSilicon Hi3519 Clock Driver"); | 215 | MODULE_DESCRIPTION("HiSilicon Hi3519 Clock Driver"); |