EFCH cd6h/cd7h port I/O may no longer be available on later AMD processors and it is recommended to use MMIO instead. Update the request and release functions to support MMIO. MMIO request/release and mmapping require details during cleanup. Add a MMIO configuration structure containing resource and vaddress details for mapping the region, accessing the region, and releasing the region. Signed-off-by: Terry Bowman <terry.bowman@xxxxxxx> To: Guenter Roeck <linux@xxxxxxxxxxxx> To: linux-watchdog@xxxxxxxxxxxxxxx To: Jean Delvare <jdelvare@xxxxxxxx> To: linux-i2c@xxxxxxxxxxxxxxx To: Wolfram Sang <wsa@xxxxxxxxxx> To: Andy Shevchenko <andy.shevchenko@xxxxxxxxx> To: Rafael J. Wysocki <rafael.j.wysocki@xxxxxxxxx> Cc: linux-kernel@xxxxxxxxxxxxxxx Cc: Wim Van Sebroeck <wim@xxxxxxxxxxxxxxxxxx> Cc: Robert Richter <rrichter@xxxxxxx> Cc: Thomas Lendacky <thomas.lendacky@xxxxxxx> --- drivers/i2c/busses/i2c-piix4.c | 76 +++++++++++++++++++++++++++------- 1 file changed, 61 insertions(+), 15 deletions(-) diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c index 58b613b78c97..ffb1367dd852 100644 --- a/drivers/i2c/busses/i2c-piix4.c +++ b/drivers/i2c/busses/i2c-piix4.c @@ -98,6 +98,9 @@ #define SB800_PIIX4_PORT_IDX_MASK_KERNCZ 0x18 #define SB800_PIIX4_PORT_IDX_SHIFT_KERNCZ 3 +#define SB800_PIIX4_FCH_PM_ADDR 0xFED80300 +#define SB800_PIIX4_FCH_PM_SIZE 8 + /* insmod parameters */ /* If force is set to anything different from 0, we forcibly enable the @@ -156,6 +159,12 @@ static const char *piix4_main_port_names_sb800[PIIX4_MAX_ADAPTERS] = { }; static const char *piix4_aux_port_name_sb800 = " port 1"; +struct sb800_mmio_cfg { + void __iomem *addr; + struct resource *res; + bool use_mmio; +}; + struct i2c_piix4_adapdata { unsigned short smba; @@ -163,26 +172,60 @@ struct i2c_piix4_adapdata { bool sb800_main; bool notify_imc; u8 port; /* Port number, shifted */ + struct sb800_mmio_cfg mmio_cfg; }; -static int piix4_sb800_region_setup(struct device *dev) +static int piix4_sb800_region_setup(struct device *dev, + struct sb800_mmio_cfg *mmio_cfg) { - if (!request_muxed_region(SB800_PIIX4_SMB_IDX, - SB800_PIIX4_SMB_MAP_SIZE, - "sb800_piix4_smb")) { - dev_err(dev, - "SMB base address index region 0x%x already in use.\n", - SB800_PIIX4_SMB_IDX); - return -EBUSY; + if (mmio_cfg->use_mmio) { + struct resource *res; + void __iomem *addr; + + res = request_mem_region(SB800_PIIX4_FCH_PM_ADDR, + SB800_PIIX4_FCH_PM_SIZE, + "sb800_piix4_smb"); + if (!res) { + dev_err(dev, + "SMBus base address memory region 0x%x already in use.\n", + SB800_PIIX4_FCH_PM_ADDR); + return -EBUSY; + } + + addr = ioremap(SB800_PIIX4_FCH_PM_ADDR, + SB800_PIIX4_FCH_PM_SIZE); + if (!addr) { + release_resource(res); + dev_err(dev, "SMBus base address mapping failed.\n"); + return -ENOMEM; + } + + mmio_cfg->res = res; + mmio_cfg->addr = addr; + } else { + if (!request_muxed_region(SB800_PIIX4_SMB_IDX, + SB800_PIIX4_SMB_MAP_SIZE, + "sb800_piix4_smb")) { + dev_err(dev, + "SMBus base address index region 0x%x already in use.\n", + SB800_PIIX4_SMB_IDX); + return -EBUSY; + } } return 0; } -static void piix4_sb800_region_release(struct device *dev) +static void piix4_sb800_region_release(struct device *dev, + struct sb800_mmio_cfg *mmio_cfg) { - release_region(SB800_PIIX4_SMB_IDX, - SB800_PIIX4_SMB_MAP_SIZE); + if (mmio_cfg->use_mmio) { + iounmap(mmio_cfg->addr); + release_resource(mmio_cfg->res); + } else { + release_region(SB800_PIIX4_SMB_IDX, + SB800_PIIX4_SMB_MAP_SIZE); + } } static int piix4_setup(struct pci_dev *PIIX4_dev, @@ -290,11 +333,14 @@ static int piix4_setup_sb800_smba(struct pci_dev *PIIX4_dev, u8 *smb_en_status, unsigned short *piix4_smba) { + struct sb800_mmio_cfg mmio_cfg; u8 smba_en_lo; u8 smba_en_hi; int retval; - retval = piix4_sb800_region_setup(&PIIX4_dev->dev); + mmio_cfg.use_mmio = 0; + + retval = piix4_sb800_region_setup(&PIIX4_dev->dev, &mmio_cfg); if (retval) return retval; @@ -303,7 +349,7 @@ static int piix4_setup_sb800_smba(struct pci_dev *PIIX4_dev, outb_p(smb_en + 1, SB800_PIIX4_SMB_IDX); smba_en_hi = inb_p(SB800_PIIX4_SMB_IDX + 1); - piix4_sb800_region_release(&PIIX4_dev->dev); + piix4_sb800_region_release(&PIIX4_dev->dev, &mmio_cfg); if (!smb_en) { *smb_en_status = smba_en_lo & 0x10; @@ -732,7 +778,7 @@ static s32 piix4_access_sb800(struct i2c_adapter *adap, u16 addr, u8 prev_port; int retval; - retval = piix4_sb800_region_setup(&adap->dev); + retval = piix4_sb800_region_setup(&adap->dev, &adapdata->mmio_cfg); if (retval) return retval; @@ -803,7 +849,7 @@ static s32 piix4_access_sb800(struct i2c_adapter *adap, u16 addr, piix4_imc_wakeup(); release: - piix4_sb800_region_release(&adap->dev); + piix4_sb800_region_release(&adap->dev, &adapdata->mmio_cfg); return retval; } -- 2.30.2