1*053fce84SStefan Roese // SPDX-License-Identifier: GPL-2.0+ 2*053fce84SStefan Roese /* 3*053fce84SStefan Roese * Ralink / Mediatek RT288x/RT3xxx/MT76xx built-in hardware watchdog timer 4*053fce84SStefan Roese * 5*053fce84SStefan Roese * Copyright (C) 2018 Stefan Roese <sr@denx.de> 6*053fce84SStefan Roese * 7*053fce84SStefan Roese * Based on the Linux driver version which is: 8*053fce84SStefan Roese * Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org> 9*053fce84SStefan Roese * Copyright (C) 2013 John Crispin <blogic@openwrt.org> 10*053fce84SStefan Roese */ 11*053fce84SStefan Roese 12*053fce84SStefan Roese #include <common.h> 13*053fce84SStefan Roese #include <dm.h> 14*053fce84SStefan Roese #include <wdt.h> 15*053fce84SStefan Roese #include <linux/io.h> 16*053fce84SStefan Roese 17*053fce84SStefan Roese DECLARE_GLOBAL_DATA_PTR; 18*053fce84SStefan Roese 19*053fce84SStefan Roese struct mt762x_wdt { 20*053fce84SStefan Roese void __iomem *regs; 21*053fce84SStefan Roese }; 22*053fce84SStefan Roese 23*053fce84SStefan Roese #define TIMER_REG_TMRSTAT 0x00 24*053fce84SStefan Roese #define TIMER_REG_TMR1CTL 0x20 25*053fce84SStefan Roese #define TIMER_REG_TMR1LOAD 0x24 26*053fce84SStefan Roese 27*053fce84SStefan Roese #define TMR1CTL_ENABLE BIT(7) 28*053fce84SStefan Roese #define TMR1CTL_RESTART BIT(9) 29*053fce84SStefan Roese #define TMR1CTL_PRESCALE_SHIFT 16 30*053fce84SStefan Roese 31*053fce84SStefan Roese static int mt762x_wdt_ping(struct mt762x_wdt *priv) 32*053fce84SStefan Roese { 33*053fce84SStefan Roese writel(TMR1CTL_RESTART, priv->regs + TIMER_REG_TMRSTAT); 34*053fce84SStefan Roese 35*053fce84SStefan Roese return 0; 36*053fce84SStefan Roese } 37*053fce84SStefan Roese 38*053fce84SStefan Roese static int mt762x_wdt_start(struct udevice *dev, u64 ms, ulong flags) 39*053fce84SStefan Roese { 40*053fce84SStefan Roese struct mt762x_wdt *priv = dev_get_priv(dev); 41*053fce84SStefan Roese 42*053fce84SStefan Roese /* set the prescaler to 1ms == 1000us */ 43*053fce84SStefan Roese writel(1000 << TMR1CTL_PRESCALE_SHIFT, priv->regs + TIMER_REG_TMR1CTL); 44*053fce84SStefan Roese writel(ms, priv->regs + TIMER_REG_TMR1LOAD); 45*053fce84SStefan Roese 46*053fce84SStefan Roese setbits_le32(priv->regs + TIMER_REG_TMR1CTL, TMR1CTL_ENABLE); 47*053fce84SStefan Roese 48*053fce84SStefan Roese return 0; 49*053fce84SStefan Roese } 50*053fce84SStefan Roese 51*053fce84SStefan Roese static int mt762x_wdt_stop(struct udevice *dev) 52*053fce84SStefan Roese { 53*053fce84SStefan Roese struct mt762x_wdt *priv = dev_get_priv(dev); 54*053fce84SStefan Roese 55*053fce84SStefan Roese mt762x_wdt_ping(priv); 56*053fce84SStefan Roese 57*053fce84SStefan Roese clrbits_le32(priv->regs + TIMER_REG_TMR1CTL, TMR1CTL_ENABLE); 58*053fce84SStefan Roese 59*053fce84SStefan Roese return 0; 60*053fce84SStefan Roese } 61*053fce84SStefan Roese 62*053fce84SStefan Roese static int mt762x_wdt_reset(struct udevice *dev) 63*053fce84SStefan Roese { 64*053fce84SStefan Roese struct mt762x_wdt *priv = dev_get_priv(dev); 65*053fce84SStefan Roese 66*053fce84SStefan Roese mt762x_wdt_ping(priv); 67*053fce84SStefan Roese 68*053fce84SStefan Roese return 0; 69*053fce84SStefan Roese } 70*053fce84SStefan Roese 71*053fce84SStefan Roese static int mt762x_wdt_probe(struct udevice *dev) 72*053fce84SStefan Roese { 73*053fce84SStefan Roese struct mt762x_wdt *priv = dev_get_priv(dev); 74*053fce84SStefan Roese 75*053fce84SStefan Roese priv->regs = dev_remap_addr(dev); 76*053fce84SStefan Roese if (!priv->regs) 77*053fce84SStefan Roese return -EINVAL; 78*053fce84SStefan Roese 79*053fce84SStefan Roese mt762x_wdt_stop(dev); 80*053fce84SStefan Roese 81*053fce84SStefan Roese return 0; 82*053fce84SStefan Roese } 83*053fce84SStefan Roese 84*053fce84SStefan Roese static const struct wdt_ops mt762x_wdt_ops = { 85*053fce84SStefan Roese .start = mt762x_wdt_start, 86*053fce84SStefan Roese .reset = mt762x_wdt_reset, 87*053fce84SStefan Roese .stop = mt762x_wdt_stop, 88*053fce84SStefan Roese }; 89*053fce84SStefan Roese 90*053fce84SStefan Roese static const struct udevice_id mt762x_wdt_ids[] = { 91*053fce84SStefan Roese { .compatible = "mediatek,mt7621-wdt" }, 92*053fce84SStefan Roese {} 93*053fce84SStefan Roese }; 94*053fce84SStefan Roese 95*053fce84SStefan Roese U_BOOT_DRIVER(mt762x_wdt) = { 96*053fce84SStefan Roese .name = "mt762x_wdt", 97*053fce84SStefan Roese .id = UCLASS_WDT, 98*053fce84SStefan Roese .of_match = mt762x_wdt_ids, 99*053fce84SStefan Roese .probe = mt762x_wdt_probe, 100*053fce84SStefan Roese .priv_auto_alloc_size = sizeof(struct mt762x_wdt), 101*053fce84SStefan Roese .ops = &mt762x_wdt_ops, 102*053fce84SStefan Roese }; 103