This patch introduces an IOCTL command to retrieve the configuration of the eSPI controller and eSPI slave0. The configuration parameters include the frequency, channel, and IO mode. 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 | 69 ++++++++++++++++++++++++++++++++++++++ drivers/spi/espi-amd.h | 1 + 2 files changed, 70 insertions(+) diff --git a/drivers/spi/espi-amd-dev.c b/drivers/spi/espi-amd-dev.c index 5f25ad2b1eef..79224f4f86fa 100644 --- a/drivers/spi/espi-amd-dev.c +++ b/drivers/spi/espi-amd-dev.c @@ -100,6 +100,72 @@ static int amd_espi_ioctl_set_conf(struct amd_espi *amd_espi, unsigned long arg) return ret; } +static int amd_espi_ioctl_get_conf(struct amd_espi *amd_espi, unsigned long arg) +{ + u32 op_freq, io_mode, slave_conf; + struct config *config; + int ret; + + config = kzalloc(sizeof(*config), GFP_KERNEL); + if (!config) + return -ENOMEM; + + ret = amd_espi_get_general_config(amd_espi, &slave_conf); + if (ret != CB_SUCCESS) + goto get_config_free; + + /* Get IO mode configuration */ + io_mode = (slave_conf & GENMASK(27, 26)) >> ESPI_SLAVE_IO_MODE_SEL_SHIFT; + switch (io_mode) { + case IO_MODE_SINGLE: + case IO_MODE_DUAL: + case IO_MODE_QUAD: + config->io_mode = io_mode; + break; + default: + dev_err(amd_espi->dev, "Invalid IO mode\n"); + ret = -EOPNOTSUPP; + goto get_config_free; + } + + /* Get operating frequency configuration */ + op_freq = (slave_conf & GENMASK(22, 20)) >> ESPI_SLAVE_OP_FREQ_SEL_SHIFT; + switch (op_freq) { + case SLAVE_OP_FREQ_16: + case SLAVE_OP_FREQ_33: + case SLAVE_OP_FREQ_66: + config->op_freq = op_freq; + break; + default: + dev_err(amd_espi->dev, "Invalid operating frequency\n"); + ret = -EOPNOTSUPP; + goto get_config_free; + } + + /* Get channel configuration */ + ret = amd_espi_get_channel_config(amd_espi); + config->channel_mode = 0; + + if (ret == -EOPNOTSUPP) { + config->channel_mode = CHAN_NOT_ENABLED; + } else { + if (ret & CHANNEL_MODE_PC) + config->channel_mode |= CHANNEL_MODE_PC; + if (ret & CHANNEL_MODE_VW) + config->channel_mode |= CHANNEL_MODE_VW; + } + + if (copy_to_user((void __user *)arg, config, sizeof(struct config))) { + ret = -EFAULT; + goto get_config_free; + } + ret = 0; + +get_config_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; @@ -113,6 +179,9 @@ static long amd_espi_ioctl(struct file *filp, unsigned int cmd, unsigned long ar case ESPI_SET_CONFIG: ret = amd_espi_ioctl_set_conf(amd_espi, arg); break; + case ESPI_GET_CONFIG: + ret = amd_espi_ioctl_get_conf(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 1de53426059b..bc15f7417c37 100644 --- a/drivers/spi/espi-amd.h +++ b/drivers/spi/espi-amd.h @@ -141,6 +141,7 @@ /* IOCTL calls */ #define ESPI_MAGIC_NUMBER 'i' #define ESPI_SET_CONFIG _IOW(ESPI_MAGIC_NUMBER, 0x1, struct config) +#define ESPI_GET_CONFIG _IOR(ESPI_MAGIC_NUMBER, 0x2, struct config) /* * enum amd_espi_versions - eSPI controller versions -- 2.34.1