Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 357591
b: refs/heads/master
c: 01560f6
h: refs/heads/master
i:
  357589: 6cf0e39
  357587: e212f4f
  357583: d43b304
v: v3
  • Loading branch information
Aaron Sierra authored and Samuel Ortiz committed Feb 13, 2013
1 parent ea98778 commit 878337d
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 34 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: fbc6ae363e5e589a28135c051a2ff835e6236d5f
refs/heads/master: 01560f6bb958b821ceec98590a7147d610a62625
109 changes: 76 additions & 33 deletions trunk/drivers/mfd/lpc_ich.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,17 +75,28 @@
#define ACPIBASE_GCS_OFF 0x3410
#define ACPIBASE_GCS_END 0x3414

#define GPIOBASE 0x48
#define GPIOCTRL 0x4C
#define GPIOBASE_ICH0 0x58
#define GPIOCTRL_ICH0 0x5C
#define GPIOBASE_ICH6 0x48
#define GPIOCTRL_ICH6 0x4C

#define RCBABASE 0xf0

#define wdt_io_res(i) wdt_res(0, i)
#define wdt_mem_res(i) wdt_res(ICH_RES_MEM_OFF, i)
#define wdt_res(b, i) (&wdt_ich_res[(b) + (i)])

static int lpc_ich_acpi_save = -1;
static int lpc_ich_gpio_save = -1;
struct lpc_ich_cfg {
int base;
int ctrl;
int save;
};

struct lpc_ich_priv {
int chipset;
struct lpc_ich_cfg acpi;
struct lpc_ich_cfg gpio;
};

static struct resource wdt_ich_res[] = {
/* ACPI - TCO */
Expand Down Expand Up @@ -661,39 +672,44 @@ MODULE_DEVICE_TABLE(pci, lpc_ich_ids);

static void lpc_ich_restore_config_space(struct pci_dev *dev)
{
if (lpc_ich_acpi_save >= 0) {
pci_write_config_byte(dev, ACPICTRL, lpc_ich_acpi_save);
lpc_ich_acpi_save = -1;
struct lpc_ich_priv *priv = pci_get_drvdata(dev);

if (priv->acpi.save >= 0) {
pci_write_config_byte(dev, priv->acpi.ctrl, priv->acpi.save);
priv->acpi.save = -1;
}

if (lpc_ich_gpio_save >= 0) {
pci_write_config_byte(dev, GPIOCTRL, lpc_ich_gpio_save);
lpc_ich_gpio_save = -1;
if (priv->gpio.save >= 0) {
pci_write_config_byte(dev, priv->gpio.ctrl, priv->gpio.save);
priv->gpio.save = -1;
}
}

static void lpc_ich_enable_acpi_space(struct pci_dev *dev)
{
struct lpc_ich_priv *priv = pci_get_drvdata(dev);
u8 reg_save;

pci_read_config_byte(dev, ACPICTRL, &reg_save);
pci_write_config_byte(dev, ACPICTRL, reg_save | 0x10);
lpc_ich_acpi_save = reg_save;
pci_read_config_byte(dev, priv->acpi.ctrl, &reg_save);
pci_write_config_byte(dev, priv->acpi.ctrl, reg_save | 0x10);
priv->acpi.save = reg_save;
}

static void lpc_ich_enable_gpio_space(struct pci_dev *dev)
{
struct lpc_ich_priv *priv = pci_get_drvdata(dev);
u8 reg_save;

pci_read_config_byte(dev, GPIOCTRL, &reg_save);
pci_write_config_byte(dev, GPIOCTRL, reg_save | 0x10);
lpc_ich_gpio_save = reg_save;
pci_read_config_byte(dev, priv->gpio.ctrl, &reg_save);
pci_write_config_byte(dev, priv->gpio.ctrl, reg_save | 0x10);
priv->gpio.save = reg_save;
}

static void lpc_ich_finalize_cell(struct mfd_cell *cell,
const struct pci_device_id *id)
static void lpc_ich_finalize_cell(struct pci_dev *dev, struct mfd_cell *cell)
{
cell->platform_data = &lpc_chipset_info[id->driver_data];
struct lpc_ich_priv *priv = pci_get_drvdata(dev);

cell->platform_data = &lpc_chipset_info[priv->chipset];
cell->pdata_size = sizeof(struct lpc_ich_info);
}

Expand Down Expand Up @@ -721,17 +737,17 @@ static int lpc_ich_check_conflict_gpio(struct resource *res)
return use_gpio ? use_gpio : ret;
}

static int lpc_ich_init_gpio(struct pci_dev *dev,
const struct pci_device_id *id)
static int lpc_ich_init_gpio(struct pci_dev *dev)
{
struct lpc_ich_priv *priv = pci_get_drvdata(dev);
u32 base_addr_cfg;
u32 base_addr;
int ret;
bool acpi_conflict = false;
struct resource *res;

/* Setup power management base register */
pci_read_config_dword(dev, ACPIBASE, &base_addr_cfg);
pci_read_config_dword(dev, priv->acpi.base, &base_addr_cfg);
base_addr = base_addr_cfg & 0x0000ff80;
if (!base_addr) {
dev_notice(&dev->dev, "I/O space for ACPI uninitialized\n");
Expand All @@ -757,7 +773,7 @@ static int lpc_ich_init_gpio(struct pci_dev *dev,

gpe0_done:
/* Setup GPIO base register */
pci_read_config_dword(dev, GPIOBASE, &base_addr_cfg);
pci_read_config_dword(dev, priv->gpio.base, &base_addr_cfg);
base_addr = base_addr_cfg & 0x0000ff80;
if (!base_addr) {
dev_notice(&dev->dev, "I/O space for GPIO uninitialized\n");
Expand All @@ -768,7 +784,7 @@ static int lpc_ich_init_gpio(struct pci_dev *dev,
/* Older devices provide fewer GPIO and have a smaller resource size. */
res = &gpio_ich_res[ICH_RES_GPIO];
res->start = base_addr;
switch (lpc_chipset_info[id->driver_data].gpio_version) {
switch (lpc_chipset_info[priv->chipset].gpio_version) {
case ICH_V5_GPIO:
case ICH_V10CORP_GPIO:
res->end = res->start + 128 - 1;
Expand All @@ -784,10 +800,10 @@ static int lpc_ich_init_gpio(struct pci_dev *dev,
acpi_conflict = true;
goto gpio_done;
}
lpc_chipset_info[id->driver_data].use_gpio = ret;
lpc_chipset_info[priv->chipset].use_gpio = ret;
lpc_ich_enable_gpio_space(dev);

lpc_ich_finalize_cell(&lpc_ich_cells[LPC_GPIO], id);
lpc_ich_finalize_cell(dev, &lpc_ich_cells[LPC_GPIO]);
ret = mfd_add_devices(&dev->dev, -1, &lpc_ich_cells[LPC_GPIO],
1, NULL, 0, NULL);

Expand All @@ -798,16 +814,16 @@ static int lpc_ich_init_gpio(struct pci_dev *dev,
return ret;
}

static int lpc_ich_init_wdt(struct pci_dev *dev,
const struct pci_device_id *id)
static int lpc_ich_init_wdt(struct pci_dev *dev)
{
struct lpc_ich_priv *priv = pci_get_drvdata(dev);
u32 base_addr_cfg;
u32 base_addr;
int ret;
struct resource *res;

/* Setup power management base register */
pci_read_config_dword(dev, ACPIBASE, &base_addr_cfg);
pci_read_config_dword(dev, priv->acpi.base, &base_addr_cfg);
base_addr = base_addr_cfg & 0x0000ff80;
if (!base_addr) {
dev_notice(&dev->dev, "I/O space for ACPI uninitialized\n");
Expand All @@ -830,7 +846,7 @@ static int lpc_ich_init_wdt(struct pci_dev *dev,
* we have to read RCBA from PCI Config space 0xf0 and use
* it as base. GCS = RCBA + ICH6_GCS(0x3410).
*/
if (lpc_chipset_info[id->driver_data].iTCO_version == 1) {
if (lpc_chipset_info[priv->chipset].iTCO_version == 1) {
/* Don't register iomem for TCO ver 1 */
lpc_ich_cells[LPC_WDT].num_resources--;
} else {
Expand All @@ -847,7 +863,7 @@ static int lpc_ich_init_wdt(struct pci_dev *dev,
res->end = base_addr + ACPIBASE_GCS_END;
}

lpc_ich_finalize_cell(&lpc_ich_cells[LPC_WDT], id);
lpc_ich_finalize_cell(dev, &lpc_ich_cells[LPC_WDT]);
ret = mfd_add_devices(&dev->dev, -1, &lpc_ich_cells[LPC_WDT],
1, NULL, 0, NULL);

Expand All @@ -858,14 +874,35 @@ static int lpc_ich_init_wdt(struct pci_dev *dev,
static int lpc_ich_probe(struct pci_dev *dev,
const struct pci_device_id *id)
{
struct lpc_ich_priv *priv;
int ret;
bool cell_added = false;

ret = lpc_ich_init_wdt(dev, id);
priv = kmalloc(GFP_KERNEL, sizeof(struct lpc_ich_priv));
if (!priv)
return -ENOMEM;

priv->chipset = id->driver_data;
priv->acpi.save = -1;
priv->acpi.base = ACPIBASE;
priv->acpi.ctrl = ACPICTRL;

priv->gpio.save = -1;
if (priv->chipset <= LPC_ICH5) {
priv->gpio.base = GPIOBASE_ICH0;
priv->gpio.ctrl = GPIOCTRL_ICH0;
} else {
priv->gpio.base = GPIOBASE_ICH6;
priv->gpio.ctrl = GPIOCTRL_ICH6;
}

pci_set_drvdata(dev, priv);

ret = lpc_ich_init_wdt(dev);
if (!ret)
cell_added = true;

ret = lpc_ich_init_gpio(dev, id);
ret = lpc_ich_init_gpio(dev);
if (!ret)
cell_added = true;

Expand All @@ -876,6 +913,8 @@ static int lpc_ich_probe(struct pci_dev *dev,
if (!cell_added) {
dev_warn(&dev->dev, "No MFD cells added\n");
lpc_ich_restore_config_space(dev);
pci_set_drvdata(dev, NULL);
kfree(priv);
return -ENODEV;
}

Expand All @@ -884,8 +923,12 @@ static int lpc_ich_probe(struct pci_dev *dev,

static void lpc_ich_remove(struct pci_dev *dev)
{
void *priv = pci_get_drvdata(dev);

mfd_remove_devices(&dev->dev);
lpc_ich_restore_config_space(dev);
pci_set_drvdata(dev, NULL);
kfree(priv);
}

static struct pci_driver lpc_ich_driver = {
Expand Down

0 comments on commit 878337d

Please sign in to comment.