Commit 7c148722 authored by Terry Bowman's avatar Terry Bowman Committed by Wolfram Sang

i2c: piix4: Add EFCH MMIO support to region request and release

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: default avatarTerry Bowman <terry.bowman@amd.com>
Reviewed-by: default avatarAndy Shevchenko <andy.shevchenko@gmail.com>
Reviewed-by: default avatarJean Delvare <jdelvare@suse.de>
[wsa: rebased after fixup in previous patch]
Signed-off-by: default avatarWolfram Sang <wsa@kernel.org>
parent fbafbd51
...@@ -98,6 +98,9 @@ ...@@ -98,6 +98,9 @@
#define SB800_PIIX4_PORT_IDX_MASK_KERNCZ 0x18 #define SB800_PIIX4_PORT_IDX_MASK_KERNCZ 0x18
#define SB800_PIIX4_PORT_IDX_SHIFT_KERNCZ 3 #define SB800_PIIX4_PORT_IDX_SHIFT_KERNCZ 3
#define SB800_PIIX4_FCH_PM_ADDR 0xFED80300
#define SB800_PIIX4_FCH_PM_SIZE 8
/* insmod parameters */ /* insmod parameters */
/* If force is set to anything different from 0, we forcibly enable the /* 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] = { ...@@ -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"; 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 { struct i2c_piix4_adapdata {
unsigned short smba; unsigned short smba;
...@@ -163,10 +172,40 @@ struct i2c_piix4_adapdata { ...@@ -163,10 +172,40 @@ struct i2c_piix4_adapdata {
bool sb800_main; bool sb800_main;
bool notify_imc; bool notify_imc;
u8 port; /* Port number, shifted */ u8 port; /* Port number, shifted */
struct sb800_mmio_cfg mmio_cfg;
}; };
static int piix4_sb800_region_request(struct device *dev) static int piix4_sb800_region_request(struct device *dev,
struct sb800_mmio_cfg *mmio_cfg)
{ {
if (mmio_cfg->use_mmio) {
struct resource *res;
void __iomem *addr;
res = request_mem_region_muxed(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;
return 0;
}
if (!request_muxed_region(SB800_PIIX4_SMB_IDX, SB800_PIIX4_SMB_MAP_SIZE, if (!request_muxed_region(SB800_PIIX4_SMB_IDX, SB800_PIIX4_SMB_MAP_SIZE,
"sb800_piix4_smb")) { "sb800_piix4_smb")) {
dev_err(dev, dev_err(dev,
...@@ -178,8 +217,15 @@ static int piix4_sb800_region_request(struct device *dev) ...@@ -178,8 +217,15 @@ static int piix4_sb800_region_request(struct device *dev)
return 0; 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)
{ {
if (mmio_cfg->use_mmio) {
iounmap(mmio_cfg->addr);
release_resource(mmio_cfg->res);
return;
}
release_region(SB800_PIIX4_SMB_IDX, SB800_PIIX4_SMB_MAP_SIZE); release_region(SB800_PIIX4_SMB_IDX, SB800_PIIX4_SMB_MAP_SIZE);
} }
...@@ -288,11 +334,13 @@ static int piix4_setup_sb800_smba(struct pci_dev *PIIX4_dev, ...@@ -288,11 +334,13 @@ static int piix4_setup_sb800_smba(struct pci_dev *PIIX4_dev,
u8 *smb_en_status, u8 *smb_en_status,
unsigned short *piix4_smba) unsigned short *piix4_smba)
{ {
struct sb800_mmio_cfg mmio_cfg;
u8 smba_en_lo; u8 smba_en_lo;
u8 smba_en_hi; u8 smba_en_hi;
int retval; int retval;
retval = piix4_sb800_region_request(&PIIX4_dev->dev); mmio_cfg.use_mmio = 0;
retval = piix4_sb800_region_request(&PIIX4_dev->dev, &mmio_cfg);
if (retval) if (retval)
return retval; return retval;
...@@ -301,7 +349,7 @@ static int piix4_setup_sb800_smba(struct pci_dev *PIIX4_dev, ...@@ -301,7 +349,7 @@ static int piix4_setup_sb800_smba(struct pci_dev *PIIX4_dev,
outb_p(smb_en + 1, SB800_PIIX4_SMB_IDX); outb_p(smb_en + 1, SB800_PIIX4_SMB_IDX);
smba_en_hi = inb_p(SB800_PIIX4_SMB_IDX + 1); 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) { if (!smb_en) {
*smb_en_status = smba_en_lo & 0x10; *smb_en_status = smba_en_lo & 0x10;
...@@ -328,6 +376,7 @@ static int piix4_setup_sb800(struct pci_dev *PIIX4_dev, ...@@ -328,6 +376,7 @@ static int piix4_setup_sb800(struct pci_dev *PIIX4_dev,
unsigned short piix4_smba; unsigned short piix4_smba;
u8 smb_en, smb_en_status, port_sel; u8 smb_en, smb_en_status, port_sel;
u8 i2ccfg, i2ccfg_offset = 0x10; u8 i2ccfg, i2ccfg_offset = 0x10;
struct sb800_mmio_cfg mmio_cfg;
int retval; int retval;
/* SB800 and later SMBus does not support forcing address */ /* SB800 and later SMBus does not support forcing address */
...@@ -407,7 +456,8 @@ static int piix4_setup_sb800(struct pci_dev *PIIX4_dev, ...@@ -407,7 +456,8 @@ static int piix4_setup_sb800(struct pci_dev *PIIX4_dev,
piix4_port_shift_sb800 = SB800_PIIX4_PORT_IDX_SHIFT; piix4_port_shift_sb800 = SB800_PIIX4_PORT_IDX_SHIFT;
} }
} else { } else {
retval = piix4_sb800_region_request(&PIIX4_dev->dev); mmio_cfg.use_mmio = 0;
retval = piix4_sb800_region_request(&PIIX4_dev->dev, &mmio_cfg);
if (retval) { if (retval) {
release_region(piix4_smba, SMBIOSIZE); release_region(piix4_smba, SMBIOSIZE);
return retval; return retval;
...@@ -420,7 +470,7 @@ static int piix4_setup_sb800(struct pci_dev *PIIX4_dev, ...@@ -420,7 +470,7 @@ static int piix4_setup_sb800(struct pci_dev *PIIX4_dev,
SB800_PIIX4_PORT_IDX; SB800_PIIX4_PORT_IDX;
piix4_port_mask_sb800 = SB800_PIIX4_PORT_IDX_MASK; piix4_port_mask_sb800 = SB800_PIIX4_PORT_IDX_MASK;
piix4_port_shift_sb800 = SB800_PIIX4_PORT_IDX_SHIFT; piix4_port_shift_sb800 = SB800_PIIX4_PORT_IDX_SHIFT;
piix4_sb800_region_release(&PIIX4_dev->dev); piix4_sb800_region_release(&PIIX4_dev->dev, &mmio_cfg);
} }
dev_info(&PIIX4_dev->dev, dev_info(&PIIX4_dev->dev,
...@@ -731,7 +781,7 @@ static s32 piix4_access_sb800(struct i2c_adapter *adap, u16 addr, ...@@ -731,7 +781,7 @@ static s32 piix4_access_sb800(struct i2c_adapter *adap, u16 addr,
u8 prev_port; u8 prev_port;
int retval; int retval;
retval = piix4_sb800_region_request(&adap->dev); retval = piix4_sb800_region_request(&adap->dev, &adapdata->mmio_cfg);
if (retval) if (retval)
return retval; return retval;
...@@ -802,7 +852,7 @@ static s32 piix4_access_sb800(struct i2c_adapter *adap, u16 addr, ...@@ -802,7 +852,7 @@ static s32 piix4_access_sb800(struct i2c_adapter *adap, u16 addr,
piix4_imc_wakeup(); piix4_imc_wakeup();
release: release:
piix4_sb800_region_release(&adap->dev); piix4_sb800_region_release(&adap->dev, &adapdata->mmio_cfg);
return retval; return retval;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment