fsl_rio.c 17.6 KB
Newer Older
M
Matt Porter 已提交
1
/*
2
 * Freescale MPC85xx/MPC86xx RapidIO support
M
Matt Porter 已提交
3
 *
4 5 6 7
 * Copyright 2009 Sysgo AG
 * Thomas Moll <thomas.moll@sysgo.com>
 * - fixed maintenance access routines, check for aligned access
 *
8 9 10 11 12
 * Copyright 2009 Integrated Device Technology, Inc.
 * Alex Bounine <alexandre.bounine@idt.com>
 * - Added Port-Write message handling
 * - Added Machine Check exception handling
 *
13
 * Copyright (C) 2007, 2008, 2010, 2011 Freescale Semiconductor, Inc.
14 15
 * Zhang Wei <wei.zhang@freescale.com>
 *
M
Matt Porter 已提交
16 17 18 19 20 21 22 23 24 25
 * Copyright 2005 MontaVista Software, Inc.
 * Matt Porter <mporter@kernel.crashing.org>
 *
 * 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.
 */

#include <linux/init.h>
L
Liu Gang 已提交
26
#include <linux/module.h>
M
Matt Porter 已提交
27 28 29
#include <linux/types.h>
#include <linux/dma-mapping.h>
#include <linux/interrupt.h>
30
#include <linux/device.h>
31
#include <linux/of_platform.h>
32
#include <linux/delay.h>
33
#include <linux/slab.h>
M
Matt Porter 已提交
34

35 36
#include <linux/io.h>
#include <linux/uaccess.h>
37
#include <asm/machdep.h>
M
Matt Porter 已提交
38

39
#include "fsl_rio.h"
40

41
#undef DEBUG_PW	/* Port-Write debugging */
42 43 44 45 46 47

#define RIO_PORT1_EDCSR		0x0640
#define RIO_PORT2_EDCSR		0x0680
#define RIO_PORT1_IECSR		0x10130
#define RIO_PORT2_IECSR		0x101B0

48
#define RIO_GCCSR		0x13c
49
#define RIO_ESCSR		0x158
50
#define ESCSR_CLEAR		0x07120204
51
#define RIO_PORT2_ESCSR		0x178
52
#define RIO_CCSR		0x15c
53 54
#define RIO_LTLEDCSR_IER	0x80000000
#define RIO_LTLEDCSR_PRT	0x01000000
55
#define IECSR_CLEAR		0x80000000
56 57
#define RIO_ISR_AACR		0x10120
#define RIO_ISR_AACR_AA		0x1	/* Accept All ID */
M
Matt Porter 已提交
58

59 60 61 62 63 64 65 66 67 68
#define __fsl_read_rio_config(x, addr, err, op)		\
	__asm__ __volatile__(				\
		"1:	"op" %1,0(%2)\n"		\
		"	eieio\n"			\
		"2:\n"					\
		".section .fixup,\"ax\"\n"		\
		"3:	li %1,-1\n"			\
		"	li %0,%3\n"			\
		"	b 2b\n"				\
		".section __ex_table,\"a\"\n"		\
69 70
			PPC_LONG_ALIGN "\n"		\
			PPC_LONG "1b,3b\n"		\
71 72 73 74
		".text"					\
		: "=r" (err), "=r" (x)			\
		: "b" (addr), "i" (-EFAULT), "0" (err))

75
void __iomem *rio_regs_win;
76 77 78 79 80
void __iomem *rmu_regs_win;
resource_size_t rio_law_start;

struct fsl_rio_dbell *dbell;
struct fsl_rio_pw *pw;
81

L
Li Yang 已提交
82
#ifdef CONFIG_E500
83
int fsl_rio_mcheck_exception(struct pt_regs *regs)
84
{
85 86
	const struct exception_table_entry *entry;
	unsigned long reason;
87

88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
	if (!rio_regs_win)
		return 0;

	reason = in_be32((u32 *)(rio_regs_win + RIO_LTLEDCSR));
	if (reason & (RIO_LTLEDCSR_IER | RIO_LTLEDCSR_PRT)) {
		/* Check if we are prepared to handle this fault */
		entry = search_exception_tables(regs->nip);
		if (entry) {
			pr_debug("RIO: %s - MC Exception handled\n",
				 __func__);
			out_be32((u32 *)(rio_regs_win + RIO_LTLEDCSR),
				 0);
			regs->msr |= MSR_RI;
			regs->nip = entry->fixup;
			return 1;
103 104 105
		}
	}

106
	return 0;
107
}
108
EXPORT_SYMBOL_GPL(fsl_rio_mcheck_exception);
L
Li Yang 已提交
109
#endif
110

M
Matt Porter 已提交
111
/**
112
 * fsl_local_config_read - Generate a MPC85xx local config space read
113
 * @mport: RapidIO master port info
M
Matt Porter 已提交
114 115 116 117 118 119 120 121
 * @index: ID of RapdiIO interface
 * @offset: Offset into configuration space
 * @len: Length (in bytes) of the maintenance transaction
 * @data: Value to be read into
 *
 * Generates a MPC85xx local configuration space read. Returns %0 on
 * success or %-EINVAL on failure.
 */
122 123
static int fsl_local_config_read(struct rio_mport *mport,
				int index, u32 offset, int len, u32 *data)
M
Matt Porter 已提交
124
{
125
	struct rio_priv *priv = mport->priv;
126
	pr_debug("fsl_local_config_read: index %d offset %8.8x\n", index,
127
		 offset);
128
	*data = in_be32(priv->regs_win + offset);
M
Matt Porter 已提交
129 130 131 132 133

	return 0;
}

/**
134
 * fsl_local_config_write - Generate a MPC85xx local config space write
135
 * @mport: RapidIO master port info
M
Matt Porter 已提交
136 137 138 139 140 141 142 143
 * @index: ID of RapdiIO interface
 * @offset: Offset into configuration space
 * @len: Length (in bytes) of the maintenance transaction
 * @data: Value to be written
 *
 * Generates a MPC85xx local configuration space write. Returns %0 on
 * success or %-EINVAL on failure.
 */
144 145
static int fsl_local_config_write(struct rio_mport *mport,
				int index, u32 offset, int len, u32 data)
M
Matt Porter 已提交
146
{
147
	struct rio_priv *priv = mport->priv;
M
Matt Porter 已提交
148
	pr_debug
149 150
		("fsl_local_config_write: index %d offset %8.8x data %8.8x\n",
		index, offset, data);
151
	out_be32(priv->regs_win + offset, data);
M
Matt Porter 已提交
152 153 154 155 156

	return 0;
}

/**
157
 * fsl_rio_config_read - Generate a MPC85xx read maintenance transaction
158
 * @mport: RapidIO master port info
M
Matt Porter 已提交
159 160 161 162 163 164 165 166 167 168 169
 * @index: ID of RapdiIO interface
 * @destid: Destination ID of transaction
 * @hopcount: Number of hops to target device
 * @offset: Offset into configuration space
 * @len: Length (in bytes) of the maintenance transaction
 * @val: Location to be read into
 *
 * Generates a MPC85xx read maintenance transaction. Returns %0 on
 * success or %-EINVAL on failure.
 */
static int
170 171
fsl_rio_config_read(struct rio_mport *mport, int index, u16 destid,
			u8 hopcount, u32 offset, int len, u32 *val)
M
Matt Porter 已提交
172
{
173
	struct rio_priv *priv = mport->priv;
M
Matt Porter 已提交
174
	u8 *data;
175
	u32 rval, err = 0;
M
Matt Porter 已提交
176 177

	pr_debug
178 179
		("fsl_rio_config_read:"
		" index %d destid %d hopcount %d offset %8.8x len %d\n",
180
		index, destid, hopcount, offset, len);
181 182 183 184 185 186

	/* 16MB maintenance window possible */
	/* allow only aligned access to maintenance registers */
	if (offset > (0x1000000 - len) || !IS_ALIGNED(offset, len))
		return -EINVAL;

187
	out_be32(&priv->maint_atmu_regs->rowtar,
188
		 (destid << 22) | (hopcount << 12) | (offset >> 12));
189
	out_be32(&priv->maint_atmu_regs->rowtear, (destid >> 10));
M
Matt Porter 已提交
190

191
	data = (u8 *) priv->maint_win + (offset & (RIO_MAINT_WIN_SIZE - 1));
M
Matt Porter 已提交
192 193
	switch (len) {
	case 1:
194
		__fsl_read_rio_config(rval, data, err, "lbz");
M
Matt Porter 已提交
195 196
		break;
	case 2:
197
		__fsl_read_rio_config(rval, data, err, "lhz");
M
Matt Porter 已提交
198
		break;
199
	case 4:
200
		__fsl_read_rio_config(rval, data, err, "lwz");
M
Matt Porter 已提交
201
		break;
202 203
	default:
		return -EINVAL;
M
Matt Porter 已提交
204 205
	}

206 207 208 209 210 211 212 213
	if (err) {
		pr_debug("RIO: cfg_read error %d for %x:%x:%x\n",
			 err, destid, hopcount, offset);
	}

	*val = rval;

	return err;
M
Matt Porter 已提交
214 215 216
}

/**
217
 * fsl_rio_config_write - Generate a MPC85xx write maintenance transaction
218
 * @mport: RapidIO master port info
M
Matt Porter 已提交
219 220 221 222 223 224 225 226 227 228 229
 * @index: ID of RapdiIO interface
 * @destid: Destination ID of transaction
 * @hopcount: Number of hops to target device
 * @offset: Offset into configuration space
 * @len: Length (in bytes) of the maintenance transaction
 * @val: Value to be written
 *
 * Generates an MPC85xx write maintenance transaction. Returns %0 on
 * success or %-EINVAL on failure.
 */
static int
230 231
fsl_rio_config_write(struct rio_mport *mport, int index, u16 destid,
			u8 hopcount, u32 offset, int len, u32 val)
M
Matt Porter 已提交
232
{
233
	struct rio_priv *priv = mport->priv;
M
Matt Porter 已提交
234 235
	u8 *data;
	pr_debug
236
		("fsl_rio_config_write:"
237 238
		" index %d destid %d hopcount %d offset %8.8x len %d val %8.8x\n",
		index, destid, hopcount, offset, len, val);
239 240 241 242 243 244

	/* 16MB maintenance windows possible */
	/* allow only aligned access to maintenance registers */
	if (offset > (0x1000000 - len) || !IS_ALIGNED(offset, len))
		return -EINVAL;

245
	out_be32(&priv->maint_atmu_regs->rowtar,
246
		 (destid << 22) | (hopcount << 12) | (offset >> 12));
247
	out_be32(&priv->maint_atmu_regs->rowtear, (destid >> 10));
M
Matt Porter 已提交
248

249
	data = (u8 *) priv->maint_win + (offset & (RIO_MAINT_WIN_SIZE - 1));
M
Matt Porter 已提交
250 251 252 253 254 255 256
	switch (len) {
	case 1:
		out_8((u8 *) data, val);
		break;
	case 2:
		out_be16((u16 *) data, val);
		break;
257
	case 4:
M
Matt Porter 已提交
258 259
		out_be32((u32 *) data, val);
		break;
260 261
	default:
		return -EINVAL;
M
Matt Porter 已提交
262 263 264 265 266
	}

	return 0;
}

267
void fsl_rio_port_error_handler(int offset)
268 269 270 271 272 273
{
	/*XXX: Error recovery is not implemented, we just clear errors */
	out_be32((u32 *)(rio_regs_win + RIO_LTLEDCSR), 0);

	if (offset == 0) {
		out_be32((u32 *)(rio_regs_win + RIO_PORT1_EDCSR), 0);
274
		out_be32((u32 *)(rio_regs_win + RIO_PORT1_IECSR), IECSR_CLEAR);
275 276 277
		out_be32((u32 *)(rio_regs_win + RIO_ESCSR), ESCSR_CLEAR);
	} else {
		out_be32((u32 *)(rio_regs_win + RIO_PORT2_EDCSR), 0);
278
		out_be32((u32 *)(rio_regs_win + RIO_PORT2_IECSR), IECSR_CLEAR);
279 280 281
		out_be32((u32 *)(rio_regs_win + RIO_PORT2_ESCSR), ESCSR_CLEAR);
	}
}
282 283 284 285 286 287 288 289 290 291 292 293 294 295
static inline void fsl_rio_info(struct device *dev, u32 ccsr)
{
	const char *str;
	if (ccsr & 1) {
		/* Serial phy */
		switch (ccsr >> 30) {
		case 0:
			str = "1";
			break;
		case 1:
			str = "4";
			break;
		default:
			str = "Unknown";
296
			break;
297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323
		}
		dev_info(dev, "Hardware port width: %s\n", str);

		switch ((ccsr >> 27) & 7) {
		case 0:
			str = "Single-lane 0";
			break;
		case 1:
			str = "Single-lane 2";
			break;
		case 2:
			str = "Four-lane";
			break;
		default:
			str = "Unknown";
			break;
		}
		dev_info(dev, "Training connection status: %s\n", str);
	} else {
		/* Parallel phy */
		if (!(ccsr & 0x80000000))
			dev_info(dev, "Output port operating in 8-bit mode\n");
		if (!(ccsr & 0x08000000))
			dev_info(dev, "Input port operating in 8-bit mode\n");
	}
}

M
Matt Porter 已提交
324
/**
325
 * fsl_rio_setup - Setup Freescale PowerPC RapidIO interface
326
 * @dev: platform_device pointer
M
Matt Porter 已提交
327 328 329 330 331
 *
 * Initializes MPC85xx RapidIO hardware interface, configures
 * master port with system-specific info, and registers the
 * master port with the RapidIO subsystem.
 */
332
int fsl_rio_setup(struct platform_device *dev)
M
Matt Porter 已提交
333 334 335
{
	struct rio_ops *ops;
	struct rio_mport *port;
336 337
	struct rio_priv *priv;
	int rc = 0;
338 339 340 341
	const u32 *dt_range, *cell, *port_index;
	u32 active_ports = 0;
	struct resource regs, rmu_regs;
	struct device_node *np, *rmu_node;
342
	int rlen;
343
	u32 ccsr;
344
	u64 range_start, range_size;
345
	int paw, aw, sw;
346 347 348
	u32 i;
	static int tmp;
	struct device_node *rmu_np[MAX_MSG_UNIT_NUM] = {NULL};
349

350
	if (!dev->dev.of_node) {
351
		dev_err(&dev->dev, "Device OF-Node is NULL");
352
		return -ENODEV;
353 354
	}

355
	rc = of_address_to_resource(dev->dev.of_node, 0, &regs);
356 357
	if (rc) {
		dev_err(&dev->dev, "Can't get %s property 'reg'\n",
358
				dev->dev.of_node->full_name);
359 360
		return -EFAULT;
	}
361 362
	dev_info(&dev->dev, "Of-device full name %s\n",
			dev->dev.of_node->full_name);
363
	dev_info(&dev->dev, "Regs: %pR\n", &regs);
364

365 366 367 368 369
	rio_regs_win = ioremap(regs.start, resource_size(&regs));
	if (!rio_regs_win) {
		dev_err(&dev->dev, "Unable to map rio register window\n");
		rc = -ENOMEM;
		goto err_rio_regs;
370 371
	}

372
	ops = kzalloc(sizeof(struct rio_ops), GFP_KERNEL);
373 374 375 376
	if (!ops) {
		rc = -ENOMEM;
		goto err_ops;
	}
377 378 379 380
	ops->lcread = fsl_local_config_read;
	ops->lcwrite = fsl_local_config_write;
	ops->cread = fsl_rio_config_read;
	ops->cwrite = fsl_rio_config_write;
381
	ops->dsend = fsl_rio_doorbell_send;
382
	ops->pwenable = fsl_rio_pw_enable;
383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402
	ops->open_outb_mbox = fsl_open_outb_mbox;
	ops->open_inb_mbox = fsl_open_inb_mbox;
	ops->close_outb_mbox = fsl_close_outb_mbox;
	ops->close_inb_mbox = fsl_close_inb_mbox;
	ops->add_outb_message = fsl_add_outb_message;
	ops->add_inb_buffer = fsl_add_inb_buffer;
	ops->get_inb_message = fsl_get_inb_message;

	rmu_node = of_parse_phandle(dev->dev.of_node, "fsl,srio-rmu-handle", 0);
	if (!rmu_node)
		goto err_rmu;
	rc = of_address_to_resource(rmu_node, 0, &rmu_regs);
	if (rc) {
		dev_err(&dev->dev, "Can't get %s property 'reg'\n",
				rmu_node->full_name);
		goto err_rmu;
	}
	rmu_regs_win = ioremap(rmu_regs.start, resource_size(&rmu_regs));
	if (!rmu_regs_win) {
		dev_err(&dev->dev, "Unable to map rmu register window\n");
403
		rc = -ENOMEM;
404 405 406 407 408
		goto err_rmu;
	}
	for_each_compatible_node(np, NULL, "fsl,srio-msg-unit") {
		rmu_np[tmp] = np;
		tmp++;
409
	}
410

411 412 413 414 415 416 417 418 419
	/*set up doobell node*/
	np = of_find_compatible_node(NULL, NULL, "fsl,srio-dbell-unit");
	if (!np) {
		rc = -ENODEV;
		goto err_dbell;
	}
	dbell = kzalloc(sizeof(struct fsl_rio_dbell), GFP_KERNEL);
	if (!(dbell)) {
		dev_err(&dev->dev, "Can't alloc memory for 'fsl_rio_dbell'\n");
420
		rc = -ENOMEM;
421
		goto err_dbell;
422
	}
423 424 425
	dbell->dev = &dev->dev;
	dbell->bellirq = irq_of_parse_and_map(np, 1);
	dev_info(&dev->dev, "bellirq: %d\n", dbell->bellirq);
426

427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460
	aw = of_n_addr_cells(np);
	dt_range = of_get_property(np, "reg", &rlen);
	if (!dt_range) {
		pr_err("%s: unable to find 'reg' property\n",
			np->full_name);
		rc = -ENOMEM;
		goto err_pw;
	}
	range_start = of_read_number(dt_range, aw);
	dbell->dbell_regs = (struct rio_dbell_regs *)(rmu_regs_win +
				(u32)range_start);

	/*set up port write node*/
	np = of_find_compatible_node(NULL, NULL, "fsl,srio-port-write-unit");
	if (!np) {
		rc = -ENODEV;
		goto err_pw;
	}
	pw = kzalloc(sizeof(struct fsl_rio_pw), GFP_KERNEL);
	if (!(pw)) {
		dev_err(&dev->dev, "Can't alloc memory for 'fsl_rio_pw'\n");
		rc = -ENOMEM;
		goto err_pw;
	}
	pw->dev = &dev->dev;
	pw->pwirq = irq_of_parse_and_map(np, 0);
	dev_info(&dev->dev, "pwirq: %d\n", pw->pwirq);
	aw = of_n_addr_cells(np);
	dt_range = of_get_property(np, "reg", &rlen);
	if (!dt_range) {
		pr_err("%s: unable to find 'reg' property\n",
			np->full_name);
		rc = -ENOMEM;
		goto err;
461
	}
462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479
	range_start = of_read_number(dt_range, aw);
	pw->pw_regs = (struct rio_pw_regs *)(rmu_regs_win + (u32)range_start);

	/*set up ports node*/
	for_each_child_of_node(dev->dev.of_node, np) {
		port_index = of_get_property(np, "cell-index", NULL);
		if (!port_index) {
			dev_err(&dev->dev, "Can't get %s property 'cell-index'\n",
					np->full_name);
			continue;
		}

		dt_range = of_get_property(np, "ranges", &rlen);
		if (!dt_range) {
			dev_err(&dev->dev, "Can't get %s property 'ranges'\n",
					np->full_name);
			continue;
		}
480

481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551
		/* Get node address wide */
		cell = of_get_property(np, "#address-cells", NULL);
		if (cell)
			aw = *cell;
		else
			aw = of_n_addr_cells(np);
		/* Get node size wide */
		cell = of_get_property(np, "#size-cells", NULL);
		if (cell)
			sw = *cell;
		else
			sw = of_n_size_cells(np);
		/* Get parent address wide wide */
		paw = of_n_addr_cells(np);
		range_start = of_read_number(dt_range + aw, paw);
		range_size = of_read_number(dt_range + aw + paw, sw);

		dev_info(&dev->dev, "%s: LAW start 0x%016llx, size 0x%016llx.\n",
				np->full_name, range_start, range_size);

		port = kzalloc(sizeof(struct rio_mport), GFP_KERNEL);
		if (!port)
			continue;

		i = *port_index - 1;
		port->index = (unsigned char)i;

		priv = kzalloc(sizeof(struct rio_priv), GFP_KERNEL);
		if (!priv) {
			dev_err(&dev->dev, "Can't alloc memory for 'priv'\n");
			kfree(port);
			continue;
		}

		INIT_LIST_HEAD(&port->dbells);
		port->iores.start = range_start;
		port->iores.end = port->iores.start + range_size - 1;
		port->iores.flags = IORESOURCE_MEM;
		port->iores.name = "rio_io_win";

		if (request_resource(&iomem_resource, &port->iores) < 0) {
			dev_err(&dev->dev, "RIO: Error requesting master port region"
				" 0x%016llx-0x%016llx\n",
				(u64)port->iores.start, (u64)port->iores.end);
				kfree(priv);
				kfree(port);
				continue;
		}
		sprintf(port->name, "RIO mport %d", i);

		priv->dev = &dev->dev;
		port->ops = ops;
		port->priv = priv;
		port->phys_efptr = 0x100;
		priv->regs_win = rio_regs_win;

		/* Probe the master port phy type */
		ccsr = in_be32(priv->regs_win + RIO_CCSR + i*0x20);
		port->phy_type = (ccsr & 1) ? RIO_PHY_SERIAL : RIO_PHY_PARALLEL;
		if (port->phy_type == RIO_PHY_PARALLEL) {
			dev_err(&dev->dev, "RIO: Parallel PHY type, unsupported port type!\n");
			release_resource(&port->iores);
			kfree(priv);
			kfree(port);
			continue;
		}
		dev_info(&dev->dev, "RapidIO PHY type: Serial\n");
		/* Checking the port training status */
		if (in_be32((priv->regs_win + RIO_ESCSR + i*0x20)) & 1) {
			dev_err(&dev->dev, "Port %d is not ready. "
			"Try to restart connection...\n", i);
552
			/* Disable ports */
553 554
			out_be32(priv->regs_win
				+ RIO_CCSR + i*0x20, 0);
555
			/* Set 1x lane */
556 557
			setbits32(priv->regs_win
				+ RIO_CCSR + i*0x20, 0x02000000);
558
			/* Enable ports */
559 560 561 562 563 564 565 566 567 568 569 570 571
			setbits32(priv->regs_win
				+ RIO_CCSR + i*0x20, 0x00600000);
			msleep(100);
			if (in_be32((priv->regs_win
					+ RIO_ESCSR + i*0x20)) & 1) {
				dev_err(&dev->dev,
					"Port %d restart failed.\n", i);
				release_resource(&port->iores);
				kfree(priv);
				kfree(port);
				continue;
			}
			dev_info(&dev->dev, "Port %d restart success!\n", i);
572
		}
573
		fsl_rio_info(&dev->dev, ccsr);
574

575
		port->sys_size = (in_be32((priv->regs_win + RIO_PEF_CAR))
576
					& RIO_PEF_CTLS) >> 4;
577 578 579 580 581 582 583 584 585 586 587 588 589 590 591
		dev_info(&dev->dev, "RapidIO Common Transport System size: %d\n",
				port->sys_size ? 65536 : 256);

		if (rio_register_mport(port)) {
			release_resource(&port->iores);
			kfree(priv);
			kfree(port);
			continue;
		}
		if (port->host_deviceid >= 0)
			out_be32(priv->regs_win + RIO_GCCSR, RIO_PORT_GEN_HOST |
				RIO_PORT_GEN_MASTER | RIO_PORT_GEN_DISCOVERED);
		else
			out_be32(priv->regs_win + RIO_GCCSR,
				RIO_PORT_GEN_MASTER);
592

593 594 595 596 597
		priv->atmu_regs = (struct rio_atmu_regs *)(priv->regs_win
			+ ((i == 0) ? RIO_ATMU_REGS_PORT1_OFFSET :
			RIO_ATMU_REGS_PORT2_OFFSET));

		priv->maint_atmu_regs = priv->atmu_regs + 1;
598

599 600 601 602
		/* Set to receive any dist ID for serial RapidIO controller. */
		if (port->phy_type == RIO_PHY_SERIAL)
			out_be32((priv->regs_win
				+ RIO_ISR_AACR + i*0x80), RIO_ISR_AACR_AA);
603

604 605 606 607 608
		/* Configure maintenance transaction window */
		out_be32(&priv->maint_atmu_regs->rowbar,
			port->iores.start >> 12);
		out_be32(&priv->maint_atmu_regs->rowar,
			 0x80077000 | (ilog2(RIO_MAINT_WIN_SIZE) - 1));
609

610 611
		priv->maint_win = ioremap(port->iores.start,
				RIO_MAINT_WIN_SIZE);
M
Matt Porter 已提交
612

613
		rio_law_start = range_start;
M
Matt Porter 已提交
614

615
		fsl_rio_setup_rmu(port, rmu_np[i]);
M
Matt Porter 已提交
616

617 618 619 620 621 622 623 624 625
		dbell->mport[i] = port;

		active_ports++;
	}

	if (!active_ports) {
		rc = -ENOLINK;
		goto err;
	}
626

627 628
	fsl_rio_doorbell_init(dbell);
	fsl_rio_port_write_init(pw);
629

630
	return 0;
631
err:
632 633 634 635 636 637
	kfree(pw);
err_pw:
	kfree(dbell);
err_dbell:
	iounmap(rmu_regs_win);
err_rmu:
638 639
	kfree(ops);
err_ops:
640 641
	iounmap(rio_regs_win);
err_rio_regs:
642
	return rc;
M
Matt Porter 已提交
643
}
644 645 646

/* The probe function for RapidIO peer-to-peer network.
 */
647
static int __devinit fsl_of_rio_rpn_probe(struct platform_device *dev)
648 649
{
	printk(KERN_INFO "Setting up RapidIO peer-to-peer network %s\n",
650
			dev->dev.of_node->full_name);
651

652
	return fsl_rio_setup(dev);
653 654 655 656
};

static const struct of_device_id fsl_of_rio_rpn_ids[] = {
	{
657
		.compatible = "fsl,srio",
658 659 660 661
	},
	{},
};

662
static struct platform_driver fsl_of_rio_rpn_driver = {
663 664 665 666 667
	.driver = {
		.name = "fsl-of-rio",
		.owner = THIS_MODULE,
		.of_match_table = fsl_of_rio_rpn_ids,
	},
668 669 670 671 672
	.probe = fsl_of_rio_rpn_probe,
};

static __init int fsl_of_rio_rpn_init(void)
{
673
	return platform_driver_register(&fsl_of_rio_rpn_driver);
674 675 676
}

subsys_initcall(fsl_of_rio_rpn_init);