diff options
author | Michal Simek <michal.simek@xilinx.com> | 2014-02-12 08:41:19 -0500 |
---|---|---|
committer | Wim Van Sebroeck <wim@iguana.be> | 2014-03-31 07:29:11 -0400 |
commit | 9066317178ca87b9d958f801c8fcf784ec31c6c3 (patch) | |
tree | 47f8b9b0b2cf86c0c8ac8e9742ad4143c51e9cd0 /drivers/watchdog | |
parent | ffb8eee4f140bbfc333381168d6fe1a7e7dc7af7 (diff) |
watchdog: xilinx: Allocate private structure per device
Only one watchdog could be used by this driver.
Create driver private data structure and move there
all variables for one instance.
Signed-off-by: Michal Simek <michal.simek@xilinx.com>
Reviewed-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
Diffstat (limited to 'drivers/watchdog')
-rw-r--r-- | drivers/watchdog/of_xilinx_wdt.c | 97 |
1 files changed, 55 insertions, 42 deletions
diff --git a/drivers/watchdog/of_xilinx_wdt.c b/drivers/watchdog/of_xilinx_wdt.c index 3bc648f40e1f..ac3f6ebd0c23 100644 --- a/drivers/watchdog/of_xilinx_wdt.c +++ b/drivers/watchdog/of_xilinx_wdt.c | |||
@@ -46,30 +46,27 @@ | |||
46 | struct xwdt_device { | 46 | struct xwdt_device { |
47 | void __iomem *base; | 47 | void __iomem *base; |
48 | u32 wdt_interval; | 48 | u32 wdt_interval; |
49 | spinlock_t spinlock; | ||
50 | struct watchdog_device xilinx_wdt_wdd; | ||
49 | }; | 51 | }; |
50 | 52 | ||
51 | static struct xwdt_device xdev; | ||
52 | |||
53 | static u32 timeout; | ||
54 | |||
55 | static DEFINE_SPINLOCK(spinlock); | ||
56 | |||
57 | static int xilinx_wdt_start(struct watchdog_device *wdd) | 53 | static int xilinx_wdt_start(struct watchdog_device *wdd) |
58 | { | 54 | { |
59 | u32 control_status_reg; | 55 | u32 control_status_reg; |
56 | struct xwdt_device *xdev = watchdog_get_drvdata(wdd); | ||
60 | 57 | ||
61 | spin_lock(&spinlock); | 58 | spin_lock(&xdev->spinlock); |
62 | 59 | ||
63 | /* Clean previous status and enable the watchdog timer */ | 60 | /* Clean previous status and enable the watchdog timer */ |
64 | control_status_reg = ioread32(xdev.base + XWT_TWCSR0_OFFSET); | 61 | control_status_reg = ioread32(xdev->base + XWT_TWCSR0_OFFSET); |
65 | control_status_reg |= (XWT_CSR0_WRS_MASK | XWT_CSR0_WDS_MASK); | 62 | control_status_reg |= (XWT_CSR0_WRS_MASK | XWT_CSR0_WDS_MASK); |
66 | 63 | ||
67 | iowrite32((control_status_reg | XWT_CSR0_EWDT1_MASK), | 64 | iowrite32((control_status_reg | XWT_CSR0_EWDT1_MASK), |
68 | xdev.base + XWT_TWCSR0_OFFSET); | 65 | xdev->base + XWT_TWCSR0_OFFSET); |
69 | 66 | ||
70 | iowrite32(XWT_CSRX_EWDT2_MASK, xdev.base + XWT_TWCSR1_OFFSET); | 67 | iowrite32(XWT_CSRX_EWDT2_MASK, xdev->base + XWT_TWCSR1_OFFSET); |
71 | 68 | ||
72 | spin_unlock(&spinlock); | 69 | spin_unlock(&xdev->spinlock); |
73 | 70 | ||
74 | return 0; | 71 | return 0; |
75 | } | 72 | } |
@@ -77,17 +74,18 @@ static int xilinx_wdt_start(struct watchdog_device *wdd) | |||
77 | static int xilinx_wdt_stop(struct watchdog_device *wdd) | 74 | static int xilinx_wdt_stop(struct watchdog_device *wdd) |
78 | { | 75 | { |
79 | u32 control_status_reg; | 76 | u32 control_status_reg; |
77 | struct xwdt_device *xdev = watchdog_get_drvdata(wdd); | ||
80 | 78 | ||
81 | spin_lock(&spinlock); | 79 | spin_lock(&xdev->spinlock); |
82 | 80 | ||
83 | control_status_reg = ioread32(xdev.base + XWT_TWCSR0_OFFSET); | 81 | control_status_reg = ioread32(xdev->base + XWT_TWCSR0_OFFSET); |
84 | 82 | ||
85 | iowrite32((control_status_reg & ~XWT_CSR0_EWDT1_MASK), | 83 | iowrite32((control_status_reg & ~XWT_CSR0_EWDT1_MASK), |
86 | xdev.base + XWT_TWCSR0_OFFSET); | 84 | xdev->base + XWT_TWCSR0_OFFSET); |
87 | 85 | ||
88 | iowrite32(0, xdev.base + XWT_TWCSR1_OFFSET); | 86 | iowrite32(0, xdev->base + XWT_TWCSR1_OFFSET); |
89 | 87 | ||
90 | spin_unlock(&spinlock); | 88 | spin_unlock(&xdev->spinlock); |
91 | pr_info("Stopped!\n"); | 89 | pr_info("Stopped!\n"); |
92 | 90 | ||
93 | return 0; | 91 | return 0; |
@@ -96,14 +94,15 @@ static int xilinx_wdt_stop(struct watchdog_device *wdd) | |||
96 | static int xilinx_wdt_keepalive(struct watchdog_device *wdd) | 94 | static int xilinx_wdt_keepalive(struct watchdog_device *wdd) |
97 | { | 95 | { |
98 | u32 control_status_reg; | 96 | u32 control_status_reg; |
97 | struct xwdt_device *xdev = watchdog_get_drvdata(wdd); | ||
99 | 98 | ||
100 | spin_lock(&spinlock); | 99 | spin_lock(&xdev->spinlock); |
101 | 100 | ||
102 | control_status_reg = ioread32(xdev.base + XWT_TWCSR0_OFFSET); | 101 | control_status_reg = ioread32(xdev->base + XWT_TWCSR0_OFFSET); |
103 | control_status_reg |= (XWT_CSR0_WRS_MASK | XWT_CSR0_WDS_MASK); | 102 | control_status_reg |= (XWT_CSR0_WRS_MASK | XWT_CSR0_WDS_MASK); |
104 | iowrite32(control_status_reg, xdev.base + XWT_TWCSR0_OFFSET); | 103 | iowrite32(control_status_reg, xdev->base + XWT_TWCSR0_OFFSET); |
105 | 104 | ||
106 | spin_unlock(&spinlock); | 105 | spin_unlock(&xdev->spinlock); |
107 | 106 | ||
108 | return 0; | 107 | return 0; |
109 | } | 108 | } |
@@ -122,29 +121,24 @@ static const struct watchdog_ops xilinx_wdt_ops = { | |||
122 | .ping = xilinx_wdt_keepalive, | 121 | .ping = xilinx_wdt_keepalive, |
123 | }; | 122 | }; |
124 | 123 | ||
125 | static struct watchdog_device xilinx_wdt_wdd = { | 124 | static u32 xwdt_selftest(struct xwdt_device *xdev) |
126 | .info = &xilinx_wdt_ident, | ||
127 | .ops = &xilinx_wdt_ops, | ||
128 | }; | ||
129 | |||
130 | static u32 xwdt_selftest(void) | ||
131 | { | 125 | { |
132 | int i; | 126 | int i; |
133 | u32 timer_value1; | 127 | u32 timer_value1; |
134 | u32 timer_value2; | 128 | u32 timer_value2; |
135 | 129 | ||
136 | spin_lock(&spinlock); | 130 | spin_lock(&xdev->spinlock); |
137 | 131 | ||
138 | timer_value1 = ioread32(xdev.base + XWT_TBR_OFFSET); | 132 | timer_value1 = ioread32(xdev->base + XWT_TBR_OFFSET); |
139 | timer_value2 = ioread32(xdev.base + XWT_TBR_OFFSET); | 133 | timer_value2 = ioread32(xdev->base + XWT_TBR_OFFSET); |
140 | 134 | ||
141 | for (i = 0; | 135 | for (i = 0; |
142 | ((i <= XWT_MAX_SELFTEST_LOOP_COUNT) && | 136 | ((i <= XWT_MAX_SELFTEST_LOOP_COUNT) && |
143 | (timer_value2 == timer_value1)); i++) { | 137 | (timer_value2 == timer_value1)); i++) { |
144 | timer_value2 = ioread32(xdev.base + XWT_TBR_OFFSET); | 138 | timer_value2 = ioread32(xdev->base + XWT_TBR_OFFSET); |
145 | } | 139 | } |
146 | 140 | ||
147 | spin_unlock(&spinlock); | 141 | spin_unlock(&xdev->spinlock); |
148 | 142 | ||
149 | if (timer_value2 != timer_value1) | 143 | if (timer_value2 != timer_value1) |
150 | return ~XWT_TIMER_FAILED; | 144 | return ~XWT_TIMER_FAILED; |
@@ -158,12 +152,23 @@ static int xwdt_probe(struct platform_device *pdev) | |||
158 | u32 *tmptr; | 152 | u32 *tmptr; |
159 | u32 *pfreq; | 153 | u32 *pfreq; |
160 | struct resource *res; | 154 | struct resource *res; |
155 | struct xwdt_device *xdev; | ||
161 | bool no_timeout = false; | 156 | bool no_timeout = false; |
157 | struct watchdog_device *xilinx_wdt_wdd; | ||
158 | |||
159 | xdev = devm_kzalloc(&pdev->dev, sizeof(*xdev), GFP_KERNEL); | ||
160 | if (!xdev) | ||
161 | return -ENOMEM; | ||
162 | |||
163 | xilinx_wdt_wdd = &xdev->xilinx_wdt_wdd; | ||
164 | xilinx_wdt_wdd->info = &xilinx_wdt_ident; | ||
165 | xilinx_wdt_wdd->ops = &xilinx_wdt_ops; | ||
166 | xilinx_wdt_wdd->parent = &pdev->dev; | ||
162 | 167 | ||
163 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 168 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
164 | xdev.base = devm_ioremap_resource(&pdev->dev, res); | 169 | xdev->base = devm_ioremap_resource(&pdev->dev, res); |
165 | if (IS_ERR(xdev.base)) | 170 | if (IS_ERR(xdev->base)) |
166 | return PTR_ERR(xdev.base); | 171 | return PTR_ERR(xdev->base); |
167 | 172 | ||
168 | pfreq = (u32 *)of_get_property(pdev->dev.of_node, | 173 | pfreq = (u32 *)of_get_property(pdev->dev.of_node, |
169 | "clock-frequency", NULL); | 174 | "clock-frequency", NULL); |
@@ -179,14 +184,14 @@ static int xwdt_probe(struct platform_device *pdev) | |||
179 | pr_warn("Parameter \"xlnx,wdt-interval\" not found in device tree!\n"); | 184 | pr_warn("Parameter \"xlnx,wdt-interval\" not found in device tree!\n"); |
180 | no_timeout = true; | 185 | no_timeout = true; |
181 | } else { | 186 | } else { |
182 | xdev.wdt_interval = *tmptr; | 187 | xdev->wdt_interval = *tmptr; |
183 | } | 188 | } |
184 | 189 | ||
185 | tmptr = (u32 *)of_get_property(pdev->dev.of_node, | 190 | tmptr = (u32 *)of_get_property(pdev->dev.of_node, |
186 | "xlnx,wdt-enable-once", NULL); | 191 | "xlnx,wdt-enable-once", NULL); |
187 | if (tmptr == NULL) { | 192 | if (tmptr == NULL) { |
188 | pr_warn("Parameter \"xlnx,wdt-enable-once\" not found in device tree!\n"); | 193 | pr_warn("Parameter \"xlnx,wdt-enable-once\" not found in device tree!\n"); |
189 | watchdog_set_nowayout(&xilinx_wdt_wdd, true); | 194 | watchdog_set_nowayout(xilinx_wdt_wdd, true); |
190 | } | 195 | } |
191 | 196 | ||
192 | /* | 197 | /* |
@@ -194,29 +199,37 @@ static int xwdt_probe(struct platform_device *pdev) | |||
194 | * ignored (interrupt), reset is only generated at second wdt overflow | 199 | * ignored (interrupt), reset is only generated at second wdt overflow |
195 | */ | 200 | */ |
196 | if (!no_timeout) | 201 | if (!no_timeout) |
197 | timeout = 2 * ((1<<xdev.wdt_interval) / *pfreq); | 202 | xilinx_wdt_wdd->timeout = 2 * ((1 << xdev->wdt_interval) / |
203 | *pfreq); | ||
204 | |||
205 | spin_lock_init(&xdev->spinlock); | ||
206 | watchdog_set_drvdata(xilinx_wdt_wdd, xdev); | ||
198 | 207 | ||
199 | rc = xwdt_selftest(); | 208 | rc = xwdt_selftest(xdev); |
200 | if (rc == XWT_TIMER_FAILED) { | 209 | if (rc == XWT_TIMER_FAILED) { |
201 | pr_err("SelfTest routine error!\n"); | 210 | pr_err("SelfTest routine error!\n"); |
202 | return rc; | 211 | return rc; |
203 | } | 212 | } |
204 | 213 | ||
205 | rc = watchdog_register_device(&xilinx_wdt_wdd); | 214 | rc = watchdog_register_device(xilinx_wdt_wdd); |
206 | if (rc) { | 215 | if (rc) { |
207 | pr_err("cannot register watchdog (err=%d)\n", rc); | 216 | pr_err("cannot register watchdog (err=%d)\n", rc); |
208 | return rc; | 217 | return rc; |
209 | } | 218 | } |
210 | 219 | ||
211 | dev_info(&pdev->dev, "Xilinx Watchdog Timer at %p with timeout %ds\n", | 220 | dev_info(&pdev->dev, "Xilinx Watchdog Timer at %p with timeout %ds\n", |
212 | xdev.base, timeout); | 221 | xdev->base, xilinx_wdt_wdd->timeout); |
222 | |||
223 | platform_set_drvdata(pdev, xdev); | ||
213 | 224 | ||
214 | return 0; | 225 | return 0; |
215 | } | 226 | } |
216 | 227 | ||
217 | static int xwdt_remove(struct platform_device *dev) | 228 | static int xwdt_remove(struct platform_device *pdev) |
218 | { | 229 | { |
219 | watchdog_unregister_device(&xilinx_wdt_wdd); | 230 | struct xwdt_device *xdev = platform_get_drvdata(pdev); |
231 | |||
232 | watchdog_unregister_device(&xdev->xilinx_wdt_wdd); | ||
220 | 233 | ||
221 | return 0; | 234 | return 0; |
222 | } | 235 | } |