ipmi_dmi.c (5285B)
1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * A hack to create a platform device from a DMI entry. This will 4 * allow autoloading of the IPMI drive based on SMBIOS entries. 5 */ 6 7#define pr_fmt(fmt) "%s" fmt, "ipmi:dmi: " 8#define dev_fmt pr_fmt 9 10#include <linux/ipmi.h> 11#include <linux/init.h> 12#include <linux/dmi.h> 13#include <linux/platform_device.h> 14#include <linux/property.h> 15#include "ipmi_dmi.h" 16#include "ipmi_plat_data.h" 17 18#define IPMI_DMI_TYPE_KCS 0x01 19#define IPMI_DMI_TYPE_SMIC 0x02 20#define IPMI_DMI_TYPE_BT 0x03 21#define IPMI_DMI_TYPE_SSIF 0x04 22 23struct ipmi_dmi_info { 24 enum si_type si_type; 25 unsigned int space; /* addr space for si, intf# for ssif */ 26 unsigned long addr; 27 u8 slave_addr; 28 struct ipmi_dmi_info *next; 29}; 30 31static struct ipmi_dmi_info *ipmi_dmi_infos; 32 33static int ipmi_dmi_nr __initdata; 34 35static void __init dmi_add_platform_ipmi(unsigned long base_addr, 36 unsigned int space, 37 u8 slave_addr, 38 int irq, 39 int offset, 40 int type) 41{ 42 const char *name; 43 struct ipmi_dmi_info *info; 44 struct ipmi_plat_data p; 45 46 memset(&p, 0, sizeof(p)); 47 48 name = "dmi-ipmi-si"; 49 p.iftype = IPMI_PLAT_IF_SI; 50 switch (type) { 51 case IPMI_DMI_TYPE_SSIF: 52 name = "dmi-ipmi-ssif"; 53 p.iftype = IPMI_PLAT_IF_SSIF; 54 p.type = SI_TYPE_INVALID; 55 break; 56 case IPMI_DMI_TYPE_BT: 57 p.type = SI_BT; 58 break; 59 case IPMI_DMI_TYPE_KCS: 60 p.type = SI_KCS; 61 break; 62 case IPMI_DMI_TYPE_SMIC: 63 p.type = SI_SMIC; 64 break; 65 default: 66 pr_err("Invalid IPMI type: %d\n", type); 67 return; 68 } 69 70 p.addr = base_addr; 71 p.space = space; 72 p.regspacing = offset; 73 p.irq = irq; 74 p.slave_addr = slave_addr; 75 p.addr_source = SI_SMBIOS; 76 77 info = kmalloc(sizeof(*info), GFP_KERNEL); 78 if (!info) { 79 pr_warn("Could not allocate dmi info\n"); 80 } else { 81 info->si_type = p.type; 82 info->space = space; 83 info->addr = base_addr; 84 info->slave_addr = slave_addr; 85 info->next = ipmi_dmi_infos; 86 ipmi_dmi_infos = info; 87 } 88 89 if (ipmi_platform_add(name, ipmi_dmi_nr, &p)) 90 ipmi_dmi_nr++; 91} 92 93/* 94 * Look up the slave address for a given interface. This is here 95 * because ACPI doesn't have a slave address while SMBIOS does, but we 96 * prefer using ACPI so the ACPI code can use the IPMI namespace. 97 * This function allows an ACPI-specified IPMI device to look up the 98 * slave address from the DMI table. 99 */ 100int ipmi_dmi_get_slave_addr(enum si_type si_type, unsigned int space, 101 unsigned long base_addr) 102{ 103 struct ipmi_dmi_info *info = ipmi_dmi_infos; 104 105 while (info) { 106 if (info->si_type == si_type && 107 info->space == space && 108 info->addr == base_addr) 109 return info->slave_addr; 110 info = info->next; 111 } 112 113 return 0; 114} 115EXPORT_SYMBOL(ipmi_dmi_get_slave_addr); 116 117#define DMI_IPMI_MIN_LENGTH 0x10 118#define DMI_IPMI_VER2_LENGTH 0x12 119#define DMI_IPMI_TYPE 4 120#define DMI_IPMI_SLAVEADDR 6 121#define DMI_IPMI_ADDR 8 122#define DMI_IPMI_ACCESS 0x10 123#define DMI_IPMI_IRQ 0x11 124#define DMI_IPMI_IO_MASK 0xfffe 125 126static void __init dmi_decode_ipmi(const struct dmi_header *dm) 127{ 128 const u8 *data = (const u8 *) dm; 129 int space = IPMI_IO_ADDR_SPACE; 130 unsigned long base_addr; 131 u8 len = dm->length; 132 u8 slave_addr; 133 int irq = 0, offset = 0; 134 int type; 135 136 if (len < DMI_IPMI_MIN_LENGTH) 137 return; 138 139 type = data[DMI_IPMI_TYPE]; 140 slave_addr = data[DMI_IPMI_SLAVEADDR]; 141 142 memcpy(&base_addr, data + DMI_IPMI_ADDR, sizeof(unsigned long)); 143 if (!base_addr) { 144 pr_err("Base address is zero, assuming no IPMI interface\n"); 145 return; 146 } 147 if (len >= DMI_IPMI_VER2_LENGTH) { 148 if (type == IPMI_DMI_TYPE_SSIF) { 149 space = 0; /* Match I2C interface 0. */ 150 base_addr = data[DMI_IPMI_ADDR] >> 1; 151 if (base_addr == 0) { 152 /* 153 * Some broken systems put the I2C address in 154 * the slave address field. We try to 155 * accommodate them here. 156 */ 157 base_addr = data[DMI_IPMI_SLAVEADDR] >> 1; 158 slave_addr = 0; 159 } 160 } else { 161 if (base_addr & 1) { 162 /* I/O */ 163 base_addr &= DMI_IPMI_IO_MASK; 164 } else { 165 /* Memory */ 166 space = IPMI_MEM_ADDR_SPACE; 167 } 168 169 /* 170 * If bit 4 of byte 0x10 is set, then the lsb 171 * for the address is odd. 172 */ 173 base_addr |= (data[DMI_IPMI_ACCESS] >> 4) & 1; 174 175 irq = data[DMI_IPMI_IRQ]; 176 177 /* 178 * The top two bits of byte 0x10 hold the 179 * register spacing. 180 */ 181 switch ((data[DMI_IPMI_ACCESS] >> 6) & 3) { 182 case 0: /* Byte boundaries */ 183 offset = 1; 184 break; 185 case 1: /* 32-bit boundaries */ 186 offset = 4; 187 break; 188 case 2: /* 16-byte boundaries */ 189 offset = 16; 190 break; 191 default: 192 pr_err("Invalid offset: 0\n"); 193 return; 194 } 195 } 196 } else { 197 /* Old DMI spec. */ 198 /* 199 * Note that technically, the lower bit of the base 200 * address should be 1 if the address is I/O and 0 if 201 * the address is in memory. So many systems get that 202 * wrong (and all that I have seen are I/O) so we just 203 * ignore that bit and assume I/O. Systems that use 204 * memory should use the newer spec, anyway. 205 */ 206 base_addr = base_addr & DMI_IPMI_IO_MASK; 207 offset = 1; 208 } 209 210 dmi_add_platform_ipmi(base_addr, space, slave_addr, irq, 211 offset, type); 212} 213 214static int __init scan_for_dmi_ipmi(void) 215{ 216 const struct dmi_device *dev = NULL; 217 218 while ((dev = dmi_find_device(DMI_DEV_TYPE_IPMI, NULL, dev))) 219 dmi_decode_ipmi((const struct dmi_header *) dev->device_data); 220 221 return 0; 222} 223subsys_initcall(scan_for_dmi_ipmi);