0001
0002
0003
0004
0005
0006 #include <linux/clocksource.h>
0007 #include <linux/module.h>
0008 #include <linux/interrupt.h>
0009 #include <linux/io.h>
0010 #include <linux/of.h>
0011 #include <linux/of_device.h>
0012 #include <linux/platform_device.h>
0013 #include <linux/pm.h>
0014 #include <linux/watchdog.h>
0015
0016
0017 #define TKETSC0 0x000
0018 #define TKETSC1 0x004
0019 #define TKEUSEC 0x008
0020 #define TKEOSC 0x00c
0021
0022 #define TKEIE(x) (0x100 + ((x) * 4))
0023 #define TKEIE_WDT_MASK(x, y) ((y) << (16 + 4 * (x)))
0024
0025
0026 #define TMRCR 0x000
0027 #define TMRCR_ENABLE BIT(31)
0028 #define TMRCR_PERIODIC BIT(30)
0029 #define TMRCR_PTV(x) ((x) & 0x0fffffff)
0030
0031 #define TMRSR 0x004
0032 #define TMRSR_INTR_CLR BIT(30)
0033
0034 #define TMRCSSR 0x008
0035 #define TMRCSSR_SRC_USEC (0 << 0)
0036
0037
0038 #define WDTCR 0x000
0039 #define WDTCR_SYSTEM_POR_RESET_ENABLE BIT(16)
0040 #define WDTCR_SYSTEM_DEBUG_RESET_ENABLE BIT(15)
0041 #define WDTCR_REMOTE_INT_ENABLE BIT(14)
0042 #define WDTCR_LOCAL_FIQ_ENABLE BIT(13)
0043 #define WDTCR_LOCAL_INT_ENABLE BIT(12)
0044 #define WDTCR_PERIOD_MASK (0xff << 4)
0045 #define WDTCR_PERIOD(x) (((x) & 0xff) << 4)
0046 #define WDTCR_TIMER_SOURCE_MASK 0xf
0047 #define WDTCR_TIMER_SOURCE(x) ((x) & 0xf)
0048
0049 #define WDTCMDR 0x008
0050 #define WDTCMDR_DISABLE_COUNTER BIT(1)
0051 #define WDTCMDR_START_COUNTER BIT(0)
0052
0053 #define WDTUR 0x00c
0054 #define WDTUR_UNLOCK_PATTERN 0x0000c45a
0055
0056 struct tegra186_timer_soc {
0057 unsigned int num_timers;
0058 unsigned int num_wdts;
0059 };
0060
0061 struct tegra186_tmr {
0062 struct tegra186_timer *parent;
0063 void __iomem *regs;
0064 unsigned int index;
0065 unsigned int hwirq;
0066 };
0067
0068 struct tegra186_wdt {
0069 struct watchdog_device base;
0070
0071 void __iomem *regs;
0072 unsigned int index;
0073 bool locked;
0074
0075 struct tegra186_tmr *tmr;
0076 };
0077
0078 static inline struct tegra186_wdt *to_tegra186_wdt(struct watchdog_device *wdd)
0079 {
0080 return container_of(wdd, struct tegra186_wdt, base);
0081 }
0082
0083 struct tegra186_timer {
0084 const struct tegra186_timer_soc *soc;
0085 struct device *dev;
0086 void __iomem *regs;
0087
0088 struct tegra186_wdt *wdt;
0089 struct clocksource usec;
0090 struct clocksource tsc;
0091 struct clocksource osc;
0092 };
0093
0094 static void tmr_writel(struct tegra186_tmr *tmr, u32 value, unsigned int offset)
0095 {
0096 writel_relaxed(value, tmr->regs + offset);
0097 }
0098
0099 static void wdt_writel(struct tegra186_wdt *wdt, u32 value, unsigned int offset)
0100 {
0101 writel_relaxed(value, wdt->regs + offset);
0102 }
0103
0104 static u32 wdt_readl(struct tegra186_wdt *wdt, unsigned int offset)
0105 {
0106 return readl_relaxed(wdt->regs + offset);
0107 }
0108
0109 static struct tegra186_tmr *tegra186_tmr_create(struct tegra186_timer *tegra,
0110 unsigned int index)
0111 {
0112 unsigned int offset = 0x10000 + index * 0x10000;
0113 struct tegra186_tmr *tmr;
0114
0115 tmr = devm_kzalloc(tegra->dev, sizeof(*tmr), GFP_KERNEL);
0116 if (!tmr)
0117 return ERR_PTR(-ENOMEM);
0118
0119 tmr->parent = tegra;
0120 tmr->regs = tegra->regs + offset;
0121 tmr->index = index;
0122 tmr->hwirq = 0;
0123
0124 return tmr;
0125 }
0126
0127 static const struct watchdog_info tegra186_wdt_info = {
0128 .options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING,
0129 .identity = "NVIDIA Tegra186 WDT",
0130 };
0131
0132 static void tegra186_wdt_disable(struct tegra186_wdt *wdt)
0133 {
0134
0135 wdt_writel(wdt, WDTUR_UNLOCK_PATTERN, WDTUR);
0136 wdt_writel(wdt, WDTCMDR_DISABLE_COUNTER, WDTCMDR);
0137
0138
0139 tmr_writel(wdt->tmr, 0, TMRCR);
0140 }
0141
0142 static void tegra186_wdt_enable(struct tegra186_wdt *wdt)
0143 {
0144 struct tegra186_timer *tegra = wdt->tmr->parent;
0145 u32 value;
0146
0147
0148 value = TKEIE_WDT_MASK(wdt->index, 1);
0149 writel(value, tegra->regs + TKEIE(wdt->tmr->hwirq));
0150
0151
0152 tmr_writel(wdt->tmr, TMRSR_INTR_CLR, TMRSR);
0153
0154
0155 tmr_writel(wdt->tmr, TMRCSSR_SRC_USEC, TMRCSSR);
0156
0157
0158 value = TMRCR_PTV(wdt->base.timeout * USEC_PER_SEC / 5) |
0159 TMRCR_PERIODIC | TMRCR_ENABLE;
0160 tmr_writel(wdt->tmr, value, TMRCR);
0161
0162 if (!wdt->locked) {
0163 value = wdt_readl(wdt, WDTCR);
0164
0165
0166 value &= ~WDTCR_TIMER_SOURCE_MASK;
0167 value |= WDTCR_TIMER_SOURCE(wdt->tmr->index);
0168
0169
0170 value &= ~WDTCR_PERIOD_MASK;
0171 value |= WDTCR_PERIOD(1);
0172
0173
0174 value |= WDTCR_LOCAL_INT_ENABLE;
0175
0176
0177 if (0)
0178 value |= WDTCR_REMOTE_INT_ENABLE |
0179 WDTCR_LOCAL_FIQ_ENABLE;
0180
0181
0182 if (0)
0183 value |= WDTCR_SYSTEM_DEBUG_RESET_ENABLE;
0184
0185
0186 value |= WDTCR_SYSTEM_POR_RESET_ENABLE;
0187
0188 wdt_writel(wdt, value, WDTCR);
0189 }
0190
0191 wdt_writel(wdt, WDTCMDR_START_COUNTER, WDTCMDR);
0192 }
0193
0194 static int tegra186_wdt_start(struct watchdog_device *wdd)
0195 {
0196 struct tegra186_wdt *wdt = to_tegra186_wdt(wdd);
0197
0198 tegra186_wdt_enable(wdt);
0199
0200 return 0;
0201 }
0202
0203 static int tegra186_wdt_stop(struct watchdog_device *wdd)
0204 {
0205 struct tegra186_wdt *wdt = to_tegra186_wdt(wdd);
0206
0207 tegra186_wdt_disable(wdt);
0208
0209 return 0;
0210 }
0211
0212 static int tegra186_wdt_ping(struct watchdog_device *wdd)
0213 {
0214 struct tegra186_wdt *wdt = to_tegra186_wdt(wdd);
0215
0216 tegra186_wdt_disable(wdt);
0217 tegra186_wdt_enable(wdt);
0218
0219 return 0;
0220 }
0221
0222 static int tegra186_wdt_set_timeout(struct watchdog_device *wdd,
0223 unsigned int timeout)
0224 {
0225 struct tegra186_wdt *wdt = to_tegra186_wdt(wdd);
0226
0227 if (watchdog_active(&wdt->base))
0228 tegra186_wdt_disable(wdt);
0229
0230 wdt->base.timeout = timeout;
0231
0232 if (watchdog_active(&wdt->base))
0233 tegra186_wdt_enable(wdt);
0234
0235 return 0;
0236 }
0237
0238 static const struct watchdog_ops tegra186_wdt_ops = {
0239 .owner = THIS_MODULE,
0240 .start = tegra186_wdt_start,
0241 .stop = tegra186_wdt_stop,
0242 .ping = tegra186_wdt_ping,
0243 .set_timeout = tegra186_wdt_set_timeout,
0244 };
0245
0246 static struct tegra186_wdt *tegra186_wdt_create(struct tegra186_timer *tegra,
0247 unsigned int index)
0248 {
0249 unsigned int offset = 0x10000, source;
0250 struct tegra186_wdt *wdt;
0251 u32 value;
0252 int err;
0253
0254 offset += tegra->soc->num_timers * 0x10000 + index * 0x10000;
0255
0256 wdt = devm_kzalloc(tegra->dev, sizeof(*wdt), GFP_KERNEL);
0257 if (!wdt)
0258 return ERR_PTR(-ENOMEM);
0259
0260 wdt->regs = tegra->regs + offset;
0261 wdt->index = index;
0262
0263
0264 value = wdt_readl(wdt, WDTCR);
0265
0266 if (value & WDTCR_LOCAL_INT_ENABLE)
0267 wdt->locked = true;
0268
0269 source = value & WDTCR_TIMER_SOURCE_MASK;
0270
0271 wdt->tmr = tegra186_tmr_create(tegra, source);
0272 if (IS_ERR(wdt->tmr))
0273 return ERR_CAST(wdt->tmr);
0274
0275 wdt->base.info = &tegra186_wdt_info;
0276 wdt->base.ops = &tegra186_wdt_ops;
0277 wdt->base.min_timeout = 1;
0278 wdt->base.max_timeout = 255;
0279 wdt->base.parent = tegra->dev;
0280
0281 err = watchdog_init_timeout(&wdt->base, 5, tegra->dev);
0282 if (err < 0) {
0283 dev_err(tegra->dev, "failed to initialize timeout: %d\n", err);
0284 return ERR_PTR(err);
0285 }
0286
0287 err = devm_watchdog_register_device(tegra->dev, &wdt->base);
0288 if (err < 0) {
0289 dev_err(tegra->dev, "failed to register WDT: %d\n", err);
0290 return ERR_PTR(err);
0291 }
0292
0293 return wdt;
0294 }
0295
0296 static u64 tegra186_timer_tsc_read(struct clocksource *cs)
0297 {
0298 struct tegra186_timer *tegra = container_of(cs, struct tegra186_timer,
0299 tsc);
0300 u32 hi, lo, ss;
0301
0302 hi = readl_relaxed(tegra->regs + TKETSC1);
0303
0304
0305
0306
0307
0308
0309 do {
0310
0311 ss = hi;
0312
0313 lo = readl_relaxed(tegra->regs + TKETSC0);
0314 hi = readl_relaxed(tegra->regs + TKETSC1);
0315 } while (hi != ss);
0316
0317 return (u64)hi << 32 | lo;
0318 }
0319
0320 static int tegra186_timer_tsc_init(struct tegra186_timer *tegra)
0321 {
0322 tegra->tsc.name = "tsc";
0323 tegra->tsc.rating = 300;
0324 tegra->tsc.read = tegra186_timer_tsc_read;
0325 tegra->tsc.mask = CLOCKSOURCE_MASK(56);
0326 tegra->tsc.flags = CLOCK_SOURCE_IS_CONTINUOUS;
0327
0328 return clocksource_register_hz(&tegra->tsc, 31250000);
0329 }
0330
0331 static u64 tegra186_timer_osc_read(struct clocksource *cs)
0332 {
0333 struct tegra186_timer *tegra = container_of(cs, struct tegra186_timer,
0334 osc);
0335
0336 return readl_relaxed(tegra->regs + TKEOSC);
0337 }
0338
0339 static int tegra186_timer_osc_init(struct tegra186_timer *tegra)
0340 {
0341 tegra->osc.name = "osc";
0342 tegra->osc.rating = 300;
0343 tegra->osc.read = tegra186_timer_osc_read;
0344 tegra->osc.mask = CLOCKSOURCE_MASK(32);
0345 tegra->osc.flags = CLOCK_SOURCE_IS_CONTINUOUS;
0346
0347 return clocksource_register_hz(&tegra->osc, 38400000);
0348 }
0349
0350 static u64 tegra186_timer_usec_read(struct clocksource *cs)
0351 {
0352 struct tegra186_timer *tegra = container_of(cs, struct tegra186_timer,
0353 usec);
0354
0355 return readl_relaxed(tegra->regs + TKEUSEC);
0356 }
0357
0358 static int tegra186_timer_usec_init(struct tegra186_timer *tegra)
0359 {
0360 tegra->usec.name = "usec";
0361 tegra->usec.rating = 300;
0362 tegra->usec.read = tegra186_timer_usec_read;
0363 tegra->usec.mask = CLOCKSOURCE_MASK(32);
0364 tegra->usec.flags = CLOCK_SOURCE_IS_CONTINUOUS;
0365
0366 return clocksource_register_hz(&tegra->usec, USEC_PER_SEC);
0367 }
0368
0369 static irqreturn_t tegra186_timer_irq(int irq, void *data)
0370 {
0371 struct tegra186_timer *tegra = data;
0372
0373 if (watchdog_active(&tegra->wdt->base)) {
0374 tegra186_wdt_disable(tegra->wdt);
0375 tegra186_wdt_enable(tegra->wdt);
0376 }
0377
0378 return IRQ_HANDLED;
0379 }
0380
0381 static int tegra186_timer_probe(struct platform_device *pdev)
0382 {
0383 struct device *dev = &pdev->dev;
0384 struct tegra186_timer *tegra;
0385 unsigned int irq;
0386 int err;
0387
0388 tegra = devm_kzalloc(dev, sizeof(*tegra), GFP_KERNEL);
0389 if (!tegra)
0390 return -ENOMEM;
0391
0392 tegra->soc = of_device_get_match_data(dev);
0393 dev_set_drvdata(dev, tegra);
0394 tegra->dev = dev;
0395
0396 tegra->regs = devm_platform_ioremap_resource(pdev, 0);
0397 if (IS_ERR(tegra->regs))
0398 return PTR_ERR(tegra->regs);
0399
0400 err = platform_get_irq(pdev, 0);
0401 if (err < 0)
0402 return err;
0403
0404 irq = err;
0405
0406
0407 tegra->wdt = tegra186_wdt_create(tegra, 0);
0408 if (IS_ERR(tegra->wdt)) {
0409 err = PTR_ERR(tegra->wdt);
0410 dev_err(dev, "failed to create WDT: %d\n", err);
0411 return err;
0412 }
0413
0414 err = tegra186_timer_tsc_init(tegra);
0415 if (err < 0) {
0416 dev_err(dev, "failed to register TSC counter: %d\n", err);
0417 return err;
0418 }
0419
0420 err = tegra186_timer_osc_init(tegra);
0421 if (err < 0) {
0422 dev_err(dev, "failed to register OSC counter: %d\n", err);
0423 goto unregister_tsc;
0424 }
0425
0426 err = tegra186_timer_usec_init(tegra);
0427 if (err < 0) {
0428 dev_err(dev, "failed to register USEC counter: %d\n", err);
0429 goto unregister_osc;
0430 }
0431
0432 err = devm_request_irq(dev, irq, tegra186_timer_irq, 0,
0433 "tegra186-timer", tegra);
0434 if (err < 0) {
0435 dev_err(dev, "failed to request IRQ#%u: %d\n", irq, err);
0436 goto unregister_usec;
0437 }
0438
0439 return 0;
0440
0441 unregister_usec:
0442 clocksource_unregister(&tegra->usec);
0443 unregister_osc:
0444 clocksource_unregister(&tegra->osc);
0445 unregister_tsc:
0446 clocksource_unregister(&tegra->tsc);
0447 return err;
0448 }
0449
0450 static int tegra186_timer_remove(struct platform_device *pdev)
0451 {
0452 struct tegra186_timer *tegra = platform_get_drvdata(pdev);
0453
0454 clocksource_unregister(&tegra->usec);
0455 clocksource_unregister(&tegra->osc);
0456 clocksource_unregister(&tegra->tsc);
0457
0458 return 0;
0459 }
0460
0461 static int __maybe_unused tegra186_timer_suspend(struct device *dev)
0462 {
0463 struct tegra186_timer *tegra = dev_get_drvdata(dev);
0464
0465 if (watchdog_active(&tegra->wdt->base))
0466 tegra186_wdt_disable(tegra->wdt);
0467
0468 return 0;
0469 }
0470
0471 static int __maybe_unused tegra186_timer_resume(struct device *dev)
0472 {
0473 struct tegra186_timer *tegra = dev_get_drvdata(dev);
0474
0475 if (watchdog_active(&tegra->wdt->base))
0476 tegra186_wdt_enable(tegra->wdt);
0477
0478 return 0;
0479 }
0480
0481 static SIMPLE_DEV_PM_OPS(tegra186_timer_pm_ops, tegra186_timer_suspend,
0482 tegra186_timer_resume);
0483
0484 static const struct tegra186_timer_soc tegra186_timer = {
0485 .num_timers = 10,
0486 .num_wdts = 3,
0487 };
0488
0489 static const struct tegra186_timer_soc tegra234_timer = {
0490 .num_timers = 16,
0491 .num_wdts = 3,
0492 };
0493
0494 static const struct of_device_id tegra186_timer_of_match[] = {
0495 { .compatible = "nvidia,tegra186-timer", .data = &tegra186_timer },
0496 { .compatible = "nvidia,tegra234-timer", .data = &tegra234_timer },
0497 { }
0498 };
0499 MODULE_DEVICE_TABLE(of, tegra186_timer_of_match);
0500
0501 static struct platform_driver tegra186_wdt_driver = {
0502 .driver = {
0503 .name = "tegra186-timer",
0504 .pm = &tegra186_timer_pm_ops,
0505 .of_match_table = tegra186_timer_of_match,
0506 },
0507 .probe = tegra186_timer_probe,
0508 .remove = tegra186_timer_remove,
0509 };
0510 module_platform_driver(tegra186_wdt_driver);
0511
0512 MODULE_AUTHOR("Thierry Reding <treding@nvidia.com>");
0513 MODULE_DESCRIPTION("NVIDIA Tegra186 timers driver");
0514 MODULE_LICENSE("GPL v2");