diff options
author | Corey Minyard <minyard@acm.org> | 2007-05-08 03:23:51 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-05-08 14:14:58 -0400 |
commit | dba9b4f6a096f39dd58d67fbc643a7c1bf2973eb (patch) | |
tree | 461a9830112b56391b165257448df11248b0d8d0 /drivers | |
parent | 24c32d733dd44dbc5b9dcd0b8de58e16fdbeac76 (diff) |
ipmi: add powerpc openfirmware sensing
Add support for of_platform_driver to the ipmi_si module. When loading the
module, the driver will be registered to of_platform. The driver will be
probed for all devices with the type ipmi. It's supporting devices with
compatible settings ipmi-kcs, ipmi-smic and ipmi-bt. Only ipmi-kcs could be
tested.
Signed-off-by: Christian Krafft <krafft@de.ibm.com>
Acked-by: Heiko J Schick <schihei@de.ibm.com>
Signed-off-by: Corey Minyard <minyard@acm.org>
Acked-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/char/ipmi/ipmi_si_intf.c | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index e22146546add..e117049fb754 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c | |||
@@ -9,6 +9,7 @@ | |||
9 | * source@mvista.com | 9 | * source@mvista.com |
10 | * | 10 | * |
11 | * Copyright 2002 MontaVista Software Inc. | 11 | * Copyright 2002 MontaVista Software Inc. |
12 | * Copyright 2006 IBM Corp., Christian Krafft <krafft@de.ibm.com> | ||
12 | * | 13 | * |
13 | * This program is free software; you can redistribute it and/or modify it | 14 | * This program is free software; you can redistribute it and/or modify it |
14 | * under the terms of the GNU General Public License as published by the | 15 | * under the terms of the GNU General Public License as published by the |
@@ -64,6 +65,11 @@ | |||
64 | #include <linux/string.h> | 65 | #include <linux/string.h> |
65 | #include <linux/ctype.h> | 66 | #include <linux/ctype.h> |
66 | 67 | ||
68 | #ifdef CONFIG_PPC_OF | ||
69 | #include <asm/of_device.h> | ||
70 | #include <asm/of_platform.h> | ||
71 | #endif | ||
72 | |||
67 | #define PFX "ipmi_si: " | 73 | #define PFX "ipmi_si: " |
68 | 74 | ||
69 | /* Measure times between events in the driver. */ | 75 | /* Measure times between events in the driver. */ |
@@ -1006,6 +1012,7 @@ static DEFINE_MUTEX(smi_infos_lock); | |||
1006 | static int smi_num; /* Used to sequence the SMIs */ | 1012 | static int smi_num; /* Used to sequence the SMIs */ |
1007 | 1013 | ||
1008 | #define DEFAULT_REGSPACING 1 | 1014 | #define DEFAULT_REGSPACING 1 |
1015 | #define DEFAULT_REGSIZE 1 | ||
1009 | 1016 | ||
1010 | static int si_trydefaults = 1; | 1017 | static int si_trydefaults = 1; |
1011 | static char *si_type[SI_MAX_PARMS]; | 1018 | static char *si_type[SI_MAX_PARMS]; |
@@ -2172,6 +2179,99 @@ static struct pci_driver ipmi_pci_driver = { | |||
2172 | #endif /* CONFIG_PCI */ | 2179 | #endif /* CONFIG_PCI */ |
2173 | 2180 | ||
2174 | 2181 | ||
2182 | #ifdef CONFIG_PPC_OF | ||
2183 | static int __devinit ipmi_of_probe(struct of_device *dev, | ||
2184 | const struct of_device_id *match) | ||
2185 | { | ||
2186 | struct smi_info *info; | ||
2187 | struct resource resource; | ||
2188 | const int *regsize, *regspacing, *regshift; | ||
2189 | struct device_node *np = dev->node; | ||
2190 | int ret; | ||
2191 | int proplen; | ||
2192 | |||
2193 | dev_info(&dev->dev, PFX "probing via device tree\n"); | ||
2194 | |||
2195 | ret = of_address_to_resource(np, 0, &resource); | ||
2196 | if (ret) { | ||
2197 | dev_warn(&dev->dev, PFX "invalid address from OF\n"); | ||
2198 | return ret; | ||
2199 | } | ||
2200 | |||
2201 | regsize = get_property(np, "reg-size", &proplen); | ||
2202 | if (regsize && proplen != 4) { | ||
2203 | dev_warn(&dev->dev, PFX "invalid regsize from OF\n"); | ||
2204 | return -EINVAL; | ||
2205 | } | ||
2206 | |||
2207 | regspacing = get_property(np, "reg-spacing", &proplen); | ||
2208 | if (regspacing && proplen != 4) { | ||
2209 | dev_warn(&dev->dev, PFX "invalid regspacing from OF\n"); | ||
2210 | return -EINVAL; | ||
2211 | } | ||
2212 | |||
2213 | regshift = get_property(np, "reg-shift", &proplen); | ||
2214 | if (regshift && proplen != 4) { | ||
2215 | dev_warn(&dev->dev, PFX "invalid regshift from OF\n"); | ||
2216 | return -EINVAL; | ||
2217 | } | ||
2218 | |||
2219 | info = kzalloc(sizeof(*info), GFP_KERNEL); | ||
2220 | |||
2221 | if (!info) { | ||
2222 | dev_err(&dev->dev, | ||
2223 | PFX "could not allocate memory for OF probe\n"); | ||
2224 | return -ENOMEM; | ||
2225 | } | ||
2226 | |||
2227 | info->si_type = (enum si_type) match->data; | ||
2228 | info->addr_source = "device-tree"; | ||
2229 | info->io_setup = mem_setup; | ||
2230 | info->irq_setup = std_irq_setup; | ||
2231 | |||
2232 | info->io.addr_type = IPMI_MEM_ADDR_SPACE; | ||
2233 | info->io.addr_data = resource.start; | ||
2234 | |||
2235 | info->io.regsize = regsize ? *regsize : DEFAULT_REGSIZE; | ||
2236 | info->io.regspacing = regspacing ? *regspacing : DEFAULT_REGSPACING; | ||
2237 | info->io.regshift = regshift ? *regshift : 0; | ||
2238 | |||
2239 | info->irq = irq_of_parse_and_map(dev->node, 0); | ||
2240 | info->dev = &dev->dev; | ||
2241 | |||
2242 | dev_dbg(&dev->dev, "addr 0x%lx regsize %ld spacing %ld irq %x\n", | ||
2243 | info->io.addr_data, info->io.regsize, info->io.regspacing, | ||
2244 | info->irq); | ||
2245 | |||
2246 | dev->dev.driver_data = (void*) info; | ||
2247 | |||
2248 | return try_smi_init(info); | ||
2249 | } | ||
2250 | |||
2251 | static int __devexit ipmi_of_remove(struct of_device *dev) | ||
2252 | { | ||
2253 | cleanup_one_si(dev->dev.driver_data); | ||
2254 | return 0; | ||
2255 | } | ||
2256 | |||
2257 | static struct of_device_id ipmi_match[] = | ||
2258 | { | ||
2259 | { .type = "ipmi", .compatible = "ipmi-kcs", .data = (void *)(unsigned long) SI_KCS }, | ||
2260 | { .type = "ipmi", .compatible = "ipmi-smic", .data = (void *)(unsigned long) SI_SMIC }, | ||
2261 | { .type = "ipmi", .compatible = "ipmi-bt", .data = (void *)(unsigned long) SI_BT }, | ||
2262 | {}, | ||
2263 | }; | ||
2264 | |||
2265 | static struct of_platform_driver ipmi_of_platform_driver = | ||
2266 | { | ||
2267 | .name = "ipmi", | ||
2268 | .match_table = ipmi_match, | ||
2269 | .probe = ipmi_of_probe, | ||
2270 | .remove = __devexit_p(ipmi_of_remove), | ||
2271 | }; | ||
2272 | #endif /* CONFIG_PPC_OF */ | ||
2273 | |||
2274 | |||
2175 | static int try_get_dev_id(struct smi_info *smi_info) | 2275 | static int try_get_dev_id(struct smi_info *smi_info) |
2176 | { | 2276 | { |
2177 | unsigned char msg[2]; | 2277 | unsigned char msg[2]; |
@@ -2801,6 +2901,10 @@ static __devinit int init_ipmi_si(void) | |||
2801 | } | 2901 | } |
2802 | #endif | 2902 | #endif |
2803 | 2903 | ||
2904 | #ifdef CONFIG_PPC_OF | ||
2905 | of_register_platform_driver(&ipmi_of_platform_driver); | ||
2906 | #endif | ||
2907 | |||
2804 | if (si_trydefaults) { | 2908 | if (si_trydefaults) { |
2805 | mutex_lock(&smi_infos_lock); | 2909 | mutex_lock(&smi_infos_lock); |
2806 | if (list_empty(&smi_infos)) { | 2910 | if (list_empty(&smi_infos)) { |
@@ -2898,6 +3002,10 @@ static __exit void cleanup_ipmi_si(void) | |||
2898 | pci_unregister_driver(&ipmi_pci_driver); | 3002 | pci_unregister_driver(&ipmi_pci_driver); |
2899 | #endif | 3003 | #endif |
2900 | 3004 | ||
3005 | #ifdef CONFIG_PPC_OF | ||
3006 | of_unregister_platform_driver(&ipmi_of_platform_driver); | ||
3007 | #endif | ||
3008 | |||
2901 | mutex_lock(&smi_infos_lock); | 3009 | mutex_lock(&smi_infos_lock); |
2902 | list_for_each_entry_safe(e, tmp_e, &smi_infos, link) | 3010 | list_for_each_entry_safe(e, tmp_e, &smi_infos, link) |
2903 | cleanup_one_si(e); | 3011 | cleanup_one_si(e); |