diff options
author | Corey Minyard <cminyard@mvista.com> | 2012-10-16 16:53:40 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-16 21:07:12 -0400 |
commit | a6c16c2803089f032f86fe15e952176c0713d6e3 (patch) | |
tree | 2705c4c5df91ffc31d8ccf2914d1ac67b1f7d901 /drivers/char/ipmi/ipmi_si_intf.c | |
parent | 9ebca93bf3b350910c66516cbec68899eeddfd8e (diff) |
IPMI: Detect register spacing on PCI interfaces
The IPMI spec defines a way to detect register spacing for PCI interfaces,
so implement it.
Signed-off-by: Steven Hsieh <sshsieh@broadcom.com>
Signed-off-by: Corey Minyard <cminyard@mvista.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/char/ipmi/ipmi_si_intf.c')
-rw-r--r-- | drivers/char/ipmi/ipmi_si_intf.c | 36 |
1 files changed, 34 insertions, 2 deletions
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 83f85cf7fb1b..32a6c7e256bd 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c | |||
@@ -2424,6 +2424,38 @@ static void ipmi_pci_cleanup(struct smi_info *info) | |||
2424 | pci_disable_device(pdev); | 2424 | pci_disable_device(pdev); |
2425 | } | 2425 | } |
2426 | 2426 | ||
2427 | static int __devinit ipmi_pci_probe_regspacing(struct smi_info *info) | ||
2428 | { | ||
2429 | if (info->si_type == SI_KCS) { | ||
2430 | unsigned char status; | ||
2431 | int regspacing; | ||
2432 | |||
2433 | info->io.regsize = DEFAULT_REGSIZE; | ||
2434 | info->io.regshift = 0; | ||
2435 | info->io_size = 2; | ||
2436 | info->handlers = &kcs_smi_handlers; | ||
2437 | |||
2438 | /* detect 1, 4, 16byte spacing */ | ||
2439 | for (regspacing = DEFAULT_REGSPACING; regspacing <= 16;) { | ||
2440 | info->io.regspacing = regspacing; | ||
2441 | if (info->io_setup(info)) { | ||
2442 | dev_err(info->dev, | ||
2443 | "Could not setup I/O space\n"); | ||
2444 | return DEFAULT_REGSPACING; | ||
2445 | } | ||
2446 | /* write invalid cmd */ | ||
2447 | info->io.outputb(&info->io, 1, 0x10); | ||
2448 | /* read status back */ | ||
2449 | status = info->io.inputb(&info->io, 1); | ||
2450 | info->io_cleanup(info); | ||
2451 | if (status) | ||
2452 | return regspacing; | ||
2453 | regspacing *= 4; | ||
2454 | } | ||
2455 | } | ||
2456 | return DEFAULT_REGSPACING; | ||
2457 | } | ||
2458 | |||
2427 | static int __devinit ipmi_pci_probe(struct pci_dev *pdev, | 2459 | static int __devinit ipmi_pci_probe(struct pci_dev *pdev, |
2428 | const struct pci_device_id *ent) | 2460 | const struct pci_device_id *ent) |
2429 | { | 2461 | { |
@@ -2476,8 +2508,8 @@ static int __devinit ipmi_pci_probe(struct pci_dev *pdev, | |||
2476 | } | 2508 | } |
2477 | info->io.addr_data = pci_resource_start(pdev, 0); | 2509 | info->io.addr_data = pci_resource_start(pdev, 0); |
2478 | 2510 | ||
2479 | info->io.regspacing = DEFAULT_REGSPACING; | 2511 | info->io.regspacing = ipmi_pci_probe_regspacing(info); |
2480 | info->io.regsize = DEFAULT_REGSPACING; | 2512 | info->io.regsize = DEFAULT_REGSIZE; |
2481 | info->io.regshift = 0; | 2513 | info->io.regshift = 0; |
2482 | 2514 | ||
2483 | info->irq = pdev->irq; | 2515 | info->irq = pdev->irq; |