Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Pull watchdog updates from Wim Van Sebroeck:

 - add support for the watchdog on Meson8 and Meson8m2

 - add support for MediaTek MT7623 and MT7622 SoC

 - add support for the r8a77995 wdt

 - explicitly request exclusive reset control for asm9260_wdt,
   zx2967_wdt, rt2880_wdt and mt7621_wdt

 - improvements to asm9260_wdt, aspeed_wdt, renesas_wdt and cadence_wdt

 - add support for reading freq via CCF + suspend/resume support for
   of_xilinx_wdt

 - constify watchdog_ops and various device-id structures

 - revert of commit 1fccb73 ("iTCO_wdt: all versions count down
   twice") (Bug 196509)

* git://www.linux-watchdog.org/linux-watchdog: (40 commits)
  watchdog: mei_wdt: constify mei_cl_device_id
  watchdog: sp805: constify amba_id
  watchdog: ziirave: constify i2c_device_id
  watchdog: sc1200: constify pnp_device_id
  dt-bindings: watchdog: renesas-wdt: Add support for the r8a77995 wdt
  watchdog: renesas_wdt: update copyright dates
  watchdog: renesas_wdt: make 'clk' a variable local to probe()
  watchdog: renesas_wdt: consistently use RuntimePM for clock management
  watchdog: aspeed: Support configuration of external signal properties
  dt-bindings: watchdog: aspeed: External reset signal properties
  drivers/watchdog: Add optional ASPEED device tree properties
  drivers/watchdog: ASPEED reference dev tree properties for config
  watchdog: da9063_wdt: Simplify by removing unneeded struct...
  watchdog: bcm7038: Check the return value from clk_prepare_enable()
  watchdog: qcom: Check for platform_get_resource() failure
  watchdog: of_xilinx_wdt: Add suspend/resume support
  watchdog: of_xilinx_wdt: Add support for reading freq via CCF
  dt-bindings: watchdog: mediatek: add support for MediaTek MT7623 and MT7622 SoC
  watchdog: max77620_wdt: constify platform_device_id
  watchdog: pcwd_usb: constify usb_device_id
  ...
  • Loading branch information
torvalds committed Sep 14, 2017
2 parents e75f801 + 4cb30b0 commit 939ae58
Show file tree
Hide file tree
Showing 30 changed files with 363 additions and 124 deletions.
40 changes: 40 additions & 0 deletions Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,49 @@ Required properties:
- reg: physical base address of the controller and length of memory mapped
region

Optional properties:

- aspeed,reset-type = "cpu|soc|system|none"

Reset behavior - Whenever a timeout occurs the watchdog can be programmed
to generate one of three different, mutually exclusive, types of resets.

Type "none" can be specified to indicate that no resets are to be done.
This is useful in situations where another watchdog engine on chip is
to perform the reset.

If 'aspeed,reset-type=' is not specfied the default is to enable system
reset.

Reset types:

- cpu: Reset CPU on watchdog timeout

- soc: Reset 'System on Chip' on watchdog timeout

- system: Reset system on watchdog timeout

- none: No reset is performed on timeout. Assumes another watchdog
engine is responsible for this.

- aspeed,alt-boot: If property is present then boot from alternate block.
- aspeed,external-signal: If property is present then signal is sent to
external reset counter (only WDT1 and WDT2). If not
specified no external signal is sent.
- aspeed,ext-pulse-duration: External signal pulse duration in microseconds

Optional properties for AST2500-compatible watchdogs:
- aspeed,ext-push-pull: If aspeed,external-signal is present, set the pin's
drive type to push-pull. The default is open-drain.
- aspeed,ext-active-high: If aspeed,external-signal is present and and the pin
is configured as push-pull, then set the pulse
polarity to active-high. The default is active-low.

Example:

wdt1: watchdog@1e785000 {
compatible = "aspeed,ast2400-wdt";
reg = <0x1e785000 0x1c>;
aspeed,reset-type = "system";
aspeed,external-signal;
};
6 changes: 5 additions & 1 deletion Documentation/devicetree/bindings/watchdog/meson-wdt.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ Meson SoCs Watchdog timer

Required properties:

- compatible : should be "amlogic,meson6-wdt" or "amlogic,meson8b-wdt"
- compatible : depending on the SoC this should be one of:
"amlogic,meson6-wdt" on Meson6 SoCs
"amlogic,meson8-wdt" and "amlogic,meson6-wdt" on Meson8 SoCs
"amlogic,meson8b-wdt" on Meson8b SoCs
"amlogic,meson8m2-wdt" and "amlogic,meson8b-wdt" on Meson8m2 SoCs
- reg : Specifies base physical address and size of the registers.

Example:
Expand Down
2 changes: 2 additions & 0 deletions Documentation/devicetree/bindings/watchdog/mtk-wdt.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ Required properties:
"mediatek,mt2701-wdt", "mediatek,mt6589-wdt": for MT2701
"mediatek,mt6589-wdt": for MT6589
"mediatek,mt6797-wdt", "mediatek,mt6589-wdt": for MT6797
"mediatek,mt7622-wdt", "mediatek,mt6589-wdt": for MT7622
"mediatek,mt7623-wdt", "mediatek,mt6589-wdt": for MT7623

- reg : Specifies base physical address and size of the registers.

Expand Down
1 change: 1 addition & 0 deletions Documentation/devicetree/bindings/watchdog/renesas-wdt.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Required properties:
Examples with soctypes are:
- "renesas,r8a7795-wdt" (R-Car H3)
- "renesas,r8a7796-wdt" (R-Car M3-W)
- "renesas,r8a77995-wdt" (R-Car D3)
- "renesas,r7s72100-wdt" (RZ/A1)

When compatible with the generic version, nodes must list the SoC-specific
Expand Down
2 changes: 1 addition & 1 deletion Documentation/watchdog/watchdog-parameters.txt
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ nowayout: Watchdog cannot be stopped once started
-------------------------------------------------
iTCO_wdt:
heartbeat: Watchdog heartbeat in seconds.
(5<=heartbeat<=74 (TCO v1) or 1226 (TCO v2), default=30)
(2<heartbeat<39 (TCO v1) or 613 (TCO v2), default=30)
nowayout: Watchdog cannot be stopped once started
(default=kernel config parameter)
-------------------------------------------------
Expand Down
4 changes: 2 additions & 2 deletions drivers/watchdog/asm9260_wdt.c
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ static unsigned int asm9260_wdt_gettimeleft(struct watchdog_device *wdd)

counter = ioread32(priv->iobase + HW_WDTV);

return DIV_ROUND_CLOSEST(counter, priv->wdt_freq);
return counter / priv->wdt_freq;
}

static int asm9260_wdt_updatetimeout(struct watchdog_device *wdd)
Expand Down Expand Up @@ -296,7 +296,7 @@ static int asm9260_wdt_probe(struct platform_device *pdev)
if (ret)
return ret;

priv->rst = devm_reset_control_get(&pdev->dev, "wdt_rst");
priv->rst = devm_reset_control_get_exclusive(&pdev->dev, "wdt_rst");
if (IS_ERR(priv->rst))
return PTR_ERR(priv->rst);

Expand Down
132 changes: 125 additions & 7 deletions drivers/watchdog/aspeed_wdt.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,21 @@ struct aspeed_wdt {
u32 ctrl;
};

struct aspeed_wdt_config {
u32 ext_pulse_width_mask;
};

static const struct aspeed_wdt_config ast2400_config = {
.ext_pulse_width_mask = 0xff,
};

static const struct aspeed_wdt_config ast2500_config = {
.ext_pulse_width_mask = 0xfffff,
};

static const struct of_device_id aspeed_wdt_of_table[] = {
{ .compatible = "aspeed,ast2400-wdt" },
{ .compatible = "aspeed,ast2500-wdt" },
{ .compatible = "aspeed,ast2400-wdt", .data = &ast2400_config },
{ .compatible = "aspeed,ast2500-wdt", .data = &ast2500_config },
{ },
};
MODULE_DEVICE_TABLE(of, aspeed_wdt_of_table);
Expand All @@ -36,12 +48,45 @@ MODULE_DEVICE_TABLE(of, aspeed_wdt_of_table);
#define WDT_CTRL 0x0C
#define WDT_CTRL_RESET_MODE_SOC (0x00 << 5)
#define WDT_CTRL_RESET_MODE_FULL_CHIP (0x01 << 5)
#define WDT_CTRL_RESET_MODE_ARM_CPU (0x10 << 5)
#define WDT_CTRL_1MHZ_CLK BIT(4)
#define WDT_CTRL_WDT_EXT BIT(3)
#define WDT_CTRL_WDT_INTR BIT(2)
#define WDT_CTRL_RESET_SYSTEM BIT(1)
#define WDT_CTRL_ENABLE BIT(0)

/*
* WDT_RESET_WIDTH controls the characteristics of the external pulse (if
* enabled), specifically:
*
* * Pulse duration
* * Drive mode: push-pull vs open-drain
* * Polarity: Active high or active low
*
* Pulse duration configuration is available on both the AST2400 and AST2500,
* though the field changes between SoCs:
*
* AST2400: Bits 7:0
* AST2500: Bits 19:0
*
* This difference is captured in struct aspeed_wdt_config.
*
* The AST2500 exposes the drive mode and polarity options, but not in a
* regular fashion. For read purposes, bit 31 represents active high or low,
* and bit 30 represents push-pull or open-drain. With respect to write, magic
* values need to be written to the top byte to change the state of the drive
* mode and polarity bits. Any other value written to the top byte has no
* effect on the state of the drive mode or polarity bits. However, the pulse
* width value must be preserved (as desired) if written.
*/
#define WDT_RESET_WIDTH 0x18
#define WDT_RESET_WIDTH_ACTIVE_HIGH BIT(31)
#define WDT_ACTIVE_HIGH_MAGIC (0xA5 << 24)
#define WDT_ACTIVE_LOW_MAGIC (0x5A << 24)
#define WDT_RESET_WIDTH_PUSH_PULL BIT(30)
#define WDT_PUSH_PULL_MAGIC (0xA8 << 24)
#define WDT_OPEN_DRAIN_MAGIC (0x8A << 24)

#define WDT_RESTART_MAGIC 0x4755

/* 32 bits at 1MHz, in milliseconds */
Expand Down Expand Up @@ -138,8 +183,13 @@ static const struct watchdog_info aspeed_wdt_info = {

static int aspeed_wdt_probe(struct platform_device *pdev)
{
const struct aspeed_wdt_config *config;
const struct of_device_id *ofdid;
struct aspeed_wdt *wdt;
struct resource *res;
struct device_node *np;
const char *reset_type;
u32 duration;
int ret;

wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL);
Expand All @@ -164,20 +214,88 @@ static int aspeed_wdt_probe(struct platform_device *pdev)
wdt->wdd.timeout = WDT_DEFAULT_TIMEOUT;
watchdog_init_timeout(&wdt->wdd, 0, &pdev->dev);

np = pdev->dev.of_node;

ofdid = of_match_node(aspeed_wdt_of_table, np);
if (!ofdid)
return -EINVAL;
config = ofdid->data;

wdt->ctrl = WDT_CTRL_1MHZ_CLK;

/*
* Control reset on a per-device basis to ensure the
* host is not affected by a BMC reboot, so only reset
* the SOC and not the full chip
* host is not affected by a BMC reboot
*/
wdt->ctrl = WDT_CTRL_RESET_MODE_SOC |
WDT_CTRL_1MHZ_CLK |
WDT_CTRL_RESET_SYSTEM;
ret = of_property_read_string(np, "aspeed,reset-type", &reset_type);
if (ret) {
wdt->ctrl |= WDT_CTRL_RESET_MODE_SOC | WDT_CTRL_RESET_SYSTEM;
} else {
if (!strcmp(reset_type, "cpu"))
wdt->ctrl |= WDT_CTRL_RESET_MODE_ARM_CPU;
else if (!strcmp(reset_type, "soc"))
wdt->ctrl |= WDT_CTRL_RESET_MODE_SOC;
else if (!strcmp(reset_type, "system"))
wdt->ctrl |= WDT_CTRL_RESET_SYSTEM;
else if (strcmp(reset_type, "none"))
return -EINVAL;
}
if (of_property_read_bool(np, "aspeed,external-signal"))
wdt->ctrl |= WDT_CTRL_WDT_EXT;

writel(wdt->ctrl, wdt->base + WDT_CTRL);

if (readl(wdt->base + WDT_CTRL) & WDT_CTRL_ENABLE) {
aspeed_wdt_start(&wdt->wdd);
set_bit(WDOG_HW_RUNNING, &wdt->wdd.status);
}

if (of_device_is_compatible(np, "aspeed,ast2500-wdt")) {
u32 reg = readl(wdt->base + WDT_RESET_WIDTH);

reg &= config->ext_pulse_width_mask;
if (of_property_read_bool(np, "aspeed,ext-push-pull"))
reg |= WDT_PUSH_PULL_MAGIC;
else
reg |= WDT_OPEN_DRAIN_MAGIC;

writel(reg, wdt->base + WDT_RESET_WIDTH);

reg &= config->ext_pulse_width_mask;
if (of_property_read_bool(np, "aspeed,ext-active-high"))
reg |= WDT_ACTIVE_HIGH_MAGIC;
else
reg |= WDT_ACTIVE_LOW_MAGIC;

writel(reg, wdt->base + WDT_RESET_WIDTH);
}

if (!of_property_read_u32(np, "aspeed,ext-pulse-duration", &duration)) {
u32 max_duration = config->ext_pulse_width_mask + 1;

if (duration == 0 || duration > max_duration) {
dev_err(&pdev->dev, "Invalid pulse duration: %uus\n",
duration);
duration = max(1U, min(max_duration, duration));
dev_info(&pdev->dev, "Pulse duration set to %uus\n",
duration);
}

/*
* The watchdog is always configured with a 1MHz source, so
* there is no need to scale the microsecond value. However we
* need to offset it - from the datasheet:
*
* "This register decides the asserting duration of wdt_ext and
* wdt_rstarm signal. The default value is 0xFF. It means the
* default asserting duration of wdt_ext and wdt_rstarm is
* 256us."
*
* This implies a value of 0 gives a 1us pulse.
*/
writel(duration - 1, wdt->base + WDT_RESET_WIDTH);
}

ret = devm_watchdog_register_device(&pdev->dev, &wdt->wdd);
if (ret) {
dev_err(&pdev->dev, "failed to register\n");
Expand Down
4 changes: 3 additions & 1 deletion drivers/watchdog/bcm7038_wdt.c
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,9 @@ static int bcm7038_wdt_probe(struct platform_device *pdev)
wdt->clk = devm_clk_get(dev, NULL);
/* If unable to get clock, use default frequency */
if (!IS_ERR(wdt->clk)) {
clk_prepare_enable(wdt->clk);
err = clk_prepare_enable(wdt->clk);
if (err)
return err;
wdt->rate = clk_get_rate(wdt->clk);
/* Prevent divide-by-zero exception */
if (!wdt->rate)
Expand Down
6 changes: 3 additions & 3 deletions drivers/watchdog/cadence_wdt.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,12 @@
static int wdt_timeout;
static int nowayout = WATCHDOG_NOWAYOUT;

module_param(wdt_timeout, int, 0);
module_param(wdt_timeout, int, 0644);
MODULE_PARM_DESC(wdt_timeout,
"Watchdog time in seconds. (default="
__MODULE_STRING(CDNS_WDT_DEFAULT_TIMEOUT) ")");

module_param(nowayout, int, 0);
module_param(nowayout, int, 0644);
MODULE_PARM_DESC(nowayout,
"Watchdog cannot be stopped once started (default="
__MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
Expand Down Expand Up @@ -368,7 +368,7 @@ static int cdns_wdt_probe(struct platform_device *pdev)
}
platform_set_drvdata(pdev, wdt);

dev_dbg(&pdev->dev, "Xilinx Watchdog Timer at %p with timeout %ds%s\n",
dev_info(&pdev->dev, "Xilinx Watchdog Timer at %p with timeout %ds%s\n",
wdt->regs, cdns_wdt_device->timeout,
nowayout ? ", nowayout" : "");

Expand Down
2 changes: 1 addition & 1 deletion drivers/watchdog/coh901327_wdt.c
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ static const struct watchdog_info coh901327_ident = {
.identity = DRV_NAME,
};

static struct watchdog_ops coh901327_ops = {
static const struct watchdog_ops coh901327_ops = {
.owner = THIS_MODULE,
.start = coh901327_start,
.stop = coh901327_stop,
Expand Down
Loading

0 comments on commit 939ae58

Please sign in to comment.