// SPDX-License-Identifier: GPL-2.0
/*
 * Siemens SIMATIC IPC driver for Watchdogs
 *
 * Copyright (c) Siemens AG, 2020-2021
 *
 * Authors:
 *  Gerd Haeussler <gerd.haeussler.ext@siemens.com>
 */

#include <linux/device.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/ioport.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/platform_data/x86/p2sb.h>
#include <linux/platform_data/x86/simatic-ipc-base.h>
#include <linux/platform_device.h>
#include <linux/sizes.h>
#include <linux/util_macros.h>
#include <linux/watchdog.h>

#define WD_ENABLE_IOADR			0x62
#define WD_TRIGGER_IOADR		0x66
#define GPIO_COMMUNITY0_PORT_ID		0xaf
#define PAD_CFG_DW0_GPP_A_23		0x4b8
#define SAFE_EN_N_427E			0x01
#define SAFE_EN_N_227E			0x04
#define WD_ENABLED			0x01
#define WD_TRIGGERED			0x80
#define WD_MACROMODE			0x02

#define TIMEOUT_MIN	2
#define TIMEOUT_DEF	64
#define TIMEOUT_MAX	64

#define GP_STATUS_REG_227E	0x404D	/* IO PORT for SAFE_EN_N on 227E */

static bool nowayout = WATCHDOG_NOWAYOUT;
module_param(nowayout, bool, 0000);
MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
		 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");

static struct resource gp_status_reg_227e_res =
	DEFINE_RES_IO_NAMED(GP_STATUS_REG_227E, SZ_1, KBUILD_MODNAME);

static struct resource io_resource_enable =
	DEFINE_RES_IO_NAMED(WD_ENABLE_IOADR, SZ_1,
			    KBUILD_MODNAME " WD_ENABLE_IOADR");

static struct resource io_resource_trigger =
	DEFINE_RES_IO_NAMED(WD_TRIGGER_IOADR, SZ_1,
			    KBUILD_MODNAME " WD_TRIGGER_IOADR");

/* the actual start will be discovered with p2sb, 0 is a placeholder */
static struct resource mem_resource =
	DEFINE_RES_MEM_NAMED(0, 0, "WD_RESET_BASE_ADR");

static u32 wd_timeout_table[] = {2, 4, 6, 8, 16, 32, 48, 64 };
static void __iomem *wd_reset_base_addr;

static int wd_start(struct watchdog_device *wdd)
{
	outb(inb(WD_ENABLE_IOADR) | WD_ENABLED, WD_ENABLE_IOADR);
	return 0;
}

static int wd_stop(struct watchdog_device *wdd)
{
	outb(inb(WD_ENABLE_IOADR) & ~WD_ENABLED, WD_ENABLE_IOADR);
	return 0;
}

static int wd_ping(struct watchdog_device *wdd)
{
	inb(WD_TRIGGER_IOADR);
	return 0;
}

static int wd_set_timeout(struct watchdog_device *wdd, unsigned int t)
{
	int timeout_idx = find_closest(t, wd_timeout_table,
				       ARRAY_SIZE(wd_timeout_table));

	outb((inb(WD_ENABLE_IOADR) & 0xc7) | timeout_idx << 3, WD_ENABLE_IOADR);
	wdd->timeout = wd_timeout_table[timeout_idx];
	return 0;
}

static const struct watchdog_info wdt_ident = {
	.options	= WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING |
			  WDIOF_SETTIMEOUT,
	.identity	= KBUILD_MODNAME,
};

static const struct watchdog_ops wdt_ops = {
	.owner		= THIS_MODULE,
	.start		= wd_start,
	.stop		= wd_stop,
	.ping		= wd_ping,
	.set_timeout	= wd_set_timeout,
};

static void wd_secondary_enable(u32 wdtmode)
{
	u16 resetbit;

	/* set safe_en_n so we are not just WDIOF_ALARMONLY */
	if (wdtmode == SIMATIC_IPC_DEVICE_227E) {
		/* enable SAFE_EN_N on GP_STATUS_REG_227E */
		resetbit = inb(GP_STATUS_REG_227E);
		outb(resetbit & ~SAFE_EN_N_227E, GP_STATUS_REG_227E);
	} else {
		/* enable SAFE_EN_N on PCH D1600 */
		resetbit = ioread16(wd_reset_base_addr);
		iowrite16(resetbit & ~SAFE_EN_N_427E, wd_reset_base_addr);
	}
}

static int wd_setup(u32 wdtmode)
{
	unsigned int bootstatus = 0;
	int timeout_idx;

	timeout_idx = find_closest(TIMEOUT_DEF, wd_timeout_table,
				   ARRAY_SIZE(wd_timeout_table));

	if (inb(WD_ENABLE_IOADR) & WD_TRIGGERED)
		bootstatus |= WDIOF_CARDRESET;

	/* reset alarm bit, set macro mode, and set timeout */
	outb(WD_TRIGGERED | WD_MACROMODE | timeout_idx << 3, WD_ENABLE_IOADR);

	wd_secondary_enable(wdtmode);

	return bootstatus;
}

static struct watchdog_device wdd_data = {
	.info = &wdt_ident,
	.ops = &wdt_ops,
	.min_timeout = TIMEOUT_MIN,
	.max_timeout = TIMEOUT_MAX
};

static int simatic_ipc_wdt_probe(struct platform_device *pdev)
{
	struct simatic_ipc_platform *plat = pdev->dev.platform_data;
	struct device *dev = &pdev->dev;
	struct resource *res;
	int ret;

	switch (plat->devmode) {
	case SIMATIC_IPC_DEVICE_227E:
		res = &gp_status_reg_227e_res;
		if (!request_muxed_region(res->start, resource_size(res), res->name)) {
			dev_err(dev,
				"Unable to register IO resource at %pR\n",
				&gp_status_reg_227e_res);
			return -EBUSY;
		}
		fallthrough;
	case SIMATIC_IPC_DEVICE_427E:
		wdd_data.parent = dev;
		break;
	default:
		return -EINVAL;
	}

	if (!devm_request_region(dev, io_resource_enable.start,
				 resource_size(&io_resource_enable),
				 io_resource_enable.name)) {
		dev_err(dev,
			"Unable to register IO resource at %#x\n",
			WD_ENABLE_IOADR);
		return -EBUSY;
	}

	if (!devm_request_region(dev, io_resource_trigger.start,
				 resource_size(&io_resource_trigger),
				 io_resource_trigger.name)) {
		dev_err(dev,
			"Unable to register IO resource at %#x\n",
			WD_TRIGGER_IOADR);
		return -EBUSY;
	}

	if (plat->devmode == SIMATIC_IPC_DEVICE_427E) {
		res = &mem_resource;

		ret = p2sb_bar(NULL, 0, res);
		if (ret)
			return ret;

		/* do the final address calculation */
		res->start = res->start + (GPIO_COMMUNITY0_PORT_ID << 16) +
			     PAD_CFG_DW0_GPP_A_23;
		res->end = res->start + SZ_4 - 1;

		wd_reset_base_addr = devm_ioremap_resource(dev, res);
		if (IS_ERR(wd_reset_base_addr))
			return PTR_ERR(wd_reset_base_addr);
	}

	wdd_data.bootstatus = wd_setup(plat->devmode);
	if (wdd_data.bootstatus)
		dev_warn(dev, "last reboot caused by watchdog reset\n");

	if (plat->devmode == SIMATIC_IPC_DEVICE_227E)
		release_region(gp_status_reg_227e_res.start,
			       resource_size(&gp_status_reg_227e_res));

	watchdog_set_nowayout(&wdd_data, nowayout);
	watchdog_stop_on_reboot(&wdd_data);
	return devm_watchdog_register_device(dev, &wdd_data);
}

static struct platform_driver simatic_ipc_wdt_driver = {
	.probe = simatic_ipc_wdt_probe,
	.driver = {
		.name = KBUILD_MODNAME,
	},
};

module_platform_driver(simatic_ipc_wdt_driver);

MODULE_DESCRIPTION("Siemens SIMATIC IPC driver for Watchdogs");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:" KBUILD_MODNAME);
MODULE_AUTHOR("Gerd Haeussler <gerd.haeussler.ext@siemens.com>");
