cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

imx2_wdt.c (12057B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Watchdog driver for IMX2 and later processors
      4 *
      5 *  Copyright (C) 2010 Wolfram Sang, Pengutronix e.K. <kernel@pengutronix.de>
      6 *  Copyright (C) 2014 Freescale Semiconductor, Inc.
      7 *
      8 * some parts adapted by similar drivers from Darius Augulis and Vladimir
      9 * Zapolskiy, additional improvements by Wim Van Sebroeck.
     10 *
     11 * NOTE: MX1 has a slightly different Watchdog than MX2 and later:
     12 *
     13 *			MX1:		MX2+:
     14 *			----		-----
     15 * Registers:		32-bit		16-bit
     16 * Stopable timer:	Yes		No
     17 * Need to enable clk:	No		Yes
     18 * Halt on suspend:	Manual		Can be automatic
     19 */
     20
     21#include <linux/clk.h>
     22#include <linux/delay.h>
     23#include <linux/init.h>
     24#include <linux/interrupt.h>
     25#include <linux/io.h>
     26#include <linux/kernel.h>
     27#include <linux/module.h>
     28#include <linux/moduleparam.h>
     29#include <linux/of_address.h>
     30#include <linux/platform_device.h>
     31#include <linux/regmap.h>
     32#include <linux/watchdog.h>
     33
     34#define DRIVER_NAME "imx2-wdt"
     35
     36#define IMX2_WDT_WCR		0x00		/* Control Register */
     37#define IMX2_WDT_WCR_WT		(0xFF << 8)	/* -> Watchdog Timeout Field */
     38#define IMX2_WDT_WCR_WDA	BIT(5)		/* -> External Reset WDOG_B */
     39#define IMX2_WDT_WCR_SRS	BIT(4)		/* -> Software Reset Signal */
     40#define IMX2_WDT_WCR_WRE	BIT(3)		/* -> WDOG Reset Enable */
     41#define IMX2_WDT_WCR_WDE	BIT(2)		/* -> Watchdog Enable */
     42#define IMX2_WDT_WCR_WDZST	BIT(0)		/* -> Watchdog timer Suspend */
     43
     44#define IMX2_WDT_WSR		0x02		/* Service Register */
     45#define IMX2_WDT_SEQ1		0x5555		/* -> service sequence 1 */
     46#define IMX2_WDT_SEQ2		0xAAAA		/* -> service sequence 2 */
     47
     48#define IMX2_WDT_WRSR		0x04		/* Reset Status Register */
     49#define IMX2_WDT_WRSR_TOUT	BIT(1)		/* -> Reset due to Timeout */
     50
     51#define IMX2_WDT_WICR		0x06		/* Interrupt Control Register */
     52#define IMX2_WDT_WICR_WIE	BIT(15)		/* -> Interrupt Enable */
     53#define IMX2_WDT_WICR_WTIS	BIT(14)		/* -> Interrupt Status */
     54#define IMX2_WDT_WICR_WICT	0xFF		/* -> Interrupt Count Timeout */
     55
     56#define IMX2_WDT_WMCR		0x08		/* Misc Register */
     57
     58#define IMX2_WDT_MAX_TIME	128U
     59#define IMX2_WDT_DEFAULT_TIME	60		/* in seconds */
     60
     61#define WDOG_SEC_TO_COUNT(s)	((s * 2 - 1) << 8)
     62
     63struct imx2_wdt_device {
     64	struct clk *clk;
     65	struct regmap *regmap;
     66	struct watchdog_device wdog;
     67	bool ext_reset;
     68	bool clk_is_on;
     69	bool no_ping;
     70};
     71
     72static bool nowayout = WATCHDOG_NOWAYOUT;
     73module_param(nowayout, bool, 0);
     74MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
     75				__MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
     76
     77static unsigned timeout;
     78module_param(timeout, uint, 0);
     79MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds (default="
     80				__MODULE_STRING(IMX2_WDT_DEFAULT_TIME) ")");
     81
     82static const struct watchdog_info imx2_wdt_info = {
     83	.identity = "imx2+ watchdog",
     84	.options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE,
     85};
     86
     87static const struct watchdog_info imx2_wdt_pretimeout_info = {
     88	.identity = "imx2+ watchdog",
     89	.options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE |
     90		   WDIOF_PRETIMEOUT,
     91};
     92
     93static int imx2_wdt_restart(struct watchdog_device *wdog, unsigned long action,
     94			    void *data)
     95{
     96	struct imx2_wdt_device *wdev = watchdog_get_drvdata(wdog);
     97	unsigned int wcr_enable = IMX2_WDT_WCR_WDE;
     98
     99	/* Use internal reset or external - not both */
    100	if (wdev->ext_reset)
    101		wcr_enable |= IMX2_WDT_WCR_SRS; /* do not assert int reset */
    102	else
    103		wcr_enable |= IMX2_WDT_WCR_WDA; /* do not assert ext-reset */
    104
    105	/* Assert SRS signal */
    106	regmap_write(wdev->regmap, IMX2_WDT_WCR, wcr_enable);
    107	/*
    108	 * Due to imx6q errata ERR004346 (WDOG: WDOG SRS bit requires to be
    109	 * written twice), we add another two writes to ensure there must be at
    110	 * least two writes happen in the same one 32kHz clock period.  We save
    111	 * the target check here, since the writes shouldn't be a huge burden
    112	 * for other platforms.
    113	 */
    114	regmap_write(wdev->regmap, IMX2_WDT_WCR, wcr_enable);
    115	regmap_write(wdev->regmap, IMX2_WDT_WCR, wcr_enable);
    116
    117	/* wait for reset to assert... */
    118	mdelay(500);
    119
    120	return 0;
    121}
    122
    123static inline void imx2_wdt_setup(struct watchdog_device *wdog)
    124{
    125	struct imx2_wdt_device *wdev = watchdog_get_drvdata(wdog);
    126	u32 val;
    127
    128	regmap_read(wdev->regmap, IMX2_WDT_WCR, &val);
    129
    130	/* Suspend timer in low power mode, write once-only */
    131	val |= IMX2_WDT_WCR_WDZST;
    132	/* Strip the old watchdog Time-Out value */
    133	val &= ~IMX2_WDT_WCR_WT;
    134	/* Generate internal chip-level reset if WDOG times out */
    135	if (!wdev->ext_reset)
    136		val &= ~IMX2_WDT_WCR_WRE;
    137	/* Or if external-reset assert WDOG_B reset only on time-out */
    138	else
    139		val |= IMX2_WDT_WCR_WRE;
    140	/* Keep Watchdog Disabled */
    141	val &= ~IMX2_WDT_WCR_WDE;
    142	/* Set the watchdog's Time-Out value */
    143	val |= WDOG_SEC_TO_COUNT(wdog->timeout);
    144
    145	regmap_write(wdev->regmap, IMX2_WDT_WCR, val);
    146
    147	/* enable the watchdog */
    148	val |= IMX2_WDT_WCR_WDE;
    149	regmap_write(wdev->regmap, IMX2_WDT_WCR, val);
    150}
    151
    152static inline bool imx2_wdt_is_running(struct imx2_wdt_device *wdev)
    153{
    154	u32 val;
    155
    156	regmap_read(wdev->regmap, IMX2_WDT_WCR, &val);
    157
    158	return val & IMX2_WDT_WCR_WDE;
    159}
    160
    161static int imx2_wdt_ping(struct watchdog_device *wdog)
    162{
    163	struct imx2_wdt_device *wdev = watchdog_get_drvdata(wdog);
    164
    165	if (!wdev->clk_is_on)
    166		return 0;
    167
    168	regmap_write(wdev->regmap, IMX2_WDT_WSR, IMX2_WDT_SEQ1);
    169	regmap_write(wdev->regmap, IMX2_WDT_WSR, IMX2_WDT_SEQ2);
    170	return 0;
    171}
    172
    173static void __imx2_wdt_set_timeout(struct watchdog_device *wdog,
    174				   unsigned int new_timeout)
    175{
    176	struct imx2_wdt_device *wdev = watchdog_get_drvdata(wdog);
    177
    178	regmap_update_bits(wdev->regmap, IMX2_WDT_WCR, IMX2_WDT_WCR_WT,
    179			   WDOG_SEC_TO_COUNT(new_timeout));
    180}
    181
    182static int imx2_wdt_set_timeout(struct watchdog_device *wdog,
    183				unsigned int new_timeout)
    184{
    185	unsigned int actual;
    186
    187	actual = min(new_timeout, IMX2_WDT_MAX_TIME);
    188	__imx2_wdt_set_timeout(wdog, actual);
    189	wdog->timeout = new_timeout;
    190	return 0;
    191}
    192
    193static int imx2_wdt_set_pretimeout(struct watchdog_device *wdog,
    194				   unsigned int new_pretimeout)
    195{
    196	struct imx2_wdt_device *wdev = watchdog_get_drvdata(wdog);
    197
    198	if (new_pretimeout >= IMX2_WDT_MAX_TIME)
    199		return -EINVAL;
    200
    201	wdog->pretimeout = new_pretimeout;
    202
    203	regmap_update_bits(wdev->regmap, IMX2_WDT_WICR,
    204			   IMX2_WDT_WICR_WIE | IMX2_WDT_WICR_WICT,
    205			   IMX2_WDT_WICR_WIE | (new_pretimeout << 1));
    206	return 0;
    207}
    208
    209static irqreturn_t imx2_wdt_isr(int irq, void *wdog_arg)
    210{
    211	struct watchdog_device *wdog = wdog_arg;
    212	struct imx2_wdt_device *wdev = watchdog_get_drvdata(wdog);
    213
    214	regmap_write_bits(wdev->regmap, IMX2_WDT_WICR,
    215			  IMX2_WDT_WICR_WTIS, IMX2_WDT_WICR_WTIS);
    216
    217	watchdog_notify_pretimeout(wdog);
    218
    219	return IRQ_HANDLED;
    220}
    221
    222static int imx2_wdt_start(struct watchdog_device *wdog)
    223{
    224	struct imx2_wdt_device *wdev = watchdog_get_drvdata(wdog);
    225
    226	if (imx2_wdt_is_running(wdev))
    227		imx2_wdt_set_timeout(wdog, wdog->timeout);
    228	else
    229		imx2_wdt_setup(wdog);
    230
    231	set_bit(WDOG_HW_RUNNING, &wdog->status);
    232
    233	return imx2_wdt_ping(wdog);
    234}
    235
    236static const struct watchdog_ops imx2_wdt_ops = {
    237	.owner = THIS_MODULE,
    238	.start = imx2_wdt_start,
    239	.ping = imx2_wdt_ping,
    240	.set_timeout = imx2_wdt_set_timeout,
    241	.set_pretimeout = imx2_wdt_set_pretimeout,
    242	.restart = imx2_wdt_restart,
    243};
    244
    245static const struct regmap_config imx2_wdt_regmap_config = {
    246	.reg_bits = 16,
    247	.reg_stride = 2,
    248	.val_bits = 16,
    249	.max_register = 0x8,
    250};
    251
    252static void imx2_wdt_action(void *data)
    253{
    254	clk_disable_unprepare(data);
    255}
    256
    257static int __init imx2_wdt_probe(struct platform_device *pdev)
    258{
    259	struct device *dev = &pdev->dev;
    260	struct imx2_wdt_device *wdev;
    261	struct watchdog_device *wdog;
    262	void __iomem *base;
    263	int ret;
    264	u32 val;
    265
    266	wdev = devm_kzalloc(dev, sizeof(*wdev), GFP_KERNEL);
    267	if (!wdev)
    268		return -ENOMEM;
    269
    270	base = devm_platform_ioremap_resource(pdev, 0);
    271	if (IS_ERR(base))
    272		return PTR_ERR(base);
    273
    274	wdev->regmap = devm_regmap_init_mmio_clk(dev, NULL, base,
    275						 &imx2_wdt_regmap_config);
    276	if (IS_ERR(wdev->regmap)) {
    277		dev_err(dev, "regmap init failed\n");
    278		return PTR_ERR(wdev->regmap);
    279	}
    280
    281	wdev->clk = devm_clk_get(dev, NULL);
    282	if (IS_ERR(wdev->clk)) {
    283		dev_err(dev, "can't get Watchdog clock\n");
    284		return PTR_ERR(wdev->clk);
    285	}
    286
    287	wdog			= &wdev->wdog;
    288	wdog->info		= &imx2_wdt_info;
    289	wdog->ops		= &imx2_wdt_ops;
    290	wdog->min_timeout	= 1;
    291	wdog->timeout		= IMX2_WDT_DEFAULT_TIME;
    292	wdog->max_hw_heartbeat_ms = IMX2_WDT_MAX_TIME * 1000;
    293	wdog->parent		= dev;
    294
    295	ret = platform_get_irq(pdev, 0);
    296	if (ret > 0)
    297		if (!devm_request_irq(dev, ret, imx2_wdt_isr, 0,
    298				      dev_name(dev), wdog))
    299			wdog->info = &imx2_wdt_pretimeout_info;
    300
    301	ret = clk_prepare_enable(wdev->clk);
    302	if (ret)
    303		return ret;
    304
    305	ret = devm_add_action_or_reset(dev, imx2_wdt_action, wdev->clk);
    306	if (ret)
    307		return ret;
    308
    309	wdev->clk_is_on = true;
    310
    311	regmap_read(wdev->regmap, IMX2_WDT_WRSR, &val);
    312	wdog->bootstatus = val & IMX2_WDT_WRSR_TOUT ? WDIOF_CARDRESET : 0;
    313
    314	wdev->ext_reset = of_property_read_bool(dev->of_node,
    315						"fsl,ext-reset-output");
    316	/*
    317	 * The i.MX7D doesn't support low power mode, so we need to ping the watchdog
    318	 * during suspend.
    319	 */
    320	wdev->no_ping = !of_device_is_compatible(dev->of_node, "fsl,imx7d-wdt");
    321	platform_set_drvdata(pdev, wdog);
    322	watchdog_set_drvdata(wdog, wdev);
    323	watchdog_set_nowayout(wdog, nowayout);
    324	watchdog_set_restart_priority(wdog, 128);
    325	watchdog_init_timeout(wdog, timeout, dev);
    326	if (wdev->no_ping)
    327		watchdog_stop_ping_on_suspend(wdog);
    328
    329	if (imx2_wdt_is_running(wdev)) {
    330		imx2_wdt_set_timeout(wdog, wdog->timeout);
    331		set_bit(WDOG_HW_RUNNING, &wdog->status);
    332	}
    333
    334	/*
    335	 * Disable the watchdog power down counter at boot. Otherwise the power
    336	 * down counter will pull down the #WDOG interrupt line for one clock
    337	 * cycle.
    338	 */
    339	regmap_write(wdev->regmap, IMX2_WDT_WMCR, 0);
    340
    341	return devm_watchdog_register_device(dev, wdog);
    342}
    343
    344static void imx2_wdt_shutdown(struct platform_device *pdev)
    345{
    346	struct watchdog_device *wdog = platform_get_drvdata(pdev);
    347	struct imx2_wdt_device *wdev = watchdog_get_drvdata(wdog);
    348
    349	if (imx2_wdt_is_running(wdev)) {
    350		/*
    351		 * We are running, configure max timeout before reboot
    352		 * will take place.
    353		 */
    354		imx2_wdt_set_timeout(wdog, IMX2_WDT_MAX_TIME);
    355		imx2_wdt_ping(wdog);
    356		dev_crit(&pdev->dev, "Device shutdown: Expect reboot!\n");
    357	}
    358}
    359
    360/* Disable watchdog if it is active or non-active but still running */
    361static int __maybe_unused imx2_wdt_suspend(struct device *dev)
    362{
    363	struct watchdog_device *wdog = dev_get_drvdata(dev);
    364	struct imx2_wdt_device *wdev = watchdog_get_drvdata(wdog);
    365
    366	/* The watchdog IP block is running */
    367	if (imx2_wdt_is_running(wdev)) {
    368		/*
    369		 * Don't update wdog->timeout, we'll restore the current value
    370		 * during resume.
    371		 */
    372		__imx2_wdt_set_timeout(wdog, IMX2_WDT_MAX_TIME);
    373		imx2_wdt_ping(wdog);
    374	}
    375
    376	if (wdev->no_ping) {
    377		clk_disable_unprepare(wdev->clk);
    378
    379		wdev->clk_is_on = false;
    380	}
    381
    382	return 0;
    383}
    384
    385/* Enable watchdog and configure it if necessary */
    386static int __maybe_unused imx2_wdt_resume(struct device *dev)
    387{
    388	struct watchdog_device *wdog = dev_get_drvdata(dev);
    389	struct imx2_wdt_device *wdev = watchdog_get_drvdata(wdog);
    390	int ret;
    391
    392	if (wdev->no_ping) {
    393		ret = clk_prepare_enable(wdev->clk);
    394
    395		if (ret)
    396			return ret;
    397
    398		wdev->clk_is_on = true;
    399	}
    400
    401	if (watchdog_active(wdog) && !imx2_wdt_is_running(wdev)) {
    402		/*
    403		 * If the watchdog is still active and resumes
    404		 * from deep sleep state, need to restart the
    405		 * watchdog again.
    406		 */
    407		imx2_wdt_setup(wdog);
    408	}
    409	if (imx2_wdt_is_running(wdev)) {
    410		imx2_wdt_set_timeout(wdog, wdog->timeout);
    411		imx2_wdt_ping(wdog);
    412	}
    413
    414	return 0;
    415}
    416
    417static SIMPLE_DEV_PM_OPS(imx2_wdt_pm_ops, imx2_wdt_suspend,
    418			 imx2_wdt_resume);
    419
    420static const struct of_device_id imx2_wdt_dt_ids[] = {
    421	{ .compatible = "fsl,imx21-wdt", },
    422	{ .compatible = "fsl,imx7d-wdt", },
    423	{ /* sentinel */ }
    424};
    425MODULE_DEVICE_TABLE(of, imx2_wdt_dt_ids);
    426
    427static struct platform_driver imx2_wdt_driver = {
    428	.shutdown	= imx2_wdt_shutdown,
    429	.driver		= {
    430		.name	= DRIVER_NAME,
    431		.pm     = &imx2_wdt_pm_ops,
    432		.of_match_table = imx2_wdt_dt_ids,
    433	},
    434};
    435
    436module_platform_driver_probe(imx2_wdt_driver, imx2_wdt_probe);
    437
    438MODULE_AUTHOR("Wolfram Sang");
    439MODULE_DESCRIPTION("Watchdog driver for IMX2 and later");
    440MODULE_LICENSE("GPL v2");
    441MODULE_ALIAS("platform:" DRIVER_NAME);