1*2ebd32ceSHenning Schild // SPDX-License-Identifier: GPL-2.0 2*2ebd32ceSHenning Schild /* 3*2ebd32ceSHenning Schild * Siemens SIMATIC IPC driver for Watchdogs 4*2ebd32ceSHenning Schild * 5*2ebd32ceSHenning Schild * Copyright (c) Siemens AG, 2020-2021 6*2ebd32ceSHenning Schild * 7*2ebd32ceSHenning Schild * Authors: 8*2ebd32ceSHenning Schild * Gerd Haeussler <gerd.haeussler.ext@siemens.com> 9*2ebd32ceSHenning Schild */ 10*2ebd32ceSHenning Schild 11*2ebd32ceSHenning Schild #include <linux/device.h> 12*2ebd32ceSHenning Schild #include <linux/errno.h> 13*2ebd32ceSHenning Schild #include <linux/init.h> 14*2ebd32ceSHenning Schild #include <linux/io.h> 15*2ebd32ceSHenning Schild #include <linux/ioport.h> 16*2ebd32ceSHenning Schild #include <linux/kernel.h> 17*2ebd32ceSHenning Schild #include <linux/module.h> 18*2ebd32ceSHenning Schild #include <linux/pci.h> 19*2ebd32ceSHenning Schild #include <linux/platform_data/x86/simatic-ipc-base.h> 20*2ebd32ceSHenning Schild #include <linux/platform_device.h> 21*2ebd32ceSHenning Schild #include <linux/sizes.h> 22*2ebd32ceSHenning Schild #include <linux/util_macros.h> 23*2ebd32ceSHenning Schild #include <linux/watchdog.h> 24*2ebd32ceSHenning Schild 25*2ebd32ceSHenning Schild #define WD_ENABLE_IOADR 0x62 26*2ebd32ceSHenning Schild #define WD_TRIGGER_IOADR 0x66 27*2ebd32ceSHenning Schild #define GPIO_COMMUNITY0_PORT_ID 0xaf 28*2ebd32ceSHenning Schild #define PAD_CFG_DW0_GPP_A_23 0x4b8 29*2ebd32ceSHenning Schild #define SAFE_EN_N_427E 0x01 30*2ebd32ceSHenning Schild #define SAFE_EN_N_227E 0x04 31*2ebd32ceSHenning Schild #define WD_ENABLED 0x01 32*2ebd32ceSHenning Schild #define WD_TRIGGERED 0x80 33*2ebd32ceSHenning Schild #define WD_MACROMODE 0x02 34*2ebd32ceSHenning Schild 35*2ebd32ceSHenning Schild #define TIMEOUT_MIN 2 36*2ebd32ceSHenning Schild #define TIMEOUT_DEF 64 37*2ebd32ceSHenning Schild #define TIMEOUT_MAX 64 38*2ebd32ceSHenning Schild 39*2ebd32ceSHenning Schild #define GP_STATUS_REG_227E 0x404D /* IO PORT for SAFE_EN_N on 227E */ 40*2ebd32ceSHenning Schild 41*2ebd32ceSHenning Schild static bool nowayout = WATCHDOG_NOWAYOUT; 42*2ebd32ceSHenning Schild module_param(nowayout, bool, 0000); 43*2ebd32ceSHenning Schild MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" 44*2ebd32ceSHenning Schild __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 45*2ebd32ceSHenning Schild 46*2ebd32ceSHenning Schild static struct resource gp_status_reg_227e_res = 47*2ebd32ceSHenning Schild DEFINE_RES_IO_NAMED(GP_STATUS_REG_227E, SZ_1, KBUILD_MODNAME); 48*2ebd32ceSHenning Schild 49*2ebd32ceSHenning Schild static struct resource io_resource_enable = 50*2ebd32ceSHenning Schild DEFINE_RES_IO_NAMED(WD_ENABLE_IOADR, SZ_1, 51*2ebd32ceSHenning Schild KBUILD_MODNAME " WD_ENABLE_IOADR"); 52*2ebd32ceSHenning Schild 53*2ebd32ceSHenning Schild static struct resource io_resource_trigger = 54*2ebd32ceSHenning Schild DEFINE_RES_IO_NAMED(WD_TRIGGER_IOADR, SZ_1, 55*2ebd32ceSHenning Schild KBUILD_MODNAME " WD_TRIGGER_IOADR"); 56*2ebd32ceSHenning Schild 57*2ebd32ceSHenning Schild /* the actual start will be discovered with pci, 0 is a placeholder */ 58*2ebd32ceSHenning Schild static struct resource mem_resource = 59*2ebd32ceSHenning Schild DEFINE_RES_MEM_NAMED(0, SZ_4, "WD_RESET_BASE_ADR"); 60*2ebd32ceSHenning Schild 61*2ebd32ceSHenning Schild static u32 wd_timeout_table[] = {2, 4, 6, 8, 16, 32, 48, 64 }; 62*2ebd32ceSHenning Schild static void __iomem *wd_reset_base_addr; 63*2ebd32ceSHenning Schild 64*2ebd32ceSHenning Schild static int wd_start(struct watchdog_device *wdd) 65*2ebd32ceSHenning Schild { 66*2ebd32ceSHenning Schild outb(inb(WD_ENABLE_IOADR) | WD_ENABLED, WD_ENABLE_IOADR); 67*2ebd32ceSHenning Schild return 0; 68*2ebd32ceSHenning Schild } 69*2ebd32ceSHenning Schild 70*2ebd32ceSHenning Schild static int wd_stop(struct watchdog_device *wdd) 71*2ebd32ceSHenning Schild { 72*2ebd32ceSHenning Schild outb(inb(WD_ENABLE_IOADR) & ~WD_ENABLED, WD_ENABLE_IOADR); 73*2ebd32ceSHenning Schild return 0; 74*2ebd32ceSHenning Schild } 75*2ebd32ceSHenning Schild 76*2ebd32ceSHenning Schild static int wd_ping(struct watchdog_device *wdd) 77*2ebd32ceSHenning Schild { 78*2ebd32ceSHenning Schild inb(WD_TRIGGER_IOADR); 79*2ebd32ceSHenning Schild return 0; 80*2ebd32ceSHenning Schild } 81*2ebd32ceSHenning Schild 82*2ebd32ceSHenning Schild static int wd_set_timeout(struct watchdog_device *wdd, unsigned int t) 83*2ebd32ceSHenning Schild { 84*2ebd32ceSHenning Schild int timeout_idx = find_closest(t, wd_timeout_table, 85*2ebd32ceSHenning Schild ARRAY_SIZE(wd_timeout_table)); 86*2ebd32ceSHenning Schild 87*2ebd32ceSHenning Schild outb((inb(WD_ENABLE_IOADR) & 0xc7) | timeout_idx << 3, WD_ENABLE_IOADR); 88*2ebd32ceSHenning Schild wdd->timeout = wd_timeout_table[timeout_idx]; 89*2ebd32ceSHenning Schild return 0; 90*2ebd32ceSHenning Schild } 91*2ebd32ceSHenning Schild 92*2ebd32ceSHenning Schild static const struct watchdog_info wdt_ident = { 93*2ebd32ceSHenning Schild .options = WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING | 94*2ebd32ceSHenning Schild WDIOF_SETTIMEOUT, 95*2ebd32ceSHenning Schild .identity = KBUILD_MODNAME, 96*2ebd32ceSHenning Schild }; 97*2ebd32ceSHenning Schild 98*2ebd32ceSHenning Schild static const struct watchdog_ops wdt_ops = { 99*2ebd32ceSHenning Schild .owner = THIS_MODULE, 100*2ebd32ceSHenning Schild .start = wd_start, 101*2ebd32ceSHenning Schild .stop = wd_stop, 102*2ebd32ceSHenning Schild .ping = wd_ping, 103*2ebd32ceSHenning Schild .set_timeout = wd_set_timeout, 104*2ebd32ceSHenning Schild }; 105*2ebd32ceSHenning Schild 106*2ebd32ceSHenning Schild static void wd_secondary_enable(u32 wdtmode) 107*2ebd32ceSHenning Schild { 108*2ebd32ceSHenning Schild u16 resetbit; 109*2ebd32ceSHenning Schild 110*2ebd32ceSHenning Schild /* set safe_en_n so we are not just WDIOF_ALARMONLY */ 111*2ebd32ceSHenning Schild if (wdtmode == SIMATIC_IPC_DEVICE_227E) { 112*2ebd32ceSHenning Schild /* enable SAFE_EN_N on GP_STATUS_REG_227E */ 113*2ebd32ceSHenning Schild resetbit = inb(GP_STATUS_REG_227E); 114*2ebd32ceSHenning Schild outb(resetbit & ~SAFE_EN_N_227E, GP_STATUS_REG_227E); 115*2ebd32ceSHenning Schild } else { 116*2ebd32ceSHenning Schild /* enable SAFE_EN_N on PCH D1600 */ 117*2ebd32ceSHenning Schild resetbit = ioread16(wd_reset_base_addr); 118*2ebd32ceSHenning Schild iowrite16(resetbit & ~SAFE_EN_N_427E, wd_reset_base_addr); 119*2ebd32ceSHenning Schild } 120*2ebd32ceSHenning Schild } 121*2ebd32ceSHenning Schild 122*2ebd32ceSHenning Schild static int wd_setup(u32 wdtmode) 123*2ebd32ceSHenning Schild { 124*2ebd32ceSHenning Schild unsigned int bootstatus = 0; 125*2ebd32ceSHenning Schild int timeout_idx; 126*2ebd32ceSHenning Schild 127*2ebd32ceSHenning Schild timeout_idx = find_closest(TIMEOUT_DEF, wd_timeout_table, 128*2ebd32ceSHenning Schild ARRAY_SIZE(wd_timeout_table)); 129*2ebd32ceSHenning Schild 130*2ebd32ceSHenning Schild if (inb(WD_ENABLE_IOADR) & WD_TRIGGERED) 131*2ebd32ceSHenning Schild bootstatus |= WDIOF_CARDRESET; 132*2ebd32ceSHenning Schild 133*2ebd32ceSHenning Schild /* reset alarm bit, set macro mode, and set timeout */ 134*2ebd32ceSHenning Schild outb(WD_TRIGGERED | WD_MACROMODE | timeout_idx << 3, WD_ENABLE_IOADR); 135*2ebd32ceSHenning Schild 136*2ebd32ceSHenning Schild wd_secondary_enable(wdtmode); 137*2ebd32ceSHenning Schild 138*2ebd32ceSHenning Schild return bootstatus; 139*2ebd32ceSHenning Schild } 140*2ebd32ceSHenning Schild 141*2ebd32ceSHenning Schild static struct watchdog_device wdd_data = { 142*2ebd32ceSHenning Schild .info = &wdt_ident, 143*2ebd32ceSHenning Schild .ops = &wdt_ops, 144*2ebd32ceSHenning Schild .min_timeout = TIMEOUT_MIN, 145*2ebd32ceSHenning Schild .max_timeout = TIMEOUT_MAX 146*2ebd32ceSHenning Schild }; 147*2ebd32ceSHenning Schild 148*2ebd32ceSHenning Schild static int simatic_ipc_wdt_probe(struct platform_device *pdev) 149*2ebd32ceSHenning Schild { 150*2ebd32ceSHenning Schild struct simatic_ipc_platform *plat = pdev->dev.platform_data; 151*2ebd32ceSHenning Schild struct device *dev = &pdev->dev; 152*2ebd32ceSHenning Schild struct resource *res; 153*2ebd32ceSHenning Schild 154*2ebd32ceSHenning Schild switch (plat->devmode) { 155*2ebd32ceSHenning Schild case SIMATIC_IPC_DEVICE_227E: 156*2ebd32ceSHenning Schild if (!devm_request_region(dev, gp_status_reg_227e_res.start, 157*2ebd32ceSHenning Schild resource_size(&gp_status_reg_227e_res), 158*2ebd32ceSHenning Schild KBUILD_MODNAME)) { 159*2ebd32ceSHenning Schild dev_err(dev, 160*2ebd32ceSHenning Schild "Unable to register IO resource at %pR\n", 161*2ebd32ceSHenning Schild &gp_status_reg_227e_res); 162*2ebd32ceSHenning Schild return -EBUSY; 163*2ebd32ceSHenning Schild } 164*2ebd32ceSHenning Schild fallthrough; 165*2ebd32ceSHenning Schild case SIMATIC_IPC_DEVICE_427E: 166*2ebd32ceSHenning Schild wdd_data.parent = dev; 167*2ebd32ceSHenning Schild break; 168*2ebd32ceSHenning Schild default: 169*2ebd32ceSHenning Schild return -EINVAL; 170*2ebd32ceSHenning Schild } 171*2ebd32ceSHenning Schild 172*2ebd32ceSHenning Schild if (!devm_request_region(dev, io_resource_enable.start, 173*2ebd32ceSHenning Schild resource_size(&io_resource_enable), 174*2ebd32ceSHenning Schild io_resource_enable.name)) { 175*2ebd32ceSHenning Schild dev_err(dev, 176*2ebd32ceSHenning Schild "Unable to register IO resource at %#x\n", 177*2ebd32ceSHenning Schild WD_ENABLE_IOADR); 178*2ebd32ceSHenning Schild return -EBUSY; 179*2ebd32ceSHenning Schild } 180*2ebd32ceSHenning Schild 181*2ebd32ceSHenning Schild if (!devm_request_region(dev, io_resource_trigger.start, 182*2ebd32ceSHenning Schild resource_size(&io_resource_trigger), 183*2ebd32ceSHenning Schild io_resource_trigger.name)) { 184*2ebd32ceSHenning Schild dev_err(dev, 185*2ebd32ceSHenning Schild "Unable to register IO resource at %#x\n", 186*2ebd32ceSHenning Schild WD_TRIGGER_IOADR); 187*2ebd32ceSHenning Schild return -EBUSY; 188*2ebd32ceSHenning Schild } 189*2ebd32ceSHenning Schild 190*2ebd32ceSHenning Schild if (plat->devmode == SIMATIC_IPC_DEVICE_427E) { 191*2ebd32ceSHenning Schild res = &mem_resource; 192*2ebd32ceSHenning Schild 193*2ebd32ceSHenning Schild /* get GPIO base from PCI */ 194*2ebd32ceSHenning Schild res->start = simatic_ipc_get_membase0(PCI_DEVFN(0x1f, 1)); 195*2ebd32ceSHenning Schild if (res->start == 0) 196*2ebd32ceSHenning Schild return -ENODEV; 197*2ebd32ceSHenning Schild 198*2ebd32ceSHenning Schild /* do the final address calculation */ 199*2ebd32ceSHenning Schild res->start = res->start + (GPIO_COMMUNITY0_PORT_ID << 16) + 200*2ebd32ceSHenning Schild PAD_CFG_DW0_GPP_A_23; 201*2ebd32ceSHenning Schild res->end += res->start; 202*2ebd32ceSHenning Schild 203*2ebd32ceSHenning Schild wd_reset_base_addr = devm_ioremap_resource(dev, res); 204*2ebd32ceSHenning Schild if (IS_ERR(wd_reset_base_addr)) 205*2ebd32ceSHenning Schild return PTR_ERR(wd_reset_base_addr); 206*2ebd32ceSHenning Schild } 207*2ebd32ceSHenning Schild 208*2ebd32ceSHenning Schild wdd_data.bootstatus = wd_setup(plat->devmode); 209*2ebd32ceSHenning Schild if (wdd_data.bootstatus) 210*2ebd32ceSHenning Schild dev_warn(dev, "last reboot caused by watchdog reset\n"); 211*2ebd32ceSHenning Schild 212*2ebd32ceSHenning Schild watchdog_set_nowayout(&wdd_data, nowayout); 213*2ebd32ceSHenning Schild watchdog_stop_on_reboot(&wdd_data); 214*2ebd32ceSHenning Schild return devm_watchdog_register_device(dev, &wdd_data); 215*2ebd32ceSHenning Schild } 216*2ebd32ceSHenning Schild 217*2ebd32ceSHenning Schild static struct platform_driver simatic_ipc_wdt_driver = { 218*2ebd32ceSHenning Schild .probe = simatic_ipc_wdt_probe, 219*2ebd32ceSHenning Schild .driver = { 220*2ebd32ceSHenning Schild .name = KBUILD_MODNAME, 221*2ebd32ceSHenning Schild }, 222*2ebd32ceSHenning Schild }; 223*2ebd32ceSHenning Schild 224*2ebd32ceSHenning Schild module_platform_driver(simatic_ipc_wdt_driver); 225*2ebd32ceSHenning Schild 226*2ebd32ceSHenning Schild MODULE_LICENSE("GPL v2"); 227*2ebd32ceSHenning Schild MODULE_ALIAS("platform:" KBUILD_MODNAME); 228*2ebd32ceSHenning Schild MODULE_AUTHOR("Gerd Haeussler <gerd.haeussler.ext@siemens.com>"); 229