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