// SPDX-License-Identifier: GPL-2.0
/*
 * A hack to create a platform device from a DMI entry.  This will
 * allow autoloading of the IPMI drive based on SMBIOS entries.
 */

#include <linux/ipmi.h>
#include <linux/init.h>
#include <linux/dmi.h>
#include <linux/platform_device.h>
#include <linux/property.h>
#include "ipmi_dmi.h"

struct ipmi_dmi_info {
	int type;
	u32 flags;
	unsigned long addr;
	u8 slave_addr;
	struct ipmi_dmi_info *next;
};

static struct ipmi_dmi_info *ipmi_dmi_infos;

static int ipmi_dmi_nr __initdata;

static void __init dmi_add_platform_ipmi(unsigned long base_addr,
					 u32 flags,
					 u8 slave_addr,
					 int irq,
					 int offset,
					 int type)
{
	struct platform_device *pdev;
	struct resource r[4];
	unsigned int num_r = 1, size;
	struct property_entry p[4] = {
		PROPERTY_ENTRY_U8("slave-addr", slave_addr),
		PROPERTY_ENTRY_U8("ipmi-type", type),
		PROPERTY_ENTRY_U16("i2c-addr", base_addr),
		{ }
	};
	char *name, *override;
	int rv;
	struct ipmi_dmi_info *info;

	info = kmalloc(sizeof(*info), GFP_KERNEL);
	if (!info) {
		pr_warn("ipmi:dmi: Could not allocate dmi info\n");
	} else {
		info->type = type;
		info->flags = flags;
		info->addr = base_addr;
		info->slave_addr = slave_addr;
		info->next = ipmi_dmi_infos;
		ipmi_dmi_infos = info;
	}

	name = "dmi-ipmi-si";
	override = "ipmi_si";
	switch (type) {
	case IPMI_DMI_TYPE_SSIF:
		name = "dmi-ipmi-ssif";
		override = "ipmi_ssif";
		offset = 1;
		size = 1;
		break;
	case IPMI_DMI_TYPE_BT:
		size = 3;
		break;
	case IPMI_DMI_TYPE_KCS:
	case IPMI_DMI_TYPE_SMIC:
		size = 2;
		break;
	default:
		pr_err("ipmi:dmi: Invalid IPMI type: %d", type);
		return;
	}

	pdev = platform_device_alloc(name, ipmi_dmi_nr);
	if (!pdev) {
		pr_err("ipmi:dmi: Error allocation IPMI platform device");
		return;
	}
	pdev->driver_override = kasprintf(GFP_KERNEL, "%s",
					  override);
	if (!pdev->driver_override)
		goto err;

	if (type == IPMI_DMI_TYPE_SSIF)
		goto add_properties;

	memset(r, 0, sizeof(r));

	r[0].start = base_addr;
	r[0].end = r[0].start + offset - 1;
	r[0].name = "IPMI Address 1";
	r[0].flags = flags;

	if (size > 1) {
		r[1].start = r[0].start + offset;
		r[1].end = r[1].start + offset - 1;
		r[1].name = "IPMI Address 2";
		r[1].flags = flags;
		num_r++;
	}

	if (size > 2) {
		r[2].start = r[1].start + offset;
		r[2].end = r[2].start + offset - 1;
		r[2].name = "IPMI Address 3";
		r[2].flags = flags;
		num_r++;
	}

	if (irq) {
		r[num_r].start = irq;
		r[num_r].end = irq;
		r[num_r].name = "IPMI IRQ";
		r[num_r].flags = IORESOURCE_IRQ;
		num_r++;
	}

	rv = platform_device_add_resources(pdev, r, num_r);
	if (rv) {
		dev_err(&pdev->dev,
			"ipmi:dmi: Unable to add resources: %d\n", rv);
		goto err;
	}

add_properties:
	rv = platform_device_add_properties(pdev, p);
	if (rv) {
		dev_err(&pdev->dev,
			"ipmi:dmi: Unable to add properties: %d\n", rv);
		goto err;
	}

	rv = platform_device_add(pdev);
	if (rv) {
		dev_err(&pdev->dev, "ipmi:dmi: Unable to add device: %d\n", rv);
		goto err;
	}

	ipmi_dmi_nr++;
	return;

err:
	platform_device_put(pdev);
}

/*
 * Look up the slave address for a given interface.  This is here
 * because ACPI doesn't have a slave address while SMBIOS does, but we
 * prefer using ACPI so the ACPI code can use the IPMI namespace.
 * This function allows an ACPI-specified IPMI device to look up the
 * slave address from the DMI table.
 */
int ipmi_dmi_get_slave_addr(int type, u32 flags, unsigned long base_addr)
{
	struct ipmi_dmi_info *info = ipmi_dmi_infos;

	while (info) {
		if (info->type == type &&
		    info->flags == flags &&
		    info->addr == base_addr)
			return info->slave_addr;
		info = info->next;
	}

	return 0;
}
EXPORT_SYMBOL(ipmi_dmi_get_slave_addr);

#define DMI_IPMI_MIN_LENGTH	0x10
#define DMI_IPMI_VER2_LENGTH	0x12
#define DMI_IPMI_TYPE		4
#define DMI_IPMI_SLAVEADDR	6
#define DMI_IPMI_ADDR		8
#define DMI_IPMI_ACCESS		0x10
#define DMI_IPMI_IRQ		0x11
#define DMI_IPMI_IO_MASK	0xfffe

static void __init dmi_decode_ipmi(const struct dmi_header *dm)
{
	const u8	*data = (const u8 *) dm;
	u32             flags = IORESOURCE_IO;
	unsigned long	base_addr;
	u8              len = dm->length;
	u8              slave_addr;
	int             irq = 0, offset;
	int             type;

	if (len < DMI_IPMI_MIN_LENGTH)
		return;

	type = data[DMI_IPMI_TYPE];
	slave_addr = data[DMI_IPMI_SLAVEADDR];

	memcpy(&base_addr, data + DMI_IPMI_ADDR, sizeof(unsigned long));
	if (len >= DMI_IPMI_VER2_LENGTH) {
		if (type == IPMI_DMI_TYPE_SSIF) {
			offset = 0;
			flags = 0;
			base_addr = data[DMI_IPMI_ADDR] >> 1;
			if (base_addr == 0) {
				/*
				 * Some broken systems put the I2C address in
				 * the slave address field.  We try to
				 * accommodate them here.
				 */
				base_addr = data[DMI_IPMI_SLAVEADDR] >> 1;
				slave_addr = 0;
			}
		} else {
			if (base_addr & 1) {
				/* I/O */
				base_addr &= DMI_IPMI_IO_MASK;
			} else {
				/* Memory */
				flags = IORESOURCE_MEM;
			}

			/*
			 * If bit 4 of byte 0x10 is set, then the lsb
			 * for the address is odd.
			 */
			base_addr |= (data[DMI_IPMI_ACCESS] >> 4) & 1;

			irq = data[DMI_IPMI_IRQ];

			/*
			 * The top two bits of byte 0x10 hold the
			 * register spacing.
			 */
			switch ((data[DMI_IPMI_ACCESS] >> 6) & 3) {
			case 0: /* Byte boundaries */
				offset = 1;
				break;
			case 1: /* 32-bit boundaries */
				offset = 4;
				break;
			case 2: /* 16-byte boundaries */
				offset = 16;
				break;
			default:
				pr_err("ipmi:dmi: Invalid offset: 0");
				return;
			}
		}
	} else {
		/* Old DMI spec. */
		/*
		 * Note that technically, the lower bit of the base
		 * address should be 1 if the address is I/O and 0 if
		 * the address is in memory.  So many systems get that
		 * wrong (and all that I have seen are I/O) so we just
		 * ignore that bit and assume I/O.  Systems that use
		 * memory should use the newer spec, anyway.
		 */
		base_addr = base_addr & DMI_IPMI_IO_MASK;
		offset = 1;
	}

	dmi_add_platform_ipmi(base_addr, flags, slave_addr, irq,
			      offset, type);
}

static int __init scan_for_dmi_ipmi(void)
{
	const struct dmi_device *dev = NULL;

	while ((dev = dmi_find_device(DMI_DEV_TYPE_IPMI, NULL, dev)))
		dmi_decode_ipmi((const struct dmi_header *) dev->device_data);

	return 0;
}
subsys_initcall(scan_for_dmi_ipmi);
