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