// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * IBM Real-Time Linux driver
 *
 * Copyright (C) IBM Corporation, 2010
 *
 * Author: Keith Mannthey <kmannth@us.ibm.com>
 *         Vernon Mauery <vernux@us.ibm.com>
 */

#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/io.h>
#include <linux/dmi.h>
#include <linux/efi.h>
#include <linux/mutex.h>
#include <asm/bios_ebda.h>

#include <linux/io-64-nonatomic-lo-hi.h>

static bool force;
module_param(force, bool, 0);
MODULE_PARM_DESC(force, "Force driver load, ignore DMI data");

static bool debug;
module_param(debug, bool, 0644);
MODULE_PARM_DESC(debug, "Show debug output");

MODULE_DESCRIPTION("IBM Premium Real Time Mode (PRTM) driver");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Keith Mannthey <kmmanth@us.ibm.com>");
MODULE_AUTHOR("Vernon Mauery <vernux@us.ibm.com>");

#define RTL_ADDR_TYPE_IO    1
#define RTL_ADDR_TYPE_MMIO  2

#define RTL_CMD_ENTER_PRTM  1
#define RTL_CMD_EXIT_PRTM   2

/* The RTL table as presented by the EBDA: */
struct ibm_rtl_table {
	char signature[5]; /* signature should be "_RTL_" */
	u8 version;
	u8 rt_status;
	u8 command;
	u8 command_status;
	u8 cmd_address_type;
	u8 cmd_granularity;
	u8 cmd_offset;
	u16 reserve1;
	u32 cmd_port_address; /* platform dependent address */
	u32 cmd_port_value;   /* platform dependent value */
} __attribute__((packed));

/* to locate "_RTL_" signature do a masked 5-byte integer compare */
#define RTL_SIGNATURE 0x0000005f4c54525fULL
#define RTL_MASK      0x000000ffffffffffULL

#define RTL_DEBUG(fmt, ...)				\
do {							\
	if (debug)					\
		pr_info(fmt, ##__VA_ARGS__);		\
} while (0)

static DEFINE_MUTEX(rtl_lock);
static struct ibm_rtl_table __iomem *rtl_table;
static void __iomem *ebda_map;
static void __iomem *rtl_cmd_addr;
static u8 rtl_cmd_type;
static u8 rtl_cmd_width;

static void __iomem *rtl_port_map(phys_addr_t addr, unsigned long len)
{
	if (rtl_cmd_type == RTL_ADDR_TYPE_MMIO)
		return ioremap(addr, len);
	return ioport_map(addr, len);
}

static void rtl_port_unmap(void __iomem *addr)
{
	if (addr && rtl_cmd_type == RTL_ADDR_TYPE_MMIO)
		iounmap(addr);
	else
		ioport_unmap(addr);
}

static int ibm_rtl_write(u8 value)
{
	int ret = 0, count = 0;
	u32 cmd_port_val;

	RTL_DEBUG("%s(%d)\n", __func__, value);

	value = value == 1 ? RTL_CMD_ENTER_PRTM : RTL_CMD_EXIT_PRTM;

	mutex_lock(&rtl_lock);

	if (ioread8(&rtl_table->rt_status) != value) {
		iowrite8(value, &rtl_table->command);

		switch (rtl_cmd_width) {
		case 8:
			cmd_port_val = ioread8(&rtl_table->cmd_port_value);
			RTL_DEBUG("cmd_port_val = %u\n", cmd_port_val);
			iowrite8((u8)cmd_port_val, rtl_cmd_addr);
			break;
		case 16:
			cmd_port_val = ioread16(&rtl_table->cmd_port_value);
			RTL_DEBUG("cmd_port_val = %u\n", cmd_port_val);
			iowrite16((u16)cmd_port_val, rtl_cmd_addr);
			break;
		case 32:
			cmd_port_val = ioread32(&rtl_table->cmd_port_value);
			RTL_DEBUG("cmd_port_val = %u\n", cmd_port_val);
			iowrite32(cmd_port_val, rtl_cmd_addr);
			break;
		}

		while (ioread8(&rtl_table->command)) {
			msleep(10);
			if (count++ > 500) {
				pr_err("Hardware not responding to "
				       "mode switch request\n");
				ret = -EIO;
				break;
			}

		}

		if (ioread8(&rtl_table->command_status)) {
			RTL_DEBUG("command_status reports failed command\n");
			ret = -EIO;
		}
	}

	mutex_unlock(&rtl_lock);
	return ret;
}

static ssize_t rtl_show_version(struct device *dev,
                                struct device_attribute *attr,
                                char *buf)
{
	return sprintf(buf, "%d\n", (int)ioread8(&rtl_table->version));
}

static ssize_t rtl_show_state(struct device *dev,
                              struct device_attribute *attr,
                              char *buf)
{
	return sprintf(buf, "%d\n", ioread8(&rtl_table->rt_status));
}

static ssize_t rtl_set_state(struct device *dev,
                             struct device_attribute *attr,
                             const char *buf,
                             size_t count)
{
	ssize_t ret;

	if (count < 1 || count > 2)
		return -EINVAL;

	switch (buf[0]) {
	case '0':
		ret = ibm_rtl_write(0);
		break;
	case '1':
		ret = ibm_rtl_write(1);
		break;
	default:
		ret = -EINVAL;
	}
	if (ret >= 0)
		ret = count;

	return ret;
}

static const struct bus_type rtl_subsys = {
	.name = "ibm_rtl",
	.dev_name = "ibm_rtl",
};

static DEVICE_ATTR(version, S_IRUGO, rtl_show_version, NULL);
static DEVICE_ATTR(state, 0600, rtl_show_state, rtl_set_state);

static struct device_attribute *rtl_attributes[] = {
	&dev_attr_version,
	&dev_attr_state,
	NULL
};


static int rtl_setup_sysfs(void) {
	int ret, i;

	ret = subsys_system_register(&rtl_subsys, NULL);
	if (!ret) {
		struct device *dev_root = bus_get_dev_root(&rtl_subsys);

		if (dev_root) {
			for (i = 0; rtl_attributes[i]; i ++)
				device_create_file(dev_root, rtl_attributes[i]);
			put_device(dev_root);
		}
	}
	return ret;
}

static void rtl_teardown_sysfs(void) {
	struct device *dev_root = bus_get_dev_root(&rtl_subsys);
	int i;

	if (dev_root) {
		for (i = 0; rtl_attributes[i]; i ++)
			device_remove_file(dev_root, rtl_attributes[i]);
		put_device(dev_root);
	}
	bus_unregister(&rtl_subsys);
}


static const struct dmi_system_id ibm_rtl_dmi_table[] __initconst = {
	{                                                  \
		.matches = {                               \
			DMI_MATCH(DMI_SYS_VENDOR, "IBM"),  \
		},                                         \
	},
	{ }
};

static int __init ibm_rtl_init(void) {
	unsigned long ebda_addr, ebda_size;
	unsigned int ebda_kb;
	int ret = -ENODEV, i;

	if (force)
		pr_warn("module loaded by force\n");
	/* first ensure that we are running on IBM HW */
	else if (efi_enabled(EFI_BOOT) || !dmi_check_system(ibm_rtl_dmi_table))
		return -ENODEV;

	/* Get the address for the Extended BIOS Data Area */
	ebda_addr = get_bios_ebda();
	if (!ebda_addr) {
		RTL_DEBUG("no BIOS EBDA found\n");
		return -ENODEV;
	}

	ebda_map = ioremap(ebda_addr, 4);
	if (!ebda_map)
		return -ENOMEM;

	/* First word in the EDBA is the Size in KB */
	ebda_kb = ioread16(ebda_map);
	RTL_DEBUG("EBDA is %d kB\n", ebda_kb);

	if (ebda_kb == 0)
		goto out;

	iounmap(ebda_map);
	ebda_size = ebda_kb*1024;

	/* Remap the whole table */
	ebda_map = ioremap(ebda_addr, ebda_size);
	if (!ebda_map)
		return -ENOMEM;

	/* search for the _RTL_ signature at the start of the table */
	for (i = 0 ; i < ebda_size/sizeof(unsigned int); i++) {
		struct ibm_rtl_table __iomem * tmp;
		tmp = (struct ibm_rtl_table __iomem *) (ebda_map+i);
		if ((readq(&tmp->signature) & RTL_MASK) == RTL_SIGNATURE) {
			phys_addr_t addr;
			unsigned int plen;
			RTL_DEBUG("found RTL_SIGNATURE at %p\n", tmp);
			rtl_table = tmp;
			/* The address, value, width and offset are platform
			 * dependent and found in the ibm_rtl_table */
			rtl_cmd_width = ioread8(&rtl_table->cmd_granularity);
			rtl_cmd_type = ioread8(&rtl_table->cmd_address_type);
			RTL_DEBUG("rtl_cmd_width = %u, rtl_cmd_type = %u\n",
				  rtl_cmd_width, rtl_cmd_type);
			addr = ioread32(&rtl_table->cmd_port_address);
			RTL_DEBUG("addr = %#llx\n", (unsigned long long)addr);
			plen = rtl_cmd_width/sizeof(char);
			rtl_cmd_addr = rtl_port_map(addr, plen);
			RTL_DEBUG("rtl_cmd_addr = %p\n", rtl_cmd_addr);
			if (!rtl_cmd_addr) {
				ret = -ENOMEM;
				break;
			}
			ret = rtl_setup_sysfs();
			break;
		}
	}

out:
	if (ret) {
		iounmap(ebda_map);
		rtl_port_unmap(rtl_cmd_addr);
	}

	return ret;
}

static void __exit ibm_rtl_exit(void)
{
	if (rtl_table) {
		RTL_DEBUG("cleaning up");
		/* do not leave the machine in SMI-free mode */
		ibm_rtl_write(0);
		/* unmap, unlink and remove all traces */
		rtl_teardown_sysfs();
		iounmap(ebda_map);
		rtl_port_unmap(rtl_cmd_addr);
	}
}

module_init(ibm_rtl_init);
module_exit(ibm_rtl_exit);
