Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (c) 2019-2020 NVIDIA Corporation. All rights reserved.
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 /* shared registers */
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 /* timer registers */
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 /* watchdog registers */
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     /* unlock and disable the watchdog */
0135     wdt_writel(wdt, WDTUR_UNLOCK_PATTERN, WDTUR);
0136     wdt_writel(wdt, WDTCMDR_DISABLE_COUNTER, WDTCMDR);
0137 
0138     /* disable timer */
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     /* unmask hardware IRQ, this may have been lost across powergate */
0148     value = TKEIE_WDT_MASK(wdt->index, 1);
0149     writel(value, tegra->regs + TKEIE(wdt->tmr->hwirq));
0150 
0151     /* clear interrupt */
0152     tmr_writel(wdt->tmr, TMRSR_INTR_CLR, TMRSR);
0153 
0154     /* select microsecond source */
0155     tmr_writel(wdt->tmr, TMRCSSR_SRC_USEC, TMRCSSR);
0156 
0157     /* configure timer (system reset happens on the fifth expiration) */
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         /* select the proper timer source */
0166         value &= ~WDTCR_TIMER_SOURCE_MASK;
0167         value |= WDTCR_TIMER_SOURCE(wdt->tmr->index);
0168 
0169         /* single timer period since that's already configured */
0170         value &= ~WDTCR_PERIOD_MASK;
0171         value |= WDTCR_PERIOD(1);
0172 
0173         /* enable local interrupt for WDT petting */
0174         value |= WDTCR_LOCAL_INT_ENABLE;
0175 
0176         /* enable local FIQ and remote interrupt for debug dump */
0177         if (0)
0178             value |= WDTCR_REMOTE_INT_ENABLE |
0179                  WDTCR_LOCAL_FIQ_ENABLE;
0180 
0181         /* enable system debug reset (doesn't properly reboot) */
0182         if (0)
0183             value |= WDTCR_SYSTEM_DEBUG_RESET_ENABLE;
0184 
0185         /* enable system POR reset */
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     /* read the watchdog configuration since it might be locked down */
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      * The 56-bit value of the TSC is spread across two registers that are
0306      * not synchronized. In order to read them atomically, ensure that the
0307      * high 24 bits match before and after reading the low 32 bits.
0308      */
0309     do {
0310         /* snapshot the high 24 bits */
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     /* create a watchdog using a preconfigured timer */
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");