Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

watchdog: max63xx: dynamically allocate device

This patch removes the static watchdog device for a new max63xx_wdt data
structure, and constifies the max63xx_timeout data.

The new structure contains pointers to pin access routines, which
abstracts mmap-specific code. This will ease future accesses like GPIO.

Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
Reviewed-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Wim Van Sebroeck <wim@iguana.be>

authored by

Vivien Didelot and committed by
Wim Van Sebroeck
b9be9660 db11cba2

+107 -69
+107 -69
drivers/watchdog/max63xx_wdt.c
··· 39 39 #define MAX6369_WDSET (7 << 0) 40 40 #define MAX6369_WDI (1 << 3) 41 41 42 - static DEFINE_SPINLOCK(io_lock); 42 + #define MAX6369_WDSET_DISABLED 3 43 43 44 44 static int nodelay; 45 - static void __iomem *wdt_base; 45 + 46 + struct max63xx_wdt { 47 + struct watchdog_device wdd; 48 + const struct max63xx_timeout *timeout; 49 + 50 + /* memory mapping */ 51 + void __iomem *base; 52 + spinlock_t lock; 53 + 54 + /* WDI and WSET bits write access routines */ 55 + void (*ping)(struct max63xx_wdt *wdt); 56 + void (*set)(struct max63xx_wdt *wdt, u8 set); 57 + }; 46 58 47 59 /* 48 60 * The timeout values used are actually the absolute minimum the chip ··· 71 59 72 60 /* Timeouts in second */ 73 61 struct max63xx_timeout { 74 - u8 wdset; 75 - u8 tdelay; 76 - u8 twd; 62 + const u8 wdset; 63 + const u8 tdelay; 64 + const u8 twd; 77 65 }; 78 66 79 - static struct max63xx_timeout max6369_table[] = { 67 + static const struct max63xx_timeout max6369_table[] = { 80 68 { 5, 1, 1 }, 81 69 { 6, 10, 10 }, 82 70 { 7, 60, 60 }, 83 71 { }, 84 72 }; 85 73 86 - static struct max63xx_timeout max6371_table[] = { 74 + static const struct max63xx_timeout max6371_table[] = { 87 75 { 6, 60, 3 }, 88 76 { 7, 60, 60 }, 89 77 { }, 90 78 }; 91 79 92 - static struct max63xx_timeout max6373_table[] = { 80 + static const struct max63xx_timeout max6373_table[] = { 93 81 { 2, 60, 1 }, 94 82 { 5, 0, 1 }, 95 83 { 1, 3, 3 }, ··· 97 85 { 6, 0, 10 }, 98 86 { }, 99 87 }; 100 - 101 - static struct max63xx_timeout *current_timeout; 102 88 103 89 static struct max63xx_timeout * 104 90 max63xx_select_timeout(struct max63xx_timeout *table, int value) ··· 118 108 119 109 static int max63xx_wdt_ping(struct watchdog_device *wdd) 120 110 { 121 - u8 val; 111 + struct max63xx_wdt *wdt = watchdog_get_drvdata(wdd); 122 112 123 - spin_lock(&io_lock); 124 - 125 - val = __raw_readb(wdt_base); 126 - 127 - __raw_writeb(val | MAX6369_WDI, wdt_base); 128 - __raw_writeb(val & ~MAX6369_WDI, wdt_base); 129 - 130 - spin_unlock(&io_lock); 113 + wdt->ping(wdt); 131 114 return 0; 132 115 } 133 116 134 117 static int max63xx_wdt_start(struct watchdog_device *wdd) 135 118 { 136 - struct max63xx_timeout *entry = watchdog_get_drvdata(wdd); 137 - u8 val; 119 + struct max63xx_wdt *wdt = watchdog_get_drvdata(wdd); 138 120 139 - spin_lock(&io_lock); 140 - 141 - val = __raw_readb(wdt_base); 142 - val &= ~MAX6369_WDSET; 143 - val |= entry->wdset; 144 - __raw_writeb(val, wdt_base); 145 - 146 - spin_unlock(&io_lock); 121 + wdt->set(wdt, wdt->timeout->wdset); 147 122 148 123 /* check for a edge triggered startup */ 149 - if (entry->tdelay == 0) 150 - max63xx_wdt_ping(wdd); 124 + if (wdt->timeout->tdelay == 0) 125 + wdt->ping(wdt); 151 126 return 0; 152 127 } 153 128 154 129 static int max63xx_wdt_stop(struct watchdog_device *wdd) 155 130 { 156 - u8 val; 131 + struct max63xx_wdt *wdt = watchdog_get_drvdata(wdd); 157 132 158 - spin_lock(&io_lock); 159 - 160 - val = __raw_readb(wdt_base); 161 - val &= ~MAX6369_WDSET; 162 - val |= 3; 163 - __raw_writeb(val, wdt_base); 164 - 165 - spin_unlock(&io_lock); 133 + wdt->set(wdt, MAX6369_WDSET_DISABLED); 166 134 return 0; 167 135 } 168 - 169 - static const struct watchdog_info max63xx_wdt_info = { 170 - .options = WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, 171 - .identity = "max63xx Watchdog", 172 - }; 173 136 174 137 static const struct watchdog_ops max63xx_wdt_ops = { 175 138 .owner = THIS_MODULE, ··· 151 168 .ping = max63xx_wdt_ping, 152 169 }; 153 170 154 - static struct watchdog_device max63xx_wdt_dev = { 155 - .info = &max63xx_wdt_info, 156 - .ops = &max63xx_wdt_ops, 171 + static const struct watchdog_info max63xx_wdt_info = { 172 + .options = WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, 173 + .identity = "max63xx Watchdog", 157 174 }; 175 + 176 + static void max63xx_mmap_ping(struct max63xx_wdt *wdt) 177 + { 178 + u8 val; 179 + 180 + spin_lock(&wdt->lock); 181 + 182 + val = __raw_readb(wdt->base); 183 + 184 + __raw_writeb(val | MAX6369_WDI, wdt->base); 185 + __raw_writeb(val & ~MAX6369_WDI, wdt->base); 186 + 187 + spin_unlock(&wdt->lock); 188 + } 189 + 190 + static void max63xx_mmap_set(struct max63xx_wdt *wdt, u8 set) 191 + { 192 + u8 val; 193 + 194 + spin_lock(&wdt->lock); 195 + 196 + val = __raw_readb(wdt->base); 197 + val &= ~MAX6369_WDSET; 198 + val |= set & MAX6369_WDSET; 199 + __raw_writeb(val, wdt->base); 200 + 201 + spin_unlock(&wdt->lock); 202 + } 203 + 204 + static int max63xx_mmap_init(struct platform_device *p, struct max63xx_wdt *wdt) 205 + { 206 + struct resource *mem = platform_get_resource(p, IORESOURCE_MEM, 0); 207 + 208 + wdt->base = devm_ioremap_resource(&p->dev, mem); 209 + if (IS_ERR(wdt->base)) 210 + return PTR_ERR(wdt->base); 211 + 212 + spin_lock_init(&wdt->lock); 213 + 214 + wdt->ping = max63xx_mmap_ping; 215 + wdt->set = max63xx_mmap_set; 216 + return 0; 217 + } 158 218 159 219 static int max63xx_wdt_probe(struct platform_device *pdev) 160 220 { 161 - struct resource *wdt_mem; 221 + struct max63xx_wdt *wdt; 162 222 struct max63xx_timeout *table; 223 + int err; 224 + 225 + wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL); 226 + if (!wdt) 227 + return -ENOMEM; 163 228 164 229 table = (struct max63xx_timeout *)pdev->id_entry->driver_data; 165 230 166 231 if (heartbeat < 1 || heartbeat > MAX_HEARTBEAT) 167 232 heartbeat = DEFAULT_HEARTBEAT; 168 233 169 - dev_info(&pdev->dev, "requesting %ds heartbeat\n", heartbeat); 170 - current_timeout = max63xx_select_timeout(table, heartbeat); 171 - 172 - if (!current_timeout) { 173 - dev_err(&pdev->dev, "unable to satisfy heartbeat request\n"); 234 + wdt->timeout = max63xx_select_timeout(table, heartbeat); 235 + if (!wdt->timeout) { 236 + dev_err(&pdev->dev, "unable to satisfy %ds heartbeat request\n", 237 + heartbeat); 174 238 return -EINVAL; 175 239 } 176 240 241 + err = max63xx_mmap_init(pdev, wdt); 242 + if (err) 243 + return err; 244 + 245 + platform_set_drvdata(pdev, &wdt->wdd); 246 + watchdog_set_drvdata(&wdt->wdd, wdt); 247 + 248 + wdt->wdd.parent = &pdev->dev; 249 + wdt->wdd.timeout = wdt->timeout->twd; 250 + wdt->wdd.info = &max63xx_wdt_info; 251 + wdt->wdd.ops = &max63xx_wdt_ops; 252 + 253 + watchdog_set_nowayout(&wdt->wdd, nowayout); 254 + 255 + err = watchdog_register_device(&wdt->wdd); 256 + if (err) 257 + return err; 258 + 177 259 dev_info(&pdev->dev, "using %ds heartbeat with %ds initial delay\n", 178 - current_timeout->twd, current_timeout->tdelay); 179 - 180 - heartbeat = current_timeout->twd; 181 - 182 - wdt_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 183 - wdt_base = devm_ioremap_resource(&pdev->dev, wdt_mem); 184 - if (IS_ERR(wdt_base)) 185 - return PTR_ERR(wdt_base); 186 - 187 - max63xx_wdt_dev.timeout = heartbeat; 188 - watchdog_set_nowayout(&max63xx_wdt_dev, nowayout); 189 - watchdog_set_drvdata(&max63xx_wdt_dev, current_timeout); 190 - 191 - return watchdog_register_device(&max63xx_wdt_dev); 260 + wdt->timeout->twd, wdt->timeout->tdelay); 261 + return 0; 192 262 } 193 263 194 264 static int max63xx_wdt_remove(struct platform_device *pdev) 195 265 { 196 - watchdog_unregister_device(&max63xx_wdt_dev); 266 + struct watchdog_device *wdd = platform_get_drvdata(pdev); 267 + 268 + watchdog_unregister_device(wdd); 197 269 return 0; 198 270 } 199 271