18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci#ifndef _ASM_X86_IO_APIC_H
38c2ecf20Sopenharmony_ci#define _ASM_X86_IO_APIC_H
48c2ecf20Sopenharmony_ci
58c2ecf20Sopenharmony_ci#include <linux/types.h>
68c2ecf20Sopenharmony_ci#include <asm/mpspec.h>
78c2ecf20Sopenharmony_ci#include <asm/apicdef.h>
88c2ecf20Sopenharmony_ci#include <asm/irq_vectors.h>
98c2ecf20Sopenharmony_ci#include <asm/x86_init.h>
108c2ecf20Sopenharmony_ci/*
118c2ecf20Sopenharmony_ci * Intel IO-APIC support for SMP and UP systems.
128c2ecf20Sopenharmony_ci *
138c2ecf20Sopenharmony_ci * Copyright (C) 1997, 1998, 1999, 2000 Ingo Molnar
148c2ecf20Sopenharmony_ci */
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci/* I/O Unit Redirection Table */
178c2ecf20Sopenharmony_ci#define IO_APIC_REDIR_VECTOR_MASK	0x000FF
188c2ecf20Sopenharmony_ci#define IO_APIC_REDIR_DEST_LOGICAL	0x00800
198c2ecf20Sopenharmony_ci#define IO_APIC_REDIR_DEST_PHYSICAL	0x00000
208c2ecf20Sopenharmony_ci#define IO_APIC_REDIR_SEND_PENDING	(1 << 12)
218c2ecf20Sopenharmony_ci#define IO_APIC_REDIR_REMOTE_IRR	(1 << 14)
228c2ecf20Sopenharmony_ci#define IO_APIC_REDIR_LEVEL_TRIGGER	(1 << 15)
238c2ecf20Sopenharmony_ci#define IO_APIC_REDIR_MASKED		(1 << 16)
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_ci/*
268c2ecf20Sopenharmony_ci * The structure of the IO-APIC:
278c2ecf20Sopenharmony_ci */
288c2ecf20Sopenharmony_ciunion IO_APIC_reg_00 {
298c2ecf20Sopenharmony_ci	u32	raw;
308c2ecf20Sopenharmony_ci	struct {
318c2ecf20Sopenharmony_ci		u32	__reserved_2	: 14,
328c2ecf20Sopenharmony_ci			LTS		:  1,
338c2ecf20Sopenharmony_ci			delivery_type	:  1,
348c2ecf20Sopenharmony_ci			__reserved_1	:  8,
358c2ecf20Sopenharmony_ci			ID		:  8;
368c2ecf20Sopenharmony_ci	} __attribute__ ((packed)) bits;
378c2ecf20Sopenharmony_ci};
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_ciunion IO_APIC_reg_01 {
408c2ecf20Sopenharmony_ci	u32	raw;
418c2ecf20Sopenharmony_ci	struct {
428c2ecf20Sopenharmony_ci		u32	version		:  8,
438c2ecf20Sopenharmony_ci			__reserved_2	:  7,
448c2ecf20Sopenharmony_ci			PRQ		:  1,
458c2ecf20Sopenharmony_ci			entries		:  8,
468c2ecf20Sopenharmony_ci			__reserved_1	:  8;
478c2ecf20Sopenharmony_ci	} __attribute__ ((packed)) bits;
488c2ecf20Sopenharmony_ci};
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ciunion IO_APIC_reg_02 {
518c2ecf20Sopenharmony_ci	u32	raw;
528c2ecf20Sopenharmony_ci	struct {
538c2ecf20Sopenharmony_ci		u32	__reserved_2	: 24,
548c2ecf20Sopenharmony_ci			arbitration	:  4,
558c2ecf20Sopenharmony_ci			__reserved_1	:  4;
568c2ecf20Sopenharmony_ci	} __attribute__ ((packed)) bits;
578c2ecf20Sopenharmony_ci};
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_ciunion IO_APIC_reg_03 {
608c2ecf20Sopenharmony_ci	u32	raw;
618c2ecf20Sopenharmony_ci	struct {
628c2ecf20Sopenharmony_ci		u32	boot_DT		:  1,
638c2ecf20Sopenharmony_ci			__reserved_1	: 31;
648c2ecf20Sopenharmony_ci	} __attribute__ ((packed)) bits;
658c2ecf20Sopenharmony_ci};
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_cistruct IO_APIC_route_entry {
688c2ecf20Sopenharmony_ci	__u32	vector		:  8,
698c2ecf20Sopenharmony_ci		delivery_mode	:  3,	/* 000: FIXED
708c2ecf20Sopenharmony_ci					 * 001: lowest prio
718c2ecf20Sopenharmony_ci					 * 111: ExtINT
728c2ecf20Sopenharmony_ci					 */
738c2ecf20Sopenharmony_ci		dest_mode	:  1,	/* 0: physical, 1: logical */
748c2ecf20Sopenharmony_ci		delivery_status	:  1,
758c2ecf20Sopenharmony_ci		polarity	:  1,
768c2ecf20Sopenharmony_ci		irr		:  1,
778c2ecf20Sopenharmony_ci		trigger		:  1,	/* 0: edge, 1: level */
788c2ecf20Sopenharmony_ci		mask		:  1,	/* 0: enabled, 1: disabled */
798c2ecf20Sopenharmony_ci		__reserved_2	: 15;
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_ci	__u32	__reserved_3	: 24,
828c2ecf20Sopenharmony_ci		dest		:  8;
838c2ecf20Sopenharmony_ci} __attribute__ ((packed));
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_cistruct IR_IO_APIC_route_entry {
868c2ecf20Sopenharmony_ci	__u64	vector		: 8,
878c2ecf20Sopenharmony_ci		zero		: 3,
888c2ecf20Sopenharmony_ci		index2		: 1,
898c2ecf20Sopenharmony_ci		delivery_status : 1,
908c2ecf20Sopenharmony_ci		polarity	: 1,
918c2ecf20Sopenharmony_ci		irr		: 1,
928c2ecf20Sopenharmony_ci		trigger		: 1,
938c2ecf20Sopenharmony_ci		mask		: 1,
948c2ecf20Sopenharmony_ci		reserved	: 31,
958c2ecf20Sopenharmony_ci		format		: 1,
968c2ecf20Sopenharmony_ci		index		: 15;
978c2ecf20Sopenharmony_ci} __attribute__ ((packed));
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_cistruct irq_alloc_info;
1008c2ecf20Sopenharmony_cistruct ioapic_domain_cfg;
1018c2ecf20Sopenharmony_ci
1028c2ecf20Sopenharmony_ci#define IOAPIC_EDGE			0
1038c2ecf20Sopenharmony_ci#define IOAPIC_LEVEL			1
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_ci#define IOAPIC_MASKED			1
1068c2ecf20Sopenharmony_ci#define IOAPIC_UNMASKED			0
1078c2ecf20Sopenharmony_ci
1088c2ecf20Sopenharmony_ci#define IOAPIC_POL_HIGH			0
1098c2ecf20Sopenharmony_ci#define IOAPIC_POL_LOW			1
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_ci#define IOAPIC_DEST_MODE_PHYSICAL	0
1128c2ecf20Sopenharmony_ci#define IOAPIC_DEST_MODE_LOGICAL	1
1138c2ecf20Sopenharmony_ci
1148c2ecf20Sopenharmony_ci#define	IOAPIC_MAP_ALLOC		0x1
1158c2ecf20Sopenharmony_ci#define	IOAPIC_MAP_CHECK		0x2
1168c2ecf20Sopenharmony_ci
1178c2ecf20Sopenharmony_ci#ifdef CONFIG_X86_IO_APIC
1188c2ecf20Sopenharmony_ci
1198c2ecf20Sopenharmony_ci/*
1208c2ecf20Sopenharmony_ci * # of IO-APICs and # of IRQ routing registers
1218c2ecf20Sopenharmony_ci */
1228c2ecf20Sopenharmony_ciextern int nr_ioapics;
1238c2ecf20Sopenharmony_ci
1248c2ecf20Sopenharmony_ciextern int mpc_ioapic_id(int ioapic);
1258c2ecf20Sopenharmony_ciextern unsigned int mpc_ioapic_addr(int ioapic);
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_ci/* # of MP IRQ source entries */
1288c2ecf20Sopenharmony_ciextern int mp_irq_entries;
1298c2ecf20Sopenharmony_ci
1308c2ecf20Sopenharmony_ci/* MP IRQ source entries */
1318c2ecf20Sopenharmony_ciextern struct mpc_intsrc mp_irqs[MAX_IRQ_SOURCES];
1328c2ecf20Sopenharmony_ci
1338c2ecf20Sopenharmony_ci/* 1 if "noapic" boot option passed */
1348c2ecf20Sopenharmony_ciextern int skip_ioapic_setup;
1358c2ecf20Sopenharmony_ci
1368c2ecf20Sopenharmony_ci/* 1 if "noapic" boot option passed */
1378c2ecf20Sopenharmony_ciextern int noioapicquirk;
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_ci/* -1 if "noapic" boot option passed */
1408c2ecf20Sopenharmony_ciextern int noioapicreroute;
1418c2ecf20Sopenharmony_ci
1428c2ecf20Sopenharmony_ciextern u32 gsi_top;
1438c2ecf20Sopenharmony_ci
1448c2ecf20Sopenharmony_ciextern unsigned long io_apic_irqs;
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_ci#define IO_APIC_IRQ(x) (((x) >= NR_IRQS_LEGACY) || ((1 << (x)) & io_apic_irqs))
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_ci/*
1498c2ecf20Sopenharmony_ci * If we use the IO-APIC for IRQ routing, disable automatic
1508c2ecf20Sopenharmony_ci * assignment of PCI IRQ's.
1518c2ecf20Sopenharmony_ci */
1528c2ecf20Sopenharmony_ci#define io_apic_assign_pci_irqs \
1538c2ecf20Sopenharmony_ci	(mp_irq_entries && !skip_ioapic_setup && io_apic_irqs)
1548c2ecf20Sopenharmony_ci
1558c2ecf20Sopenharmony_cistruct irq_cfg;
1568c2ecf20Sopenharmony_ciextern void ioapic_insert_resources(void);
1578c2ecf20Sopenharmony_ciextern int arch_early_ioapic_init(void);
1588c2ecf20Sopenharmony_ci
1598c2ecf20Sopenharmony_ciextern int save_ioapic_entries(void);
1608c2ecf20Sopenharmony_ciextern void mask_ioapic_entries(void);
1618c2ecf20Sopenharmony_ciextern int restore_ioapic_entries(void);
1628c2ecf20Sopenharmony_ci
1638c2ecf20Sopenharmony_ciextern void setup_ioapic_ids_from_mpc(void);
1648c2ecf20Sopenharmony_ciextern void setup_ioapic_ids_from_mpc_nocheck(void);
1658c2ecf20Sopenharmony_ci
1668c2ecf20Sopenharmony_ciextern int mp_find_ioapic(u32 gsi);
1678c2ecf20Sopenharmony_ciextern int mp_find_ioapic_pin(int ioapic, u32 gsi);
1688c2ecf20Sopenharmony_ciextern int mp_map_gsi_to_irq(u32 gsi, unsigned int flags,
1698c2ecf20Sopenharmony_ci			     struct irq_alloc_info *info);
1708c2ecf20Sopenharmony_ciextern void mp_unmap_irq(int irq);
1718c2ecf20Sopenharmony_ciextern int mp_register_ioapic(int id, u32 address, u32 gsi_base,
1728c2ecf20Sopenharmony_ci			      struct ioapic_domain_cfg *cfg);
1738c2ecf20Sopenharmony_ciextern int mp_unregister_ioapic(u32 gsi_base);
1748c2ecf20Sopenharmony_ciextern int mp_ioapic_registered(u32 gsi_base);
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_ciextern void ioapic_set_alloc_attr(struct irq_alloc_info *info,
1778c2ecf20Sopenharmony_ci				  int node, int trigger, int polarity);
1788c2ecf20Sopenharmony_ci
1798c2ecf20Sopenharmony_ciextern void mp_save_irq(struct mpc_intsrc *m);
1808c2ecf20Sopenharmony_ci
1818c2ecf20Sopenharmony_ciextern void disable_ioapic_support(void);
1828c2ecf20Sopenharmony_ci
1838c2ecf20Sopenharmony_ciextern void __init io_apic_init_mappings(void);
1848c2ecf20Sopenharmony_ciextern unsigned int native_io_apic_read(unsigned int apic, unsigned int reg);
1858c2ecf20Sopenharmony_ciextern void native_restore_boot_irq_mode(void);
1868c2ecf20Sopenharmony_ci
1878c2ecf20Sopenharmony_cistatic inline unsigned int io_apic_read(unsigned int apic, unsigned int reg)
1888c2ecf20Sopenharmony_ci{
1898c2ecf20Sopenharmony_ci	return x86_apic_ops.io_apic_read(apic, reg);
1908c2ecf20Sopenharmony_ci}
1918c2ecf20Sopenharmony_ci
1928c2ecf20Sopenharmony_ciextern void setup_IO_APIC(void);
1938c2ecf20Sopenharmony_ciextern void enable_IO_APIC(void);
1948c2ecf20Sopenharmony_ciextern void clear_IO_APIC(void);
1958c2ecf20Sopenharmony_ciextern void restore_boot_irq_mode(void);
1968c2ecf20Sopenharmony_ciextern int IO_APIC_get_PCI_irq_vector(int bus, int devfn, int pin);
1978c2ecf20Sopenharmony_ciextern void print_IO_APICs(void);
1988c2ecf20Sopenharmony_ci#else  /* !CONFIG_X86_IO_APIC */
1998c2ecf20Sopenharmony_ci
2008c2ecf20Sopenharmony_ci#define IO_APIC_IRQ(x)		0
2018c2ecf20Sopenharmony_ci#define io_apic_assign_pci_irqs 0
2028c2ecf20Sopenharmony_ci#define setup_ioapic_ids_from_mpc x86_init_noop
2038c2ecf20Sopenharmony_cistatic inline void ioapic_insert_resources(void) { }
2048c2ecf20Sopenharmony_cistatic inline int arch_early_ioapic_init(void) { return 0; }
2058c2ecf20Sopenharmony_cistatic inline void print_IO_APICs(void) {}
2068c2ecf20Sopenharmony_ci#define gsi_top (NR_IRQS_LEGACY)
2078c2ecf20Sopenharmony_cistatic inline int mp_find_ioapic(u32 gsi) { return 0; }
2088c2ecf20Sopenharmony_cistatic inline int mp_map_gsi_to_irq(u32 gsi, unsigned int flags,
2098c2ecf20Sopenharmony_ci				    struct irq_alloc_info *info)
2108c2ecf20Sopenharmony_ci{
2118c2ecf20Sopenharmony_ci	return gsi;
2128c2ecf20Sopenharmony_ci}
2138c2ecf20Sopenharmony_ci
2148c2ecf20Sopenharmony_cistatic inline void mp_unmap_irq(int irq) { }
2158c2ecf20Sopenharmony_ci
2168c2ecf20Sopenharmony_cistatic inline int save_ioapic_entries(void)
2178c2ecf20Sopenharmony_ci{
2188c2ecf20Sopenharmony_ci	return -ENOMEM;
2198c2ecf20Sopenharmony_ci}
2208c2ecf20Sopenharmony_ci
2218c2ecf20Sopenharmony_cistatic inline void mask_ioapic_entries(void) { }
2228c2ecf20Sopenharmony_cistatic inline int restore_ioapic_entries(void)
2238c2ecf20Sopenharmony_ci{
2248c2ecf20Sopenharmony_ci	return -ENOMEM;
2258c2ecf20Sopenharmony_ci}
2268c2ecf20Sopenharmony_ci
2278c2ecf20Sopenharmony_cistatic inline void mp_save_irq(struct mpc_intsrc *m) { }
2288c2ecf20Sopenharmony_cistatic inline void disable_ioapic_support(void) { }
2298c2ecf20Sopenharmony_cistatic inline void io_apic_init_mappings(void) { }
2308c2ecf20Sopenharmony_ci#define native_io_apic_read		NULL
2318c2ecf20Sopenharmony_ci#define native_restore_boot_irq_mode	NULL
2328c2ecf20Sopenharmony_ci
2338c2ecf20Sopenharmony_cistatic inline void setup_IO_APIC(void) { }
2348c2ecf20Sopenharmony_cistatic inline void enable_IO_APIC(void) { }
2358c2ecf20Sopenharmony_cistatic inline void restore_boot_irq_mode(void) { }
2368c2ecf20Sopenharmony_ci
2378c2ecf20Sopenharmony_ci#endif
2388c2ecf20Sopenharmony_ci
2398c2ecf20Sopenharmony_ci#endif /* _ASM_X86_IO_APIC_H */
240