1 /* 2 * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com> 3 * 4 * Adapted from coreboot src/arch/x86/include/arch/smp/mpspec.h 5 * 6 * SPDX-License-Identifier: GPL-2.0+ 7 */ 8 9 #ifndef __ASM_MPSPEC_H 10 #define __ASM_MPSPEC_H 11 12 /* 13 * Structure definitions for SMP machines following the 14 * Intel MultiProcessor Specification 1.4 15 */ 16 17 #define MPSPEC_V14 4 18 19 #define MPF_SIGNATURE "_MP_" 20 21 struct mp_floating_table { 22 char mpf_signature[4]; /* "_MP_" */ 23 u32 mpf_physptr; /* Configuration table address */ 24 u8 mpf_length; /* Our length (paragraphs) */ 25 u8 mpf_spec; /* Specification version */ 26 u8 mpf_checksum; /* Checksum (makes sum 0) */ 27 u8 mpf_feature1; /* Predefined or Unique configuration? */ 28 u8 mpf_feature2; /* Bit7 set for IMCR/PIC */ 29 u8 mpf_feature3; /* Unused (0) */ 30 u8 mpf_feature4; /* Unused (0) */ 31 u8 mpf_feature5; /* Unused (0) */ 32 }; 33 34 #define MPC_SIGNATURE "PCMP" 35 36 struct mp_config_table { 37 char mpc_signature[4]; /* "PCMP" */ 38 u16 mpc_length; /* Size of table */ 39 u8 mpc_spec; /* Specification version */ 40 u8 mpc_checksum; /* Checksum (makes sum 0) */ 41 char mpc_oem[8]; /* OEM ID */ 42 char mpc_product[12]; /* Product ID */ 43 u32 mpc_oemptr; /* OEM table address */ 44 u16 mpc_oemsize; /* OEM table size */ 45 u16 mpc_entry_count; /* Number of entries in the table */ 46 u32 mpc_lapic; /* Local APIC address */ 47 u16 mpe_length; /* Extended table size */ 48 u8 mpe_checksum; /* Extended table checksum */ 49 u8 reserved; 50 }; 51 52 /* Base MP configuration table entry types */ 53 54 enum mp_base_config_entry_type { 55 MP_PROCESSOR, 56 MP_BUS, 57 MP_IOAPIC, 58 MP_INTSRC, 59 MP_LINTSRC 60 }; 61 62 #define MPC_CPU_EN (1 << 0) 63 #define MPC_CPU_BP (1 << 1) 64 65 struct mpc_config_processor { 66 u8 mpc_type; 67 u8 mpc_apicid; 68 u8 mpc_apicver; 69 u8 mpc_cpuflag; 70 u32 mpc_cpusignature; 71 u32 mpc_cpufeature; 72 u32 mpc_reserved[2]; 73 }; 74 75 #define BUSTYPE_CBUS "CBUS " 76 #define BUSTYPE_CBUSII "CBUSII" 77 #define BUSTYPE_EISA "EISA " 78 #define BUSTYPE_FUTURE "FUTURE" 79 #define BUSTYPE_INTERN "INTERN" 80 #define BUSTYPE_ISA "ISA " 81 #define BUSTYPE_MBI "MBI " 82 #define BUSTYPE_MBII "MBII " 83 #define BUSTYPE_MCA "MCA " 84 #define BUSTYPE_MPI "MPI " 85 #define BUSTYPE_MPSA "MPSA " 86 #define BUSTYPE_NUBUS "NUBUS " 87 #define BUSTYPE_PCI "PCI " 88 #define BUSTYPE_PCMCIA "PCMCIA" 89 #define BUSTYPE_TC "TC " 90 #define BUSTYPE_VL "VL " 91 #define BUSTYPE_VME "VME " 92 #define BUSTYPE_XPRESS "XPRESS" 93 94 struct mpc_config_bus { 95 u8 mpc_type; 96 u8 mpc_busid; 97 u8 mpc_bustype[6]; 98 }; 99 100 #define MPC_APIC_USABLE (1 << 0) 101 102 struct mpc_config_ioapic { 103 u8 mpc_type; 104 u8 mpc_apicid; 105 u8 mpc_apicver; 106 u8 mpc_flags; 107 u32 mpc_apicaddr; 108 }; 109 110 enum mp_irq_source_types { 111 MP_INT, 112 MP_NMI, 113 MP_SMI, 114 MP_EXTINT 115 }; 116 117 #define MP_IRQ_POLARITY_DEFAULT 0x0 118 #define MP_IRQ_POLARITY_HIGH 0x1 119 #define MP_IRQ_POLARITY_LOW 0x3 120 #define MP_IRQ_POLARITY_MASK 0x3 121 #define MP_IRQ_TRIGGER_DEFAULT 0x0 122 #define MP_IRQ_TRIGGER_EDGE 0x4 123 #define MP_IRQ_TRIGGER_LEVEL 0xc 124 #define MP_IRQ_TRIGGER_MASK 0xc 125 126 #define MP_APIC_ALL 0xff 127 128 struct mpc_config_intsrc { 129 u8 mpc_type; 130 u8 mpc_irqtype; 131 u16 mpc_irqflag; 132 u8 mpc_srcbus; 133 u8 mpc_srcbusirq; 134 u8 mpc_dstapic; 135 u8 mpc_dstirq; 136 }; 137 138 struct mpc_config_lintsrc { 139 u8 mpc_type; 140 u8 mpc_irqtype; 141 u16 mpc_irqflag; 142 u8 mpc_srcbusid; 143 u8 mpc_srcbusirq; 144 u8 mpc_destapic; 145 u8 mpc_destlint; 146 }; 147 148 /* Extended MP configuration table entry types */ 149 150 enum mp_ext_config_entry_type { 151 MPE_SYSTEM_ADDRESS_SPACE = 128, 152 MPE_BUS_HIERARCHY, 153 MPE_COMPAT_ADDRESS_SPACE 154 }; 155 156 struct mp_ext_config { 157 u8 mpe_type; 158 u8 mpe_length; 159 }; 160 161 #define ADDRESS_TYPE_IO 0 162 #define ADDRESS_TYPE_MEM 1 163 #define ADDRESS_TYPE_PREFETCH 2 164 165 struct mp_ext_system_address_space { 166 u8 mpe_type; 167 u8 mpe_length; 168 u8 mpe_busid; 169 u8 mpe_addr_type; 170 u32 mpe_addr_base_low; 171 u32 mpe_addr_base_high; 172 u32 mpe_addr_length_low; 173 u32 mpe_addr_length_high; 174 }; 175 176 #define BUS_SUBTRACTIVE_DECODE (1 << 0) 177 178 struct mp_ext_bus_hierarchy { 179 u8 mpe_type; 180 u8 mpe_length; 181 u8 mpe_busid; 182 u8 mpe_bus_info; 183 u8 mpe_parent_busid; 184 u8 reserved[3]; 185 }; 186 187 #define ADDRESS_RANGE_ADD 0 188 #define ADDRESS_RANGE_SUBTRACT 1 189 190 /* 191 * X100 - X3FF 192 * X500 - X7FF 193 * X900 - XBFF 194 * XD00 - XFFF 195 */ 196 #define RANGE_LIST_IO_ISA 0 197 /* 198 * X3B0 - X3BB 199 * X3C0 - X3DF 200 * X7B0 - X7BB 201 * X7C0 - X7DF 202 * XBB0 - XBBB 203 * XBC0 - XBDF 204 * XFB0 - XFBB 205 * XFC0 - XCDF 206 */ 207 #define RANGE_LIST_IO_VGA 1 208 209 struct mp_ext_compat_address_space { 210 u8 mpe_type; 211 u8 mpe_length; 212 u8 mpe_busid; 213 u8 mpe_addr_modifier; 214 u32 mpe_range_list; 215 }; 216 217 /** 218 * mp_next_mpc_entry() - Compute MP configuration table end to be used as 219 * next base table entry start address 220 * 221 * This computes the end address of current MP configuration table, without 222 * counting any extended configuration table entry. 223 * 224 * @mc: configuration table header address 225 * @return: configuration table end address 226 */ 227 static inline ulong mp_next_mpc_entry(struct mp_config_table *mc) 228 { 229 return (ulong)mc + mc->mpc_length; 230 } 231 232 /** 233 * mp_add_mpc_entry() - Add a base MP configuration table entry 234 * 235 * This adds the base MP configuration table entry size with 236 * added base table entry length and increases entry count by 1. 237 * 238 * @mc: configuration table header address 239 * @length: length of the added table entry 240 */ 241 static inline void mp_add_mpc_entry(struct mp_config_table *mc, uint length) 242 { 243 mc->mpc_length += length; 244 mc->mpc_entry_count++; 245 } 246 247 /** 248 * mp_next_mpe_entry() - Compute MP configuration table end to be used as 249 * next extended table entry start address 250 * 251 * This computes the end address of current MP configuration table, 252 * including any extended configuration table entry. 253 * 254 * @mc: configuration table header address 255 * @return: configuration table end address 256 */ 257 static inline ulong mp_next_mpe_entry(struct mp_config_table *mc) 258 { 259 return (ulong)mc + mc->mpc_length + mc->mpe_length; 260 } 261 262 /** 263 * mp_add_mpe_entry() - Add an extended MP configuration table entry 264 * 265 * This adds the extended MP configuration table entry size with 266 * added extended table entry length. 267 * 268 * @mc: configuration table header address 269 * @mpe: extended table entry base address 270 */ 271 static inline void mp_add_mpe_entry(struct mp_config_table *mc, 272 struct mp_ext_config *mpe) 273 { 274 mc->mpe_length += mpe->mpe_length; 275 } 276 277 /** 278 * mp_write_floating_table() - Write the MP floating table 279 * 280 * This writes the MP floating table, and points MP configuration table 281 * to its end address so that MP configuration table follows immediately 282 * after the floating table. 283 * 284 * @mf: MP floating table base address 285 * @return: MP configuration table header address 286 */ 287 struct mp_config_table *mp_write_floating_table(struct mp_floating_table *mf); 288 289 /** 290 * mp_config_table_init() - Initialize the MP configuration table header 291 * 292 * This populates the MP configuration table header with valid bits. 293 * 294 * @mc: MP configuration table header address 295 */ 296 void mp_config_table_init(struct mp_config_table *mc); 297 298 /** 299 * mp_write_processor() - Write a processor entry 300 * 301 * This writes a processor entry to the configuration table. 302 * 303 * @mc: MP configuration table header address 304 */ 305 void mp_write_processor(struct mp_config_table *mc); 306 307 /** 308 * mp_write_bus() - Write a bus entry 309 * 310 * This writes a bus entry to the configuration table. 311 * 312 * @mc: MP configuration table header address 313 * @id: bus id 314 * @bustype: bus type name 315 */ 316 void mp_write_bus(struct mp_config_table *mc, int id, const char *bustype); 317 318 /** 319 * mp_write_ioapic() - Write an I/O APIC entry 320 * 321 * This writes an I/O APIC entry to the configuration table. 322 * 323 * @mc: MP configuration table header address 324 * @id: I/O APIC id 325 * @ver: I/O APIC version 326 * @apicaddr: I/O APIC address 327 */ 328 void mp_write_ioapic(struct mp_config_table *mc, int id, int ver, u32 apicaddr); 329 330 /** 331 * mp_write_intsrc() - Write an I/O interrupt assignment entry 332 * 333 * This writes an I/O interrupt assignment entry to the configuration table. 334 * 335 * @mc: MP configuration table header address 336 * @irqtype: IRQ type (INT/NMI/SMI/ExtINT) 337 * @irqflag: IRQ flag (level/trigger) 338 * @srcbus: source bus id where the interrupt comes from 339 * @srcbusirq: IRQ number mapped on the source bus 340 * @dstapic: destination I/O APIC id where the interrupt goes to 341 * @dstirq: destination I/O APIC pin where the interrupt goes to 342 */ 343 void mp_write_intsrc(struct mp_config_table *mc, int irqtype, int irqflag, 344 int srcbus, int srcbusirq, int dstapic, int dstirq); 345 346 /** 347 * mp_write_pci_intsrc() - Write a PCI interrupt assignment entry 348 * 349 * This writes a PCI interrupt assignment entry to the configuration table. 350 * 351 * @mc: MP configuration table header address 352 * @irqtype: IRQ type (INT/NMI/SMI/ExtINT) 353 * @srcbus: PCI bus number where the interrupt comes from 354 * @dev: device number on the PCI bus 355 * @pin: PCI interrupt pin (INT A/B/C/D) 356 * @dstapic: destination I/O APIC id where the interrupt goes to 357 * @dstirq: destination I/O APIC pin where the interrupt goes to 358 */ 359 void mp_write_pci_intsrc(struct mp_config_table *mc, int irqtype, 360 int srcbus, int dev, int pin, int dstapic, int dstirq); 361 362 /** 363 * mp_write_lintsrc() - Write a local interrupt assignment entry 364 * 365 * This writes a local interrupt assignment entry to the configuration table. 366 * 367 * @mc: MP configuration table header address 368 * @irqtype: IRQ type (INT/NMI/SMI/ExtINT) 369 * @irqflag: IRQ flag (level/trigger) 370 * @srcbus: PCI bus number where the interrupt comes from 371 * @srcbusirq: IRQ number mapped on the source bus 372 * @dstapic: destination local APIC id where the interrupt goes to 373 * @destlint: destination local APIC pin where the interrupt goes to 374 */ 375 void mp_write_lintsrc(struct mp_config_table *mc, int irqtype, int irqflag, 376 int srcbus, int srcbusirq, int destapic, int destlint); 377 378 379 /** 380 * mp_write_address_space() - Write a system address space entry 381 * 382 * This writes a system address space entry to the configuration table. 383 * 384 * @mc: MP configuration table header address 385 * @busid: bus id for the bus where system address space is mapped 386 * @addr_type: system address type 387 * @addr_base_low: starting address low 388 * @addr_base_high: starting address high 389 * @addr_length_low: address length low 390 * @addr_length_high: address length high 391 */ 392 void mp_write_address_space(struct mp_config_table *mc, 393 int busid, int addr_type, 394 u32 addr_base_low, u32 addr_base_high, 395 u32 addr_length_low, u32 addr_length_high); 396 397 /** 398 * mp_write_bus_hierarchy() - Write a bus hierarchy descriptor entry 399 * 400 * This writes a bus hierarchy descriptor entry to the configuration table. 401 * 402 * @mc: MP configuration table header address 403 * @busid: bus id 404 * @bus_info: bit0 indicates if the bus is a subtractive decode bus 405 * @parent_busid: parent bus id 406 */ 407 void mp_write_bus_hierarchy(struct mp_config_table *mc, 408 int busid, int bus_info, int parent_busid); 409 410 /** 411 * mp_write_compat_address_space() - Write a compat bus address space entry 412 * 413 * This writes a compatibility bus address space modifier entry to the 414 * configuration table. 415 * 416 * @mc: MP configuration table header address 417 * @busid: bus id 418 * @addr_modifier: add or subtract to predefined address range list 419 * @range_list: list of predefined address space ranges 420 */ 421 void mp_write_compat_address_space(struct mp_config_table *mc, int busid, 422 int addr_modifier, u32 range_list); 423 424 /** 425 * mptable_finalize() - Finalize the MP table 426 * 427 * This finalizes the MP table by calculating required checksums. 428 * 429 * @mc: MP configuration table header address 430 * @return: MP table end address 431 */ 432 u32 mptable_finalize(struct mp_config_table *mc); 433 434 /** 435 * mp_determine_pci_dstirq() - Determine PCI device's int pin on the I/O APIC 436 * 437 * This determines a PCI device's interrupt pin number on the I/O APIC. 438 * 439 * This can be implemented by platform codes to handle specifal cases, which 440 * do not conform to the normal chipset/board design where PIRQ[A-H] are mapped 441 * directly to I/O APIC INTPIN#16-23. 442 * 443 * @bus: bus number of the pci device 444 * @dev: device number of the pci device 445 * @func: function number of the pci device 446 * @pirq: PIRQ number the PCI device's interrupt pin is routed to 447 * @return: interrupt pin number on the I/O APIC 448 */ 449 int mp_determine_pci_dstirq(int bus, int dev, int func, int pirq); 450 451 /** 452 * write_mp_table() - Write MP table 453 * 454 * This writes MP table at a given address. 455 * 456 * @addr: start address to write MP table 457 * @return: end address of MP table 458 */ 459 ulong write_mp_table(ulong addr); 460 461 #endif /* __ASM_MPSPEC_H */ 462