aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUwe Kleine-König <u.kleine-koenig@pengutronix.de>2015-08-12 04:15:56 -0400
committerWim Van Sebroeck <wim@iguana.be>2015-09-09 15:37:29 -0400
commit7997ebad4d747ff5561cb5ec0c7423e0d4e628d5 (patch)
tree49b3e2ed1ea5a058d7d454a59cfd611e9eb5ed59
parentde5f71222bd544558d81701454eb457b295de96e (diff)
watchdog: mpc8xxx: use dynamic memory for device specific data
Instead of relying on global static memory dynamically allocate the needed data. This has the benefit of some saved bytes if the driver is not in use and making it possible to bind more than one device (even though this has no known use case). Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> Reviewed-by: Guenter Roeck <linux@roeck-us.net> Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
-rw-r--r--drivers/watchdog/mpc8xxx_wdt.c88
1 files changed, 53 insertions, 35 deletions
diff --git a/drivers/watchdog/mpc8xxx_wdt.c b/drivers/watchdog/mpc8xxx_wdt.c
index a6790fcfa69b..0b69797d3417 100644
--- a/drivers/watchdog/mpc8xxx_wdt.c
+++ b/drivers/watchdog/mpc8xxx_wdt.c
@@ -50,7 +50,12 @@ struct mpc8xxx_wdt_type {
50 bool hw_enabled; 50 bool hw_enabled;
51}; 51};
52 52
53static struct mpc8xxx_wdt __iomem *wd_base; 53struct mpc8xxx_wdt_ddata {
54 struct mpc8xxx_wdt __iomem *base;
55 struct watchdog_device wdd;
56 struct timer_list timer;
57 spinlock_t lock;
58};
54 59
55static u16 timeout = 0xffff; 60static u16 timeout = 0xffff;
56module_param(timeout, ushort, 0); 61module_param(timeout, ushort, 0);
@@ -67,33 +72,29 @@ module_param(nowayout, bool, 0);
67MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started " 72MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started "
68 "(default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 73 "(default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
69 74
70static DEFINE_SPINLOCK(wdt_spinlock); 75static void mpc8xxx_wdt_keepalive(struct mpc8xxx_wdt_ddata *ddata)
71
72static void mpc8xxx_wdt_keepalive(void)
73{ 76{
74 /* Ping the WDT */ 77 /* Ping the WDT */
75 spin_lock(&wdt_spinlock); 78 spin_lock(&ddata->lock);
76 out_be16(&wd_base->swsrr, 0x556c); 79 out_be16(&ddata->base->swsrr, 0x556c);
77 out_be16(&wd_base->swsrr, 0xaa39); 80 out_be16(&ddata->base->swsrr, 0xaa39);
78 spin_unlock(&wdt_spinlock); 81 spin_unlock(&ddata->lock);
79} 82}
80 83
81static struct watchdog_device mpc8xxx_wdt_dev;
82static void mpc8xxx_wdt_timer_ping(unsigned long arg);
83static DEFINE_TIMER(wdt_timer, mpc8xxx_wdt_timer_ping, 0,
84 (unsigned long)&mpc8xxx_wdt_dev);
85
86static void mpc8xxx_wdt_timer_ping(unsigned long arg) 84static void mpc8xxx_wdt_timer_ping(unsigned long arg)
87{ 85{
88 struct watchdog_device *w = (struct watchdog_device *)arg; 86 struct mpc8xxx_wdt_ddata *ddata = (void *)arg;
89 87
90 mpc8xxx_wdt_keepalive(); 88 mpc8xxx_wdt_keepalive(ddata);
91 /* We're pinging it twice faster than needed, just to be sure. */ 89 /* We're pinging it twice faster than needed, just to be sure. */
92 mod_timer(&wdt_timer, jiffies + HZ * w->timeout / 2); 90 mod_timer(&ddata->timer, jiffies + HZ * ddata->wdd.timeout / 2);
93} 91}
94 92
95static int mpc8xxx_wdt_start(struct watchdog_device *w) 93static int mpc8xxx_wdt_start(struct watchdog_device *w)
96{ 94{
95 struct mpc8xxx_wdt_ddata *ddata =
96 container_of(w, struct mpc8xxx_wdt_ddata, wdd);
97
97 u32 tmp = SWCRR_SWEN | SWCRR_SWPR; 98 u32 tmp = SWCRR_SWEN | SWCRR_SWPR;
98 99
99 /* Good, fire up the show */ 100 /* Good, fire up the show */
@@ -102,22 +103,28 @@ static int mpc8xxx_wdt_start(struct watchdog_device *w)
102 103
103 tmp |= timeout << 16; 104 tmp |= timeout << 16;
104 105
105 out_be32(&wd_base->swcrr, tmp); 106 out_be32(&ddata->base->swcrr, tmp);
106 107
107 del_timer_sync(&wdt_timer); 108 del_timer_sync(&ddata->timer);
108 109
109 return 0; 110 return 0;
110} 111}
111 112
112static int mpc8xxx_wdt_ping(struct watchdog_device *w) 113static int mpc8xxx_wdt_ping(struct watchdog_device *w)
113{ 114{
114 mpc8xxx_wdt_keepalive(); 115 struct mpc8xxx_wdt_ddata *ddata =
116 container_of(w, struct mpc8xxx_wdt_ddata, wdd);
117
118 mpc8xxx_wdt_keepalive(ddata);
115 return 0; 119 return 0;
116} 120}
117 121
118static int mpc8xxx_wdt_stop(struct watchdog_device *w) 122static int mpc8xxx_wdt_stop(struct watchdog_device *w)
119{ 123{
120 mod_timer(&wdt_timer, jiffies); 124 struct mpc8xxx_wdt_ddata *ddata =
125 container_of(w, struct mpc8xxx_wdt_ddata, wdd);
126
127 mod_timer(&ddata->timer, jiffies);
121 return 0; 128 return 0;
122} 129}
123 130
@@ -134,16 +141,12 @@ static struct watchdog_ops mpc8xxx_wdt_ops = {
134 .stop = mpc8xxx_wdt_stop, 141 .stop = mpc8xxx_wdt_stop,
135}; 142};
136 143
137static struct watchdog_device mpc8xxx_wdt_dev = {
138 .info = &mpc8xxx_wdt_info,
139 .ops = &mpc8xxx_wdt_ops,
140};
141
142static int mpc8xxx_wdt_probe(struct platform_device *ofdev) 144static int mpc8xxx_wdt_probe(struct platform_device *ofdev)
143{ 145{
144 int ret; 146 int ret;
145 struct resource *res; 147 struct resource *res;
146 const struct mpc8xxx_wdt_type *wdt_type; 148 const struct mpc8xxx_wdt_type *wdt_type;
149 struct mpc8xxx_wdt_ddata *ddata;
147 u32 freq = fsl_get_sys_freq(); 150 u32 freq = fsl_get_sys_freq();
148 bool enabled; 151 bool enabled;
149 unsigned int timeout_sec; 152 unsigned int timeout_sec;
@@ -155,25 +158,36 @@ static int mpc8xxx_wdt_probe(struct platform_device *ofdev)
155 if (!freq || freq == -1) 158 if (!freq || freq == -1)
156 return -EINVAL; 159 return -EINVAL;
157 160
161 ddata = devm_kzalloc(&ofdev->dev, sizeof(*ddata), GFP_KERNEL);
162 if (!ddata)
163 return -ENOMEM;
164
158 res = platform_get_resource(ofdev, IORESOURCE_MEM, 0); 165 res = platform_get_resource(ofdev, IORESOURCE_MEM, 0);
159 wd_base = devm_ioremap_resource(&ofdev->dev, res); 166 ddata->base = devm_ioremap_resource(&ofdev->dev, res);
160 if (IS_ERR(wd_base)) 167 if (IS_ERR(ddata->base))
161 return PTR_ERR(wd_base); 168 return PTR_ERR(ddata->base);
162 169
163 enabled = in_be32(&wd_base->swcrr) & SWCRR_SWEN; 170 enabled = in_be32(&ddata->base->swcrr) & SWCRR_SWEN;
164 if (!enabled && wdt_type->hw_enabled) { 171 if (!enabled && wdt_type->hw_enabled) {
165 pr_info("could not be enabled in software\n"); 172 pr_info("could not be enabled in software\n");
166 return -ENOSYS; 173 return -ENOSYS;
167 } 174 }
168 175
176 spin_lock_init(&ddata->lock);
177 setup_timer(&ddata->timer, mpc8xxx_wdt_timer_ping,
178 (unsigned long)ddata);
179
180 ddata->wdd.info = &mpc8xxx_wdt_info,
181 ddata->wdd.ops = &mpc8xxx_wdt_ops,
182
169 /* Calculate the timeout in seconds */ 183 /* Calculate the timeout in seconds */
170 timeout_sec = (timeout * wdt_type->prescaler) / freq; 184 timeout_sec = (timeout * wdt_type->prescaler) / freq;
171 185
172 mpc8xxx_wdt_dev.timeout = timeout_sec; 186 ddata->wdd.timeout = timeout_sec;
173 187
174 watchdog_set_nowayout(&mpc8xxx_wdt_dev, nowayout); 188 watchdog_set_nowayout(&ddata->wdd, nowayout);
175 189
176 ret = watchdog_register_device(&mpc8xxx_wdt_dev); 190 ret = watchdog_register_device(&ddata->wdd);
177 if (ret) { 191 if (ret) {
178 pr_err("cannot register watchdog device (err=%d)\n", ret); 192 pr_err("cannot register watchdog device (err=%d)\n", ret);
179 return ret; 193 return ret;
@@ -188,16 +202,20 @@ static int mpc8xxx_wdt_probe(struct platform_device *ofdev)
188 * userspace handles it. 202 * userspace handles it.
189 */ 203 */
190 if (enabled) 204 if (enabled)
191 mod_timer(&wdt_timer, jiffies); 205 mod_timer(&ddata->timer, jiffies);
206
207 platform_set_drvdata(ofdev, ddata);
192 return 0; 208 return 0;
193} 209}
194 210
195static int mpc8xxx_wdt_remove(struct platform_device *ofdev) 211static int mpc8xxx_wdt_remove(struct platform_device *ofdev)
196{ 212{
213 struct mpc8xxx_wdt_ddata *ddata = platform_get_drvdata(ofdev);
214
197 pr_crit("Watchdog removed, expect the %s soon!\n", 215 pr_crit("Watchdog removed, expect the %s soon!\n",
198 reset ? "reset" : "machine check exception"); 216 reset ? "reset" : "machine check exception");
199 del_timer_sync(&wdt_timer); 217 del_timer_sync(&ddata->timer);
200 watchdog_unregister_device(&mpc8xxx_wdt_dev); 218 watchdog_unregister_device(&ddata->wdd);
201 219
202 return 0; 220 return 0;
203} 221}