On 1/31/21 3:44 PM, Boris Lysov wrote: > Add support for 16-bit control registers. > Some old Mediatek SoCs such as mt6577 use 16-bit I/O operations > for controlling watchdog. This commit redefines read/write > functions and some values in mtk_wdt driver depending on the > 16-bit register support flag in kernel configuration. > By default, driver still uses 32-bit values and I/O functions, so > currently supported devices are unaffected. > > Signed-off-by: Boris Lysov <arzamas-16@xxxxxxx> We can't do this. With this flag enabled, the watchdog won't support other SoCs, and there is nothing that prevents the flag from being set for those SoCs. This has to be handled differently, without configuration flag. Maybe use regmap for register addresses, and use the compatible string to determine which regmap settings to use, or use accessor functions in mtk_wdt_dev. Guenter > --- > drivers/watchdog/Kconfig | 9 +++++++++ > drivers/watchdog/mtk_wdt.c | 34 ++++++++++++++++++++++++---------- > 2 files changed, 33 insertions(+), 10 deletions(-) > > diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig > index 7ff941e71b79..83a4b57ede3f 100644 > --- a/drivers/watchdog/Kconfig > +++ b/drivers/watchdog/Kconfig > @@ -865,6 +865,15 @@ config MEDIATEK_WATCHDOG > To compile this driver as a module, choose M here: the > module will be called mtk_wdt. > > +config MEDIATEK_WATCHDOG_16BIT > + bool "Support 16-bit control registers" > + depends on MEDIATEK_WATCHDOG=y > + help > + Some Mediatek SoCs such as mt6577 have 16-bit registers for > + controlling watchdog. Newer SoCs usually use 32-bit read/write > + operations. > + If in doubt, say N. > + > config DIGICOLOR_WATCHDOG > tristate "Conexant Digicolor SoCs watchdog support" > depends on ARCH_DIGICOLOR || COMPILE_TEST > diff --git a/drivers/watchdog/mtk_wdt.c b/drivers/watchdog/mtk_wdt.c > index d6a6393f609d..0ab3cbcf0d93 100644 > --- a/drivers/watchdog/mtk_wdt.c > +++ b/drivers/watchdog/mtk_wdt.c > @@ -43,13 +43,27 @@ > #define WDT_MODE_IRQ_EN (1 << 3) > #define WDT_MODE_AUTO_START (1 << 4) > #define WDT_MODE_DUAL_EN (1 << 6) > -#define WDT_MODE_KEY 0x22000000 > > #define WDT_SWRST 0x14 > #define WDT_SWRST_KEY 0x1209 > > #define WDT_SWSYSRST 0x18U > + > +#ifdef CONFIG_MEDIATEK_WATCHDOG_16BIT > +#define WDT_MODE_KEY 0x2200 > +#define WDT_SWSYS_RST_KEY 0x8800 > +#define mtk_wdt_read(a) readw(a) > +#define mtk_wdt_write(v, a) writew(v, a) > +#define mtk_wdt_ioread(a) ioread16(a) > +#define mtk_wdt_iowrite(v, a) iowrite16(v, a) > +#else > +#define WDT_MODE_KEY 0x22000000 > #define WDT_SWSYS_RST_KEY 0x88000000 > +#define mtk_wdt_read(a) readl(a) > +#define mtk_wdt_write(v, a) writel(v, a) > +#define mtk_wdt_ioread(a) ioread32(a) > +#define mtk_wdt_iowrite(v, a) iowrite32(v, a) > +#endif > > #define DRV_NAME "mtk-wdt" > #define DRV_VERSION "1.0" > @@ -86,13 +100,13 @@ static int toprgu_reset_update(struct reset_controller_dev *rcdev, > > spin_lock_irqsave(&data->lock, flags); > > - tmp = readl(data->wdt_base + WDT_SWSYSRST); > + tmp = mtk_wdt_read(data->wdt_base + WDT_SWSYSRST); > if (assert) > tmp |= BIT(id); > else > tmp &= ~BIT(id); > tmp |= WDT_SWSYS_RST_KEY; > - writel(tmp, data->wdt_base + WDT_SWSYSRST); > + mtk_wdt_write(tmp, data->wdt_base + WDT_SWSYSRST); > > spin_unlock_irqrestore(&data->lock, flags); > > @@ -157,7 +171,7 @@ static int mtk_wdt_restart(struct watchdog_device *wdt_dev, > wdt_base = mtk_wdt->wdt_base; > > while (1) { > - writel(WDT_SWRST_KEY, wdt_base + WDT_SWRST); > + mtk_wdt_write(WDT_SWRST_KEY, wdt_base + WDT_SWRST); > mdelay(5); > } > > @@ -169,7 +183,7 @@ static int mtk_wdt_ping(struct watchdog_device *wdt_dev) > struct mtk_wdt_dev *mtk_wdt = watchdog_get_drvdata(wdt_dev); > void __iomem *wdt_base = mtk_wdt->wdt_base; > > - iowrite32(WDT_RST_RELOAD, wdt_base + WDT_RST); > + mtk_wdt_iowrite(WDT_RST_RELOAD, wdt_base + WDT_RST); > > return 0; > } > @@ -188,7 +202,7 @@ static int mtk_wdt_set_timeout(struct watchdog_device *wdt_dev, > * The clock has 32 KHz > */ > reg = WDT_LENGTH_TIMEOUT(timeout << 6) | WDT_LENGTH_KEY; > - iowrite32(reg, wdt_base + WDT_LENGTH); > + mtk_wdt_iowrite(reg, wdt_base + WDT_LENGTH); > > mtk_wdt_ping(wdt_dev); > > @@ -201,10 +215,10 @@ static int mtk_wdt_stop(struct watchdog_device *wdt_dev) > void __iomem *wdt_base = mtk_wdt->wdt_base; > u32 reg; > > - reg = readl(wdt_base + WDT_MODE); > + reg = mtk_wdt_read(wdt_base + WDT_MODE); > reg &= ~WDT_MODE_EN; > reg |= WDT_MODE_KEY; > - iowrite32(reg, wdt_base + WDT_MODE); > + mtk_wdt_iowrite(reg, wdt_base + WDT_MODE); > > return 0; > } > @@ -220,10 +234,10 @@ static int mtk_wdt_start(struct watchdog_device *wdt_dev) > if (ret < 0) > return ret; > > - reg = ioread32(wdt_base + WDT_MODE); > + reg = mtk_wdt_ioread(wdt_base + WDT_MODE); > reg &= ~(WDT_MODE_IRQ_EN | WDT_MODE_DUAL_EN); > reg |= (WDT_MODE_EN | WDT_MODE_KEY); > - iowrite32(reg, wdt_base + WDT_MODE); > + mtk_wdt_iowrite(reg, wdt_base + WDT_MODE); > > return 0; > } >