pci.c 22.5 KB
Newer Older
L
Linus Torvalds 已提交
1 2
/*
 * Copyright (C) 2001 Allan Trautman, IBM Corporation
3
 * Copyright (C) 2005,2007  Stephen Rothwell, IBM Corp
L
Linus Torvalds 已提交
4 5
 *
 * iSeries specific routines for PCI.
6
 *
L
Linus Torvalds 已提交
7 8 9 10 11 12
 * Based on code from pci.c and iSeries_pci.c 32bit
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
13
 *
L
Linus Torvalds 已提交
14 15 16 17
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
18
 *
L
Linus Torvalds 已提交
19 20 21 22
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 */
23 24 25

#undef DEBUG

26
#include <linux/jiffies.h>
L
Linus Torvalds 已提交
27
#include <linux/kernel.h>
28
#include <linux/list.h>
L
Linus Torvalds 已提交
29
#include <linux/string.h>
30
#include <linux/slab.h>
L
Linus Torvalds 已提交
31 32 33
#include <linux/init.h>
#include <linux/module.h>
#include <linux/pci.h>
34
#include <linux/of.h>
35
#include <linux/ratelimit.h>
L
Linus Torvalds 已提交
36

37
#include <asm/types.h>
L
Linus Torvalds 已提交
38 39 40 41 42 43
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/prom.h>
#include <asm/machdep.h>
#include <asm/pci-bridge.h>
#include <asm/iommu.h>
44
#include <asm/abs_addr.h>
45
#include <asm/firmware.h>
L
Linus Torvalds 已提交
46

47
#include <asm/iseries/hv_types.h>
48
#include <asm/iseries/hv_call_xm.h>
49
#include <asm/iseries/mf.h>
50
#include <asm/iseries/iommu.h>
L
Linus Torvalds 已提交
51

52
#include <asm/ppc-pci.h>
L
Linus Torvalds 已提交
53

54
#include "irq.h"
55
#include "pci.h"
56
#include "call_pci.h"
57

58 59
#define PCI_RETRY_MAX	3
static int limit_pci_retries = 1;	/* Set Retry Error on. */
L
Linus Torvalds 已提交
60 61 62 63 64 65 66 67

/*
 * Table defines
 * Each Entry size is 4 MB * 1024 Entries = 4GB I/O address space.
 */
#define IOMM_TABLE_MAX_ENTRIES	1024
#define IOMM_TABLE_ENTRY_SIZE	0x0000000000400000UL
#define BASE_IO_MEMORY		0xE000000000000000UL
68
#define END_IO_MEMORY		0xEFFFFFFFFFFFFFFFUL
L
Linus Torvalds 已提交
69

70
static unsigned long max_io_memory = BASE_IO_MEMORY;
L
Linus Torvalds 已提交
71 72 73 74 75
static long current_iomm_table_entry;

/*
 * Lookup Tables.
 */
76
static struct device_node *iomm_table[IOMM_TABLE_MAX_ENTRIES];
77
static u64 ds_addr_table[IOMM_TABLE_MAX_ENTRIES];
L
Linus Torvalds 已提交
78 79 80

static DEFINE_SPINLOCK(iomm_table_lock);

81 82 83 84 85 86
/*
 * Generate a Direct Select Address for the Hypervisor
 */
static inline u64 iseries_ds_addr(struct device_node *node)
{
	struct pci_dn *pdn = PCI_DN(node);
87
	const u32 *sbp = of_get_property(node, "linux,subbus", NULL);
88

89
	return ((u64)pdn->busno << 48) + ((u64)(sbp ? *sbp : 0) << 40)
90 91 92
			+ ((u64)0x10 << 32);
}

93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289
/*
 * Size of Bus VPD data
 */
#define BUS_VPDSIZE      1024

/*
 * Bus Vpd Tags
 */
#define VPD_END_OF_AREA		0x79
#define VPD_ID_STRING		0x82
#define VPD_VENDOR_AREA		0x84

/*
 * Mfg Area Tags
 */
#define VPD_FRU_FRAME_ID	0x4649	/* "FI" */
#define VPD_SLOT_MAP_FORMAT	0x4D46	/* "MF" */
#define VPD_SLOT_MAP		0x534D	/* "SM" */

/*
 * Structures of the areas
 */
struct mfg_vpd_area {
	u16	tag;
	u8	length;
	u8	data1;
	u8	data2;
};
#define MFG_ENTRY_SIZE   3

struct slot_map {
	u8	agent;
	u8	secondary_agent;
	u8	phb;
	char	card_location[3];
	char	parms[8];
	char	reserved[2];
};
#define SLOT_ENTRY_SIZE   16

/*
 * Parse the Slot Area
 */
static void __init iseries_parse_slot_area(struct slot_map *map, int len,
		HvAgentId agent, u8 *phb, char card[4])
{
	/*
	 * Parse Slot label until we find the one requested
	 */
	while (len > 0) {
		if (map->agent == agent) {
			/*
			 * If Phb wasn't found, grab the entry first one found.
			 */
			if (*phb == 0xff)
				*phb = map->phb;
			/* Found it, extract the data. */
			if (map->phb == *phb) {
				memcpy(card, &map->card_location, 3);
				card[3]  = 0;
				break;
			}
		}
		/* Point to the next Slot */
		map = (struct slot_map *)((char *)map + SLOT_ENTRY_SIZE);
		len -= SLOT_ENTRY_SIZE;
	}
}

/*
 * Parse the Mfg Area
 */
static void __init iseries_parse_mfg_area(struct mfg_vpd_area *area, int len,
		HvAgentId agent, u8 *phb, u8 *frame, char card[4])
{
	u16 slot_map_fmt = 0;

	/* Parse Mfg Data */
	while (len > 0) {
		int mfg_tag_len = area->length;
		/* Frame ID         (FI 4649020310 ) */
		if (area->tag == VPD_FRU_FRAME_ID)
			*frame = area->data1;
		/* Slot Map Format  (MF 4D46020004 ) */
		else if (area->tag == VPD_SLOT_MAP_FORMAT)
			slot_map_fmt = (area->data1 * 256)
				+ area->data2;
		/* Slot Map         (SM 534D90 */
		else if (area->tag == VPD_SLOT_MAP) {
			struct slot_map *slot_map;

			if (slot_map_fmt == 0x1004)
				slot_map = (struct slot_map *)((char *)area
						+ MFG_ENTRY_SIZE + 1);
			else
				slot_map = (struct slot_map *)((char *)area
						+ MFG_ENTRY_SIZE);
			iseries_parse_slot_area(slot_map, mfg_tag_len,
					agent, phb, card);
		}
		/*
		 * Point to the next Mfg Area
		 * Use defined size, sizeof give wrong answer
		 */
		area = (struct mfg_vpd_area *)((char *)area + mfg_tag_len
				+ MFG_ENTRY_SIZE);
		len -= (mfg_tag_len + MFG_ENTRY_SIZE);
	}
}

/*
 * Look for "BUS".. Data is not Null terminated.
 * PHBID of 0xFF indicates PHB was not found in VPD Data.
 */
static u8 __init iseries_parse_phbid(u8 *area, int len)
{
	while (len > 0) {
		if ((*area == 'B') && (*(area + 1) == 'U')
				&& (*(area + 2) == 'S')) {
			area += 3;
			while (*area == ' ')
				area++;
			return *area & 0x0F;
		}
		area++;
		len--;
	}
	return 0xff;
}

/*
 * Parse out the VPD Areas
 */
static void __init iseries_parse_vpd(u8 *data, int data_len,
		HvAgentId agent, u8 *frame, char card[4])
{
	u8 phb = 0xff;

	while (data_len > 0) {
		int len;
		u8 tag = *data;

		if (tag == VPD_END_OF_AREA)
			break;
		len = *(data + 1) + (*(data + 2) * 256);
		data += 3;
		data_len -= 3;
		if (tag == VPD_ID_STRING)
			phb = iseries_parse_phbid(data, len);
		else if (tag == VPD_VENDOR_AREA)
			iseries_parse_mfg_area((struct mfg_vpd_area *)data, len,
					agent, &phb, frame, card);
		/* Point to next Area. */
		data += len;
		data_len -= len;
	}
}

static int __init iseries_get_location_code(u16 bus, HvAgentId agent,
		u8 *frame, char card[4])
{
	int status = 0;
	int bus_vpd_len = 0;
	u8 *bus_vpd = kmalloc(BUS_VPDSIZE, GFP_KERNEL);

	if (bus_vpd == NULL) {
		printk("PCI: Bus VPD Buffer allocation failure.\n");
		return 0;
	}
	bus_vpd_len = HvCallPci_getBusVpd(bus, iseries_hv_addr(bus_vpd),
					BUS_VPDSIZE);
	if (bus_vpd_len == 0) {
		printk("PCI: Bus VPD Buffer zero length.\n");
		goto out_free;
	}
	/* printk("PCI: bus_vpd: %p, %d\n",bus_vpd, bus_vpd_len); */
	/* Make sure this is what I think it is */
	if (*bus_vpd != VPD_ID_STRING) {
		printk("PCI: Bus VPD Buffer missing starting tag.\n");
		goto out_free;
	}
	iseries_parse_vpd(bus_vpd, bus_vpd_len, agent, frame, card);
	status = 1;
out_free:
	kfree(bus_vpd);
	return status;
}

/*
 * Prints the device information.
 * - Pass in pci_dev* pointer to the device.
 * - Pass in the device count
 *
 * Format:
 * PCI: Bus  0, Device 26, Vendor 0x12AE  Frame  1, Card  C10  Ethernet
 * controller
 */
290 291
static void __init iseries_device_information(struct pci_dev *pdev,
					      u16 bus, HvSubBusNumber subbus)
292 293 294 295 296 297 298 299 300
{
	u8 frame = 0;
	char card[4];
	HvAgentId agent;

	agent = ISERIES_PCI_AGENTID(ISERIES_GET_DEVICE_FROM_SUBBUS(subbus),
			ISERIES_GET_FUNCTION_FROM_SUBBUS(subbus));

	if (iseries_get_location_code(bus, agent, &frame, card)) {
301 302 303
		printk(KERN_INFO "PCI: %s, Vendor %04X Frame%3d, "
		       "Card %4s  0x%04X\n", pci_name(pdev), pdev->vendor,
		       frame, card, (int)(pdev->class >> 8));
304 305 306
	}
}

L
Linus Torvalds 已提交
307 308 309 310 311 312 313 314 315 316 317 318
/*
 * iomm_table_allocate_entry
 *
 * Adds pci_dev entry in address translation table
 *
 * - Allocates the number of entries required in table base on BAR
 *   size.
 * - Allocates starting at BASE_IO_MEMORY and increases.
 * - The size is round up to be a multiple of entry size.
 * - CurrentIndex is incremented to keep track of the last entry.
 * - Builds the resource entry for allocated BARs.
 */
319
static void __init iomm_table_allocate_entry(struct pci_dev *dev, int bar_num)
L
Linus Torvalds 已提交
320 321 322
{
	struct resource *bar_res = &dev->resource[bar_num];
	long bar_size = pci_resource_len(dev, bar_num);
323
	struct device_node *dn = pci_device_to_OF_node(dev);
L
Linus Torvalds 已提交
324 325 326 327 328 329 330 331 332 333

	/*
	 * No space to allocate, quick exit, skip Allocation.
	 */
	if (bar_size == 0)
		return;
	/*
	 * Set Resource values.
	 */
	spin_lock(&iomm_table_lock);
334
	bar_res->start = BASE_IO_MEMORY +
L
Linus Torvalds 已提交
335 336 337 338 339 340
		IOMM_TABLE_ENTRY_SIZE * current_iomm_table_entry;
	bar_res->end = bar_res->start + bar_size - 1;
	/*
	 * Allocate the number of table entries needed for BAR.
	 */
	while (bar_size > 0 ) {
341
		iomm_table[current_iomm_table_entry] = dn;
342
		ds_addr_table[current_iomm_table_entry] =
343
			iseries_ds_addr(dn) | (bar_num << 24);
L
Linus Torvalds 已提交
344 345 346 347
		bar_size -= IOMM_TABLE_ENTRY_SIZE;
		++current_iomm_table_entry;
	}
	max_io_memory = BASE_IO_MEMORY +
348
		IOMM_TABLE_ENTRY_SIZE * current_iomm_table_entry;
L
Linus Torvalds 已提交
349 350 351 352 353 354 355 356 357 358 359 360 361 362
	spin_unlock(&iomm_table_lock);
}

/*
 * allocate_device_bars
 *
 * - Allocates ALL pci_dev BAR's and updates the resources with the
 *   BAR value.  BARS with zero length will have the resources
 *   The HvCallPci_getBarParms is used to get the size of the BAR
 *   space.  It calls iomm_table_allocate_entry to allocate
 *   each entry.
 * - Loops through The Bar resources(0 - 5) including the ROM
 *   is resource(6).
 */
363
static void __init allocate_device_bars(struct pci_dev *dev)
L
Linus Torvalds 已提交
364 365 366
{
	int bar_num;

367
	for (bar_num = 0; bar_num <= PCI_ROM_RESOURCE; ++bar_num)
L
Linus Torvalds 已提交
368 369 370 371 372 373 374 375 376 377
		iomm_table_allocate_entry(dev, bar_num);
}

/*
 * Log error information to system console.
 * Filter out the device not there errors.
 * PCI: EADs Connect Failed 0x18.58.10 Rc: 0x00xx
 * PCI: Read Vendor Failed 0x18.58.10 Rc: 0x00xx
 * PCI: Connect Bus Unit Failed 0x18.58.10 Rc: 0x00xx
 */
378 379
static void pci_log_error(char *error, int bus, int subbus,
		int agent, int hv_res)
L
Linus Torvalds 已提交
380
{
381
	if (hv_res == 0x0302)
L
Linus Torvalds 已提交
382 383
		return;
	printk(KERN_ERR "PCI: %s Failed: 0x%02X.%02X.%02X Rc: 0x%04X",
384
	       error, bus, subbus, agent, hv_res);
L
Linus Torvalds 已提交
385 386
}

387 388 389
/*
 * Look down the chain to find the matching Device Device
 */
390
static struct device_node *find_device_node(int bus, int devfn)
391 392 393 394 395 396 397 398 399 400 401 402
{
	struct device_node *node;

	for (node = NULL; (node = of_find_all_nodes(node)); ) {
		struct pci_dn *pdn = PCI_DN(node);

		if (pdn && (bus == pdn->busno) && (devfn == pdn->devfn))
			return node;
	}
	return NULL;
}

L
Linus Torvalds 已提交
403
/*
404 405 406
 * iSeries_pcibios_fixup_resources
 *
 * Fixes up all resources for devices
L
Linus Torvalds 已提交
407
 */
408
void __init iSeries_pcibios_fixup_resources(struct pci_dev *pdev)
L
Linus Torvalds 已提交
409
{
410 411 412
	const u32 *agent;
	const u32 *sub_bus;
	unsigned char bus = pdev->bus->number;
413
	struct device_node *node;
414 415
	int i;

416
	node = pci_device_to_OF_node(pdev);
417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437
	pr_debug("PCI: iSeries %s, pdev %p, node %p\n",
		 pci_name(pdev), pdev, node);
	if (!node) {
		printk("PCI: %s disabled, device tree entry not found !\n",
		       pci_name(pdev));
		for (i = 0; i <= PCI_ROM_RESOURCE; i++)
			pdev->resource[i].flags = 0;
		return;
	}
	sub_bus = of_get_property(node, "linux,subbus", NULL);
	agent = of_get_property(node, "linux,agent-id", NULL);
	if (agent && sub_bus) {
		u8 irq = iSeries_allocate_IRQ(bus, 0, *sub_bus);
		int err;

		err = HvCallXm_connectBusUnit(bus, *sub_bus, *agent, irq);
		if (err)
			pci_log_error("Connect Bus Unit",
				      bus, *sub_bus, *agent, err);
		else {
			err = HvCallPci_configStore8(bus, *sub_bus,
438
					*agent, PCI_INTERRUPT_LINE, irq);
439 440
			if (err)
				pci_log_error("PciCfgStore Irq Failed!",
441
						bus, *sub_bus, *agent, err);
442 443
			else
				pdev->irq = irq;
444
		}
L
Linus Torvalds 已提交
445
	}
446 447

	allocate_device_bars(pdev);
448 449 450 451 452
	if (likely(sub_bus))
		iseries_device_information(pdev, bus, *sub_bus);
	else
		printk(KERN_ERR "PCI: Device node %s has missing or invalid "
				"linux,subbus property\n", node->full_name);
453 454 455 456 457 458 459 460 461
}

/*
 * iSeries_pci_final_fixup(void)
 */
void __init iSeries_pci_final_fixup(void)
{
	/* Fix up at the device node and pci_dev relationship */
	mf_display_src(0xC9000100);
L
Linus Torvalds 已提交
462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487
	iSeries_activate_IRQs();
	mf_display_src(0xC9000200);
}

/*
 * Config space read and write functions.
 * For now at least, we look for the device node for the bus and devfn
 * that we are asked to access.  It may be possible to translate the devfn
 * to a subbus and deviceid more directly.
 */
static u64 hv_cfg_read_func[4]  = {
	HvCallPciConfigLoad8, HvCallPciConfigLoad16,
	HvCallPciConfigLoad32, HvCallPciConfigLoad32
};

static u64 hv_cfg_write_func[4] = {
	HvCallPciConfigStore8, HvCallPciConfigStore16,
	HvCallPciConfigStore32, HvCallPciConfigStore32
};

/*
 * Read PCI config space
 */
static int iSeries_pci_read_config(struct pci_bus *bus, unsigned int devfn,
		int offset, int size, u32 *val)
{
488
	struct device_node *node = find_device_node(bus->number, devfn);
L
Linus Torvalds 已提交
489 490 491 492 493 494 495 496 497 498 499
	u64 fn;
	struct HvCallPci_LoadReturn ret;

	if (node == NULL)
		return PCIBIOS_DEVICE_NOT_FOUND;
	if (offset > 255) {
		*val = ~0;
		return PCIBIOS_BAD_REGISTER_NUMBER;
	}

	fn = hv_cfg_read_func[(size - 1) & 3];
500
	HvCall3Ret16(fn, &ret, iseries_ds_addr(node), offset, 0);
L
Linus Torvalds 已提交
501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517

	if (ret.rc != 0) {
		*val = ~0;
		return PCIBIOS_DEVICE_NOT_FOUND;	/* or something */
	}

	*val = ret.value;
	return 0;
}

/*
 * Write PCI config space
 */

static int iSeries_pci_write_config(struct pci_bus *bus, unsigned int devfn,
		int offset, int size, u32 val)
{
518
	struct device_node *node = find_device_node(bus->number, devfn);
L
Linus Torvalds 已提交
519 520 521 522 523 524 525 526 527
	u64 fn;
	u64 ret;

	if (node == NULL)
		return PCIBIOS_DEVICE_NOT_FOUND;
	if (offset > 255)
		return PCIBIOS_BAD_REGISTER_NUMBER;

	fn = hv_cfg_write_func[(size - 1) & 3];
528
	ret = HvCall4(fn, iseries_ds_addr(node), offset, val, 0);
L
Linus Torvalds 已提交
529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549

	if (ret != 0)
		return PCIBIOS_DEVICE_NOT_FOUND;

	return 0;
}

static struct pci_ops iSeries_pci_ops = {
	.read = iSeries_pci_read_config,
	.write = iSeries_pci_write_config
};

/*
 * Check Return Code
 * -> On Failure, print and log information.
 *    Increment Retry Count, if exceeds max, panic partition.
 *
 * PCI: Device 23.90 ReadL I/O Error( 0): 0x1234
 * PCI: Device 23.90 ReadL Retry( 1)
 * PCI: Device 23.90 ReadL Retry Successful(1)
 */
550
static int check_return_code(char *type, struct device_node *dn,
551
		int *retry, u64 ret)
L
Linus Torvalds 已提交
552 553
{
	if (ret != 0)  {
554
		struct pci_dn *pdn = PCI_DN(dn);
555

556
		(*retry)++;
L
Linus Torvalds 已提交
557
		printk("PCI: %s: Device 0x%04X:%02X  I/O Error(%2d): 0x%04X\n",
558
				type, pdn->busno, pdn->devfn,
559
				*retry, (int)ret);
L
Linus Torvalds 已提交
560 561 562 563
		/*
		 * Bump the retry and check for retry count exceeded.
		 * If, Exceeded, panic the system.
		 */
564 565
		if (((*retry) > PCI_RETRY_MAX) &&
				(limit_pci_retries > 0)) {
L
Linus Torvalds 已提交
566
			mf_display_src(0xB6000103);
567
			panic_timeout = 0;
L
Linus Torvalds 已提交
568 569 570 571 572
			panic("PCI: Hardware I/O Error, SRC B6000103, "
					"Automatic Reboot Disabled.\n");
		}
		return -1;	/* Retry Try */
	}
573
	return 0;
L
Linus Torvalds 已提交
574 575 576 577 578 579 580
}

/*
 * Translate the I/O Address into a device node, bar, and bar offset.
 * Note: Make sure the passed variable end up on the stack to avoid
 * the exposure of being device global.
 */
581
static inline struct device_node *xlate_iomm_address(
582
		const volatile void __iomem *addr,
583
		u64 *dsaptr, u64 *bar_offset, const char *func)
L
Linus Torvalds 已提交
584
{
585 586 587 588
	unsigned long orig_addr;
	unsigned long base_addr;
	unsigned long ind;
	struct device_node *dn;
L
Linus Torvalds 已提交
589

590
	orig_addr = (unsigned long __force)addr;
591
	if ((orig_addr < BASE_IO_MEMORY) || (orig_addr >= max_io_memory)) {
592
		static DEFINE_RATELIMIT_STATE(ratelimit, 60 * HZ, 10);
593

594
		if (__ratelimit(&ratelimit))
595 596 597
			printk(KERN_ERR
				"iSeries_%s: invalid access at IO address %p\n",
				func, addr);
L
Linus Torvalds 已提交
598
		return NULL;
599
	}
600 601 602 603 604
	base_addr = orig_addr - BASE_IO_MEMORY;
	ind = base_addr / IOMM_TABLE_ENTRY_SIZE;
	dn = iomm_table[ind];

	if (dn != NULL) {
605
		*dsaptr = ds_addr_table[ind];
606
		*bar_offset = base_addr % IOMM_TABLE_ENTRY_SIZE;
L
Linus Torvalds 已提交
607
	} else
608 609
		panic("PCI: Invalid PCI IO address detected!\n");
	return dn;
L
Linus Torvalds 已提交
610 611 612 613 614
}

/*
 * Read MM I/O Instructions for the iSeries
 * On MM I/O error, all ones are returned and iSeries_pci_IoError is cal
615
 * else, data is returned in Big Endian format.
L
Linus Torvalds 已提交
616
 */
617
static u8 iseries_readb(const volatile void __iomem *addr)
L
Linus Torvalds 已提交
618
{
619
	u64 bar_offset;
L
Linus Torvalds 已提交
620
	u64 dsa;
621
	int retry = 0;
L
Linus Torvalds 已提交
622
	struct HvCallPci_LoadReturn ret;
623
	struct device_node *dn =
624
		xlate_iomm_address(addr, &dsa, &bar_offset, "read_byte");
L
Linus Torvalds 已提交
625

626
	if (dn == NULL)
L
Linus Torvalds 已提交
627 628
		return 0xff;
	do {
629 630
		HvCall3Ret16(HvCallPciBarLoad8, &ret, dsa, bar_offset, 0);
	} while (check_return_code("RDB", dn, &retry, ret.rc) != 0);
L
Linus Torvalds 已提交
631

632
	return ret.value;
L
Linus Torvalds 已提交
633 634
}

635
static u16 iseries_readw_be(const volatile void __iomem *addr)
L
Linus Torvalds 已提交
636
{
637
	u64 bar_offset;
L
Linus Torvalds 已提交
638
	u64 dsa;
639
	int retry = 0;
L
Linus Torvalds 已提交
640
	struct HvCallPci_LoadReturn ret;
641
	struct device_node *dn =
642
		xlate_iomm_address(addr, &dsa, &bar_offset, "read_word");
L
Linus Torvalds 已提交
643

644
	if (dn == NULL)
L
Linus Torvalds 已提交
645 646 647
		return 0xffff;
	do {
		HvCall3Ret16(HvCallPciBarLoad16, &ret, dsa,
648 649
				bar_offset, 0);
	} while (check_return_code("RDW", dn, &retry, ret.rc) != 0);
L
Linus Torvalds 已提交
650

651
	return ret.value;
L
Linus Torvalds 已提交
652 653
}

654
static u32 iseries_readl_be(const volatile void __iomem *addr)
L
Linus Torvalds 已提交
655
{
656
	u64 bar_offset;
L
Linus Torvalds 已提交
657
	u64 dsa;
658
	int retry = 0;
L
Linus Torvalds 已提交
659
	struct HvCallPci_LoadReturn ret;
660
	struct device_node *dn =
661
		xlate_iomm_address(addr, &dsa, &bar_offset, "read_long");
L
Linus Torvalds 已提交
662

663
	if (dn == NULL)
L
Linus Torvalds 已提交
664 665 666
		return 0xffffffff;
	do {
		HvCall3Ret16(HvCallPciBarLoad32, &ret, dsa,
667 668
				bar_offset, 0);
	} while (check_return_code("RDL", dn, &retry, ret.rc) != 0);
L
Linus Torvalds 已提交
669

670
	return ret.value;
L
Linus Torvalds 已提交
671 672 673 674 675 676
}

/*
 * Write MM I/O Instructions for the iSeries
 *
 */
677
static void iseries_writeb(u8 data, volatile void __iomem *addr)
L
Linus Torvalds 已提交
678
{
679
	u64 bar_offset;
L
Linus Torvalds 已提交
680
	u64 dsa;
681
	int retry = 0;
L
Linus Torvalds 已提交
682
	u64 rc;
683
	struct device_node *dn =
684
		xlate_iomm_address(addr, &dsa, &bar_offset, "write_byte");
L
Linus Torvalds 已提交
685

686
	if (dn == NULL)
L
Linus Torvalds 已提交
687 688
		return;
	do {
689 690
		rc = HvCall4(HvCallPciBarStore8, dsa, bar_offset, data, 0);
	} while (check_return_code("WWB", dn, &retry, rc) != 0);
L
Linus Torvalds 已提交
691 692
}

693
static void iseries_writew_be(u16 data, volatile void __iomem *addr)
L
Linus Torvalds 已提交
694
{
695
	u64 bar_offset;
L
Linus Torvalds 已提交
696
	u64 dsa;
697
	int retry = 0;
L
Linus Torvalds 已提交
698
	u64 rc;
699
	struct device_node *dn =
700
		xlate_iomm_address(addr, &dsa, &bar_offset, "write_word");
L
Linus Torvalds 已提交
701

702
	if (dn == NULL)
L
Linus Torvalds 已提交
703 704
		return;
	do {
705 706
		rc = HvCall4(HvCallPciBarStore16, dsa, bar_offset, data, 0);
	} while (check_return_code("WWW", dn, &retry, rc) != 0);
L
Linus Torvalds 已提交
707 708
}

709
static void iseries_writel_be(u32 data, volatile void __iomem *addr)
L
Linus Torvalds 已提交
710
{
711
	u64 bar_offset;
L
Linus Torvalds 已提交
712
	u64 dsa;
713
	int retry = 0;
L
Linus Torvalds 已提交
714
	u64 rc;
715
	struct device_node *dn =
716
		xlate_iomm_address(addr, &dsa, &bar_offset, "write_long");
L
Linus Torvalds 已提交
717

718
	if (dn == NULL)
L
Linus Torvalds 已提交
719 720
		return;
	do {
721 722
		rc = HvCall4(HvCallPciBarStore32, dsa, bar_offset, data, 0);
	} while (check_return_code("WWL", dn, &retry, rc) != 0);
L
Linus Torvalds 已提交
723
}
724

725
static u16 iseries_readw(const volatile void __iomem *addr)
726
{
727
	return le16_to_cpu(iseries_readw_be(addr));
728 729
}

730
static u32 iseries_readl(const volatile void __iomem *addr)
731
{
732
	return le32_to_cpu(iseries_readl_be(addr));
733 734
}

735
static void iseries_writew(u16 data, volatile void __iomem *addr)
736
{
737
	iseries_writew_be(cpu_to_le16(data), addr);
738 739
}

740
static void iseries_writel(u32 data, volatile void __iomem *addr)
741
{
742
	iseries_writel(cpu_to_le32(data), addr);
743 744
}

745 746
static void iseries_readsb(const volatile void __iomem *addr, void *buf,
			   unsigned long count)
747
{
748 749
	u8 *dst = buf;
	while(count-- > 0)
750
		*(dst++) = iseries_readb(addr);
751 752
}

753 754
static void iseries_readsw(const volatile void __iomem *addr, void *buf,
			   unsigned long count)
755
{
756 757
	u16 *dst = buf;
	while(count-- > 0)
758
		*(dst++) = iseries_readw_be(addr);
759 760
}

761 762
static void iseries_readsl(const volatile void __iomem *addr, void *buf,
			   unsigned long count)
763
{
764 765
	u32 *dst = buf;
	while(count-- > 0)
766
		*(dst++) = iseries_readl_be(addr);
767 768
}

769 770
static void iseries_writesb(volatile void __iomem *addr, const void *buf,
			    unsigned long count)
771
{
772 773
	const u8 *src = buf;
	while(count-- > 0)
774
		iseries_writeb(*(src++), addr);
775 776
}

777 778
static void iseries_writesw(volatile void __iomem *addr, const void *buf,
			    unsigned long count)
779
{
780 781
	const u16 *src = buf;
	while(count-- > 0)
782
		iseries_writew_be(*(src++), addr);
783 784
}

785 786
static void iseries_writesl(volatile void __iomem *addr, const void *buf,
			    unsigned long count)
787
{
788 789
	const u32 *src = buf;
	while(count-- > 0)
790
		iseries_writel_be(*(src++), addr);
791 792
}

793 794
static void iseries_memset_io(volatile void __iomem *addr, int c,
			      unsigned long n)
795
{
796
	volatile char __iomem *d = addr;
797

798
	while (n-- > 0)
799
		iseries_writeb(c, d++);
800 801
}

802 803
static void iseries_memcpy_fromio(void *dest, const volatile void __iomem *src,
				  unsigned long n)
804
{
805 806
	char *d = dest;
	const volatile char __iomem *s = src;
807

808
	while (n-- > 0)
809
		*d++ = iseries_readb(s++);
810 811
}

812 813
static void iseries_memcpy_toio(volatile void __iomem *dest, const void *src,
				unsigned long n)
814
{
815 816
	const char *s = src;
	volatile char __iomem *d = dest;
817

818
	while (n-- > 0)
819
		iseries_writeb(*s++, d++);
820 821
}

822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852
/* We only set MMIO ops. The default PIO ops will be default
 * to the MMIO ops + pci_io_base which is 0 on iSeries as
 * expected so both should work.
 *
 * Note that we don't implement the readq/writeq versions as
 * I don't know of an HV call for doing so. Thus, the default
 * operation will be used instead, which will fault a the value
 * return by iSeries for MMIO addresses always hits a non mapped
 * area. This is as good as the BUG() we used to have there.
 */
static struct ppc_pci_io __initdata iseries_pci_io = {
	.readb = iseries_readb,
	.readw = iseries_readw,
	.readl = iseries_readl,
	.readw_be = iseries_readw_be,
	.readl_be = iseries_readl_be,
	.writeb = iseries_writeb,
	.writew = iseries_writew,
	.writel = iseries_writel,
	.writew_be = iseries_writew_be,
	.writel_be = iseries_writel_be,
	.readsb = iseries_readsb,
	.readsw = iseries_readsw,
	.readsl = iseries_readsl,
	.writesb = iseries_writesb,
	.writesw = iseries_writesw,
	.writesl = iseries_writesl,
	.memset_io = iseries_memset_io,
	.memcpy_fromio = iseries_memcpy_fromio,
	.memcpy_toio = iseries_memcpy_toio,
};
853

854 855 856 857 858 859 860 861 862 863
/*
 * iSeries_pcibios_init
 *
 * Description:
 *   This function checks for all possible system PCI host bridges that connect
 *   PCI buses.  The system hypervisor is queried as to the guest partition
 *   ownership status.  A pci_controller is built for any bus which is partially
 *   owned or fully owned by this guest partition.
 */
void __init iSeries_pcibios_init(void)
864
{
865 866 867
	struct pci_controller *phb;
	struct device_node *root = of_find_node_by_path("/");
	struct device_node *node = NULL;
868

869 870
	/* Install IO hooks */
	ppc_pci_io = iseries_pci_io;
871

872 873
	pci_probe_only = 1;

874 875 876 877 878
	/* iSeries has no IO space in the common sense, it needs to set
	 * the IO base to 0
	 */
	pci_io_base = 0;

879 880 881 882 883 884 885 886
	if (root == NULL) {
		printk(KERN_CRIT "iSeries_pcibios_init: can't find root "
				"of device tree\n");
		return;
	}
	while ((node = of_get_next_child(root, node)) != NULL) {
		HvBusNumber bus;
		const u32 *busp;
887

888 889
		if ((node->type == NULL) || (strcmp(node->type, "pci") != 0))
			continue;
890

891
		busp = of_get_property(node, "bus-range", NULL);
892 893 894 895 896 897 898
		if (busp == NULL)
			continue;
		bus = *busp;
		printk("bus %d appears to exist\n", bus);
		phb = pcibios_alloc_controller(node);
		if (phb == NULL)
			continue;
899 900
		/* All legacy iSeries PHBs are in domain zero */
		phb->global_number = 0;
901

902 903 904
		phb->first_busno = bus;
		phb->last_busno = bus;
		phb->ops = &iSeries_pci_ops;
905 906 907 908 909 910 911 912 913
		phb->io_base_virt = (void __iomem *)_IO_BASE;
		phb->io_resource.flags = IORESOURCE_IO;
		phb->io_resource.start = BASE_IO_MEMORY;
		phb->io_resource.end = END_IO_MEMORY;
		phb->io_resource.name = "iSeries PCI IO";
		phb->mem_resources[0].flags = IORESOURCE_MEM;
		phb->mem_resources[0].start = BASE_IO_MEMORY;
		phb->mem_resources[0].end = END_IO_MEMORY;
		phb->mem_resources[0].name = "Series PCI MEM";
914
	}
915

916
	of_node_put(root);
917

918
	pci_devs_phb_init();
919
}
920