^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * PIC32 watchdog driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Joshua Henderson <joshua.henderson@microchip.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (c) 2016, Microchip Technology Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/of_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/pm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/watchdog.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <asm/mach-pic32/pic32.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) /* Watchdog Timer Registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define WDTCON_REG 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) /* Watchdog Timer Control Register fields */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define WDTCON_WIN_EN BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define WDTCON_RMCS_MASK 0x0003
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define WDTCON_RMCS_SHIFT 0x0006
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define WDTCON_RMPS_MASK 0x001F
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define WDTCON_RMPS_SHIFT 0x0008
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define WDTCON_ON BIT(15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define WDTCON_CLR_KEY 0x5743
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) /* Reset Control Register fields for watchdog */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define RESETCON_TIMEOUT_IDLE BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define RESETCON_TIMEOUT_SLEEP BIT(3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define RESETCON_WDT_TIMEOUT BIT(4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) struct pic32_wdt {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) void __iomem *regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) void __iomem *rst_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) struct clk *clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) static inline bool pic32_wdt_is_win_enabled(struct pic32_wdt *wdt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) return !!(readl(wdt->regs + WDTCON_REG) & WDTCON_WIN_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) static inline u32 pic32_wdt_get_post_scaler(struct pic32_wdt *wdt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) u32 v = readl(wdt->regs + WDTCON_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) return (v >> WDTCON_RMPS_SHIFT) & WDTCON_RMPS_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) static inline u32 pic32_wdt_get_clk_id(struct pic32_wdt *wdt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) u32 v = readl(wdt->regs + WDTCON_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) return (v >> WDTCON_RMCS_SHIFT) & WDTCON_RMCS_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) static int pic32_wdt_bootstatus(struct pic32_wdt *wdt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) u32 v = readl(wdt->rst_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) writel(RESETCON_WDT_TIMEOUT, PIC32_CLR(wdt->rst_base));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) return v & RESETCON_WDT_TIMEOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) static u32 pic32_wdt_get_timeout_secs(struct pic32_wdt *wdt, struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) unsigned long rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) u32 period, ps, terminal;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) rate = clk_get_rate(wdt->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) dev_dbg(dev, "wdt: clk_id %d, clk_rate %lu (prescale)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) pic32_wdt_get_clk_id(wdt), rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) /* default, prescaler of 32 (i.e. div-by-32) is implicit. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) rate >>= 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) if (!rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) /* calculate terminal count from postscaler. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) ps = pic32_wdt_get_post_scaler(wdt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) terminal = BIT(ps);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) /* find time taken (in secs) to reach terminal count */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) period = terminal / rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) dev_dbg(dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) "wdt: clk_rate %lu (postscale) / terminal %d, timeout %dsec\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) rate, terminal, period);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) return period;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) static void pic32_wdt_keepalive(struct pic32_wdt *wdt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) /* write key through single half-word */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) writew(WDTCON_CLR_KEY, wdt->regs + WDTCON_REG + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) static int pic32_wdt_start(struct watchdog_device *wdd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) struct pic32_wdt *wdt = watchdog_get_drvdata(wdd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) writel(WDTCON_ON, PIC32_SET(wdt->regs + WDTCON_REG));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) pic32_wdt_keepalive(wdt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) static int pic32_wdt_stop(struct watchdog_device *wdd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) struct pic32_wdt *wdt = watchdog_get_drvdata(wdd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) writel(WDTCON_ON, PIC32_CLR(wdt->regs + WDTCON_REG));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) * Cannot touch registers in the CPU cycle following clearing the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) * ON bit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) nop();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) static int pic32_wdt_ping(struct watchdog_device *wdd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) struct pic32_wdt *wdt = watchdog_get_drvdata(wdd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) pic32_wdt_keepalive(wdt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) static const struct watchdog_ops pic32_wdt_fops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) .start = pic32_wdt_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) .stop = pic32_wdt_stop,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) .ping = pic32_wdt_ping,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) static const struct watchdog_info pic32_wdt_ident = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) .options = WDIOF_KEEPALIVEPING |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) WDIOF_MAGICCLOSE | WDIOF_CARDRESET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) .identity = "PIC32 Watchdog",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) static struct watchdog_device pic32_wdd = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) .info = &pic32_wdt_ident,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) .ops = &pic32_wdt_fops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) static const struct of_device_id pic32_wdt_dt_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) { .compatible = "microchip,pic32mzda-wdt", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) { /* sentinel */ }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) MODULE_DEVICE_TABLE(of, pic32_wdt_dt_ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) static void pic32_clk_disable_unprepare(void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) clk_disable_unprepare(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) static int pic32_wdt_drv_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) struct device *dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) struct watchdog_device *wdd = &pic32_wdd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) struct pic32_wdt *wdt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) wdt = devm_kzalloc(dev, sizeof(*wdt), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) if (!wdt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) wdt->regs = devm_platform_ioremap_resource(pdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) if (IS_ERR(wdt->regs))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) return PTR_ERR(wdt->regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) wdt->rst_base = devm_ioremap(dev, PIC32_BASE_RESET, 0x10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) if (!wdt->rst_base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) wdt->clk = devm_clk_get(dev, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) if (IS_ERR(wdt->clk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) dev_err(dev, "clk not found\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) return PTR_ERR(wdt->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) ret = clk_prepare_enable(wdt->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) dev_err(dev, "clk enable failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) ret = devm_add_action_or_reset(dev, pic32_clk_disable_unprepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) wdt->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) if (pic32_wdt_is_win_enabled(wdt)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) dev_err(dev, "windowed-clear mode is not supported.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) wdd->timeout = pic32_wdt_get_timeout_secs(wdt, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) if (!wdd->timeout) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) dev_err(dev, "failed to read watchdog register timeout\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) dev_info(dev, "timeout %d\n", wdd->timeout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) wdd->bootstatus = pic32_wdt_bootstatus(wdt) ? WDIOF_CARDRESET : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) watchdog_set_nowayout(wdd, WATCHDOG_NOWAYOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) watchdog_set_drvdata(wdd, wdt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) ret = devm_watchdog_register_device(dev, wdd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) platform_set_drvdata(pdev, wdd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) static struct platform_driver pic32_wdt_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) .probe = pic32_wdt_drv_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) .name = "pic32-wdt",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) .of_match_table = of_match_ptr(pic32_wdt_dt_ids),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) module_platform_driver(pic32_wdt_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) MODULE_AUTHOR("Joshua Henderson <joshua.henderson@microchip.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) MODULE_DESCRIPTION("Microchip PIC32 Watchdog Timer");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) MODULE_LICENSE("GPL");