From e0e3e2a1c66c03c5cf77afedbac829d31ca06ec0 Mon Sep 17 00:00:00 2001 From: Oleksandr Shulzhenko Date: Fri, 20 May 2022 14:52:26 +0200 Subject: i3c: mctp: Add PECI-related functionality to I3C MCTP driver - Handler for PECI messages have been added; - i3c_mctp_client and platform_device for PECI have been added. Signed-off-by: Oleksandr Shulzhenko --- drivers/i3c/mctp/i3c-mctp.c | 54 +++++++++++++++++++++++++++++++++++++++ include/linux/i3c/mctp/i3c-mctp.h | 12 +++++++++ 2 files changed, 66 insertions(+) diff --git a/drivers/i3c/mctp/i3c-mctp.c b/drivers/i3c/mctp/i3c-mctp.c index fbfcd1310901..9d7eca05c874 100644 --- a/drivers/i3c/mctp/i3c-mctp.c +++ b/drivers/i3c/mctp/i3c-mctp.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -27,6 +28,7 @@ struct i3c_mctp { struct cdev cdev; struct device *dev; struct delayed_work polling_work; + struct platform_device *i3c_peci; int id; /* * Restrict an access to the /dev descriptor to one @@ -36,6 +38,7 @@ struct i3c_mctp { int device_open; /* Currently only one userspace client is supported */ struct i3c_mctp_client *default_client; + struct i3c_mctp_client *peci_client; }; struct i3c_mctp_client { @@ -105,6 +108,16 @@ out: static struct i3c_mctp_client *i3c_mctp_find_client(struct i3c_mctp *priv, struct i3c_mctp_packet *packet) { + u8 *msg_hdr = (u8 *)packet->data.payload; + u8 mctp_type = msg_hdr[MCTP_MSG_HDR_MSG_TYPE_OFFSET]; + u16 vendor = (msg_hdr[MCTP_MSG_HDR_VENDOR_OFFSET] << 8 + | msg_hdr[MCTP_MSG_HDR_VENDOR_OFFSET + 1]); + u8 intel_msg_op_code = msg_hdr[MCTP_MSG_HDR_OPCODE_OFFSET]; + + if (priv->peci_client && mctp_type == MCTP_MSG_TYPE_VDM_PCI && + vendor == MCTP_VDM_PCI_INTEL_VENDOR_ID && intel_msg_op_code == MCTP_VDM_PCI_INTEL_PECI) + return priv->peci_client; + return priv->default_client; } @@ -263,6 +276,41 @@ static const struct file_operations i3c_mctp_fops = { .release = i3c_mctp_release, }; +/** + * i3c_mctp_add_peci_client() - registers PECI client + * @i3c: I3C device to get the PECI client for + * + * Return: pointer to PECI client, -ENOMEM - in case of client alloc fault + */ +struct i3c_mctp_client *i3c_mctp_add_peci_client(struct i3c_device *i3c) +{ + struct i3c_mctp *priv = dev_get_drvdata(i3cdev_to_dev(i3c)); + struct i3c_mctp_client *client; + + client = i3c_mctp_client_alloc(priv); + if (IS_ERR(client)) + return ERR_PTR(-ENOMEM); + + priv->peci_client = client; + + return priv->peci_client; +} +EXPORT_SYMBOL_GPL(i3c_mctp_add_peci_client); + +/** + * i3c_mctp_remove_peci_client() - un-registers PECI client + * @client: i3c_mctp_client to be freed + */ +void i3c_mctp_remove_peci_client(struct i3c_mctp_client *client) +{ + struct i3c_mctp *priv = client->priv; + + i3c_mctp_client_free(priv->peci_client); + + priv->peci_client = NULL; +} +EXPORT_SYMBOL_GPL(i3c_mctp_remove_peci_client); + static struct i3c_mctp *i3c_mctp_alloc(struct i3c_device *i3c) { struct i3c_mctp *priv; @@ -466,6 +514,11 @@ static int i3c_mctp_probe(struct i3c_device *i3cdev) dev_set_drvdata(i3cdev_to_dev(i3cdev), priv); + priv->i3c_peci = platform_device_register_data(i3cdev_to_dev(i3cdev), "peci-i3c", priv->id, + NULL, 0); + if (IS_ERR(priv->i3c_peci)) + dev_warn(priv->dev, "failed to register peci-i3c device\n"); + if (i3c_mctp_enable_ibi(i3cdev)) { INIT_DELAYED_WORK(&priv->polling_work, i3c_mctp_polling_work); schedule_delayed_work(&priv->polling_work, msecs_to_jiffies(POLLING_TIMEOUT_MS)); @@ -488,6 +541,7 @@ static void i3c_mctp_remove(struct i3c_device *i3cdev) i3c_device_free_ibi(i3cdev); i3c_mctp_client_free(priv->default_client); priv->default_client = NULL; + platform_device_unregister(priv->i3c_peci); device_destroy(i3c_mctp_class, MKDEV(MAJOR(i3c_mctp_devt), priv->id)); cdev_del(&priv->cdev); diff --git a/include/linux/i3c/mctp/i3c-mctp.h b/include/linux/i3c/mctp/i3c-mctp.h index 72f6fae922b5..dd20750d79d8 100644 --- a/include/linux/i3c/mctp/i3c-mctp.h +++ b/include/linux/i3c/mctp/i3c-mctp.h @@ -8,6 +8,16 @@ #define I3C_MCTP_PAYLOAD_SIZE 64 #define I3C_MCTP_HDR_SIZE 4 +/* PECI MCTP Intel VDM definitions */ +#define MCTP_MSG_TYPE_VDM_PCI 0x7E +#define MCTP_VDM_PCI_INTEL_VENDOR_ID 0x8086 +#define MCTP_VDM_PCI_INTEL_PECI 0x2 + +/* MCTP message header offsets */ +#define MCTP_MSG_HDR_MSG_TYPE_OFFSET 0 +#define MCTP_MSG_HDR_VENDOR_OFFSET 1 +#define MCTP_MSG_HDR_OPCODE_OFFSET 4 + struct i3c_mctp_client; struct mctp_protocol_hdr { @@ -34,5 +44,7 @@ int i3c_mctp_get_eid(struct i3c_mctp_client *client, u8 domain_id, u8 *eid); int i3c_mctp_send_packet(struct i3c_device *i3c, struct i3c_mctp_packet *tx_packet); struct i3c_mctp_packet *i3c_mctp_receive_packet(struct i3c_mctp_client *client, unsigned long timeout); +struct i3c_mctp_client *i3c_mctp_add_peci_client(struct i3c_device *i3c); +void i3c_mctp_remove_peci_client(struct i3c_mctp_client *client); #endif /* I3C_MCTP_H */ -- cgit v1.2.3