[PATCH v3 6/9] i2c: piix4: Add EFCH MMIO support to region request and release

From: Terry Bowman
Date: Wed Jan 19 2022 - 18:09:08 EST


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>
---
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..7aa6ceb27e4b 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_muxed_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