mei: implement power gating isolation hbm layer
authorTomas Winkler <tomas.winkler@intel.com>
Tue, 18 Mar 2014 20:51:55 +0000 (22:51 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 3 May 2014 23:20:23 +0000 (19:20 -0400)
Add send message functions and receive dispatch stubs
for power gating isolation hbm protocol.

The protocol consist of requests for entering and exiting
the power gating isolation state and their responses.

Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
Signed-off-by: Alexander Usyskin <alexander.usyskin@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/misc/mei/hbm.c
drivers/misc/mei/hbm.h
drivers/misc/mei/hw.h
drivers/misc/mei/init.c
drivers/misc/mei/mei_dev.h

index 4960288e543a2657fbf80689eef5003b93f83428..a16b47c855aa48262eb4f78f7c2e26b7cdbad104 100644 (file)
@@ -14,6 +14,7 @@
  *
  */
 
+#include <linux/export.h>
 #include <linux/pci.h>
 #include <linux/sched.h>
 #include <linux/wait.h>
@@ -289,6 +290,34 @@ static int mei_hbm_prop_req(struct mei_device *dev)
        return 0;
 }
 
+/*
+ * mei_hbm_pg - sends pg command
+ *
+ * @dev: the device structure
+ * @pg_cmd: the pg command code
+ *
+ * This function returns -EIO on write failure
+ */
+int mei_hbm_pg(struct mei_device *dev, u8 pg_cmd)
+{
+       struct mei_msg_hdr *mei_hdr = &dev->wr_msg.hdr;
+       struct hbm_power_gate *req;
+       const size_t len = sizeof(struct hbm_power_gate);
+       int ret;
+
+       mei_hbm_hdr(mei_hdr, len);
+
+       req = (struct hbm_power_gate *)dev->wr_msg.data;
+       memset(req, 0, len);
+       req->hbm_cmd = pg_cmd;
+
+       ret = mei_write_message(dev, mei_hdr, dev->wr_msg.data);
+       if (ret)
+               dev_err(&dev->pdev->dev, "power gate command write failed.\n");
+       return ret;
+}
+EXPORT_SYMBOL_GPL(mei_hbm_pg);
+
 /**
  * mei_hbm_stop_req - send stop request message
  *
@@ -701,6 +730,18 @@ int mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr)
                mei_hbm_cl_flow_control_res(dev, flow_control);
                break;
 
+       case MEI_PG_ISOLATION_ENTRY_RES_CMD:
+               dev_dbg(&dev->pdev->dev, "power gate isolation entry response received\n");
+               if (waitqueue_active(&dev->wait_pg))
+                       wake_up(&dev->wait_pg);
+               break;
+
+       case MEI_PG_ISOLATION_EXIT_REQ_CMD:
+               dev_dbg(&dev->pdev->dev, "power gate isolation exit request received\n");
+               if (waitqueue_active(&dev->wait_pg))
+                       wake_up(&dev->wait_pg);
+               break;
+
        case HOST_CLIENT_PROPERTIES_RES_CMD:
                dev_dbg(&dev->pdev->dev, "hbm: properties response: message received.\n");
 
index 20e8782711c0c5f53e8e43c97b0c32476b3d27c8..8e39cee408d0167abea5ce05d3c9e3c4eb9ce82d 100644 (file)
@@ -57,6 +57,7 @@ int mei_hbm_cl_disconnect_req(struct mei_device *dev, struct mei_cl *cl);
 int mei_hbm_cl_disconnect_rsp(struct mei_device *dev, struct mei_cl *cl);
 int mei_hbm_cl_connect_req(struct mei_device *dev, struct mei_cl *cl);
 bool mei_hbm_version_is_supported(struct mei_device *dev);
+int mei_hbm_pg(struct mei_device *dev, u8 pg_cmd);
 
 #endif /* _MEI_HBM_H_ */
 
index 6b476ab49b2e0d538f4097e093bd19377aa74ec4..1d70968d90b685e6a052de7bc3a92f4d6bf59bf3 100644 (file)
 
 #define MEI_FLOW_CONTROL_CMD                0x08
 
+#define MEI_PG_ISOLATION_ENTRY_REQ_CMD      0x0a
+#define MEI_PG_ISOLATION_ENTRY_RES_CMD      0x8a
+#define MEI_PG_ISOLATION_EXIT_REQ_CMD       0x0b
+#define MEI_PG_ISOLATION_EXIT_RES_CMD       0x8b
+
 /*
  * MEI Stop Reason
  * used by hbm_host_stop_request.reason
@@ -207,6 +212,17 @@ struct hbm_props_response {
        struct mei_client_properties client_properties;
 } __packed;
 
+/**
+ * struct hbm_power_gate - power gate request/response
+ *
+ * @hbm_cmd - bus message command header
+ * @reserved[3]
+ */
+struct hbm_power_gate {
+       u8 hbm_cmd;
+       u8 reserved[3];
+} __packed;
+
 /**
  * struct hbm_client_connect_request - connect/disconnect request
  *
index 4460975c0eefcc97c765dd83fcafc0a3f3290cd3..cc604e1d9457f97254d6015f9755d83b05978472 100644 (file)
@@ -312,6 +312,7 @@ void mei_device_init(struct mei_device *dev)
        INIT_LIST_HEAD(&dev->device_list);
        mutex_init(&dev->device_lock);
        init_waitqueue_head(&dev->wait_hw_ready);
+       init_waitqueue_head(&dev->wait_pg);
        init_waitqueue_head(&dev->wait_recvd_msg);
        init_waitqueue_head(&dev->wait_stop_wd);
        dev->dev_state = MEI_DEV_INITIALIZING;
index 94a516716d226b0ec448a468c8b17545af0842cc..4d4c041a7e4fa04ed551916150d1521e3f3f929b 100644 (file)
@@ -371,6 +371,7 @@ struct mei_device {
         * waiting queue for receive message from FW
         */
        wait_queue_head_t wait_hw_ready;
+       wait_queue_head_t wait_pg;
        wait_queue_head_t wait_recvd_msg;
        wait_queue_head_t wait_stop_wd;