diff options
author | Ezequiel Garcia <ezequiel.garcia@free-electrons.com> | 2014-02-10 18:00:29 -0500 |
---|---|---|
committer | Jason Cooper <jason@lakedaemon.net> | 2014-02-21 22:44:02 -0500 |
commit | 1924227bcda1d1844b8cc54b557b85a1d9b323f0 (patch) | |
tree | 119f574cd4b68cc2303273e21a5b1500c2f51a4e | |
parent | fc723856a42196779bc9a09f1fef997395f8a7d8 (diff) |
watchdog: orion: Add per-compatible clock initialization
Following the introduction of the compatible-data field,
it's now possible to further abstract the clock initialization.
This will allow to support SoC with a different clock setup.
Reviewed-by: Guenter Roeck <linux@roeck-us.net>
Tested-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
Tested-by: Willy Tarreau <w@1wt.eu>
Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
Acked-by: Wim Van Sebroeck <wim@iguana.be>
Tested-By: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
Signed-off-by: Jason Cooper <jason@lakedaemon.net>
-rw-r--r-- | drivers/watchdog/orion_wdt.c | 53 |
1 files changed, 32 insertions, 21 deletions
diff --git a/drivers/watchdog/orion_wdt.c b/drivers/watchdog/orion_wdt.c index b220e34285d1..b48fd0871f17 100644 --- a/drivers/watchdog/orion_wdt.c +++ b/drivers/watchdog/orion_wdt.c | |||
@@ -42,10 +42,14 @@ | |||
42 | static bool nowayout = WATCHDOG_NOWAYOUT; | 42 | static bool nowayout = WATCHDOG_NOWAYOUT; |
43 | static int heartbeat = -1; /* module parameter (seconds) */ | 43 | static int heartbeat = -1; /* module parameter (seconds) */ |
44 | 44 | ||
45 | struct orion_watchdog; | ||
46 | |||
45 | struct orion_watchdog_data { | 47 | struct orion_watchdog_data { |
46 | int wdt_counter_offset; | 48 | int wdt_counter_offset; |
47 | int wdt_enable_bit; | 49 | int wdt_enable_bit; |
48 | int rstout_enable_bit; | 50 | int rstout_enable_bit; |
51 | int (*clock_init)(struct platform_device *, | ||
52 | struct orion_watchdog *); | ||
49 | }; | 53 | }; |
50 | 54 | ||
51 | struct orion_watchdog { | 55 | struct orion_watchdog { |
@@ -57,6 +61,22 @@ struct orion_watchdog { | |||
57 | const struct orion_watchdog_data *data; | 61 | const struct orion_watchdog_data *data; |
58 | }; | 62 | }; |
59 | 63 | ||
64 | static int orion_wdt_clock_init(struct platform_device *pdev, | ||
65 | struct orion_watchdog *dev) | ||
66 | { | ||
67 | int ret; | ||
68 | |||
69 | dev->clk = devm_clk_get(&pdev->dev, NULL); | ||
70 | if (IS_ERR(dev->clk)) | ||
71 | return PTR_ERR(dev->clk); | ||
72 | ret = clk_prepare_enable(dev->clk); | ||
73 | if (ret) | ||
74 | return ret; | ||
75 | |||
76 | dev->clk_rate = clk_get_rate(dev->clk); | ||
77 | return 0; | ||
78 | } | ||
79 | |||
60 | static int orion_wdt_ping(struct watchdog_device *wdt_dev) | 80 | static int orion_wdt_ping(struct watchdog_device *wdt_dev) |
61 | { | 81 | { |
62 | struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev); | 82 | struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev); |
@@ -172,6 +192,7 @@ static const struct orion_watchdog_data orion_data = { | |||
172 | .rstout_enable_bit = BIT(1), | 192 | .rstout_enable_bit = BIT(1), |
173 | .wdt_enable_bit = BIT(4), | 193 | .wdt_enable_bit = BIT(4), |
174 | .wdt_counter_offset = 0x24, | 194 | .wdt_counter_offset = 0x24, |
195 | .clock_init = orion_wdt_clock_init, | ||
175 | }; | 196 | }; |
176 | 197 | ||
177 | static const struct of_device_id orion_wdt_of_match_table[] = { | 198 | static const struct of_device_id orion_wdt_of_match_table[] = { |
@@ -206,34 +227,24 @@ static int orion_wdt_probe(struct platform_device *pdev) | |||
206 | dev->wdt.min_timeout = 1; | 227 | dev->wdt.min_timeout = 1; |
207 | dev->data = match->data; | 228 | dev->data = match->data; |
208 | 229 | ||
209 | dev->clk = devm_clk_get(&pdev->dev, NULL); | ||
210 | if (IS_ERR(dev->clk)) { | ||
211 | dev_err(&pdev->dev, "Orion Watchdog missing clock\n"); | ||
212 | return PTR_ERR(dev->clk); | ||
213 | } | ||
214 | ret = clk_prepare_enable(dev->clk); | ||
215 | if (ret) | ||
216 | return ret; | ||
217 | dev->clk_rate = clk_get_rate(dev->clk); | ||
218 | |||
219 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 230 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
220 | if (!res) { | 231 | if (!res) |
221 | ret = -ENODEV; | 232 | return -ENODEV; |
222 | goto disable_clk; | ||
223 | } | ||
224 | 233 | ||
225 | dev->reg = devm_ioremap(&pdev->dev, res->start, | 234 | dev->reg = devm_ioremap(&pdev->dev, res->start, |
226 | resource_size(res)); | 235 | resource_size(res)); |
227 | if (!dev->reg) { | 236 | if (!dev->reg) |
228 | ret = -ENOMEM; | 237 | return -ENOMEM; |
229 | goto disable_clk; | ||
230 | } | ||
231 | 238 | ||
232 | dev->rstout = orion_wdt_ioremap_rstout(pdev, res->start & | 239 | dev->rstout = orion_wdt_ioremap_rstout(pdev, res->start & |
233 | INTERNAL_REGS_MASK); | 240 | INTERNAL_REGS_MASK); |
234 | if (!dev->rstout) { | 241 | if (!dev->rstout) |
235 | ret = -ENODEV; | 242 | return -ENODEV; |
236 | goto disable_clk; | 243 | |
244 | ret = dev->data->clock_init(pdev, dev); | ||
245 | if (ret) { | ||
246 | dev_err(&pdev->dev, "cannot initialize clock\n"); | ||
247 | return ret; | ||
237 | } | 248 | } |
238 | 249 | ||
239 | wdt_max_duration = WDT_MAX_CYCLE_COUNT / dev->clk_rate; | 250 | wdt_max_duration = WDT_MAX_CYCLE_COUNT / dev->clk_rate; |