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