This patch introduces support for a new IOCTL command to set the channel of eSPI controller. Currently espi_amd driver supports to enable peripheral and virtual wire channels. Co-developed-by: Krishnamoorthi M <krishnamoorthi.m@xxxxxxx> Signed-off-by: Krishnamoorthi M <krishnamoorthi.m@xxxxxxx> Co-developed-by: Akshata MukundShetty <akshata.mukundshetty@xxxxxxx> Signed-off-by: Akshata MukundShetty <akshata.mukundshetty@xxxxxxx> Signed-off-by: Raju Rangoju <Raju.Rangoju@xxxxxxx> --- drivers/spi/espi-amd-dev.c | 49 ++++++++++++++++++++++++++++++++++++++ drivers/spi/espi-amd.h | 1 + 2 files changed, 50 insertions(+) diff --git a/drivers/spi/espi-amd-dev.c b/drivers/spi/espi-amd-dev.c index 821cc0486657..c78a9b2b059b 100644 --- a/drivers/spi/espi-amd-dev.c +++ b/drivers/spi/espi-amd-dev.c @@ -203,6 +203,52 @@ static int amd_espi_ioctl_set_io_mode(struct amd_espi *amd_espi, unsigned long a return ret; } +static int amd_espi_ioctl_set_channel_mode(struct amd_espi *amd_espi, unsigned long arg) +{ + struct config *config; + u32 slave_config; + int ret; + + config = kzalloc(sizeof(*config), GFP_KERNEL); + if (!config) + return -ENOMEM; + + if (copy_from_user(config, (void __user *)arg, sizeof(struct config))) { + ret = -EFAULT; + goto set_chan_mode_free; + } + + ret = amd_espi_get_general_config(amd_espi, &slave_config); + if (ret != CB_SUCCESS) { + dev_err(amd_espi->dev, "Get configuration failed\n"); + goto set_chan_mode_free; + } + + switch (config->channel_mode) { + case CHANNEL_MODE_PC: + ret = amd_espi_setup_periph_channel(amd_espi, slave_config); + if (ret != CB_SUCCESS) { + dev_err(amd_espi->dev, "Setup peripheral channel failed\n"); + goto set_chan_mode_free; + } + break; + case CHANNEL_MODE_VW: + ret = amd_espi_setup_vw_channel(amd_espi, slave_config); + if (ret != CB_SUCCESS) { + dev_err(amd_espi->dev, "Setup virtual wire channel failed\n"); + goto set_chan_mode_free; + } + break; + default: + dev_err(amd_espi->dev, "Channel: not supported\n"); + ret = -EOPNOTSUPP; + } + +set_chan_mode_free: + kfree(config); + return ret; +} + static long amd_espi_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { struct amd_espi *amd_espi = filp->private_data; @@ -227,6 +273,9 @@ static long amd_espi_ioctl(struct file *filp, unsigned int cmd, unsigned long ar case ESPI_SET_IO_MODE: ret = amd_espi_ioctl_set_io_mode(amd_espi, arg); break; + case ESPI_SET_CHAN_MODE: + ret = amd_espi_ioctl_set_channel_mode(amd_espi, arg); + break; default: dev_err(amd_espi->dev, "ESPI command not found, returning error\n"); ret = -EINVAL; diff --git a/drivers/spi/espi-amd.h b/drivers/spi/espi-amd.h index f1185f877a05..3774918d994f 100644 --- a/drivers/spi/espi-amd.h +++ b/drivers/spi/espi-amd.h @@ -144,6 +144,7 @@ #define ESPI_GET_CONFIG _IOR(ESPI_MAGIC_NUMBER, 0x2, struct config) #define ESPI_INBAND_RESET _IO(ESPI_MAGIC_NUMBER, 0x3) #define ESPI_SET_IO_MODE _IOW(ESPI_MAGIC_NUMBER, 0x4, struct config) +#define ESPI_SET_CHAN_MODE _IOW(ESPI_MAGIC_NUMBER, 0x5, struct config) /* * enum amd_espi_versions - eSPI controller versions -- 2.34.1