| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177 | 
							- /*
 
-  * drivers/watchdog/orion_wdt.c
 
-  *
 
-  * Watchdog driver for Orion/Kirkwood processors
 
-  *
 
-  * Authors:	Tomas Hlavacek <tmshlvck@gmail.com>
 
-  * 		Sylver Bruneau <sylver.bruneau@googlemail.com>
 
-  * 		Marek Behun <marek.behun@nic.cz>
 
-  *
 
-  * This file is licensed under  the terms of the GNU General Public
 
-  * License version 2. This program is licensed "as is" without any
 
-  * warranty of any kind, whether express or implied.
 
-  */
 
- #include <common.h>
 
- #include <dm.h>
 
- #include <wdt.h>
 
- #include <asm/io.h>
 
- #include <asm/arch/cpu.h>
 
- #include <asm/arch/soc.h>
 
- DECLARE_GLOBAL_DATA_PTR;
 
- struct orion_wdt_priv {
 
- 	void __iomem *reg;
 
- 	int wdt_counter_offset;
 
- 	void __iomem *rstout;
 
- 	void __iomem *rstout_mask;
 
- 	u32 timeout;
 
- };
 
- #define RSTOUT_ENABLE_BIT		BIT(8)
 
- #define RSTOUT_MASK_BIT			BIT(10)
 
- #define WDT_ENABLE_BIT			BIT(8)
 
- #define TIMER_CTRL			0x0000
 
- #define TIMER_A370_STATUS		0x04
 
- #define WDT_AXP_FIXED_ENABLE_BIT	BIT(10)
 
- #define WDT_A370_EXPIRED		BIT(31)
 
- static int orion_wdt_reset(struct udevice *dev)
 
- {
 
- 	struct orion_wdt_priv *priv = dev_get_priv(dev);
 
- 	/* Reload watchdog duration */
 
- 	writel(priv->timeout, priv->reg + priv->wdt_counter_offset);
 
- 	return 0;
 
- }
 
- static int orion_wdt_start(struct udevice *dev, u64 timeout, ulong flags)
 
- {
 
- 	struct orion_wdt_priv *priv = dev_get_priv(dev);
 
- 	u32 reg;
 
- 	priv->timeout = (u32) timeout;
 
- 	/* Enable the fixed watchdog clock input */
 
- 	reg = readl(priv->reg + TIMER_CTRL);
 
- 	reg |= WDT_AXP_FIXED_ENABLE_BIT;
 
- 	writel(reg, priv->reg + TIMER_CTRL);
 
- 	/* Set watchdog duration */
 
- 	writel(priv->timeout, priv->reg + priv->wdt_counter_offset);
 
- 	/* Clear the watchdog expiration bit */
 
- 	reg = readl(priv->reg + TIMER_A370_STATUS);
 
- 	reg &= ~WDT_A370_EXPIRED;
 
- 	writel(reg, priv->reg + TIMER_A370_STATUS);
 
- 	/* Enable watchdog timer */
 
- 	reg = readl(priv->reg + TIMER_CTRL);
 
- 	reg |= WDT_ENABLE_BIT;
 
- 	writel(reg, priv->reg + TIMER_CTRL);
 
- 	/* Enable reset on watchdog */
 
- 	reg = readl(priv->rstout);
 
- 	reg |= RSTOUT_ENABLE_BIT;
 
- 	writel(reg, priv->rstout);
 
- 	reg = readl(priv->rstout_mask);
 
- 	reg &= ~RSTOUT_MASK_BIT;
 
- 	writel(reg, priv->rstout_mask);
 
- 	return 0;
 
- }
 
- static int orion_wdt_stop(struct udevice *dev)
 
- {
 
- 	struct orion_wdt_priv *priv = dev_get_priv(dev);
 
- 	u32 reg;
 
- 	/* Disable reset on watchdog */
 
- 	reg = readl(priv->rstout_mask);
 
- 	reg |= RSTOUT_MASK_BIT;
 
- 	writel(reg, priv->rstout_mask);
 
- 	reg = readl(priv->rstout);
 
- 	reg &= ~RSTOUT_ENABLE_BIT;
 
- 	writel(reg, priv->rstout);
 
- 	/* Disable watchdog timer */
 
- 	reg = readl(priv->reg + TIMER_CTRL);
 
- 	reg &= ~WDT_ENABLE_BIT;
 
- 	writel(reg, priv->reg + TIMER_CTRL);
 
- 	return 0;
 
- }
 
- static inline bool save_reg_from_ofdata(struct udevice *dev, int index,
 
- 					void __iomem **reg, int *offset)
 
- {
 
- 	fdt_addr_t addr;
 
- 	fdt_size_t off;
 
- 	addr = fdtdec_get_addr_size_auto_noparent(
 
- 		gd->fdt_blob, dev_of_offset(dev), "reg", index, &off, true);
 
- 	if (addr == FDT_ADDR_T_NONE)
 
- 		return false;
 
- 	*reg = (void __iomem *) addr;
 
- 	if (offset)
 
- 		*offset = off;
 
- 	return true;
 
- }
 
- static int orion_wdt_ofdata_to_platdata(struct udevice *dev)
 
- {
 
- 	struct orion_wdt_priv *priv = dev_get_priv(dev);
 
- 	if (!save_reg_from_ofdata(dev, 0, &priv->reg,
 
- 				  &priv->wdt_counter_offset))
 
- 		goto err;
 
- 	if (!save_reg_from_ofdata(dev, 1, &priv->rstout, NULL))
 
- 		goto err;
 
- 	if (!save_reg_from_ofdata(dev, 2, &priv->rstout_mask, NULL))
 
- 		goto err;
 
- 	return 0;
 
- err:
 
- 	debug("%s: Could not determine Orion wdt IO addresses\n", __func__);
 
- 	return -ENXIO;
 
- }
 
- static int orion_wdt_probe(struct udevice *dev)
 
- {
 
- 	debug("%s: Probing wdt%u\n", __func__, dev->seq);
 
- 	orion_wdt_stop(dev);
 
- 	return 0;
 
- }
 
- static const struct wdt_ops orion_wdt_ops = {
 
- 	.start = orion_wdt_start,
 
- 	.reset = orion_wdt_reset,
 
- 	.stop = orion_wdt_stop,
 
- };
 
- static const struct udevice_id orion_wdt_ids[] = {
 
- 	{ .compatible = "marvell,armada-380-wdt" },
 
- 	{}
 
- };
 
- U_BOOT_DRIVER(orion_wdt) = {
 
- 	.name = "orion_wdt",
 
- 	.id = UCLASS_WDT,
 
- 	.of_match = orion_wdt_ids,
 
- 	.probe = orion_wdt_probe,
 
- 	.priv_auto_alloc_size = sizeof(struct orion_wdt_priv),
 
- 	.ofdata_to_platdata = orion_wdt_ofdata_to_platdata,
 
- 	.ops = &orion_wdt_ops,
 
- };
 
 
  |