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: Terry Bowman <terry.bowman@amd.com> Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com> Reviewed-by: Jean Delvare <jdelvare@suse.de> [wsa: rebased after fixup in previous patch] Signed-off-by: Wolfram Sang <wsa@kernel.org>
This commit is contained in:
parent
fbafbd51bf
commit
7c148722d0
@ -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] = {
|
|||||||
};
|
};
|
||||||
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 {
|
|||||||
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)
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user