aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/watchdog
diff options
context:
space:
mode:
authorMichal Simek <michal.simek@xilinx.com>2014-02-12 08:41:19 -0500
committerWim Van Sebroeck <wim@iguana.be>2014-03-31 07:29:11 -0400
commit9066317178ca87b9d958f801c8fcf784ec31c6c3 (patch)
tree47f8b9b0b2cf86c0c8ac8e9742ad4143c51e9cd0 /drivers/watchdog
parentffb8eee4f140bbfc333381168d6fe1a7e7dc7af7 (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.c97
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 @@
46struct xwdt_device { 46struct 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
51static struct xwdt_device xdev;
52
53static u32 timeout;
54
55static DEFINE_SPINLOCK(spinlock);
56
57static int xilinx_wdt_start(struct watchdog_device *wdd) 53static 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)
77static int xilinx_wdt_stop(struct watchdog_device *wdd) 74static 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)
96static int xilinx_wdt_keepalive(struct watchdog_device *wdd) 94static 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
125static struct watchdog_device xilinx_wdt_wdd = { 124static u32 xwdt_selftest(struct xwdt_device *xdev)
126 .info = &xilinx_wdt_ident,
127 .ops = &xilinx_wdt_ops,
128};
129
130static 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
217static int xwdt_remove(struct platform_device *dev) 228static 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}