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

orion_wdt.c (18129B)


      1/*
      2 * drivers/watchdog/orion_wdt.c
      3 *
      4 * Watchdog driver for Orion/Kirkwood processors
      5 *
      6 * Author: Sylver Bruneau <sylver.bruneau@googlemail.com>
      7 *
      8 * This file is licensed under  the terms of the GNU General Public
      9 * License version 2. This program is licensed "as is" without any
     10 * warranty of any kind, whether express or implied.
     11 */
     12
     13#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
     14
     15#include <linux/module.h>
     16#include <linux/moduleparam.h>
     17#include <linux/types.h>
     18#include <linux/kernel.h>
     19#include <linux/platform_device.h>
     20#include <linux/watchdog.h>
     21#include <linux/interrupt.h>
     22#include <linux/io.h>
     23#include <linux/clk.h>
     24#include <linux/err.h>
     25#include <linux/of.h>
     26#include <linux/of_device.h>
     27
     28/* RSTOUT mask register physical address for Orion5x, Kirkwood and Dove */
     29#define ORION_RSTOUT_MASK_OFFSET	0x20108
     30
     31/* Internal registers can be configured at any 1 MiB aligned address */
     32#define INTERNAL_REGS_MASK		~(SZ_1M - 1)
     33
     34/*
     35 * Watchdog timer block registers.
     36 */
     37#define TIMER_CTRL		0x0000
     38#define TIMER1_FIXED_ENABLE_BIT	BIT(12)
     39#define WDT_AXP_FIXED_ENABLE_BIT BIT(10)
     40#define TIMER1_ENABLE_BIT	BIT(2)
     41
     42#define TIMER_A370_STATUS	0x0004
     43#define WDT_A370_EXPIRED	BIT(31)
     44#define TIMER1_STATUS_BIT	BIT(8)
     45
     46#define TIMER1_VAL_OFF		0x001c
     47
     48#define WDT_MAX_CYCLE_COUNT	0xffffffff
     49
     50#define WDT_A370_RATIO_MASK(v)	((v) << 16)
     51#define WDT_A370_RATIO_SHIFT	5
     52#define WDT_A370_RATIO		(1 << WDT_A370_RATIO_SHIFT)
     53
     54static bool nowayout = WATCHDOG_NOWAYOUT;
     55static int heartbeat;		/* module parameter (seconds) */
     56
     57struct orion_watchdog;
     58
     59struct orion_watchdog_data {
     60	int wdt_counter_offset;
     61	int wdt_enable_bit;
     62	int rstout_enable_bit;
     63	int rstout_mask_bit;
     64	int (*clock_init)(struct platform_device *,
     65			  struct orion_watchdog *);
     66	int (*enabled)(struct orion_watchdog *);
     67	int (*start)(struct watchdog_device *);
     68	int (*stop)(struct watchdog_device *);
     69};
     70
     71struct orion_watchdog {
     72	struct watchdog_device wdt;
     73	void __iomem *reg;
     74	void __iomem *rstout;
     75	void __iomem *rstout_mask;
     76	unsigned long clk_rate;
     77	struct clk *clk;
     78	const struct orion_watchdog_data *data;
     79};
     80
     81static int orion_wdt_clock_init(struct platform_device *pdev,
     82				struct orion_watchdog *dev)
     83{
     84	int ret;
     85
     86	dev->clk = clk_get(&pdev->dev, NULL);
     87	if (IS_ERR(dev->clk))
     88		return PTR_ERR(dev->clk);
     89	ret = clk_prepare_enable(dev->clk);
     90	if (ret) {
     91		clk_put(dev->clk);
     92		return ret;
     93	}
     94
     95	dev->clk_rate = clk_get_rate(dev->clk);
     96	return 0;
     97}
     98
     99static int armada370_wdt_clock_init(struct platform_device *pdev,
    100				    struct orion_watchdog *dev)
    101{
    102	int ret;
    103
    104	dev->clk = clk_get(&pdev->dev, NULL);
    105	if (IS_ERR(dev->clk))
    106		return PTR_ERR(dev->clk);
    107	ret = clk_prepare_enable(dev->clk);
    108	if (ret) {
    109		clk_put(dev->clk);
    110		return ret;
    111	}
    112
    113	/* Setup watchdog input clock */
    114	atomic_io_modify(dev->reg + TIMER_CTRL,
    115			WDT_A370_RATIO_MASK(WDT_A370_RATIO_SHIFT),
    116			WDT_A370_RATIO_MASK(WDT_A370_RATIO_SHIFT));
    117
    118	dev->clk_rate = clk_get_rate(dev->clk) / WDT_A370_RATIO;
    119	return 0;
    120}
    121
    122static int armada375_wdt_clock_init(struct platform_device *pdev,
    123				    struct orion_watchdog *dev)
    124{
    125	int ret;
    126
    127	dev->clk = of_clk_get_by_name(pdev->dev.of_node, "fixed");
    128	if (!IS_ERR(dev->clk)) {
    129		ret = clk_prepare_enable(dev->clk);
    130		if (ret) {
    131			clk_put(dev->clk);
    132			return ret;
    133		}
    134
    135		atomic_io_modify(dev->reg + TIMER_CTRL,
    136				WDT_AXP_FIXED_ENABLE_BIT,
    137				WDT_AXP_FIXED_ENABLE_BIT);
    138		dev->clk_rate = clk_get_rate(dev->clk);
    139
    140		return 0;
    141	}
    142
    143	/* Mandatory fallback for proper devicetree backward compatibility */
    144	dev->clk = clk_get(&pdev->dev, NULL);
    145	if (IS_ERR(dev->clk))
    146		return PTR_ERR(dev->clk);
    147
    148	ret = clk_prepare_enable(dev->clk);
    149	if (ret) {
    150		clk_put(dev->clk);
    151		return ret;
    152	}
    153
    154	atomic_io_modify(dev->reg + TIMER_CTRL,
    155			WDT_A370_RATIO_MASK(WDT_A370_RATIO_SHIFT),
    156			WDT_A370_RATIO_MASK(WDT_A370_RATIO_SHIFT));
    157	dev->clk_rate = clk_get_rate(dev->clk) / WDT_A370_RATIO;
    158
    159	return 0;
    160}
    161
    162static int armadaxp_wdt_clock_init(struct platform_device *pdev,
    163				   struct orion_watchdog *dev)
    164{
    165	int ret;
    166	u32 val;
    167
    168	dev->clk = of_clk_get_by_name(pdev->dev.of_node, "fixed");
    169	if (IS_ERR(dev->clk))
    170		return PTR_ERR(dev->clk);
    171	ret = clk_prepare_enable(dev->clk);
    172	if (ret) {
    173		clk_put(dev->clk);
    174		return ret;
    175	}
    176
    177	/* Fix the wdt and timer1 clock frequency to 25MHz */
    178	val = WDT_AXP_FIXED_ENABLE_BIT | TIMER1_FIXED_ENABLE_BIT;
    179	atomic_io_modify(dev->reg + TIMER_CTRL, val, val);
    180
    181	dev->clk_rate = clk_get_rate(dev->clk);
    182	return 0;
    183}
    184
    185static int orion_wdt_ping(struct watchdog_device *wdt_dev)
    186{
    187	struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev);
    188	/* Reload watchdog duration */
    189	writel(dev->clk_rate * wdt_dev->timeout,
    190	       dev->reg + dev->data->wdt_counter_offset);
    191	if (dev->wdt.info->options & WDIOF_PRETIMEOUT)
    192		writel(dev->clk_rate * (wdt_dev->timeout - wdt_dev->pretimeout),
    193		       dev->reg + TIMER1_VAL_OFF);
    194
    195	return 0;
    196}
    197
    198static int armada375_start(struct watchdog_device *wdt_dev)
    199{
    200	struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev);
    201	u32 reg;
    202
    203	/* Set watchdog duration */
    204	writel(dev->clk_rate * wdt_dev->timeout,
    205	       dev->reg + dev->data->wdt_counter_offset);
    206	if (dev->wdt.info->options & WDIOF_PRETIMEOUT)
    207		writel(dev->clk_rate * (wdt_dev->timeout - wdt_dev->pretimeout),
    208		       dev->reg + TIMER1_VAL_OFF);
    209
    210	/* Clear the watchdog expiration bit */
    211	atomic_io_modify(dev->reg + TIMER_A370_STATUS, WDT_A370_EXPIRED, 0);
    212
    213	/* Enable watchdog timer */
    214	reg = dev->data->wdt_enable_bit;
    215	if (dev->wdt.info->options & WDIOF_PRETIMEOUT)
    216		reg |= TIMER1_ENABLE_BIT;
    217	atomic_io_modify(dev->reg + TIMER_CTRL, reg, reg);
    218
    219	/* Enable reset on watchdog */
    220	reg = readl(dev->rstout);
    221	reg |= dev->data->rstout_enable_bit;
    222	writel(reg, dev->rstout);
    223
    224	atomic_io_modify(dev->rstout_mask, dev->data->rstout_mask_bit, 0);
    225	return 0;
    226}
    227
    228static int armada370_start(struct watchdog_device *wdt_dev)
    229{
    230	struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev);
    231	u32 reg;
    232
    233	/* Set watchdog duration */
    234	writel(dev->clk_rate * wdt_dev->timeout,
    235	       dev->reg + dev->data->wdt_counter_offset);
    236
    237	/* Clear the watchdog expiration bit */
    238	atomic_io_modify(dev->reg + TIMER_A370_STATUS, WDT_A370_EXPIRED, 0);
    239
    240	/* Enable watchdog timer */
    241	reg = dev->data->wdt_enable_bit;
    242	if (dev->wdt.info->options & WDIOF_PRETIMEOUT)
    243		reg |= TIMER1_ENABLE_BIT;
    244	atomic_io_modify(dev->reg + TIMER_CTRL, reg, reg);
    245
    246	/* Enable reset on watchdog */
    247	reg = readl(dev->rstout);
    248	reg |= dev->data->rstout_enable_bit;
    249	writel(reg, dev->rstout);
    250	return 0;
    251}
    252
    253static int orion_start(struct watchdog_device *wdt_dev)
    254{
    255	struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev);
    256
    257	/* Set watchdog duration */
    258	writel(dev->clk_rate * wdt_dev->timeout,
    259	       dev->reg + dev->data->wdt_counter_offset);
    260
    261	/* Enable watchdog timer */
    262	atomic_io_modify(dev->reg + TIMER_CTRL, dev->data->wdt_enable_bit,
    263						dev->data->wdt_enable_bit);
    264
    265	/* Enable reset on watchdog */
    266	atomic_io_modify(dev->rstout, dev->data->rstout_enable_bit,
    267				      dev->data->rstout_enable_bit);
    268
    269	return 0;
    270}
    271
    272static int orion_wdt_start(struct watchdog_device *wdt_dev)
    273{
    274	struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev);
    275
    276	/* There are some per-SoC quirks to handle */
    277	return dev->data->start(wdt_dev);
    278}
    279
    280static int orion_stop(struct watchdog_device *wdt_dev)
    281{
    282	struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev);
    283
    284	/* Disable reset on watchdog */
    285	atomic_io_modify(dev->rstout, dev->data->rstout_enable_bit, 0);
    286
    287	/* Disable watchdog timer */
    288	atomic_io_modify(dev->reg + TIMER_CTRL, dev->data->wdt_enable_bit, 0);
    289
    290	return 0;
    291}
    292
    293static int armada375_stop(struct watchdog_device *wdt_dev)
    294{
    295	struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev);
    296	u32 reg, mask;
    297
    298	/* Disable reset on watchdog */
    299	atomic_io_modify(dev->rstout_mask, dev->data->rstout_mask_bit,
    300					   dev->data->rstout_mask_bit);
    301	reg = readl(dev->rstout);
    302	reg &= ~dev->data->rstout_enable_bit;
    303	writel(reg, dev->rstout);
    304
    305	/* Disable watchdog timer */
    306	mask = dev->data->wdt_enable_bit;
    307	if (wdt_dev->info->options & WDIOF_PRETIMEOUT)
    308		mask |= TIMER1_ENABLE_BIT;
    309	atomic_io_modify(dev->reg + TIMER_CTRL, mask, 0);
    310
    311	return 0;
    312}
    313
    314static int armada370_stop(struct watchdog_device *wdt_dev)
    315{
    316	struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev);
    317	u32 reg, mask;
    318
    319	/* Disable reset on watchdog */
    320	reg = readl(dev->rstout);
    321	reg &= ~dev->data->rstout_enable_bit;
    322	writel(reg, dev->rstout);
    323
    324	/* Disable watchdog timer */
    325	mask = dev->data->wdt_enable_bit;
    326	if (wdt_dev->info->options & WDIOF_PRETIMEOUT)
    327		mask |= TIMER1_ENABLE_BIT;
    328	atomic_io_modify(dev->reg + TIMER_CTRL, mask, 0);
    329
    330	return 0;
    331}
    332
    333static int orion_wdt_stop(struct watchdog_device *wdt_dev)
    334{
    335	struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev);
    336
    337	return dev->data->stop(wdt_dev);
    338}
    339
    340static int orion_enabled(struct orion_watchdog *dev)
    341{
    342	bool enabled, running;
    343
    344	enabled = readl(dev->rstout) & dev->data->rstout_enable_bit;
    345	running = readl(dev->reg + TIMER_CTRL) & dev->data->wdt_enable_bit;
    346
    347	return enabled && running;
    348}
    349
    350static int armada375_enabled(struct orion_watchdog *dev)
    351{
    352	bool masked, enabled, running;
    353
    354	masked = readl(dev->rstout_mask) & dev->data->rstout_mask_bit;
    355	enabled = readl(dev->rstout) & dev->data->rstout_enable_bit;
    356	running = readl(dev->reg + TIMER_CTRL) & dev->data->wdt_enable_bit;
    357
    358	return !masked && enabled && running;
    359}
    360
    361static int orion_wdt_enabled(struct watchdog_device *wdt_dev)
    362{
    363	struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev);
    364
    365	return dev->data->enabled(dev);
    366}
    367
    368static unsigned int orion_wdt_get_timeleft(struct watchdog_device *wdt_dev)
    369{
    370	struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev);
    371	return readl(dev->reg + dev->data->wdt_counter_offset) / dev->clk_rate;
    372}
    373
    374static struct watchdog_info orion_wdt_info = {
    375	.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
    376	.identity = "Orion Watchdog",
    377};
    378
    379static const struct watchdog_ops orion_wdt_ops = {
    380	.owner = THIS_MODULE,
    381	.start = orion_wdt_start,
    382	.stop = orion_wdt_stop,
    383	.ping = orion_wdt_ping,
    384	.get_timeleft = orion_wdt_get_timeleft,
    385};
    386
    387static irqreturn_t orion_wdt_irq(int irq, void *devid)
    388{
    389	panic("Watchdog Timeout");
    390	return IRQ_HANDLED;
    391}
    392
    393static irqreturn_t orion_wdt_pre_irq(int irq, void *devid)
    394{
    395	struct orion_watchdog *dev = devid;
    396
    397	atomic_io_modify(dev->reg + TIMER_A370_STATUS,
    398			 TIMER1_STATUS_BIT, 0);
    399	watchdog_notify_pretimeout(&dev->wdt);
    400	return IRQ_HANDLED;
    401}
    402
    403/*
    404 * The original devicetree binding for this driver specified only
    405 * one memory resource, so in order to keep DT backwards compatibility
    406 * we try to fallback to a hardcoded register address, if the resource
    407 * is missing from the devicetree.
    408 */
    409static void __iomem *orion_wdt_ioremap_rstout(struct platform_device *pdev,
    410					      phys_addr_t internal_regs)
    411{
    412	struct resource *res;
    413	phys_addr_t rstout;
    414
    415	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
    416	if (res)
    417		return devm_ioremap(&pdev->dev, res->start,
    418				    resource_size(res));
    419
    420	rstout = internal_regs + ORION_RSTOUT_MASK_OFFSET;
    421
    422	WARN(1, FW_BUG "falling back to hardcoded RSTOUT reg %pa\n", &rstout);
    423	return devm_ioremap(&pdev->dev, rstout, 0x4);
    424}
    425
    426static const struct orion_watchdog_data orion_data = {
    427	.rstout_enable_bit = BIT(1),
    428	.wdt_enable_bit = BIT(4),
    429	.wdt_counter_offset = 0x24,
    430	.clock_init = orion_wdt_clock_init,
    431	.enabled = orion_enabled,
    432	.start = orion_start,
    433	.stop = orion_stop,
    434};
    435
    436static const struct orion_watchdog_data armada370_data = {
    437	.rstout_enable_bit = BIT(8),
    438	.wdt_enable_bit = BIT(8),
    439	.wdt_counter_offset = 0x34,
    440	.clock_init = armada370_wdt_clock_init,
    441	.enabled = orion_enabled,
    442	.start = armada370_start,
    443	.stop = armada370_stop,
    444};
    445
    446static const struct orion_watchdog_data armadaxp_data = {
    447	.rstout_enable_bit = BIT(8),
    448	.wdt_enable_bit = BIT(8),
    449	.wdt_counter_offset = 0x34,
    450	.clock_init = armadaxp_wdt_clock_init,
    451	.enabled = orion_enabled,
    452	.start = armada370_start,
    453	.stop = armada370_stop,
    454};
    455
    456static const struct orion_watchdog_data armada375_data = {
    457	.rstout_enable_bit = BIT(8),
    458	.rstout_mask_bit = BIT(10),
    459	.wdt_enable_bit = BIT(8),
    460	.wdt_counter_offset = 0x34,
    461	.clock_init = armada375_wdt_clock_init,
    462	.enabled = armada375_enabled,
    463	.start = armada375_start,
    464	.stop = armada375_stop,
    465};
    466
    467static const struct orion_watchdog_data armada380_data = {
    468	.rstout_enable_bit = BIT(8),
    469	.rstout_mask_bit = BIT(10),
    470	.wdt_enable_bit = BIT(8),
    471	.wdt_counter_offset = 0x34,
    472	.clock_init = armadaxp_wdt_clock_init,
    473	.enabled = armada375_enabled,
    474	.start = armada375_start,
    475	.stop = armada375_stop,
    476};
    477
    478static const struct of_device_id orion_wdt_of_match_table[] = {
    479	{
    480		.compatible = "marvell,orion-wdt",
    481		.data = &orion_data,
    482	},
    483	{
    484		.compatible = "marvell,armada-370-wdt",
    485		.data = &armada370_data,
    486	},
    487	{
    488		.compatible = "marvell,armada-xp-wdt",
    489		.data = &armadaxp_data,
    490	},
    491	{
    492		.compatible = "marvell,armada-375-wdt",
    493		.data = &armada375_data,
    494	},
    495	{
    496		.compatible = "marvell,armada-380-wdt",
    497		.data = &armada380_data,
    498	},
    499	{},
    500};
    501MODULE_DEVICE_TABLE(of, orion_wdt_of_match_table);
    502
    503static int orion_wdt_get_regs(struct platform_device *pdev,
    504			      struct orion_watchdog *dev)
    505{
    506	struct device_node *node = pdev->dev.of_node;
    507	struct resource *res;
    508
    509	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
    510	if (!res)
    511		return -ENODEV;
    512	dev->reg = devm_ioremap(&pdev->dev, res->start,
    513				resource_size(res));
    514	if (!dev->reg)
    515		return -ENOMEM;
    516
    517	/* Each supported compatible has some RSTOUT register quirk */
    518	if (of_device_is_compatible(node, "marvell,orion-wdt")) {
    519
    520		dev->rstout = orion_wdt_ioremap_rstout(pdev, res->start &
    521						       INTERNAL_REGS_MASK);
    522		if (!dev->rstout)
    523			return -ENODEV;
    524
    525	} else if (of_device_is_compatible(node, "marvell,armada-370-wdt") ||
    526		   of_device_is_compatible(node, "marvell,armada-xp-wdt")) {
    527
    528		/* Dedicated RSTOUT register, can be requested. */
    529		dev->rstout = devm_platform_ioremap_resource(pdev, 1);
    530		if (IS_ERR(dev->rstout))
    531			return PTR_ERR(dev->rstout);
    532
    533	} else if (of_device_is_compatible(node, "marvell,armada-375-wdt") ||
    534		   of_device_is_compatible(node, "marvell,armada-380-wdt")) {
    535
    536		/* Dedicated RSTOUT register, can be requested. */
    537		dev->rstout = devm_platform_ioremap_resource(pdev, 1);
    538		if (IS_ERR(dev->rstout))
    539			return PTR_ERR(dev->rstout);
    540
    541		res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
    542		if (!res)
    543			return -ENODEV;
    544		dev->rstout_mask = devm_ioremap(&pdev->dev, res->start,
    545						resource_size(res));
    546		if (!dev->rstout_mask)
    547			return -ENOMEM;
    548
    549	} else {
    550		return -ENODEV;
    551	}
    552
    553	return 0;
    554}
    555
    556static int orion_wdt_probe(struct platform_device *pdev)
    557{
    558	struct orion_watchdog *dev;
    559	const struct of_device_id *match;
    560	unsigned int wdt_max_duration;	/* (seconds) */
    561	int ret, irq;
    562
    563	dev = devm_kzalloc(&pdev->dev, sizeof(struct orion_watchdog),
    564			   GFP_KERNEL);
    565	if (!dev)
    566		return -ENOMEM;
    567
    568	match = of_match_device(orion_wdt_of_match_table, &pdev->dev);
    569	if (!match)
    570		/* Default legacy match */
    571		match = &orion_wdt_of_match_table[0];
    572
    573	dev->wdt.info = &orion_wdt_info;
    574	dev->wdt.ops = &orion_wdt_ops;
    575	dev->wdt.min_timeout = 1;
    576	dev->data = match->data;
    577
    578	ret = orion_wdt_get_regs(pdev, dev);
    579	if (ret)
    580		return ret;
    581
    582	ret = dev->data->clock_init(pdev, dev);
    583	if (ret) {
    584		dev_err(&pdev->dev, "cannot initialize clock\n");
    585		return ret;
    586	}
    587
    588	wdt_max_duration = WDT_MAX_CYCLE_COUNT / dev->clk_rate;
    589
    590	dev->wdt.timeout = wdt_max_duration;
    591	dev->wdt.max_timeout = wdt_max_duration;
    592	dev->wdt.parent = &pdev->dev;
    593	watchdog_init_timeout(&dev->wdt, heartbeat, &pdev->dev);
    594
    595	platform_set_drvdata(pdev, &dev->wdt);
    596	watchdog_set_drvdata(&dev->wdt, dev);
    597
    598	/*
    599	 * Let's make sure the watchdog is fully stopped, unless it's
    600	 * explicitly enabled. This may be the case if the module was
    601	 * removed and re-inserted, or if the bootloader explicitly
    602	 * set a running watchdog before booting the kernel.
    603	 */
    604	if (!orion_wdt_enabled(&dev->wdt))
    605		orion_wdt_stop(&dev->wdt);
    606	else
    607		set_bit(WDOG_HW_RUNNING, &dev->wdt.status);
    608
    609	/* Request the IRQ only after the watchdog is disabled */
    610	irq = platform_get_irq_optional(pdev, 0);
    611	if (irq > 0) {
    612		/*
    613		 * Not all supported platforms specify an interrupt for the
    614		 * watchdog, so let's make it optional.
    615		 */
    616		ret = devm_request_irq(&pdev->dev, irq, orion_wdt_irq, 0,
    617				       pdev->name, dev);
    618		if (ret < 0) {
    619			dev_err(&pdev->dev, "failed to request IRQ\n");
    620			goto disable_clk;
    621		}
    622	}
    623
    624	/* Optional 2nd interrupt for pretimeout */
    625	irq = platform_get_irq_optional(pdev, 1);
    626	if (irq > 0) {
    627		orion_wdt_info.options |= WDIOF_PRETIMEOUT;
    628		ret = devm_request_irq(&pdev->dev, irq, orion_wdt_pre_irq,
    629				       0, pdev->name, dev);
    630		if (ret < 0) {
    631			dev_err(&pdev->dev, "failed to request IRQ\n");
    632			goto disable_clk;
    633		}
    634	}
    635
    636
    637	watchdog_set_nowayout(&dev->wdt, nowayout);
    638	ret = watchdog_register_device(&dev->wdt);
    639	if (ret)
    640		goto disable_clk;
    641
    642	pr_info("Initial timeout %d sec%s\n",
    643		dev->wdt.timeout, nowayout ? ", nowayout" : "");
    644	return 0;
    645
    646disable_clk:
    647	clk_disable_unprepare(dev->clk);
    648	clk_put(dev->clk);
    649	return ret;
    650}
    651
    652static int orion_wdt_remove(struct platform_device *pdev)
    653{
    654	struct watchdog_device *wdt_dev = platform_get_drvdata(pdev);
    655	struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev);
    656
    657	watchdog_unregister_device(wdt_dev);
    658	clk_disable_unprepare(dev->clk);
    659	clk_put(dev->clk);
    660	return 0;
    661}
    662
    663static void orion_wdt_shutdown(struct platform_device *pdev)
    664{
    665	struct watchdog_device *wdt_dev = platform_get_drvdata(pdev);
    666	orion_wdt_stop(wdt_dev);
    667}
    668
    669static struct platform_driver orion_wdt_driver = {
    670	.probe		= orion_wdt_probe,
    671	.remove		= orion_wdt_remove,
    672	.shutdown	= orion_wdt_shutdown,
    673	.driver		= {
    674		.name	= "orion_wdt",
    675		.of_match_table = orion_wdt_of_match_table,
    676	},
    677};
    678
    679module_platform_driver(orion_wdt_driver);
    680
    681MODULE_AUTHOR("Sylver Bruneau <sylver.bruneau@googlemail.com>");
    682MODULE_DESCRIPTION("Orion Processor Watchdog");
    683
    684module_param(heartbeat, int, 0);
    685MODULE_PARM_DESC(heartbeat, "Initial watchdog heartbeat in seconds");
    686
    687module_param(nowayout, bool, 0);
    688MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
    689				__MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
    690
    691MODULE_LICENSE("GPL v2");
    692MODULE_ALIAS("platform:orion_wdt");