Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fdbeb7de authored by Thomas Bogendoerfer's avatar Thomas Bogendoerfer Committed by Linus Torvalds
Browse files

BMC support for PARISC machines



The last line of PARISC machines (C8000, RP34x0, etc.) have a BMC for
controlling temperature, fan speed and other stuff.  The BMC is
connected via a special bus and listed in the firmware device tree.
This change adds support for these BMCs to the IPMI driver.

Signed-off-by: default avatarThomas Bogendoerfer <tsbogend@alpha.franken.de>
Signed-off-by: default avatarCorey Minyard <cminyard@mvista.com>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent a798e2d2
Loading
Loading
Loading
Loading
+75 −0
Original line number Diff line number Diff line
@@ -71,6 +71,11 @@
#include <linux/of_address.h>
#include <linux/of_irq.h>

#ifdef CONFIG_PARISC
#include <asm/hardware.h>	/* for register_parisc_driver() stuff */
#include <asm/parisc-device.h>
#endif

#define PFX "ipmi_si: "

/* Measure times between events in the driver. */
@@ -298,6 +303,9 @@ static int pci_registered;
#ifdef CONFIG_ACPI
static int pnp_registered;
#endif
#ifdef CONFIG_PARISC
static int parisc_registered;
#endif

static unsigned int kipmid_max_busy_us[SI_MAX_PARMS];
static int num_max_busy_us;
@@ -2699,6 +2707,62 @@ static struct platform_driver ipmi_driver = {
	.remove		= ipmi_remove,
};

#ifdef CONFIG_PARISC
static int ipmi_parisc_probe(struct parisc_device *dev)
{
	struct smi_info *info;

	info = smi_info_alloc();

	if (!info) {
		dev_err(&dev->dev,
			"could not allocate memory for PARISC probe\n");
		return -ENOMEM;
	}

	info->si_type		= SI_KCS;
	info->addr_source	= SI_DEVICETREE;
	info->io_setup		= mem_setup;
	info->io.addr_type	= IPMI_MEM_ADDR_SPACE;
	info->io.addr_data	= dev->hpa.start;
	info->io.regsize	= 1;
	info->io.regspacing	= 1;
	info->io.regshift	= 0;
	info->irq		= 0; /* no interrupt */
	info->irq_setup		= NULL;
	info->dev		= &dev->dev;

	dev_dbg(&dev->dev, "addr 0x%lx\n", info->io.addr_data);

	dev_set_drvdata(&dev->dev, info);

	if (add_smi(info)) {
		kfree(info);
		return -EBUSY;
	}

	return 0;
}

static int ipmi_parisc_remove(struct parisc_device *dev)
{
	cleanup_one_si(dev_get_drvdata(&dev->dev));
	return 0;
}

static struct parisc_device_id ipmi_parisc_tbl[] = {
	{ HPHW_MC, HVERSION_REV_ANY_ID, 0x004, 0xC0 },
	{ 0, }
};

static struct parisc_driver ipmi_parisc_driver = {
	.name =		"ipmi",
	.id_table =	ipmi_parisc_tbl,
	.probe =	ipmi_parisc_probe,
	.remove =	ipmi_parisc_remove,
};
#endif /* CONFIG_PARISC */

static int wait_for_msg_done(struct smi_info *smi_info)
{
	enum si_sm_result     smi_result;
@@ -3464,6 +3528,13 @@ static int init_ipmi_si(void)
		spmi_find_bmc();
#endif

#ifdef CONFIG_PARISC
	register_parisc_driver(&ipmi_parisc_driver);
	parisc_registered = 1;
	/* poking PC IO addresses will crash machine, don't do it */
	si_trydefaults = 0;
#endif

	/* We prefer devices with interrupts, but in the case of a machine
	   with multiple BMCs we assume that there will be several instances
	   of a given type so if we succeed in registering a type then also
@@ -3610,6 +3681,10 @@ static void cleanup_ipmi_si(void)
	if (pnp_registered)
		pnp_unregister_driver(&ipmi_pnp_driver);
#endif
#ifdef CONFIG_PARISC
	if (parisc_registered)
		unregister_parisc_driver(&ipmi_parisc_driver);
#endif

	platform_driver_unregister(&ipmi_driver);