es7000_32.c 17.7 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3
/*
 * Written by: Garry Forsgren, Unisys Corporation
 *             Natalie Protasevich, Unisys Corporation
I
Ingo Molnar 已提交
4
 *
L
Linus Torvalds 已提交
5 6 7
 * This file contains the code to configure and interface
 * with Unisys ES7000 series hardware system manager.
 *
I
Ingo Molnar 已提交
8 9 10 11
 * Copyright (c) 2003 Unisys Corporation.
 * Copyright (C) 2009, Red Hat, Inc., Ingo Molnar
 *
 *   All Rights Reserved.
L
Linus Torvalds 已提交
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of version 2 of the GNU General Public License as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it would be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write the Free Software Foundation, Inc., 59
 * Temple Place - Suite 330, Boston MA 02111-1307, USA.
 *
 * Contact information: Unisys Corporation, Township Line & Union Meeting
 * Roads-A, Unisys Way, Blue Bell, Pennsylvania, 19424, or:
 *
 * http://www.unisys.com
 */
I
Ingo Molnar 已提交
30 31 32 33
#include <linux/notifier.h>
#include <linux/spinlock.h>
#include <linux/cpumask.h>
#include <linux/threads.h>
L
Linus Torvalds 已提交
34
#include <linux/kernel.h>
I
Ingo Molnar 已提交
35 36
#include <linux/module.h>
#include <linux/reboot.h>
L
Linus Torvalds 已提交
37
#include <linux/string.h>
I
Ingo Molnar 已提交
38
#include <linux/types.h>
L
Linus Torvalds 已提交
39 40
#include <linux/errno.h>
#include <linux/acpi.h>
I
Ingo Molnar 已提交
41
#include <linux/init.h>
I
Ingo Molnar 已提交
42
#include <linux/nmi.h>
I
Ingo Molnar 已提交
43
#include <linux/smp.h>
I
Ingo Molnar 已提交
44
#include <linux/io.h>
I
Ingo Molnar 已提交
45

L
Linus Torvalds 已提交
46
#include <asm/apicdef.h>
I
Ingo Molnar 已提交
47 48 49
#include <asm/atomic.h>
#include <asm/fixmap.h>
#include <asm/mpspec.h>
50
#include <asm/setup.h>
I
Ingo Molnar 已提交
51 52
#include <asm/apic.h>
#include <asm/ipi.h>
L
Linus Torvalds 已提交
53

Y
Yinghai Lu 已提交
54 55 56 57
/*
 * ES7000 chipsets
 */

I
Ingo Molnar 已提交
58 59 60
#define NON_UNISYS			0
#define ES7000_CLASSIC			1
#define ES7000_ZORRO			2
Y
Yinghai Lu 已提交
61

I
Ingo Molnar 已提交
62 63
#define	MIP_REG				1
#define	MIP_PSAI_REG			4
Y
Yinghai Lu 已提交
64

I
Ingo Molnar 已提交
65 66 67
#define	MIP_BUSY			1
#define	MIP_SPIN			0xf0000
#define	MIP_VALID			0x0100000000000000ULL
68
#define	MIP_SW_APIC			0x1020b
Y
Yinghai Lu 已提交
69

I
Ingo Molnar 已提交
70
#define	MIP_PORT(val)			((val >> 32) & 0xffff)
Y
Yinghai Lu 已提交
71

I
Ingo Molnar 已提交
72
#define	MIP_RD_LO(val)			(val & 0xffffffff)
Y
Yinghai Lu 已提交
73

74 75 76 77 78 79 80 81 82 83 84
struct mip_reg {
	unsigned long long		off_0x00;
	unsigned long long		off_0x08;
	unsigned long long		off_0x10;
	unsigned long long		off_0x18;
	unsigned long long		off_0x20;
	unsigned long long		off_0x28;
	unsigned long long		off_0x30;
	unsigned long long		off_0x38;
};

Y
Yinghai Lu 已提交
85
struct mip_reg_info {
I
Ingo Molnar 已提交
86 87 88 89
	unsigned long long		mip_info;
	unsigned long long		delivery_info;
	unsigned long long		host_reg;
	unsigned long long		mip_reg;
Y
Yinghai Lu 已提交
90 91 92
};

struct psai {
I
Ingo Molnar 已提交
93 94 95
	unsigned long long		entry_type;
	unsigned long long		addr;
	unsigned long long		bep_addr;
Y
Yinghai Lu 已提交
96 97 98
};

#ifdef CONFIG_ACPI
I
Ingo Molnar 已提交
99

100
struct es7000_oem_table {
I
Ingo Molnar 已提交
101 102 103
	struct acpi_table_header	Header;
	u32				OEMTableAddr;
	u32				OEMTableSize;
Y
Yinghai Lu 已提交
104
};
I
Ingo Molnar 已提交
105 106 107 108

static unsigned long			oem_addrX;
static unsigned long			oem_size;

Y
Yinghai Lu 已提交
109 110
#endif

L
Linus Torvalds 已提交
111 112 113 114
/*
 * ES7000 Globals
 */

I
Ingo Molnar 已提交
115
static volatile unsigned long		*psai;
I
Ingo Molnar 已提交
116 117 118
static struct mip_reg			*mip_reg;
static struct mip_reg			*host_reg;
static int 				mip_port;
I
Ingo Molnar 已提交
119 120
static unsigned long			mip_addr;
static unsigned long			host_addr;
L
Linus Torvalds 已提交
121

I
Ingo Molnar 已提交
122
int					es7000_plat;
123

L
Linus Torvalds 已提交
124 125 126 127
/*
 * GSI override for ES7000 platforms.
 */

I
Ingo Molnar 已提交
128
static unsigned int			base;
L
Linus Torvalds 已提交
129 130 131 132

static int
es7000_rename_gsi(int ioapic, int gsi)
{
133 134 135
	if (es7000_plat == ES7000_ZORRO)
		return gsi;

L
Linus Torvalds 已提交
136 137 138 139 140 141
	if (!base) {
		int i;
		for (i = 0; i < nr_ioapics; i++)
			base += nr_ioapic_registers[i];
	}

Y
Yinghai Lu 已提交
142
	if (!ioapic && (gsi < 16))
L
Linus Torvalds 已提交
143
		gsi += base;
I
Ingo Molnar 已提交
144

L
Linus Torvalds 已提交
145 146 147
	return gsi;
}

148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
static int wakeup_secondary_cpu_via_mip(int cpu, unsigned long eip)
{
	unsigned long vect = 0, psaival = 0;

	if (psai == NULL)
		return -1;

	vect = ((unsigned long)__pa(eip)/0x1000) << 16;
	psaival = (0x1000000 | vect | cpu);

	while (*psai & 0x1000000)
		;

	*psai = psaival;

	return 0;
}
165

166
static int es7000_apic_is_cluster(void)
167
{
168 169
	/* MPENTIUMIII */
	if (boot_cpu_data.x86 == 6 &&
170 171
	    (boot_cpu_data.x86_model >= 7 || boot_cpu_data.x86_model <= 11))
		return 1;
172

173 174
	return 0;
}
175

176
static void setup_unisys(void)
177 178 179 180 181 182 183 184 185
{
	/*
	 * Determine the generation of the ES7000 currently running.
	 *
	 * es7000_plat = 1 if the machine is a 5xx ES7000 box
	 * es7000_plat = 2 if the machine is a x86_64 ES7000 box
	 *
	 */
	if (!(boot_cpu_data.x86 <= 15 && boot_cpu_data.x86_model <= 2))
186
		es7000_plat = ES7000_ZORRO;
187
	else
188
		es7000_plat = ES7000_CLASSIC;
189 190 191
	ioapic_renumber_irq = es7000_rename_gsi;
}

L
Linus Torvalds 已提交
192
/*
I
Ingo Molnar 已提交
193
 * Parse the OEM Table:
L
Linus Torvalds 已提交
194
 */
195
static int parse_unisys_oem(char *oemptr)
L
Linus Torvalds 已提交
196
{
197
	int			i;
L
Linus Torvalds 已提交
198
	int 			success = 0;
199 200 201 202
	unsigned char		type, size;
	unsigned long		val;
	char			*tp = NULL;
	struct psai		*psaip = NULL;
L
Linus Torvalds 已提交
203 204 205 206 207 208 209
	struct mip_reg_info 	*mi;
	struct mip_reg		*host, *mip;

	tp = oemptr;

	tp += 8;

210
	for (i = 0; i <= 6; i++) {
L
Linus Torvalds 已提交
211 212 213 214 215 216 217 218 219 220 221 222 223 224 225
		type = *tp++;
		size = *tp++;
		tp -= 2;
		switch (type) {
		case MIP_REG:
			mi = (struct mip_reg_info *)tp;
			val = MIP_RD_LO(mi->host_reg);
			host_addr = val;
			host = (struct mip_reg *)val;
			host_reg = __va(host);
			val = MIP_RD_LO(mi->mip_reg);
			mip_port = MIP_PORT(mi->mip_info);
			mip_addr = val;
			mip = (struct mip_reg *)val;
			mip_reg = __va(mip);
226 227 228 229
			pr_debug("es7000_mipcfg: host_reg = 0x%lx \n",
				 (unsigned long)host_reg);
			pr_debug("es7000_mipcfg: mip_reg = 0x%lx \n",
				 (unsigned long)mip_reg);
L
Linus Torvalds 已提交
230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247
			success++;
			break;
		case MIP_PSAI_REG:
			psaip = (struct psai *)tp;
			if (tp != NULL) {
				if (psaip->addr)
					psai = __va(psaip->addr);
				else
					psai = NULL;
				success++;
			}
			break;
		default:
			break;
		}
		tp += size;
	}

I
Ingo Molnar 已提交
248
	if (success < 2)
249
		es7000_plat = NON_UNISYS;
I
Ingo Molnar 已提交
250
	else
251
		setup_unisys();
I
Ingo Molnar 已提交
252

L
Linus Torvalds 已提交
253 254 255
	return es7000_plat;
}

256
#ifdef CONFIG_ACPI
257
static int find_unisys_acpi_oem_table(unsigned long *oem_addr)
L
Linus Torvalds 已提交
258
{
259
	struct acpi_table_header *header = NULL;
I
Ingo Molnar 已提交
260
	struct es7000_oem_table *table;
261
	acpi_size tbl_size;
I
Ingo Molnar 已提交
262 263
	acpi_status ret;
	int i = 0;
264

I
Ingo Molnar 已提交
265 266 267 268
	for (;;) {
		ret = acpi_get_table_with_size("OEM1", i++, &header, &tbl_size);
		if (!ACPI_SUCCESS(ret))
			return -1;
269

I
Ingo Molnar 已提交
270 271
		if (!memcmp((char *) &header->oem_id, "UNISYS", 6))
			break;
272

273
		early_acpi_os_unmap_memory(header, tbl_size);
L
Linus Torvalds 已提交
274
	}
I
Ingo Molnar 已提交
275 276 277 278 279 280 281 282 283 284 285

	table = (void *)header;

	oem_addrX	= table->OEMTableAddr;
	oem_size	= table->OEMTableSize;

	early_acpi_os_unmap_memory(header, tbl_size);

	*oem_addr	= (unsigned long)__acpi_map_table(oem_addrX, oem_size);

	return 0;
L
Linus Torvalds 已提交
286
}
287

288
static void unmap_unisys_acpi_oem_table(unsigned long oem_addr)
289
{
290 291 292 293
	if (!oem_addr)
		return;

	__acpi_unmap_table((char *)oem_addr, oem_size);
294
}
I
Ingo Molnar 已提交
295 296 297 298 299 300 301 302 303 304 305

static int es7000_check_dsdt(void)
{
	struct acpi_table_header header;

	if (ACPI_SUCCESS(acpi_get_table_header(ACPI_SIG_DSDT, 0, &header)) &&
	    !strncmp(header.oem_id, "UNISYS", 6))
		return 1;
	return 0;
}

306
static int es7000_acpi_ret;
307

I
Ingo Molnar 已提交
308
/* Hook from generic ACPI tables.c */
309
static int es7000_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
I
Ingo Molnar 已提交
310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329
{
	unsigned long oem_addr = 0;
	int check_dsdt;
	int ret = 0;

	/* check dsdt at first to avoid clear fix_map for oem_addr */
	check_dsdt = es7000_check_dsdt();

	if (!find_unisys_acpi_oem_table(&oem_addr)) {
		if (check_dsdt) {
			ret = parse_unisys_oem((char *)oem_addr);
		} else {
			setup_unisys();
			ret = 1;
		}
		/*
		 * we need to unmap it
		 */
		unmap_unisys_acpi_oem_table(oem_addr);
	}
330 331 332 333

	es7000_acpi_ret = ret;

	return ret && !es7000_apic_is_cluster();
I
Ingo Molnar 已提交
334
}
335

336
static int es7000_acpi_madt_oem_check_cluster(char *oem_id, char *oem_table_id)
337 338 339 340 341 342
{
	int ret = es7000_acpi_ret;

	return ret && es7000_apic_is_cluster();
}

I
Ingo Molnar 已提交
343
#else /* !CONFIG_ACPI: */
344
static int es7000_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
I
Ingo Molnar 已提交
345 346 347
{
	return 0;
}
348

349
static int es7000_acpi_madt_oem_check_cluster(char *oem_id, char *oem_table_id)
350 351 352
{
	return 0;
}
I
Ingo Molnar 已提交
353
#endif /* !CONFIG_ACPI */
L
Linus Torvalds 已提交
354

I
Ingo Molnar 已提交
355
static void es7000_spin(int n)
L
Linus Torvalds 已提交
356 357 358 359 360 361 362
{
	int i = 0;

	while (i++ < n)
		rep_nop();
}

363
static int es7000_mip_write(struct mip_reg *mip_reg)
L
Linus Torvalds 已提交
364
{
I
Ingo Molnar 已提交
365 366
	int status = 0;
	int spin;
L
Linus Torvalds 已提交
367 368

	spin = MIP_SPIN;
I
Ingo Molnar 已提交
369 370
	while ((host_reg->off_0x38 & MIP_VALID) != 0) {
		if (--spin <= 0) {
I
Ingo Molnar 已提交
371
			WARN(1,	"Timeout waiting for Host Valid Flag\n");
I
Ingo Molnar 已提交
372 373
			return -1;
		}
L
Linus Torvalds 已提交
374 375 376 377 378 379 380 381
		es7000_spin(MIP_SPIN);
	}

	memcpy(host_reg, mip_reg, sizeof(struct mip_reg));
	outb(1, mip_port);

	spin = MIP_SPIN;

I
Ingo Molnar 已提交
382
	while ((mip_reg->off_0x38 & MIP_VALID) == 0) {
L
Linus Torvalds 已提交
383
		if (--spin <= 0) {
I
Ingo Molnar 已提交
384
			WARN(1,	"Timeout waiting for MIP Valid Flag\n");
L
Linus Torvalds 已提交
385 386 387 388 389
			return -1;
		}
		es7000_spin(MIP_SPIN);
	}

I
Ingo Molnar 已提交
390 391 392
	status = (mip_reg->off_0x00 & 0xffff0000000000ULL) >> 48;
	mip_reg->off_0x38 &= ~MIP_VALID;

L
Linus Torvalds 已提交
393 394 395
	return status;
}

396
static void es7000_enable_apic_mode(void)
L
Linus Torvalds 已提交
397
{
398 399 400 401
	struct mip_reg es7000_mip_reg;
	int mip_status;

	if (!es7000_plat)
L
Linus Torvalds 已提交
402
		return;
403

I
Ingo Molnar 已提交
404
	printk(KERN_INFO "ES7000: Enabling APIC mode.\n");
405 406 407
	memset(&es7000_mip_reg, 0, sizeof(struct mip_reg));
	es7000_mip_reg.off_0x00 = MIP_SW_APIC;
	es7000_mip_reg.off_0x38 = MIP_VALID;
408

I
Ingo Molnar 已提交
409 410
	while ((mip_status = es7000_mip_write(&es7000_mip_reg)) != 0)
		WARN(1, "Command failed, status = %x\n", mip_status);
L
Linus Torvalds 已提交
411
}
I
Ingo Molnar 已提交
412

413
static void es7000_vector_allocation_domain(int cpu, struct cpumask *retmask)
I
Ingo Molnar 已提交
414 415 416 417 418 419 420 421 422
{
	/* Careful. Some cpus do not strictly honor the set of cpus
	 * specified in the interrupt destination when using lowest
	 * priority interrupt delivery mode.
	 *
	 * In particular there was a hyperthreading cpu observed to
	 * deliver interrupts to the wrong hyperthread when only one
	 * hyperthread was specified in the interrupt desitination.
	 */
423 424
	cpumask_clear(retmask);
	cpumask_bits(retmask)[0] = APIC_ALL_CPUS;
I
Ingo Molnar 已提交
425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440
}


static void es7000_wait_for_init_deassert(atomic_t *deassert)
{
	while (!atomic_read(deassert))
		cpu_relax();
}

static unsigned int es7000_get_apic_id(unsigned long x)
{
	return (x >> 24) & 0xFF;
}

static void es7000_send_IPI_mask(const struct cpumask *mask, int vector)
{
441
	default_send_IPI_mask_sequence_phys(mask, vector);
I
Ingo Molnar 已提交
442 443 444 445
}

static void es7000_send_IPI_allbutself(int vector)
{
446
	default_send_IPI_mask_allbutself_phys(cpu_online_mask, vector);
I
Ingo Molnar 已提交
447 448 449 450 451 452 453 454 455
}

static void es7000_send_IPI_all(int vector)
{
	es7000_send_IPI_mask(cpu_online_mask, vector);
}

static int es7000_apic_id_registered(void)
{
456
	return 1;
I
Ingo Molnar 已提交
457 458
}

459
static const struct cpumask *target_cpus_cluster(void)
I
Ingo Molnar 已提交
460
{
461
	return cpu_all_mask;
I
Ingo Molnar 已提交
462 463
}

464
static const struct cpumask *es7000_target_cpus(void)
I
Ingo Molnar 已提交
465
{
466
	return cpumask_of(smp_processor_id());
I
Ingo Molnar 已提交
467 468 469 470 471 472 473 474 475 476 477 478 479 480
}

static unsigned long
es7000_check_apicid_used(physid_mask_t bitmap, int apicid)
{
	return 0;
}
static unsigned long es7000_check_apicid_present(int bit)
{
	return physid_isset(bit, phys_cpu_present_map);
}

static unsigned long calculate_ldr(int cpu)
{
I
Ingo Molnar 已提交
481
	unsigned long id = per_cpu(x86_bios_cpu_apicid, cpu);
I
Ingo Molnar 已提交
482

I
Ingo Molnar 已提交
483
	return SET_APIC_LOGICAL_ID(id);
I
Ingo Molnar 已提交
484 485 486 487 488 489 490 491 492 493 494 495 496 497
}

/*
 * Set up the logical destination ID.
 *
 * Intel recommends to set DFR, LdR and TPR before enabling
 * an APIC.  See e.g. "AP-388 82489DX User's Manual" (Intel
 * document number 292116).  So here it goes...
 */
static void es7000_init_apic_ldr_cluster(void)
{
	unsigned long val;
	int cpu = smp_processor_id();

498
	apic_write(APIC_DFR, APIC_DFR_CLUSTER);
I
Ingo Molnar 已提交
499 500 501 502 503 504 505 506 507
	val = calculate_ldr(cpu);
	apic_write(APIC_LDR, val);
}

static void es7000_init_apic_ldr(void)
{
	unsigned long val;
	int cpu = smp_processor_id();

508
	apic_write(APIC_DFR, APIC_DFR_FLAT);
I
Ingo Molnar 已提交
509 510 511 512 513 514 515
	val = calculate_ldr(cpu);
	apic_write(APIC_LDR, val);
}

static void es7000_setup_apic_routing(void)
{
	int apic = per_cpu(x86_bios_cpu_apicid, smp_processor_id());
I
Ingo Molnar 已提交
516 517 518

	printk(KERN_INFO
	  "Enabling APIC mode:  %s. Using %d I/O APICs, target cpus %lx\n",
I
Ingo Molnar 已提交
519 520
		(apic_version[apic] == 0x14) ?
			"Physical Cluster" : "Logical Cluster",
521
		nr_ioapics, cpumask_bits(es7000_target_cpus())[0]);
I
Ingo Molnar 已提交
522 523 524 525 526 527 528 529 530 531 532 533 534
}

static int es7000_apicid_to_node(int logical_apicid)
{
	return 0;
}


static int es7000_cpu_present_to_apicid(int mps_cpu)
{
	if (!mps_cpu)
		return boot_cpu_physical_apicid;
	else if (mps_cpu < nr_cpu_ids)
I
Ingo Molnar 已提交
535
		return per_cpu(x86_bios_cpu_apicid, mps_cpu);
I
Ingo Molnar 已提交
536 537 538 539
	else
		return BAD_APICID;
}

I
Ingo Molnar 已提交
540 541
static int cpu_id;

I
Ingo Molnar 已提交
542 543 544 545
static physid_mask_t es7000_apicid_to_cpu_present(int phys_apicid)
{
	physid_mask_t mask;

I
Ingo Molnar 已提交
546 547
	mask = physid_mask_of_physid(cpu_id);
	++cpu_id;
I
Ingo Molnar 已提交
548 549 550 551 552 553 554 555 556 557

	return mask;
}

/* Mapping from cpu number to logical apicid */
static int es7000_cpu_to_logical_apicid(int cpu)
{
#ifdef CONFIG_SMP
	if (cpu >= nr_cpu_ids)
		return BAD_APICID;
558
	return cpu_2_logical_apicid[cpu];
I
Ingo Molnar 已提交
559 560 561 562 563 564 565 566 567 568 569 570 571 572
#else
	return logical_smp_processor_id();
#endif
}

static physid_mask_t es7000_ioapic_phys_id_map(physid_mask_t phys_map)
{
	/* For clustered we don't have a good way to do this yet - hack */
	return physids_promote(0xff);
}

static int es7000_check_phys_apicid_present(int cpu_physical_apicid)
{
	boot_cpu_physical_apicid = read_apic_id();
I
Ingo Molnar 已提交
573
	return 1;
I
Ingo Molnar 已提交
574 575
}

576
static unsigned int es7000_cpu_mask_to_apicid(const struct cpumask *cpumask)
I
Ingo Molnar 已提交
577
{
578 579
	unsigned int round = 0;
	int cpu, uninitialized_var(apicid);
I
Ingo Molnar 已提交
580 581

	/*
582
	 * The cpus in the mask must all be on the apic cluster.
I
Ingo Molnar 已提交
583
	 */
584 585
	for_each_cpu(cpu, cpumask) {
		int new_apicid = es7000_cpu_to_logical_apicid(cpu);
I
Ingo Molnar 已提交
586

587 588
		if (round && APIC_CLUSTER(apicid) != APIC_CLUSTER(new_apicid)) {
			WARN(1, "Not a valid mask!");
I
Ingo Molnar 已提交
589

590
			return BAD_APICID;
I
Ingo Molnar 已提交
591
		}
592 593
		apicid = new_apicid;
		round++;
I
Ingo Molnar 已提交
594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627
	}
	return apicid;
}

static unsigned int
es7000_cpu_mask_to_apicid_and(const struct cpumask *inmask,
			      const struct cpumask *andmask)
{
	int apicid = es7000_cpu_to_logical_apicid(0);
	cpumask_var_t cpumask;

	if (!alloc_cpumask_var(&cpumask, GFP_ATOMIC))
		return apicid;

	cpumask_and(cpumask, inmask, andmask);
	cpumask_and(cpumask, cpumask, cpu_online_mask);
	apicid = es7000_cpu_mask_to_apicid(cpumask);

	free_cpumask_var(cpumask);

	return apicid;
}

static int es7000_phys_pkg_id(int cpuid_apic, int index_msb)
{
	return cpuid_apic >> index_msb;
}

static int probe_es7000(void)
{
	/* probed later in mptable/ACPI hooks */
	return 0;
}

628 629 630
static int es7000_mps_ret;
static int es7000_mps_oem_check(struct mpc_table *mpc, char *oem,
		char *productid)
I
Ingo Molnar 已提交
631
{
632 633
	int ret = 0;

I
Ingo Molnar 已提交
634 635 636 637 638
	if (mpc->oemptr) {
		struct mpc_oemtable *oem_table =
			(struct mpc_oemtable *)mpc->oemptr;

		if (!strncmp(oem, "UNISYS", 6))
639
			ret = parse_unisys_oem((char *)oem_table);
I
Ingo Molnar 已提交
640
	}
641 642 643 644 645 646

	es7000_mps_ret = ret;

	return ret && !es7000_apic_is_cluster();
}

647 648
static int es7000_mps_oem_check_cluster(struct mpc_table *mpc, char *oem,
		char *productid)
649 650 651 652
{
	int ret = es7000_mps_ret;

	return ret && es7000_apic_is_cluster();
I
Ingo Molnar 已提交
653 654
}

655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691
struct apic apic_es7000_cluster = {

	.name				= "es7000",
	.probe				= probe_es7000,
	.acpi_madt_oem_check		= es7000_acpi_madt_oem_check_cluster,
	.apic_id_registered		= es7000_apic_id_registered,

	.irq_delivery_mode		= dest_LowestPrio,
	/* logical delivery broadcast to all procs: */
	.irq_dest_mode			= 1,

	.target_cpus			= target_cpus_cluster,
	.disable_esr			= 1,
	.dest_logical			= 0,
	.check_apicid_used		= es7000_check_apicid_used,
	.check_apicid_present		= es7000_check_apicid_present,

	.vector_allocation_domain	= es7000_vector_allocation_domain,
	.init_apic_ldr			= es7000_init_apic_ldr_cluster,

	.ioapic_phys_id_map		= es7000_ioapic_phys_id_map,
	.setup_apic_routing		= es7000_setup_apic_routing,
	.multi_timer_check		= NULL,
	.apicid_to_node			= es7000_apicid_to_node,
	.cpu_to_logical_apicid		= es7000_cpu_to_logical_apicid,
	.cpu_present_to_apicid		= es7000_cpu_present_to_apicid,
	.apicid_to_cpu_present		= es7000_apicid_to_cpu_present,
	.setup_portio_remap		= NULL,
	.check_phys_apicid_present	= es7000_check_phys_apicid_present,
	.enable_apic_mode		= es7000_enable_apic_mode,
	.phys_pkg_id			= es7000_phys_pkg_id,
	.mps_oem_check			= es7000_mps_oem_check_cluster,

	.get_apic_id			= es7000_get_apic_id,
	.set_apic_id			= NULL,
	.apic_id_mask			= 0xFF << 24,

692
	.cpu_mask_to_apicid		= es7000_cpu_mask_to_apicid,
693 694 695 696 697 698 699 700
	.cpu_mask_to_apicid_and		= es7000_cpu_mask_to_apicid_and,

	.send_IPI_mask			= es7000_send_IPI_mask,
	.send_IPI_mask_allbutself	= NULL,
	.send_IPI_allbutself		= es7000_send_IPI_allbutself,
	.send_IPI_all			= es7000_send_IPI_all,
	.send_IPI_self			= default_send_IPI_self,

701
	.wakeup_secondary_cpu		= wakeup_secondary_cpu_via_mip,
702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718

	.trampoline_phys_low		= 0x467,
	.trampoline_phys_high		= 0x469,

	.wait_for_init_deassert		= NULL,

	/* Nothing to do for most platforms, since cleared by the INIT cycle: */
	.smp_callin_clear_local_apic	= NULL,
	.inquire_remote_apic		= default_inquire_remote_apic,

	.read				= native_apic_mem_read,
	.write				= native_apic_mem_write,
	.icr_read			= native_apic_icr_read,
	.icr_write			= native_apic_icr_write,
	.wait_icr_idle			= native_apic_wait_icr_idle,
	.safe_wait_icr_idle		= native_safe_apic_wait_icr_idle,
};
I
Ingo Molnar 已提交
719

720
struct apic apic_es7000 = {
I
Ingo Molnar 已提交
721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763

	.name				= "es7000",
	.probe				= probe_es7000,
	.acpi_madt_oem_check		= es7000_acpi_madt_oem_check,
	.apic_id_registered		= es7000_apic_id_registered,

	.irq_delivery_mode		= dest_Fixed,
	/* phys delivery to target CPUs: */
	.irq_dest_mode			= 0,

	.target_cpus			= es7000_target_cpus,
	.disable_esr			= 1,
	.dest_logical			= 0,
	.check_apicid_used		= es7000_check_apicid_used,
	.check_apicid_present		= es7000_check_apicid_present,

	.vector_allocation_domain	= es7000_vector_allocation_domain,
	.init_apic_ldr			= es7000_init_apic_ldr,

	.ioapic_phys_id_map		= es7000_ioapic_phys_id_map,
	.setup_apic_routing		= es7000_setup_apic_routing,
	.multi_timer_check		= NULL,
	.apicid_to_node			= es7000_apicid_to_node,
	.cpu_to_logical_apicid		= es7000_cpu_to_logical_apicid,
	.cpu_present_to_apicid		= es7000_cpu_present_to_apicid,
	.apicid_to_cpu_present		= es7000_apicid_to_cpu_present,
	.setup_portio_remap		= NULL,
	.check_phys_apicid_present	= es7000_check_phys_apicid_present,
	.enable_apic_mode		= es7000_enable_apic_mode,
	.phys_pkg_id			= es7000_phys_pkg_id,
	.mps_oem_check			= es7000_mps_oem_check,

	.get_apic_id			= es7000_get_apic_id,
	.set_apic_id			= NULL,
	.apic_id_mask			= 0xFF << 24,

	.cpu_mask_to_apicid		= es7000_cpu_mask_to_apicid,
	.cpu_mask_to_apicid_and		= es7000_cpu_mask_to_apicid_and,

	.send_IPI_mask			= es7000_send_IPI_mask,
	.send_IPI_mask_allbutself	= NULL,
	.send_IPI_allbutself		= es7000_send_IPI_allbutself,
	.send_IPI_all			= es7000_send_IPI_all,
764
	.send_IPI_self			= default_send_IPI_self,
I
Ingo Molnar 已提交
765 766 767 768 769 770 771 772 773

	.trampoline_phys_low		= 0x467,
	.trampoline_phys_high		= 0x469,

	.wait_for_init_deassert		= es7000_wait_for_init_deassert,

	/* Nothing to do for most platforms, since cleared by the INIT cycle: */
	.smp_callin_clear_local_apic	= NULL,
	.inquire_remote_apic		= default_inquire_remote_apic,
Y
Yinghai Lu 已提交
774 775 776 777 778 779 780

	.read				= native_apic_mem_read,
	.write				= native_apic_mem_write,
	.icr_read			= native_apic_icr_read,
	.icr_write			= native_apic_icr_write,
	.wait_icr_idle			= native_apic_wait_icr_idle,
	.safe_wait_icr_idle		= native_safe_apic_wait_icr_idle,
I
Ingo Molnar 已提交
781
};