diff mbox

[1/6] plat/qemu: move platform definition to astbmc

Message ID 5735A7A4.3040307@fr.ibm.com
State Changes Requested
Headers show

Commit Message

Cédric Le Goater May 13, 2016, 10:08 a.m. UTC
On 05/10/2016 07:14 AM, Stewart Smith wrote:
> Cédric Le Goater <clg@fr.ibm.com> writes:
>> This patch a simple move of the code towards the AST BMC platform
>> directory to make future changes easier. The qemu and the AST BMC
>> (palmetto, etc) platforms have a lot in common.
>>
>> Signed-off-by: Cédric Le Goater <clg@fr.ibm.com>
> 
> With the possibility of a powernv qemu hooked up to an openbmc qemu, it
> makes me wonder if this is the right direction to take....
> 
> I'd prefer extending things where they are now, which leaves us open to
> take the qemu platform down two different routes depending on what kind of
> session you launch (unless, of course, those two approaches are
> represented differently in the device tree coming from qemu, in which
> case it may make sense to have two qemu platforms in skiboot).
> 
> Thoughts?

OK. I agree, there is no need to make the platform common now. Their routes 
might diverge. Below is a new patch, close the very first initial version. 

The only significant difference for the moment with the ast platform is on 
the RTC device which lives under the LPC bus on qemu.

Tested with the latest qemu powernv+ipmi patchset  :

	https://github.com/legoater/qemu/tree/powernv-ipmi

which is now based on a v2.6.0.

Also tested with the original qemu using travis. 

Thanks,

C.



From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= <clg@fr.ibm.com>
Date: Fri, 13 May 2016 11:36:52 +0200
Subject: [PATCH 1/2] plat/qemu: add Open Power devices
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This brings the qemu platform to the level of an Open Power platform.
It adds the BT device used to communicate with the BMC using IPMI
messaging, power_downs and reboots the way OpenPower systems operate.

The device tree is checked for UART and RTC device nodes and updated
if qemu has not defined them already. The initialization of the BT and
IPMI interfaces depends on the availability of the BT device which
needs to be explicitly defined by qemu. These tests enable skiboot to
maintain compatibility with previous versions of qemu which did not
update the device tree with enabled devices.

Signed-off-by: Cédric Le Goater <clg@fr.ibm.com>
---
 platforms/qemu/qemu.c | 115 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 115 insertions(+)
diff mbox

Patch

diff --git a/platforms/qemu/qemu.c b/platforms/qemu/qemu.c
index 66a6aa3970c2..ecb3060ae405 100644
--- a/platforms/qemu/qemu.c
+++ b/platforms/qemu/qemu.c
@@ -21,6 +21,60 @@ 
 #include <console.h>
 #include <opal.h>
 #include <psi.h>
+#include <bt.h>
+#include <errorlog.h>
+#include <ipmi.h>
+
+/* BT config */
+#define BT_IO_BASE	0xe4
+#define BT_IO_COUNT	3
+#define BT_LPC_IRQ	10
+
+static bool bt_device_present;
+
+static void qemu_ipmi_error(struct ipmi_msg *msg)
+{
+	prlog(PR_DEBUG, "QEMU: error sending msg. cc = %02x\n", msg->cc);
+
+	ipmi_free_msg(msg);
+}
+
+static void qemu_ipmi_setenables(void)
+{
+	struct ipmi_msg *msg;
+
+	struct {
+		uint8_t oem2_en : 1;
+		uint8_t oem1_en : 1;
+		uint8_t oem0_en : 1;
+		uint8_t reserved : 1;
+		uint8_t sel_en : 1;
+		uint8_t msgbuf_en : 1;
+		uint8_t msgbuf_full_int_en : 1;
+		uint8_t rxmsg_queue_int_en : 1;
+	} data;
+
+	memset(&data, 0, sizeof(data));
+
+	/* The spec says we need to read-modify-write to not clobber
+	 * the state of the other flags. These are set on by the bmc */
+	data.rxmsg_queue_int_en = 1;
+	data.sel_en = 1;
+
+	/* These are the ones we want to set on */
+	data.msgbuf_en = 1;
+
+	msg = ipmi_mkmsg_simple(IPMI_SET_ENABLES, &data, sizeof(data));
+	if (!msg) {
+		prlog(PR_ERR, "QEMU: failed to set enables\n");
+		return;
+	}
+
+	msg->error = qemu_ipmi_error;
+
+	ipmi_queue_msg(msg);
+
+}
 
 static void qemu_init(void)
 {
@@ -32,6 +86,27 @@  static void qemu_init(void)
 	 * chiptod_init()
 	 */
 	lpc_rtc_init();
+
+	if (!bt_device_present)
+		return;
+
+	/* Register the BT interface with the IPMI layer */
+	bt_init();
+	/* Initialize elog */
+	elog_init();
+	ipmi_sel_init();
+	ipmi_wdt_init();
+	ipmi_opal_init();
+	ipmi_fru_init(0);
+	ipmi_sensor_init();
+
+	/* As soon as IPMI is up, inform BMC we are in "S0" */
+	ipmi_set_power_state(IPMI_PWR_SYS_S0_WORKING, IPMI_PWR_NOCHANGE);
+
+	/* Enable IPMI OEM message interrupts */
+	qemu_ipmi_setenables();
+
+	ipmi_set_fw_progress_sensor(IPMI_FW_MOTHERBOARD_INIT);
 }
 
 static void qemu_dt_fixup_uart(struct dt_node *lpc)
@@ -53,6 +128,14 @@  static void qemu_dt_fixup_uart(struct dt_node *lpc)
 #define UART_IO_COUNT	8
 #define UART_LPC_IRQ	4
 
+	/* check if the UART device was defined by qemu */
+	dt_for_each_child(lpc, uart) {
+		if (dt_node_is_compatible(uart, "pnpPNP,501")) {
+			prlog(PR_WARNING, "QEMU: uart device already here\n");
+			return;
+		}
+	}
+
 	snprintf(namebuf, sizeof(namebuf), "serial@i%x", UART_IO_BASE);
 	uart = dt_new(lpc, namebuf);
 
@@ -84,6 +167,14 @@  static void qemu_dt_fixup_rtc(struct dt_node *lpc)
 	struct dt_node *rtc;
 	char namebuf[32];
 
+	/* check if the RTC device was defined by qemu */
+	dt_for_each_child(lpc, rtc) {
+		if (dt_node_is_compatible(rtc, "pnpPNP,b00")) {
+			prlog(PR_WARNING, "QEMU: rtc device already here\n");
+			return;
+		}
+	}
+
 	/*
 	 * Follows the structure expected by the kernel file
 	 * arch/powerpc/sysdev/rtc_cmos_setup.c
@@ -113,6 +204,12 @@  static void qemu_dt_fixup(void)
 
 	qemu_dt_fixup_rtc(primary_lpc);
 	qemu_dt_fixup_uart(primary_lpc);
+
+	/* check if the BT device was defined by qemu */
+	dt_for_each_child(primary_lpc, n) {
+		if (dt_node_is_compatible(n, "bt"))
+			bt_device_present = true;
+	}
 }
 
 static void qemu_ext_irq_serirq_cpld(unsigned int chip_id)
@@ -120,6 +217,21 @@  static void qemu_ext_irq_serirq_cpld(unsigned int chip_id)
 	lpc_all_interrupts(chip_id);
 }
 
+static int64_t qemu_ipmi_power_down(uint64_t request)
+{
+	if (request != IPMI_CHASSIS_PWR_DOWN) {
+		prlog(PR_WARNING, "PLAT: unexpected shutdown request %llx\n",
+				   request);
+	}
+
+	return ipmi_chassis_control(request);
+}
+
+static int64_t qemu_ipmi_reboot(void)
+{
+	return ipmi_chassis_control(IPMI_CHASSIS_HARD_RESET);
+}
+
 static bool qemu_probe(void)
 {
 	if (!dt_node_is_compatible(dt_root, "qemu,powernv"))
@@ -145,4 +257,7 @@  DECLARE_PLATFORM(qemu) = {
 	.probe		= qemu_probe,
 	.init		= qemu_init,
 	.external_irq   = qemu_ext_irq_serirq_cpld,
+	.cec_power_down = qemu_ipmi_power_down,
+	.cec_reboot     = qemu_ipmi_reboot,
+	.terminate	= ipmi_terminate,
 };