0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043 #include <linux/io.h>
0044 #include <linux/io-64-nonatomic-lo-hi.h>
0045 #include <linux/interrupt.h>
0046 #include <linux/module.h>
0047 #include <linux/moduleparam.h>
0048 #include <linux/of.h>
0049 #include <linux/of_device.h>
0050 #include <linux/platform_device.h>
0051 #include <linux/uaccess.h>
0052 #include <linux/watchdog.h>
0053 #include <asm/arch_timer.h>
0054
0055 #define DRV_NAME "sbsa-gwdt"
0056 #define WATCHDOG_NAME "SBSA Generic Watchdog"
0057
0058
0059
0060 #define SBSA_GWDT_WRR 0x000
0061
0062
0063 #define SBSA_GWDT_WCS 0x000
0064 #define SBSA_GWDT_WOR 0x008
0065 #define SBSA_GWDT_WCV 0x010
0066
0067
0068 #define SBSA_GWDT_W_IIDR 0xfcc
0069 #define SBSA_GWDT_IDR 0xfd0
0070
0071
0072 #define SBSA_GWDT_WCS_EN BIT(0)
0073 #define SBSA_GWDT_WCS_WS0 BIT(1)
0074 #define SBSA_GWDT_WCS_WS1 BIT(2)
0075
0076 #define SBSA_GWDT_VERSION_MASK 0xF
0077 #define SBSA_GWDT_VERSION_SHIFT 16
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087 struct sbsa_gwdt {
0088 struct watchdog_device wdd;
0089 u32 clk;
0090 int version;
0091 void __iomem *refresh_base;
0092 void __iomem *control_base;
0093 };
0094
0095 #define DEFAULT_TIMEOUT 10
0096
0097 static unsigned int timeout;
0098 module_param(timeout, uint, 0);
0099 MODULE_PARM_DESC(timeout,
0100 "Watchdog timeout in seconds. (>=0, default="
0101 __MODULE_STRING(DEFAULT_TIMEOUT) ")");
0102
0103
0104
0105
0106
0107
0108
0109 static int action;
0110 module_param(action, int, 0);
0111 MODULE_PARM_DESC(action, "after watchdog gets WS0 interrupt, do: "
0112 "0 = skip(*) 1 = panic");
0113
0114 static bool nowayout = WATCHDOG_NOWAYOUT;
0115 module_param(nowayout, bool, S_IRUGO);
0116 MODULE_PARM_DESC(nowayout,
0117 "Watchdog cannot be stopped once started (default="
0118 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128 static u64 sbsa_gwdt_reg_read(struct sbsa_gwdt *gwdt)
0129 {
0130 if (gwdt->version == 0)
0131 return readl(gwdt->control_base + SBSA_GWDT_WOR);
0132 else
0133 return lo_hi_readq(gwdt->control_base + SBSA_GWDT_WOR);
0134 }
0135
0136 static void sbsa_gwdt_reg_write(u64 val, struct sbsa_gwdt *gwdt)
0137 {
0138 if (gwdt->version == 0)
0139 writel((u32)val, gwdt->control_base + SBSA_GWDT_WOR);
0140 else
0141 lo_hi_writeq(val, gwdt->control_base + SBSA_GWDT_WOR);
0142 }
0143
0144
0145
0146
0147 static int sbsa_gwdt_set_timeout(struct watchdog_device *wdd,
0148 unsigned int timeout)
0149 {
0150 struct sbsa_gwdt *gwdt = watchdog_get_drvdata(wdd);
0151
0152 wdd->timeout = timeout;
0153
0154 if (action)
0155 sbsa_gwdt_reg_write(gwdt->clk * timeout, gwdt);
0156 else
0157
0158
0159
0160
0161
0162 sbsa_gwdt_reg_write(gwdt->clk / 2 * timeout, gwdt);
0163
0164 return 0;
0165 }
0166
0167 static unsigned int sbsa_gwdt_get_timeleft(struct watchdog_device *wdd)
0168 {
0169 struct sbsa_gwdt *gwdt = watchdog_get_drvdata(wdd);
0170 u64 timeleft = 0;
0171
0172
0173
0174
0175
0176
0177 if (!action &&
0178 !(readl(gwdt->control_base + SBSA_GWDT_WCS) & SBSA_GWDT_WCS_WS0))
0179 timeleft += sbsa_gwdt_reg_read(gwdt);
0180
0181 timeleft += lo_hi_readq(gwdt->control_base + SBSA_GWDT_WCV) -
0182 arch_timer_read_counter();
0183
0184 do_div(timeleft, gwdt->clk);
0185
0186 return timeleft;
0187 }
0188
0189 static int sbsa_gwdt_keepalive(struct watchdog_device *wdd)
0190 {
0191 struct sbsa_gwdt *gwdt = watchdog_get_drvdata(wdd);
0192
0193
0194
0195
0196
0197 writel(0, gwdt->refresh_base + SBSA_GWDT_WRR);
0198
0199 return 0;
0200 }
0201
0202 static void sbsa_gwdt_get_version(struct watchdog_device *wdd)
0203 {
0204 struct sbsa_gwdt *gwdt = watchdog_get_drvdata(wdd);
0205 int ver;
0206
0207 ver = readl(gwdt->control_base + SBSA_GWDT_W_IIDR);
0208 ver = (ver >> SBSA_GWDT_VERSION_SHIFT) & SBSA_GWDT_VERSION_MASK;
0209
0210 gwdt->version = ver;
0211 }
0212
0213 static int sbsa_gwdt_start(struct watchdog_device *wdd)
0214 {
0215 struct sbsa_gwdt *gwdt = watchdog_get_drvdata(wdd);
0216
0217
0218 writel(SBSA_GWDT_WCS_EN, gwdt->control_base + SBSA_GWDT_WCS);
0219
0220 return 0;
0221 }
0222
0223 static int sbsa_gwdt_stop(struct watchdog_device *wdd)
0224 {
0225 struct sbsa_gwdt *gwdt = watchdog_get_drvdata(wdd);
0226
0227
0228 writel(0, gwdt->control_base + SBSA_GWDT_WCS);
0229
0230 return 0;
0231 }
0232
0233 static irqreturn_t sbsa_gwdt_interrupt(int irq, void *dev_id)
0234 {
0235 panic(WATCHDOG_NAME " timeout");
0236
0237 return IRQ_HANDLED;
0238 }
0239
0240 static const struct watchdog_info sbsa_gwdt_info = {
0241 .identity = WATCHDOG_NAME,
0242 .options = WDIOF_SETTIMEOUT |
0243 WDIOF_KEEPALIVEPING |
0244 WDIOF_MAGICCLOSE |
0245 WDIOF_CARDRESET,
0246 };
0247
0248 static const struct watchdog_ops sbsa_gwdt_ops = {
0249 .owner = THIS_MODULE,
0250 .start = sbsa_gwdt_start,
0251 .stop = sbsa_gwdt_stop,
0252 .ping = sbsa_gwdt_keepalive,
0253 .set_timeout = sbsa_gwdt_set_timeout,
0254 .get_timeleft = sbsa_gwdt_get_timeleft,
0255 };
0256
0257 static int sbsa_gwdt_probe(struct platform_device *pdev)
0258 {
0259 void __iomem *rf_base, *cf_base;
0260 struct device *dev = &pdev->dev;
0261 struct watchdog_device *wdd;
0262 struct sbsa_gwdt *gwdt;
0263 int ret, irq;
0264 u32 status;
0265
0266 gwdt = devm_kzalloc(dev, sizeof(*gwdt), GFP_KERNEL);
0267 if (!gwdt)
0268 return -ENOMEM;
0269 platform_set_drvdata(pdev, gwdt);
0270
0271 cf_base = devm_platform_ioremap_resource(pdev, 0);
0272 if (IS_ERR(cf_base))
0273 return PTR_ERR(cf_base);
0274
0275 rf_base = devm_platform_ioremap_resource(pdev, 1);
0276 if (IS_ERR(rf_base))
0277 return PTR_ERR(rf_base);
0278
0279
0280
0281
0282
0283
0284 gwdt->clk = arch_timer_get_cntfrq();
0285 gwdt->refresh_base = rf_base;
0286 gwdt->control_base = cf_base;
0287
0288 wdd = &gwdt->wdd;
0289 wdd->parent = dev;
0290 wdd->info = &sbsa_gwdt_info;
0291 wdd->ops = &sbsa_gwdt_ops;
0292 wdd->min_timeout = 1;
0293 wdd->timeout = DEFAULT_TIMEOUT;
0294 watchdog_set_drvdata(wdd, gwdt);
0295 watchdog_set_nowayout(wdd, nowayout);
0296 sbsa_gwdt_get_version(wdd);
0297 if (gwdt->version == 0)
0298 wdd->max_hw_heartbeat_ms = U32_MAX / gwdt->clk * 1000;
0299 else
0300 wdd->max_hw_heartbeat_ms = GENMASK_ULL(47, 0) / gwdt->clk * 1000;
0301
0302 status = readl(cf_base + SBSA_GWDT_WCS);
0303 if (status & SBSA_GWDT_WCS_WS1) {
0304 dev_warn(dev, "System reset by WDT.\n");
0305 wdd->bootstatus |= WDIOF_CARDRESET;
0306 }
0307 if (status & SBSA_GWDT_WCS_EN)
0308 set_bit(WDOG_HW_RUNNING, &wdd->status);
0309
0310 if (action) {
0311 irq = platform_get_irq(pdev, 0);
0312 if (irq < 0) {
0313 action = 0;
0314 dev_warn(dev, "unable to get ws0 interrupt.\n");
0315 } else {
0316
0317
0318
0319
0320 writel(0, rf_base + SBSA_GWDT_WRR);
0321 if (devm_request_irq(dev, irq, sbsa_gwdt_interrupt, 0,
0322 pdev->name, gwdt)) {
0323 action = 0;
0324 dev_warn(dev, "unable to request IRQ %d.\n",
0325 irq);
0326 }
0327 }
0328 if (!action)
0329 dev_warn(dev, "falling back to single stage mode.\n");
0330 }
0331
0332
0333
0334
0335 if (!action)
0336 wdd->max_hw_heartbeat_ms *= 2;
0337
0338 watchdog_init_timeout(wdd, timeout, dev);
0339
0340
0341
0342
0343
0344 sbsa_gwdt_set_timeout(wdd, wdd->timeout);
0345
0346 watchdog_stop_on_reboot(wdd);
0347 ret = devm_watchdog_register_device(dev, wdd);
0348 if (ret)
0349 return ret;
0350
0351 dev_info(dev, "Initialized with %ds timeout @ %u Hz, action=%d.%s\n",
0352 wdd->timeout, gwdt->clk, action,
0353 status & SBSA_GWDT_WCS_EN ? " [enabled]" : "");
0354
0355 return 0;
0356 }
0357
0358
0359 static int __maybe_unused sbsa_gwdt_suspend(struct device *dev)
0360 {
0361 struct sbsa_gwdt *gwdt = dev_get_drvdata(dev);
0362
0363 if (watchdog_active(&gwdt->wdd))
0364 sbsa_gwdt_stop(&gwdt->wdd);
0365
0366 return 0;
0367 }
0368
0369
0370 static int __maybe_unused sbsa_gwdt_resume(struct device *dev)
0371 {
0372 struct sbsa_gwdt *gwdt = dev_get_drvdata(dev);
0373
0374 if (watchdog_active(&gwdt->wdd))
0375 sbsa_gwdt_start(&gwdt->wdd);
0376
0377 return 0;
0378 }
0379
0380 static const struct dev_pm_ops sbsa_gwdt_pm_ops = {
0381 SET_SYSTEM_SLEEP_PM_OPS(sbsa_gwdt_suspend, sbsa_gwdt_resume)
0382 };
0383
0384 static const struct of_device_id sbsa_gwdt_of_match[] = {
0385 { .compatible = "arm,sbsa-gwdt", },
0386 {},
0387 };
0388 MODULE_DEVICE_TABLE(of, sbsa_gwdt_of_match);
0389
0390 static const struct platform_device_id sbsa_gwdt_pdev_match[] = {
0391 { .name = DRV_NAME, },
0392 {},
0393 };
0394 MODULE_DEVICE_TABLE(platform, sbsa_gwdt_pdev_match);
0395
0396 static struct platform_driver sbsa_gwdt_driver = {
0397 .driver = {
0398 .name = DRV_NAME,
0399 .pm = &sbsa_gwdt_pm_ops,
0400 .of_match_table = sbsa_gwdt_of_match,
0401 },
0402 .probe = sbsa_gwdt_probe,
0403 .id_table = sbsa_gwdt_pdev_match,
0404 };
0405
0406 module_platform_driver(sbsa_gwdt_driver);
0407
0408 MODULE_DESCRIPTION("SBSA Generic Watchdog Driver");
0409 MODULE_AUTHOR("Fu Wei <fu.wei@linaro.org>");
0410 MODULE_AUTHOR("Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>");
0411 MODULE_AUTHOR("Al Stone <al.stone@linaro.org>");
0412 MODULE_AUTHOR("Timur Tabi <timur@codeaurora.org>");
0413 MODULE_LICENSE("GPL v2");