[PATCH v2 3/5] drivers/fsi: Add On-Chip Controller (OCC) driver

2017-07-05 Thread Eddie James
From: "Edward A. James" 

The OCC is a device embedded on a POWER processor that collects and
aggregates sensor data from the processor and system. The OCC can
provide the raw sensor data as well as perform thermal and power
management on the system.

This driver provides an atomic communications channel between a service
processor (e.g. a BMC) and the OCC. The driver is dependent on the FSI
SBEFIFO driver to get hardware access through the SBE to the OCC SRAM.
Commands are issued to the SBE to send or fetch data to the SRAM.

The format of communications to the OCC is writing a command to SRAM,
followed by a sending a "doorbell" or attention to the OCC, followed by
reading the response from OCC. All of this takes place atomically so
that multiple users don't collide in the SRAM.

Signed-off-by: Edward A. James 
---
 drivers/fsi/Kconfig  |  10 +
 drivers/fsi/Makefile |   1 +
 drivers/fsi/occ.c| 712 +++
 3 files changed, 723 insertions(+)
 create mode 100644 drivers/fsi/occ.c

diff --git a/drivers/fsi/Kconfig b/drivers/fsi/Kconfig
index 8c4d903..9d59276 100644
--- a/drivers/fsi/Kconfig
+++ b/drivers/fsi/Kconfig
@@ -40,6 +40,16 @@ config FSI_SBEFIFO
a pipe-like FSI device for communicating with the self boot engine
(SBE) on POWER processors.
 
+config OCCFIFO
+   tristate "OCC SBEFIFO client device driver"
+   depends on FSI_SBEFIFO
+   ---help---
+   This option enables an SBEFIFO based On-Chip Controller (OCC) device
+   driver. The OCC is a device embedded on a POWER processor that collects
+   and aggregates sensor data from the processor and system. The OCC can
+   provide the raw sensor data as well as perform thermal and power
+   management on the system.
+
 endif
 
 endmenu
diff --git a/drivers/fsi/Makefile b/drivers/fsi/Makefile
index 851182e..7f5ca61 100644
--- a/drivers/fsi/Makefile
+++ b/drivers/fsi/Makefile
@@ -4,3 +4,4 @@ obj-$(CONFIG_FSI_MASTER_HUB) += fsi-master-hub.o
 obj-$(CONFIG_FSI_MASTER_GPIO) += fsi-master-gpio.o
 obj-$(CONFIG_FSI_SCOM) += fsi-scom.o
 obj-$(CONFIG_FSI_SBEFIFO) += fsi-sbefifo.o
+obj-$(CONFIG_OCCFIFO) += occ.o
diff --git a/drivers/fsi/occ.c b/drivers/fsi/occ.c
new file mode 100644
index 000..df13dcb
--- /dev/null
+++ b/drivers/fsi/occ.c
@@ -0,0 +1,712 @@
+/*
+ * Copyright 2017 IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define OCC_SRAM_BYTES 4096
+#define OCC_CMD_DATA_BYTES 4090
+#define OCC_RESP_DATA_BYTES4089
+
+#define OCC_RESP_CMD_IN_PRG0xFF
+
+#define OCC_TIMEOUT_MS 1000
+#define OCC_CMD_IN_PRG_WAIT_MS 50
+
+struct occ {
+   struct device *sbefifo;
+   char name[32];
+   int idx;
+   struct miscdevice mdev;
+   struct list_head xfrs;
+   spinlock_t list_lock;
+   struct mutex occ_lock;
+   struct work_struct work;
+};
+
+#define to_occ(x)  container_of((x), struct occ, mdev)
+
+struct occ_response {
+   u8 seq_no;
+   u8 cmd_type;
+   u8 return_status;
+   __be16 data_length;
+   u8 data[OCC_RESP_DATA_BYTES];
+   __be16 checksum;
+} __packed;
+
+/*
+ * transfer flags are NOT mutually exclusive
+ *
+ * Initial flags are none; transfer is created and queued from write(). All
+ *  flags are cleared when the transfer is completed by closing the file or
+ *  reading all of the available response data.
+ * XFR_IN_PROGRESS is set when a transfer is started from occ_worker_putsram,
+ *  and cleared if the transfer fails or occ_worker_getsram completes.
+ * XFR_COMPLETE is set when a transfer fails or finishes occ_worker_getsram.
+ * XFR_CANCELED is set when the transfer's client is released.
+ * XFR_WAITING is set from read() if the transfer isn't complete and
+ *  O_NONBLOCK wasn't specified. Cleared in read() when transfer completes or
+ *  fails.
+ */
+enum {
+   XFR_IN_PROGRESS,
+   XFR_COMPLETE,
+   XFR_CANCELED,
+   XFR_WAITING,
+};
+
+struct occ_xfr {
+   struct list_head link;
+   int rc;
+   u8 buf[OCC_SRAM_BYTES];
+   size_t cmd_data_length;
+   size_t resp_data_length;
+   unsigned long flags;
+};
+
+/*
+ * client flags
+ *
+ * CLIENT_NONBLOCKING is set during open() if the file was opened with the
+ *  O_NONBLOCK flag.
+ * CLIENT_XFR_PENDING is set during write() and cleared when all data has been
+ *  read.
+ */
+enum {
+   CLIENT_NONBLOCKING,
+   CLIENT_XFR_PENDING,
+};
+
+struct occ_client {
+   struct occ *occ;
+   struct 

[PATCH v2 3/5] drivers/fsi: Add On-Chip Controller (OCC) driver

2017-07-05 Thread Eddie James
From: "Edward A. James" 

The OCC is a device embedded on a POWER processor that collects and
aggregates sensor data from the processor and system. The OCC can
provide the raw sensor data as well as perform thermal and power
management on the system.

This driver provides an atomic communications channel between a service
processor (e.g. a BMC) and the OCC. The driver is dependent on the FSI
SBEFIFO driver to get hardware access through the SBE to the OCC SRAM.
Commands are issued to the SBE to send or fetch data to the SRAM.

The format of communications to the OCC is writing a command to SRAM,
followed by a sending a "doorbell" or attention to the OCC, followed by
reading the response from OCC. All of this takes place atomically so
that multiple users don't collide in the SRAM.

Signed-off-by: Edward A. James 
---
 drivers/fsi/Kconfig  |  10 +
 drivers/fsi/Makefile |   1 +
 drivers/fsi/occ.c| 712 +++
 3 files changed, 723 insertions(+)
 create mode 100644 drivers/fsi/occ.c

diff --git a/drivers/fsi/Kconfig b/drivers/fsi/Kconfig
index 8c4d903..9d59276 100644
--- a/drivers/fsi/Kconfig
+++ b/drivers/fsi/Kconfig
@@ -40,6 +40,16 @@ config FSI_SBEFIFO
a pipe-like FSI device for communicating with the self boot engine
(SBE) on POWER processors.
 
+config OCCFIFO
+   tristate "OCC SBEFIFO client device driver"
+   depends on FSI_SBEFIFO
+   ---help---
+   This option enables an SBEFIFO based On-Chip Controller (OCC) device
+   driver. The OCC is a device embedded on a POWER processor that collects
+   and aggregates sensor data from the processor and system. The OCC can
+   provide the raw sensor data as well as perform thermal and power
+   management on the system.
+
 endif
 
 endmenu
diff --git a/drivers/fsi/Makefile b/drivers/fsi/Makefile
index 851182e..7f5ca61 100644
--- a/drivers/fsi/Makefile
+++ b/drivers/fsi/Makefile
@@ -4,3 +4,4 @@ obj-$(CONFIG_FSI_MASTER_HUB) += fsi-master-hub.o
 obj-$(CONFIG_FSI_MASTER_GPIO) += fsi-master-gpio.o
 obj-$(CONFIG_FSI_SCOM) += fsi-scom.o
 obj-$(CONFIG_FSI_SBEFIFO) += fsi-sbefifo.o
+obj-$(CONFIG_OCCFIFO) += occ.o
diff --git a/drivers/fsi/occ.c b/drivers/fsi/occ.c
new file mode 100644
index 000..df13dcb
--- /dev/null
+++ b/drivers/fsi/occ.c
@@ -0,0 +1,712 @@
+/*
+ * Copyright 2017 IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define OCC_SRAM_BYTES 4096
+#define OCC_CMD_DATA_BYTES 4090
+#define OCC_RESP_DATA_BYTES4089
+
+#define OCC_RESP_CMD_IN_PRG0xFF
+
+#define OCC_TIMEOUT_MS 1000
+#define OCC_CMD_IN_PRG_WAIT_MS 50
+
+struct occ {
+   struct device *sbefifo;
+   char name[32];
+   int idx;
+   struct miscdevice mdev;
+   struct list_head xfrs;
+   spinlock_t list_lock;
+   struct mutex occ_lock;
+   struct work_struct work;
+};
+
+#define to_occ(x)  container_of((x), struct occ, mdev)
+
+struct occ_response {
+   u8 seq_no;
+   u8 cmd_type;
+   u8 return_status;
+   __be16 data_length;
+   u8 data[OCC_RESP_DATA_BYTES];
+   __be16 checksum;
+} __packed;
+
+/*
+ * transfer flags are NOT mutually exclusive
+ *
+ * Initial flags are none; transfer is created and queued from write(). All
+ *  flags are cleared when the transfer is completed by closing the file or
+ *  reading all of the available response data.
+ * XFR_IN_PROGRESS is set when a transfer is started from occ_worker_putsram,
+ *  and cleared if the transfer fails or occ_worker_getsram completes.
+ * XFR_COMPLETE is set when a transfer fails or finishes occ_worker_getsram.
+ * XFR_CANCELED is set when the transfer's client is released.
+ * XFR_WAITING is set from read() if the transfer isn't complete and
+ *  O_NONBLOCK wasn't specified. Cleared in read() when transfer completes or
+ *  fails.
+ */
+enum {
+   XFR_IN_PROGRESS,
+   XFR_COMPLETE,
+   XFR_CANCELED,
+   XFR_WAITING,
+};
+
+struct occ_xfr {
+   struct list_head link;
+   int rc;
+   u8 buf[OCC_SRAM_BYTES];
+   size_t cmd_data_length;
+   size_t resp_data_length;
+   unsigned long flags;
+};
+
+/*
+ * client flags
+ *
+ * CLIENT_NONBLOCKING is set during open() if the file was opened with the
+ *  O_NONBLOCK flag.
+ * CLIENT_XFR_PENDING is set during write() and cleared when all data has been
+ *  read.
+ */
+enum {
+   CLIENT_NONBLOCKING,
+   CLIENT_XFR_PENDING,
+};
+
+struct occ_client {
+   struct occ *occ;
+   struct occ_xfr xfr;
+   spinlock_t lock;
+