xref: /qemu/hw/acpi/ipmi.c (revision 86e91dd713414dda40bb16aabe2f1fc9ba95a3a7)
1*86e91dd7SCorey Minyard /*
2*86e91dd7SCorey Minyard  * IPMI ACPI firmware handling
3*86e91dd7SCorey Minyard  *
4*86e91dd7SCorey Minyard  * Copyright (c) 2015,2016 Corey Minyard, MontaVista Software, LLC
5*86e91dd7SCorey Minyard  *
6*86e91dd7SCorey Minyard  * This work is licensed under the terms of the GNU GPL, version 2 or later.
7*86e91dd7SCorey Minyard  * See the COPYING file in the top-level directory.
8*86e91dd7SCorey Minyard  */
9*86e91dd7SCorey Minyard 
10*86e91dd7SCorey Minyard #include "qemu/osdep.h"
11*86e91dd7SCorey Minyard #include "hw/ipmi/ipmi.h"
12*86e91dd7SCorey Minyard #include "hw/acpi/aml-build.h"
13*86e91dd7SCorey Minyard #include "hw/acpi/acpi.h"
14*86e91dd7SCorey Minyard #include "hw/acpi/ipmi.h"
15*86e91dd7SCorey Minyard 
16*86e91dd7SCorey Minyard static Aml *aml_ipmi_crs(IPMIFwInfo *info)
17*86e91dd7SCorey Minyard {
18*86e91dd7SCorey Minyard     Aml *crs = aml_resource_template();
19*86e91dd7SCorey Minyard 
20*86e91dd7SCorey Minyard     /*
21*86e91dd7SCorey Minyard      * The base address is fixed and cannot change.  That may be different
22*86e91dd7SCorey Minyard      * if someone does PCI, but we aren't there yet.
23*86e91dd7SCorey Minyard      */
24*86e91dd7SCorey Minyard     switch (info->memspace) {
25*86e91dd7SCorey Minyard     case IPMI_MEMSPACE_IO:
26*86e91dd7SCorey Minyard         aml_append(crs, aml_io(AML_DECODE16, info->base_address,
27*86e91dd7SCorey Minyard                                info->base_address + info->register_length - 1,
28*86e91dd7SCorey Minyard                                info->register_spacing, info->register_length));
29*86e91dd7SCorey Minyard         break;
30*86e91dd7SCorey Minyard     case IPMI_MEMSPACE_MEM32:
31*86e91dd7SCorey Minyard         aml_append(crs,
32*86e91dd7SCorey Minyard                    aml_dword_memory(AML_POS_DECODE,
33*86e91dd7SCorey Minyard                             AML_MIN_FIXED, AML_MAX_FIXED,
34*86e91dd7SCorey Minyard                             AML_NON_CACHEABLE, AML_READ_WRITE,
35*86e91dd7SCorey Minyard                             0xffffffff,
36*86e91dd7SCorey Minyard                             info->base_address,
37*86e91dd7SCorey Minyard                             info->base_address + info->register_length - 1,
38*86e91dd7SCorey Minyard                             info->register_spacing, info->register_length));
39*86e91dd7SCorey Minyard         break;
40*86e91dd7SCorey Minyard     case IPMI_MEMSPACE_MEM64:
41*86e91dd7SCorey Minyard         aml_append(crs,
42*86e91dd7SCorey Minyard                    aml_qword_memory(AML_POS_DECODE,
43*86e91dd7SCorey Minyard                             AML_MIN_FIXED, AML_MAX_FIXED,
44*86e91dd7SCorey Minyard                             AML_NON_CACHEABLE, AML_READ_WRITE,
45*86e91dd7SCorey Minyard                             0xffffffffffffffffULL,
46*86e91dd7SCorey Minyard                             info->base_address,
47*86e91dd7SCorey Minyard                             info->base_address + info->register_length - 1,
48*86e91dd7SCorey Minyard                             info->register_spacing, info->register_length));
49*86e91dd7SCorey Minyard         break;
50*86e91dd7SCorey Minyard     case IPMI_MEMSPACE_SMBUS:
51*86e91dd7SCorey Minyard         aml_append(crs, aml_return(aml_int(info->base_address)));
52*86e91dd7SCorey Minyard         break;
53*86e91dd7SCorey Minyard     default:
54*86e91dd7SCorey Minyard         abort();
55*86e91dd7SCorey Minyard     }
56*86e91dd7SCorey Minyard 
57*86e91dd7SCorey Minyard     if (info->interrupt_number) {
58*86e91dd7SCorey Minyard         aml_append(crs, aml_irq_no_flags(info->interrupt_number));
59*86e91dd7SCorey Minyard     }
60*86e91dd7SCorey Minyard 
61*86e91dd7SCorey Minyard     return crs;
62*86e91dd7SCorey Minyard }
63*86e91dd7SCorey Minyard 
64*86e91dd7SCorey Minyard static Aml *aml_ipmi_device(IPMIFwInfo *info)
65*86e91dd7SCorey Minyard {
66*86e91dd7SCorey Minyard     Aml *dev;
67*86e91dd7SCorey Minyard     uint16_t version = ((info->ipmi_spec_major_revision << 8)
68*86e91dd7SCorey Minyard                         | (info->ipmi_spec_minor_revision << 4));
69*86e91dd7SCorey Minyard 
70*86e91dd7SCorey Minyard     assert(info->ipmi_spec_minor_revision <= 15);
71*86e91dd7SCorey Minyard 
72*86e91dd7SCorey Minyard     dev = aml_device("MI%d", info->uuid);
73*86e91dd7SCorey Minyard     aml_append(dev, aml_name_decl("_HID", aml_eisaid("IPI0001")));
74*86e91dd7SCorey Minyard     aml_append(dev, aml_name_decl("_STR", aml_string("ipmi_%s",
75*86e91dd7SCorey Minyard                                                      info->interface_name)));
76*86e91dd7SCorey Minyard     aml_append(dev, aml_name_decl("_UID", aml_int(info->uuid)));
77*86e91dd7SCorey Minyard     aml_append(dev, aml_name_decl("_CRS", aml_ipmi_crs(info)));
78*86e91dd7SCorey Minyard     aml_append(dev, aml_name_decl("_IFT", aml_int(info->interface_type)));
79*86e91dd7SCorey Minyard     aml_append(dev, aml_name_decl("_SRV", aml_int(version)));
80*86e91dd7SCorey Minyard 
81*86e91dd7SCorey Minyard     return dev;
82*86e91dd7SCorey Minyard }
83*86e91dd7SCorey Minyard 
84*86e91dd7SCorey Minyard void build_acpi_ipmi_devices(Aml *scope, BusState *bus)
85*86e91dd7SCorey Minyard {
86*86e91dd7SCorey Minyard 
87*86e91dd7SCorey Minyard     BusChild *kid;
88*86e91dd7SCorey Minyard 
89*86e91dd7SCorey Minyard     QTAILQ_FOREACH(kid, &bus->children,  sibling) {
90*86e91dd7SCorey Minyard         IPMIInterface *ii;
91*86e91dd7SCorey Minyard         IPMIInterfaceClass *iic;
92*86e91dd7SCorey Minyard         IPMIFwInfo info;
93*86e91dd7SCorey Minyard         Object *obj = object_dynamic_cast(OBJECT(kid->child),
94*86e91dd7SCorey Minyard                                           TYPE_IPMI_INTERFACE);
95*86e91dd7SCorey Minyard 
96*86e91dd7SCorey Minyard         if (!obj) {
97*86e91dd7SCorey Minyard             continue;
98*86e91dd7SCorey Minyard         }
99*86e91dd7SCorey Minyard 
100*86e91dd7SCorey Minyard         ii = IPMI_INTERFACE(obj);
101*86e91dd7SCorey Minyard         iic = IPMI_INTERFACE_GET_CLASS(obj);
102*86e91dd7SCorey Minyard         iic->get_fwinfo(ii, &info);
103*86e91dd7SCorey Minyard         aml_append(scope, aml_ipmi_device(&info));
104*86e91dd7SCorey Minyard     }
105*86e91dd7SCorey Minyard }
106