This patch adds support for a new IOCTL command in the espi_amd driver to set the operating frequency of the eSPI controller. The frequency value can be one of the following supported options: 16MHz, 33MHz or 66MHz. 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 | 40 ++++++++++++++++++++++++++++++++++++++ drivers/spi/espi-amd.h | 1 + 2 files changed, 41 insertions(+) diff --git a/drivers/spi/espi-amd-dev.c b/drivers/spi/espi-amd-dev.c index c78a9b2b059b..9f1968566980 100644 --- a/drivers/spi/espi-amd-dev.c +++ b/drivers/spi/espi-amd-dev.c @@ -249,6 +249,43 @@ static int amd_espi_ioctl_set_channel_mode(struct amd_espi *amd_espi, unsigned l return ret; } +static int amd_espi_ioctl_set_freq(struct amd_espi *amd_espi, unsigned long arg) +{ + u32 ctrlr_config, slave_config; + struct config *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_freq_free; + } + + ctrlr_config = readl(ESPI_BASE + AMD_ESPI_SLAVE0_CONFIG_REG); + + ret = amd_espi_get_general_config(amd_espi, &slave_config); + if (ret != CB_SUCCESS) + goto set_freq_free; + + ret = amd_espi_set_freqmode(amd_espi, &slave_config, &ctrlr_config, config->op_freq); + if (ret != CB_SUCCESS) + goto set_freq_free; + + ret = amd_espi_set_config(amd_espi, slave_config, ESPI_SLAVE_GENERAL_CAPS_CFG); + if (ret != CB_SUCCESS) { + dev_err(amd_espi->dev, "Set operating frequency failed\n"); + goto set_freq_free; + } + writel(ctrlr_config, (ESPI_BASE + AMD_ESPI_SLAVE0_CONFIG_REG)); + +set_freq_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; @@ -276,6 +313,9 @@ static long amd_espi_ioctl(struct file *filp, unsigned int cmd, unsigned long ar case ESPI_SET_CHAN_MODE: ret = amd_espi_ioctl_set_channel_mode(amd_espi, arg); break; + case ESPI_SET_FREQ: + ret = amd_espi_ioctl_set_freq(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 3774918d994f..e5760db7c1d3 100644 --- a/drivers/spi/espi-amd.h +++ b/drivers/spi/espi-amd.h @@ -145,6 +145,7 @@ #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) +#define ESPI_SET_FREQ _IOW(ESPI_MAGIC_NUMBER, 0x6, struct config) /* * enum amd_espi_versions - eSPI controller versions -- 2.34.1