blob: 036ff690d3fd49e5d5d48d70bb839877db47969b [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Christophe Leroy89067642018-03-16 17:21:01 +01002/*
3 * Copyright 2017 CS Systemes d'Information
Christophe Leroy89067642018-03-16 17:21:01 +01004 */
5
Charles Frey3b446282020-02-19 16:50:15 +00006#include <env.h>
Christophe Leroy40159302018-11-21 08:51:45 +00007#include <dm.h>
8#include <wdt.h>
Christophe Leroy0fe1a202023-04-03 10:27:39 +02009#include <clock_legacy.h>
Christophe Leroy89067642018-03-16 17:21:01 +010010#include <asm/io.h>
11
Christophe Leroy0fe1a202023-04-03 10:27:39 +020012struct mpc8xxx_wdt {
13 __be32 res0;
14 __be32 swcrr; /* System watchdog control register */
15#define SWCRR_SWTC 0xFFFF0000 /* Software Watchdog Time Count. */
16#define SWCRR_BME 0x00000080 /* Bus monitor enable (mpc8xx) */
17#define SWCRR_SWF 0x00000008 /* Software Watchdog Freeze (mpc8xx). */
18#define SWCRR_SWEN 0x00000004 /* Watchdog Enable bit. */
19#define SWCRR_SWRI 0x00000002 /* Software Watchdog Reset/Interrupt Select bit.*/
20#define SWCRR_SWPR 0x00000001 /* Software Watchdog Counter Prescale bit. */
21 __be32 swcnr; /* System watchdog count register */
22 u8 res1[2];
23 __be16 swsrr; /* System watchdog service register */
24 u8 res2[0xf0];
25};
26
27struct mpc8xxx_wdt_priv {
28 struct mpc8xxx_wdt __iomem *base;
29};
30
31static int mpc8xxx_wdt_reset(struct udevice *dev)
Christophe Leroy89067642018-03-16 17:21:01 +010032{
Christophe Leroy0fe1a202023-04-03 10:27:39 +020033 struct mpc8xxx_wdt_priv *priv = dev_get_priv(dev);
34
35 out_be16(&priv->base->swsrr, 0x556c); /* write magic1 */
36 out_be16(&priv->base->swsrr, 0xaa39); /* write magic2 */
Christophe Leroy89067642018-03-16 17:21:01 +010037
Christophe Leroy0fe1a202023-04-03 10:27:39 +020038 return 0;
Christophe Leroy89067642018-03-16 17:21:01 +010039}
40
Christophe Leroy1919fce2023-04-03 10:27:39 +020041static int mpc8xxx_wdt_start(struct udevice *dev, u64 timeout, ulong flags)
Christophe Leroy40159302018-11-21 08:51:45 +000042{
Christophe Leroy0fe1a202023-04-03 10:27:39 +020043 struct mpc8xxx_wdt_priv *priv = dev_get_priv(dev);
Charles Frey3b446282020-02-19 16:50:15 +000044 const char *mode = env_get("watchdog_mode");
Christophe Leroy0fe1a202023-04-03 10:27:39 +020045 ulong prescaler = dev_get_driver_data(dev);
46 u16 swtc = min_t(u16, timeout * get_board_sys_clk() / 1000 / prescaler, U16_MAX);
47 u32 val;
48
49 mpc8xxx_wdt_reset(dev);
Charles Frey3b446282020-02-19 16:50:15 +000050
51 if (strcmp(mode, "off") == 0)
Christophe Leroy0fe1a202023-04-03 10:27:39 +020052 val = (swtc << 16) | SWCRR_SWPR;
Charles Frey3b446282020-02-19 16:50:15 +000053 else if (strcmp(mode, "nmi") == 0)
Christophe Leroy0fe1a202023-04-03 10:27:39 +020054 val = (swtc << 16) | SWCRR_SWPR | SWCRR_SWEN;
55 else
56 val = (swtc << 16) | SWCRR_SWPR | SWCRR_SWEN | SWCRR_SWRI;
57
58 if (IS_ENABLED(CONFIG_WDT_MPC8xxx_BME))
59 val |= (CONFIG_WDT_MPC8xxx_BMT << 8) | SWCRR_BME;
Christophe Leroy40159302018-11-21 08:51:45 +000060
Christophe Leroy0fe1a202023-04-03 10:27:39 +020061 out_be32(&priv->base->swcrr, val);
Christophe Leroy40159302018-11-21 08:51:45 +000062
Christophe Leroy0fe1a202023-04-03 10:27:39 +020063 if (!(in_be32(&priv->base->swcrr) & SWCRR_SWEN))
Christophe Leroy40159302018-11-21 08:51:45 +000064 return -EBUSY;
65 return 0;
66
67}
68
Christophe Leroy1919fce2023-04-03 10:27:39 +020069static int mpc8xxx_wdt_stop(struct udevice *dev)
Christophe Leroy40159302018-11-21 08:51:45 +000070{
Christophe Leroy0fe1a202023-04-03 10:27:39 +020071 struct mpc8xxx_wdt_priv *priv = dev_get_priv(dev);
Christophe Leroy40159302018-11-21 08:51:45 +000072
Christophe Leroy0fe1a202023-04-03 10:27:39 +020073 clrbits_be32(&priv->base->swcrr, SWCRR_SWEN);
Christophe Leroy40159302018-11-21 08:51:45 +000074
Christophe Leroy0fe1a202023-04-03 10:27:39 +020075 if (in_be32(&priv->base->swcrr) & SWCRR_SWEN)
Christophe Leroy40159302018-11-21 08:51:45 +000076 return -EBUSY;
77 return 0;
78}
79
Christophe Leroy0fe1a202023-04-03 10:27:39 +020080static int mpc8xxx_wdt_of_to_plat(struct udevice *dev)
Christophe Leroy40159302018-11-21 08:51:45 +000081{
Christophe Leroy0fe1a202023-04-03 10:27:39 +020082 struct mpc8xxx_wdt_priv *priv = dev_get_priv(dev);
83
84 priv->base = (void __iomem *)devfdt_remap_addr(dev);
85
86 if (!priv->base)
87 return -EINVAL;
Christophe Leroy40159302018-11-21 08:51:45 +000088
89 return 0;
90}
91
Christophe Leroy1919fce2023-04-03 10:27:39 +020092static const struct wdt_ops mpc8xxx_wdt_ops = {
93 .start = mpc8xxx_wdt_start,
94 .reset = mpc8xxx_wdt_reset,
95 .stop = mpc8xxx_wdt_stop,
Christophe Leroy40159302018-11-21 08:51:45 +000096};
97
Christophe Leroy1919fce2023-04-03 10:27:39 +020098static const struct udevice_id mpc8xxx_wdt_ids[] = {
Christophe Leroy0fe1a202023-04-03 10:27:39 +020099 { .compatible = "fsl,pq1-wdt", .data = 0x800 },
Christophe Leroy39d37952023-04-03 10:39:59 +0200100 { .compatible = "fsl,pq2pro-wdt", .data = 0x10000 },
Christophe Leroy40159302018-11-21 08:51:45 +0000101 {}
102};
103
Christophe Leroy1919fce2023-04-03 10:27:39 +0200104U_BOOT_DRIVER(wdt_mpc8xxx) = {
105 .name = "wdt_mpc8xxx",
Christophe Leroy40159302018-11-21 08:51:45 +0000106 .id = UCLASS_WDT,
Christophe Leroy1919fce2023-04-03 10:27:39 +0200107 .of_match = mpc8xxx_wdt_ids,
108 .ops = &mpc8xxx_wdt_ops,
Christophe Leroy0fe1a202023-04-03 10:27:39 +0200109 .of_to_plat = mpc8xxx_wdt_of_to_plat,
110 .priv_auto = sizeof(struct mpc8xxx_wdt_priv),
Christophe Leroy40159302018-11-21 08:51:45 +0000111};