fsl_rio.c 32.3 KB
Newer Older
M
Matt Porter 已提交
1
/*
2
 * Freescale MPC85xx/MPC86xx RapidIO support
M
Matt Porter 已提交
3
 *
4 5 6
 * Copyright (C) 2007, 2008 Freescale Semiconductor, Inc.
 * Zhang Wei <wei.zhang@freescale.com>
 *
M
Matt Porter 已提交
7 8 9 10 11 12 13 14 15 16 17 18 19 20
 * 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>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/dma-mapping.h>
#include <linux/interrupt.h>
21
#include <linux/device.h>
M
Matt Porter 已提交
22 23
#include <linux/rio.h>
#include <linux/rio_drv.h>
24
#include <linux/of_platform.h>
25
#include <linux/delay.h>
M
Matt Porter 已提交
26 27 28

#include <asm/io.h>

29 30 31 32 33
/* RapidIO definition irq, which read from OF-tree */
#define IRQ_RIO_BELL(m)		(((struct rio_priv *)(m->priv))->bellirq)
#define IRQ_RIO_TX(m)		(((struct rio_priv *)(m->priv))->txirq)
#define IRQ_RIO_RX(m)		(((struct rio_priv *)(m->priv))->rxirq)

M
Matt Porter 已提交
34
#define RIO_ATMU_REGS_OFFSET	0x10c00
35 36 37 38 39 40
#define RIO_P_MSG_REGS_OFFSET	0x11000
#define RIO_S_MSG_REGS_OFFSET	0x13000
#define RIO_ESCSR		0x158
#define RIO_CCSR		0x15c
#define RIO_ISR_AACR		0x10120
#define RIO_ISR_AACR_AA		0x1	/* Accept All ID */
M
Matt Porter 已提交
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
#define RIO_MAINT_WIN_SIZE	0x400000
#define RIO_DBELL_WIN_SIZE	0x1000

#define RIO_MSG_OMR_MUI		0x00000002
#define RIO_MSG_OSR_TE		0x00000080
#define RIO_MSG_OSR_QOI		0x00000020
#define RIO_MSG_OSR_QFI		0x00000010
#define RIO_MSG_OSR_MUB		0x00000004
#define RIO_MSG_OSR_EOMI	0x00000002
#define RIO_MSG_OSR_QEI		0x00000001

#define RIO_MSG_IMR_MI		0x00000002
#define RIO_MSG_ISR_TE		0x00000080
#define RIO_MSG_ISR_QFI		0x00000010
#define RIO_MSG_ISR_DIQI	0x00000001

#define RIO_MSG_DESC_SIZE	32
#define RIO_MSG_BUFFER_SIZE	4096
#define RIO_MIN_TX_RING_SIZE	2
#define RIO_MAX_TX_RING_SIZE	2048
#define RIO_MIN_RX_RING_SIZE	2
#define RIO_MAX_RX_RING_SIZE	2048

#define DOORBELL_DMR_DI		0x00000002
#define DOORBELL_DSR_TE		0x00000080
#define DOORBELL_DSR_QFI	0x00000010
#define DOORBELL_DSR_DIQI	0x00000001
68 69
#define DOORBELL_TID_OFFSET	0x02
#define DOORBELL_SID_OFFSET	0x04
M
Matt Porter 已提交
70 71 72
#define DOORBELL_INFO_OFFSET	0x06

#define DOORBELL_MESSAGE_SIZE	0x08
73 74
#define DBELL_SID(x)		(*(u16 *)(x + DOORBELL_SID_OFFSET))
#define DBELL_TID(x)		(*(u16 *)(x + DOORBELL_TID_OFFSET))
M
Matt Porter 已提交
75 76 77 78
#define DBELL_INF(x)		(*(u16 *)(x + DOORBELL_INFO_OFFSET))

struct rio_atmu_regs {
	u32 rowtar;
79
	u32 rowtear;
M
Matt Porter 已提交
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
	u32 rowbar;
	u32 pad2;
	u32 rowar;
	u32 pad3[3];
};

struct rio_msg_regs {
	u32 omr;
	u32 osr;
	u32 pad1;
	u32 odqdpar;
	u32 pad2;
	u32 osar;
	u32 odpr;
	u32 odatr;
	u32 odcr;
	u32 pad3;
	u32 odqepar;
	u32 pad4[13];
	u32 imr;
	u32 isr;
	u32 pad5;
	u32 ifqdpar;
	u32 pad6;
	u32 ifqepar;
105 106 107 108 109 110 111 112 113
	u32 pad7[226];
	u32 odmr;
	u32 odsr;
	u32 res0[4];
	u32 oddpr;
	u32 oddatr;
	u32 res1[3];
	u32 odretcr;
	u32 res2[12];
M
Matt Porter 已提交
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
	u32 dmr;
	u32 dsr;
	u32 pad8;
	u32 dqdpar;
	u32 pad9;
	u32 dqepar;
	u32 pad10[26];
	u32 pwmr;
	u32 pwsr;
	u32 pad11;
	u32 pwqbar;
};

struct rio_tx_desc {
	u32 res1;
	u32 saddr;
	u32 dport;
	u32 dattr;
	u32 res2;
	u32 res3;
	u32 dwcnt;
	u32 res4;
};

138
struct rio_dbell_ring {
M
Matt Porter 已提交
139 140
	void *virt;
	dma_addr_t phys;
141
};
M
Matt Porter 已提交
142

143
struct rio_msg_tx_ring {
M
Matt Porter 已提交
144 145 146 147 148 149
	void *virt;
	dma_addr_t phys;
	void *virt_buffer[RIO_MAX_TX_RING_SIZE];
	dma_addr_t phys_buffer[RIO_MAX_TX_RING_SIZE];
	int tx_slot;
	int size;
150
	void *dev_id;
151
};
M
Matt Porter 已提交
152

153
struct rio_msg_rx_ring {
M
Matt Porter 已提交
154 155 156 157 158
	void *virt;
	dma_addr_t phys;
	void *virt_buffer[RIO_MAX_RX_RING_SIZE];
	int rx_slot;
	int size;
159
	void *dev_id;
160 161 162
};

struct rio_priv {
163
	struct device *dev;
164 165 166 167 168 169 170 171 172 173 174 175 176 177
	void __iomem *regs_win;
	struct rio_atmu_regs __iomem *atmu_regs;
	struct rio_atmu_regs __iomem *maint_atmu_regs;
	struct rio_atmu_regs __iomem *dbell_atmu_regs;
	void __iomem *dbell_win;
	void __iomem *maint_win;
	struct rio_msg_regs __iomem *msg_regs;
	struct rio_dbell_ring dbell_ring;
	struct rio_msg_tx_ring msg_tx_ring;
	struct rio_msg_rx_ring msg_rx_ring;
	int bellirq;
	int txirq;
	int rxirq;
};
M
Matt Porter 已提交
178 179

/**
180
 * fsl_rio_doorbell_send - Send a MPC85xx doorbell message
181
 * @mport: RapidIO master port info
M
Matt Porter 已提交
182 183 184 185 186 187 188
 * @index: ID of RapidIO interface
 * @destid: Destination ID of target device
 * @data: 16-bit info field of RapidIO doorbell message
 *
 * Sends a MPC85xx doorbell message. Returns %0 on success or
 * %-EINVAL on failure.
 */
189 190
static int fsl_rio_doorbell_send(struct rio_mport *mport,
				int index, u16 destid, u16 data)
M
Matt Porter 已提交
191
{
192
	struct rio_priv *priv = mport->priv;
193
	pr_debug("fsl_doorbell_send: index %d destid %4.4x data %4.4x\n",
M
Matt Porter 已提交
194
		 index, destid, data);
195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210
	switch (mport->phy_type) {
	case RIO_PHY_PARALLEL:
		out_be32(&priv->dbell_atmu_regs->rowtar, destid << 22);
		out_be16(priv->dbell_win, data);
		break;
	case RIO_PHY_SERIAL:
		/* In the serial version silicons, such as MPC8548, MPC8641,
		 * below operations is must be.
		 */
		out_be32(&priv->msg_regs->odmr, 0x00000000);
		out_be32(&priv->msg_regs->odretcr, 0x00000004);
		out_be32(&priv->msg_regs->oddpr, destid << 16);
		out_be32(&priv->msg_regs->oddatr, data);
		out_be32(&priv->msg_regs->odmr, 0x00000001);
		break;
	}
M
Matt Porter 已提交
211 212 213 214 215

	return 0;
}

/**
216
 * fsl_local_config_read - Generate a MPC85xx local config space read
217
 * @mport: RapidIO master port info
M
Matt Porter 已提交
218 219 220 221 222 223 224 225
 * @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.
 */
226 227
static int fsl_local_config_read(struct rio_mport *mport,
				int index, u32 offset, int len, u32 *data)
M
Matt Porter 已提交
228
{
229
	struct rio_priv *priv = mport->priv;
230
	pr_debug("fsl_local_config_read: index %d offset %8.8x\n", index,
M
Matt Porter 已提交
231
		 offset);
232
	*data = in_be32(priv->regs_win + offset);
M
Matt Porter 已提交
233 234 235 236 237

	return 0;
}

/**
238
 * fsl_local_config_write - Generate a MPC85xx local config space write
239
 * @mport: RapidIO master port info
M
Matt Porter 已提交
240 241 242 243 244 245 246 247
 * @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.
 */
248 249
static int fsl_local_config_write(struct rio_mport *mport,
				int index, u32 offset, int len, u32 data)
M
Matt Porter 已提交
250
{
251
	struct rio_priv *priv = mport->priv;
M
Matt Porter 已提交
252
	pr_debug
253
	    ("fsl_local_config_write: index %d offset %8.8x data %8.8x\n",
M
Matt Porter 已提交
254
	     index, offset, data);
255
	out_be32(priv->regs_win + offset, data);
M
Matt Porter 已提交
256 257 258 259 260

	return 0;
}

/**
261
 * fsl_rio_config_read - Generate a MPC85xx read maintenance transaction
262
 * @mport: RapidIO master port info
M
Matt Porter 已提交
263 264 265 266 267 268 269 270 271 272 273
 * @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
274 275
fsl_rio_config_read(struct rio_mport *mport, int index, u16 destid,
			u8 hopcount, u32 offset, int len, u32 *val)
M
Matt Porter 已提交
276
{
277
	struct rio_priv *priv = mport->priv;
M
Matt Porter 已提交
278 279 280
	u8 *data;

	pr_debug
281
	    ("fsl_rio_config_read: index %d destid %d hopcount %d offset %8.8x len %d\n",
M
Matt Porter 已提交
282
	     index, destid, hopcount, offset, len);
283
	out_be32(&priv->maint_atmu_regs->rowtar,
M
Matt Porter 已提交
284 285
		 (destid << 22) | (hopcount << 12) | ((offset & ~0x3) >> 9));

286
	data = (u8 *) priv->maint_win + offset;
M
Matt Porter 已提交
287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302
	switch (len) {
	case 1:
		*val = in_8((u8 *) data);
		break;
	case 2:
		*val = in_be16((u16 *) data);
		break;
	default:
		*val = in_be32((u32 *) data);
		break;
	}

	return 0;
}

/**
303
 * fsl_rio_config_write - Generate a MPC85xx write maintenance transaction
304
 * @mport: RapidIO master port info
M
Matt Porter 已提交
305 306 307 308 309 310 311 312 313 314 315
 * @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
316 317
fsl_rio_config_write(struct rio_mport *mport, int index, u16 destid,
			u8 hopcount, u32 offset, int len, u32 val)
M
Matt Porter 已提交
318
{
319
	struct rio_priv *priv = mport->priv;
M
Matt Porter 已提交
320 321
	u8 *data;
	pr_debug
322
	    ("fsl_rio_config_write: index %d destid %d hopcount %d offset %8.8x len %d val %8.8x\n",
M
Matt Porter 已提交
323
	     index, destid, hopcount, offset, len, val);
324
	out_be32(&priv->maint_atmu_regs->rowtar,
M
Matt Porter 已提交
325 326
		 (destid << 22) | (hopcount << 12) | ((offset & ~0x3) >> 9));

327
	data = (u8 *) priv->maint_win + offset;
M
Matt Porter 已提交
328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357
	switch (len) {
	case 1:
		out_8((u8 *) data, val);
		break;
	case 2:
		out_be16((u16 *) data, val);
		break;
	default:
		out_be32((u32 *) data, val);
		break;
	}

	return 0;
}

/**
 * rio_hw_add_outb_message - Add message to the MPC85xx outbound message queue
 * @mport: Master port with outbound message queue
 * @rdev: Target of outbound message
 * @mbox: Outbound mailbox
 * @buffer: Message to add to outbound queue
 * @len: Length of message
 *
 * Adds the @buffer message to the MPC85xx outbound message queue. Returns
 * %0 on success or %-EINVAL on failure.
 */
int
rio_hw_add_outb_message(struct rio_mport *mport, struct rio_dev *rdev, int mbox,
			void *buffer, size_t len)
{
358
	struct rio_priv *priv = mport->priv;
M
Matt Porter 已提交
359
	u32 omr;
360 361
	struct rio_tx_desc *desc = (struct rio_tx_desc *)priv->msg_tx_ring.virt
					+ priv->msg_tx_ring.tx_slot;
M
Matt Porter 已提交
362 363 364 365 366 367 368 369 370 371 372 373
	int ret = 0;

	pr_debug
	    ("RIO: rio_hw_add_outb_message(): destid %4.4x mbox %d buffer %8.8x len %8.8x\n",
	     rdev->destid, mbox, (int)buffer, len);

	if ((len < 8) || (len > RIO_MAX_MSG_SIZE)) {
		ret = -EINVAL;
		goto out;
	}

	/* Copy and clear rest of buffer */
374 375
	memcpy(priv->msg_tx_ring.virt_buffer[priv->msg_tx_ring.tx_slot], buffer,
			len);
M
Matt Porter 已提交
376
	if (len < (RIO_MAX_MSG_SIZE - 4))
377 378
		memset(priv->msg_tx_ring.virt_buffer[priv->msg_tx_ring.tx_slot]
				+ len, 0, RIO_MAX_MSG_SIZE - len);
M
Matt Porter 已提交
379

380 381 382 383
	switch (mport->phy_type) {
	case RIO_PHY_PARALLEL:
		/* Set mbox field for message */
		desc->dport = mbox & 0x3;
M
Matt Porter 已提交
384

385 386 387 388 389 390 391 392 393 394 395
		/* Enable EOMI interrupt, set priority, and set destid */
		desc->dattr = 0x28000000 | (rdev->destid << 2);
		break;
	case RIO_PHY_SERIAL:
		/* Set mbox field for message, and set destid */
		desc->dport = (rdev->destid << 16) | (mbox & 0x3);

		/* Enable EOMI interrupt and priority */
		desc->dattr = 0x28000000;
		break;
	}
M
Matt Porter 已提交
396 397 398 399 400

	/* Set transfer size aligned to next power of 2 (in double words) */
	desc->dwcnt = is_power_of_2(len) ? len : 1 << get_bitmask_order(len);

	/* Set snooping and source buffer address */
401 402
	desc->saddr = 0x00000004
		| priv->msg_tx_ring.phys_buffer[priv->msg_tx_ring.tx_slot];
M
Matt Porter 已提交
403 404

	/* Increment enqueue pointer */
405 406
	omr = in_be32(&priv->msg_regs->omr);
	out_be32(&priv->msg_regs->omr, omr | RIO_MSG_OMR_MUI);
M
Matt Porter 已提交
407 408

	/* Go to next descriptor */
409 410
	if (++priv->msg_tx_ring.tx_slot == priv->msg_tx_ring.size)
		priv->msg_tx_ring.tx_slot = 0;
M
Matt Porter 已提交
411 412 413 414 415 416 417 418

      out:
	return ret;
}

EXPORT_SYMBOL_GPL(rio_hw_add_outb_message);

/**
419
 * fsl_rio_tx_handler - MPC85xx outbound message interrupt handler
M
Matt Porter 已提交
420 421 422 423
 * @irq: Linux interrupt number
 * @dev_instance: Pointer to interrupt-specific data
 *
 * Handles outbound message interrupts. Executes a register outbound
424
 * mailbox event handler and acks the interrupt occurrence.
M
Matt Porter 已提交
425 426
 */
static irqreturn_t
427
fsl_rio_tx_handler(int irq, void *dev_instance)
M
Matt Porter 已提交
428 429 430
{
	int osr;
	struct rio_mport *port = (struct rio_mport *)dev_instance;
431
	struct rio_priv *priv = port->priv;
M
Matt Porter 已提交
432

433
	osr = in_be32(&priv->msg_regs->osr);
M
Matt Porter 已提交
434 435 436

	if (osr & RIO_MSG_OSR_TE) {
		pr_info("RIO: outbound message transmission error\n");
437
		out_be32(&priv->msg_regs->osr, RIO_MSG_OSR_TE);
M
Matt Porter 已提交
438 439 440 441 442
		goto out;
	}

	if (osr & RIO_MSG_OSR_QOI) {
		pr_info("RIO: outbound message queue overflow\n");
443
		out_be32(&priv->msg_regs->osr, RIO_MSG_OSR_QOI);
M
Matt Porter 已提交
444 445 446 447
		goto out;
	}

	if (osr & RIO_MSG_OSR_EOMI) {
448 449 450 451
		u32 dqp = in_be32(&priv->msg_regs->odqdpar);
		int slot = (dqp - priv->msg_tx_ring.phys) >> 5;
		port->outb_msg[0].mcback(port, priv->msg_tx_ring.dev_id, -1,
				slot);
M
Matt Porter 已提交
452 453

		/* Ack the end-of-message interrupt */
454
		out_be32(&priv->msg_regs->osr, RIO_MSG_OSR_EOMI);
M
Matt Porter 已提交
455 456 457 458 459 460 461 462 463
	}

      out:
	return IRQ_HANDLED;
}

/**
 * rio_open_outb_mbox - Initialize MPC85xx outbound mailbox
 * @mport: Master port implementing the outbound message unit
464
 * @dev_id: Device specific pointer to pass on event
M
Matt Porter 已提交
465 466 467 468 469 470 471
 * @mbox: Mailbox to open
 * @entries: Number of entries in the outbound mailbox ring
 *
 * Initializes buffer ring, request the outbound message interrupt,
 * and enables the outbound message unit. Returns %0 on success and
 * %-EINVAL or %-ENOMEM on failure.
 */
472
int rio_open_outb_mbox(struct rio_mport *mport, void *dev_id, int mbox, int entries)
M
Matt Porter 已提交
473 474
{
	int i, j, rc = 0;
475
	struct rio_priv *priv = mport->priv;
M
Matt Porter 已提交
476 477 478 479 480 481 482 483

	if ((entries < RIO_MIN_TX_RING_SIZE) ||
	    (entries > RIO_MAX_TX_RING_SIZE) || (!is_power_of_2(entries))) {
		rc = -EINVAL;
		goto out;
	}

	/* Initialize shadow copy ring */
484 485 486 487 488
	priv->msg_tx_ring.dev_id = dev_id;
	priv->msg_tx_ring.size = entries;

	for (i = 0; i < priv->msg_tx_ring.size; i++) {
		priv->msg_tx_ring.virt_buffer[i] =
489
			dma_alloc_coherent(priv->dev, RIO_MSG_BUFFER_SIZE,
490 491
				&priv->msg_tx_ring.phys_buffer[i], GFP_KERNEL);
		if (!priv->msg_tx_ring.virt_buffer[i]) {
M
Matt Porter 已提交
492
			rc = -ENOMEM;
493 494
			for (j = 0; j < priv->msg_tx_ring.size; j++)
				if (priv->msg_tx_ring.virt_buffer[j])
495
					dma_free_coherent(priv->dev,
496 497 498 499 500
							RIO_MSG_BUFFER_SIZE,
							priv->msg_tx_ring.
							virt_buffer[j],
							priv->msg_tx_ring.
							phys_buffer[j]);
M
Matt Porter 已提交
501 502 503 504 505
			goto out;
		}
	}

	/* Initialize outbound message descriptor ring */
506
	priv->msg_tx_ring.virt = dma_alloc_coherent(priv->dev,
507 508 509
				priv->msg_tx_ring.size * RIO_MSG_DESC_SIZE,
				&priv->msg_tx_ring.phys, GFP_KERNEL);
	if (!priv->msg_tx_ring.virt) {
M
Matt Porter 已提交
510 511 512
		rc = -ENOMEM;
		goto out_dma;
	}
513 514 515
	memset(priv->msg_tx_ring.virt, 0,
			priv->msg_tx_ring.size * RIO_MSG_DESC_SIZE);
	priv->msg_tx_ring.tx_slot = 0;
M
Matt Porter 已提交
516 517

	/* Point dequeue/enqueue pointers at first entry in ring */
518 519
	out_be32(&priv->msg_regs->odqdpar, priv->msg_tx_ring.phys);
	out_be32(&priv->msg_regs->odqepar, priv->msg_tx_ring.phys);
M
Matt Porter 已提交
520 521

	/* Configure for snooping */
522
	out_be32(&priv->msg_regs->osar, 0x00000004);
M
Matt Porter 已提交
523 524

	/* Clear interrupt status */
525
	out_be32(&priv->msg_regs->osr, 0x000000b3);
M
Matt Porter 已提交
526 527

	/* Hook up outbound message handler */
528 529 530
	rc = request_irq(IRQ_RIO_TX(mport), fsl_rio_tx_handler, 0,
			 "msg_tx", (void *)mport);
	if (rc < 0)
M
Matt Porter 已提交
531 532 533 534 535 536 537 538 539
		goto out_irq;

	/*
	 * Configure outbound message unit
	 *      Snooping
	 *      Interrupts (all enabled, except QEIE)
	 *      Chaining mode
	 *      Disable
	 */
540
	out_be32(&priv->msg_regs->omr, 0x00100220);
M
Matt Porter 已提交
541 542

	/* Set number of entries */
543 544
	out_be32(&priv->msg_regs->omr,
		 in_be32(&priv->msg_regs->omr) |
M
Matt Porter 已提交
545 546 547
		 ((get_bitmask_order(entries) - 2) << 12));

	/* Now enable the unit */
548
	out_be32(&priv->msg_regs->omr, in_be32(&priv->msg_regs->omr) | 0x1);
M
Matt Porter 已提交
549 550 551 552 553

      out:
	return rc;

      out_irq:
554 555
	dma_free_coherent(priv->dev,
			  priv->msg_tx_ring.size * RIO_MSG_DESC_SIZE,
556
			  priv->msg_tx_ring.virt, priv->msg_tx_ring.phys);
M
Matt Porter 已提交
557 558

      out_dma:
559
	for (i = 0; i < priv->msg_tx_ring.size; i++)
560
		dma_free_coherent(priv->dev, RIO_MSG_BUFFER_SIZE,
561 562
				  priv->msg_tx_ring.virt_buffer[i],
				  priv->msg_tx_ring.phys_buffer[i]);
M
Matt Porter 已提交
563 564 565 566 567 568 569 570 571 572 573 574 575 576

	return rc;
}

/**
 * rio_close_outb_mbox - Shut down MPC85xx outbound mailbox
 * @mport: Master port implementing the outbound message unit
 * @mbox: Mailbox to close
 *
 * Disables the outbound message unit, free all buffers, and
 * frees the outbound message interrupt.
 */
void rio_close_outb_mbox(struct rio_mport *mport, int mbox)
{
577
	struct rio_priv *priv = mport->priv;
M
Matt Porter 已提交
578
	/* Disable inbound message unit */
579
	out_be32(&priv->msg_regs->omr, 0);
M
Matt Porter 已提交
580 581

	/* Free ring */
582 583
	dma_free_coherent(priv->dev,
			  priv->msg_tx_ring.size * RIO_MSG_DESC_SIZE,
584
			  priv->msg_tx_ring.virt, priv->msg_tx_ring.phys);
M
Matt Porter 已提交
585 586

	/* Free interrupt */
587
	free_irq(IRQ_RIO_TX(mport), (void *)mport);
M
Matt Porter 已提交
588 589 590
}

/**
591
 * fsl_rio_rx_handler - MPC85xx inbound message interrupt handler
M
Matt Porter 已提交
592 593 594 595
 * @irq: Linux interrupt number
 * @dev_instance: Pointer to interrupt-specific data
 *
 * Handles inbound message interrupts. Executes a registered inbound
596
 * mailbox event handler and acks the interrupt occurrence.
M
Matt Porter 已提交
597 598
 */
static irqreturn_t
599
fsl_rio_rx_handler(int irq, void *dev_instance)
M
Matt Porter 已提交
600 601 602
{
	int isr;
	struct rio_mport *port = (struct rio_mport *)dev_instance;
603
	struct rio_priv *priv = port->priv;
M
Matt Porter 已提交
604

605
	isr = in_be32(&priv->msg_regs->isr);
M
Matt Porter 已提交
606 607 608

	if (isr & RIO_MSG_ISR_TE) {
		pr_info("RIO: inbound message reception error\n");
609
		out_be32((void *)&priv->msg_regs->isr, RIO_MSG_ISR_TE);
M
Matt Porter 已提交
610 611 612 613 614 615 616 617 618 619 620
		goto out;
	}

	/* XXX Need to check/dispatch until queue empty */
	if (isr & RIO_MSG_ISR_DIQI) {
		/*
		 * We implement *only* mailbox 0, but can receive messages
		 * for any mailbox/letter to that mailbox destination. So,
		 * make the callback with an unknown/invalid mailbox number
		 * argument.
		 */
621
		port->inb_msg[0].mcback(port, priv->msg_rx_ring.dev_id, -1, -1);
M
Matt Porter 已提交
622 623

		/* Ack the queueing interrupt */
624
		out_be32(&priv->msg_regs->isr, RIO_MSG_ISR_DIQI);
M
Matt Porter 已提交
625 626 627 628 629 630 631 632 633
	}

      out:
	return IRQ_HANDLED;
}

/**
 * rio_open_inb_mbox - Initialize MPC85xx inbound mailbox
 * @mport: Master port implementing the inbound message unit
634
 * @dev_id: Device specific pointer to pass on event
M
Matt Porter 已提交
635 636 637 638 639 640 641
 * @mbox: Mailbox to open
 * @entries: Number of entries in the inbound mailbox ring
 *
 * Initializes buffer ring, request the inbound message interrupt,
 * and enables the inbound message unit. Returns %0 on success
 * and %-EINVAL or %-ENOMEM on failure.
 */
642
int rio_open_inb_mbox(struct rio_mport *mport, void *dev_id, int mbox, int entries)
M
Matt Porter 已提交
643 644
{
	int i, rc = 0;
645
	struct rio_priv *priv = mport->priv;
M
Matt Porter 已提交
646 647 648 649 650 651 652 653

	if ((entries < RIO_MIN_RX_RING_SIZE) ||
	    (entries > RIO_MAX_RX_RING_SIZE) || (!is_power_of_2(entries))) {
		rc = -EINVAL;
		goto out;
	}

	/* Initialize client buffer ring */
654 655 656 657 658
	priv->msg_rx_ring.dev_id = dev_id;
	priv->msg_rx_ring.size = entries;
	priv->msg_rx_ring.rx_slot = 0;
	for (i = 0; i < priv->msg_rx_ring.size; i++)
		priv->msg_rx_ring.virt_buffer[i] = NULL;
M
Matt Porter 已提交
659 660

	/* Initialize inbound message ring */
661
	priv->msg_rx_ring.virt = dma_alloc_coherent(priv->dev,
662 663 664
				priv->msg_rx_ring.size * RIO_MAX_MSG_SIZE,
				&priv->msg_rx_ring.phys, GFP_KERNEL);
	if (!priv->msg_rx_ring.virt) {
M
Matt Porter 已提交
665 666 667 668 669
		rc = -ENOMEM;
		goto out;
	}

	/* Point dequeue/enqueue pointers at first entry in ring */
670 671
	out_be32(&priv->msg_regs->ifqdpar, (u32) priv->msg_rx_ring.phys);
	out_be32(&priv->msg_regs->ifqepar, (u32) priv->msg_rx_ring.phys);
M
Matt Porter 已提交
672 673

	/* Clear interrupt status */
674
	out_be32(&priv->msg_regs->isr, 0x00000091);
M
Matt Porter 已提交
675 676

	/* Hook up inbound message handler */
677 678 679
	rc = request_irq(IRQ_RIO_RX(mport), fsl_rio_rx_handler, 0,
			 "msg_rx", (void *)mport);
	if (rc < 0) {
680
		dma_free_coherent(priv->dev, RIO_MSG_BUFFER_SIZE,
681 682
				  priv->msg_tx_ring.virt_buffer[i],
				  priv->msg_tx_ring.phys_buffer[i]);
M
Matt Porter 已提交
683 684 685 686 687 688 689 690 691 692
		goto out;
	}

	/*
	 * Configure inbound message unit:
	 *      Snooping
	 *      4KB max message size
	 *      Unmask all interrupt sources
	 *      Disable
	 */
693
	out_be32(&priv->msg_regs->imr, 0x001b0060);
M
Matt Porter 已提交
694 695

	/* Set number of queue entries */
696
	setbits32(&priv->msg_regs->imr, (get_bitmask_order(entries) - 2) << 12);
M
Matt Porter 已提交
697 698

	/* Now enable the unit */
699
	setbits32(&priv->msg_regs->imr, 0x1);
M
Matt Porter 已提交
700 701 702 703 704 705 706 707 708 709 710 711 712 713 714

      out:
	return rc;
}

/**
 * rio_close_inb_mbox - Shut down MPC85xx inbound mailbox
 * @mport: Master port implementing the inbound message unit
 * @mbox: Mailbox to close
 *
 * Disables the inbound message unit, free all buffers, and
 * frees the inbound message interrupt.
 */
void rio_close_inb_mbox(struct rio_mport *mport, int mbox)
{
715
	struct rio_priv *priv = mport->priv;
M
Matt Porter 已提交
716
	/* Disable inbound message unit */
717
	out_be32(&priv->msg_regs->imr, 0);
M
Matt Porter 已提交
718 719

	/* Free ring */
720
	dma_free_coherent(priv->dev, priv->msg_rx_ring.size * RIO_MAX_MSG_SIZE,
721
			  priv->msg_rx_ring.virt, priv->msg_rx_ring.phys);
M
Matt Porter 已提交
722 723

	/* Free interrupt */
724
	free_irq(IRQ_RIO_RX(mport), (void *)mport);
M
Matt Porter 已提交
725 726 727 728 729 730 731 732 733 734 735 736 737 738
}

/**
 * rio_hw_add_inb_buffer - Add buffer to the MPC85xx inbound message queue
 * @mport: Master port implementing the inbound message unit
 * @mbox: Inbound mailbox number
 * @buf: Buffer to add to inbound queue
 *
 * Adds the @buf buffer to the MPC85xx inbound message queue. Returns
 * %0 on success or %-EINVAL on failure.
 */
int rio_hw_add_inb_buffer(struct rio_mport *mport, int mbox, void *buf)
{
	int rc = 0;
739
	struct rio_priv *priv = mport->priv;
M
Matt Porter 已提交
740 741

	pr_debug("RIO: rio_hw_add_inb_buffer(), msg_rx_ring.rx_slot %d\n",
742
		 priv->msg_rx_ring.rx_slot);
M
Matt Porter 已提交
743

744
	if (priv->msg_rx_ring.virt_buffer[priv->msg_rx_ring.rx_slot]) {
M
Matt Porter 已提交
745 746
		printk(KERN_ERR
		       "RIO: error adding inbound buffer %d, buffer exists\n",
747
		       priv->msg_rx_ring.rx_slot);
M
Matt Porter 已提交
748 749 750 751
		rc = -EINVAL;
		goto out;
	}

752 753 754
	priv->msg_rx_ring.virt_buffer[priv->msg_rx_ring.rx_slot] = buf;
	if (++priv->msg_rx_ring.rx_slot == priv->msg_rx_ring.size)
		priv->msg_rx_ring.rx_slot = 0;
M
Matt Porter 已提交
755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771

      out:
	return rc;
}

EXPORT_SYMBOL_GPL(rio_hw_add_inb_buffer);

/**
 * rio_hw_get_inb_message - Fetch inbound message from the MPC85xx message unit
 * @mport: Master port implementing the inbound message unit
 * @mbox: Inbound mailbox number
 *
 * Gets the next available inbound message from the inbound message queue.
 * A pointer to the message is returned on success or NULL on failure.
 */
void *rio_hw_get_inb_message(struct rio_mport *mport, int mbox)
{
772
	struct rio_priv *priv = mport->priv;
M
Matt Porter 已提交
773 774 775 776
	u32 phys_buf, virt_buf;
	void *buf = NULL;
	int buf_idx;

777
	phys_buf = in_be32(&priv->msg_regs->ifqdpar);
M
Matt Porter 已提交
778 779

	/* If no more messages, then bail out */
780
	if (phys_buf == in_be32(&priv->msg_regs->ifqepar))
M
Matt Porter 已提交
781 782
		goto out2;

783 784 785 786
	virt_buf = (u32) priv->msg_rx_ring.virt + (phys_buf
						- priv->msg_rx_ring.phys);
	buf_idx = (phys_buf - priv->msg_rx_ring.phys) / RIO_MAX_MSG_SIZE;
	buf = priv->msg_rx_ring.virt_buffer[buf_idx];
M
Matt Porter 已提交
787 788 789 790 791 792 793 794 795 796 797

	if (!buf) {
		printk(KERN_ERR
		       "RIO: inbound message copy failed, no buffers\n");
		goto out1;
	}

	/* Copy max message size, caller is expected to allocate that big */
	memcpy(buf, (void *)virt_buf, RIO_MAX_MSG_SIZE);

	/* Clear the available buffer */
798
	priv->msg_rx_ring.virt_buffer[buf_idx] = NULL;
M
Matt Porter 已提交
799 800

      out1:
801
	setbits32(&priv->msg_regs->imr, RIO_MSG_IMR_MI);
M
Matt Porter 已提交
802 803 804 805 806 807 808 809

      out2:
	return buf;
}

EXPORT_SYMBOL_GPL(rio_hw_get_inb_message);

/**
810
 * fsl_rio_dbell_handler - MPC85xx doorbell interrupt handler
M
Matt Porter 已提交
811 812 813 814 815 816 817
 * @irq: Linux interrupt number
 * @dev_instance: Pointer to interrupt-specific data
 *
 * Handles doorbell interrupts. Parses a list of registered
 * doorbell event handlers and executes a matching event handler.
 */
static irqreturn_t
818
fsl_rio_dbell_handler(int irq, void *dev_instance)
M
Matt Porter 已提交
819 820 821
{
	int dsr;
	struct rio_mport *port = (struct rio_mport *)dev_instance;
822
	struct rio_priv *priv = port->priv;
M
Matt Porter 已提交
823

824
	dsr = in_be32(&priv->msg_regs->dsr);
M
Matt Porter 已提交
825 826 827

	if (dsr & DOORBELL_DSR_TE) {
		pr_info("RIO: doorbell reception error\n");
828
		out_be32(&priv->msg_regs->dsr, DOORBELL_DSR_TE);
M
Matt Porter 已提交
829 830 831 832 833
		goto out;
	}

	if (dsr & DOORBELL_DSR_QFI) {
		pr_info("RIO: doorbell queue full\n");
834
		out_be32(&priv->msg_regs->dsr, DOORBELL_DSR_QFI);
M
Matt Porter 已提交
835 836 837 838 839 840
		goto out;
	}

	/* XXX Need to check/dispatch until queue empty */
	if (dsr & DOORBELL_DSR_DIQI) {
		u32 dmsg =
841 842
		    (u32) priv->dbell_ring.virt +
		    (in_be32(&priv->msg_regs->dqdpar) & 0xfff);
M
Matt Porter 已提交
843 844 845 846 847 848 849 850 851 852 853 854 855 856 857
		struct rio_dbell *dbell;
		int found = 0;

		pr_debug
		    ("RIO: processing doorbell, sid %2.2x tid %2.2x info %4.4x\n",
		     DBELL_SID(dmsg), DBELL_TID(dmsg), DBELL_INF(dmsg));

		list_for_each_entry(dbell, &port->dbells, node) {
			if ((dbell->res->start <= DBELL_INF(dmsg)) &&
			    (dbell->res->end >= DBELL_INF(dmsg))) {
				found = 1;
				break;
			}
		}
		if (found) {
858
			dbell->dinb(port, dbell->dev_id, DBELL_SID(dmsg), DBELL_TID(dmsg),
M
Matt Porter 已提交
859 860 861 862 863 864
				    DBELL_INF(dmsg));
		} else {
			pr_debug
			    ("RIO: spurious doorbell, sid %2.2x tid %2.2x info %4.4x\n",
			     DBELL_SID(dmsg), DBELL_TID(dmsg), DBELL_INF(dmsg));
		}
865 866
		setbits32(&priv->msg_regs->dmr, DOORBELL_DMR_DI);
		out_be32(&priv->msg_regs->dsr, DOORBELL_DSR_DIQI);
M
Matt Porter 已提交
867 868 869 870 871 872 873
	}

      out:
	return IRQ_HANDLED;
}

/**
874
 * fsl_rio_doorbell_init - MPC85xx doorbell interface init
M
Matt Porter 已提交
875 876 877
 * @mport: Master port implementing the inbound doorbell unit
 *
 * Initializes doorbell unit hardware and inbound DMA buffer
878
 * ring. Called from fsl_rio_setup(). Returns %0 on success
M
Matt Porter 已提交
879 880
 * or %-ENOMEM on failure.
 */
881
static int fsl_rio_doorbell_init(struct rio_mport *mport)
M
Matt Porter 已提交
882
{
883
	struct rio_priv *priv = mport->priv;
M
Matt Porter 已提交
884 885 886
	int rc = 0;

	/* Map outbound doorbell window immediately after maintenance window */
887 888 889
	priv->dbell_win = ioremap(mport->iores.start + RIO_MAINT_WIN_SIZE,
			    RIO_DBELL_WIN_SIZE);
	if (!priv->dbell_win) {
M
Matt Porter 已提交
890 891 892 893 894 895 896
		printk(KERN_ERR
		       "RIO: unable to map outbound doorbell window\n");
		rc = -ENOMEM;
		goto out;
	}

	/* Initialize inbound doorbells */
897
	priv->dbell_ring.virt = dma_alloc_coherent(priv->dev, 512 *
898 899
		    DOORBELL_MESSAGE_SIZE, &priv->dbell_ring.phys, GFP_KERNEL);
	if (!priv->dbell_ring.virt) {
M
Matt Porter 已提交
900 901
		printk(KERN_ERR "RIO: unable allocate inbound doorbell ring\n");
		rc = -ENOMEM;
902
		iounmap(priv->dbell_win);
M
Matt Porter 已提交
903 904 905 906
		goto out;
	}

	/* Point dequeue/enqueue pointers at first entry in ring */
907 908
	out_be32(&priv->msg_regs->dqdpar, (u32) priv->dbell_ring.phys);
	out_be32(&priv->msg_regs->dqepar, (u32) priv->dbell_ring.phys);
M
Matt Porter 已提交
909 910

	/* Clear interrupt status */
911
	out_be32(&priv->msg_regs->dsr, 0x00000091);
M
Matt Porter 已提交
912 913

	/* Hook up doorbell handler */
914 915 916 917
	rc = request_irq(IRQ_RIO_BELL(mport), fsl_rio_dbell_handler, 0,
			 "dbell_rx", (void *)mport);
	if (rc < 0) {
		iounmap(priv->dbell_win);
918
		dma_free_coherent(priv->dev, 512 * DOORBELL_MESSAGE_SIZE,
919
				  priv->dbell_ring.virt, priv->dbell_ring.phys);
M
Matt Porter 已提交
920 921 922 923 924 925
		printk(KERN_ERR
		       "MPC85xx RIO: unable to request inbound doorbell irq");
		goto out;
	}

	/* Configure doorbells for snooping, 512 entries, and enable */
926
	out_be32(&priv->msg_regs->dmr, 0x00108161);
M
Matt Porter 已提交
927 928 929 930 931 932 933

      out:
	return rc;
}

static char *cmdline = NULL;

934
static int fsl_rio_get_hdid(int index)
M
Matt Porter 已提交
935 936 937 938 939 940 941 942
{
	/* XXX Need to parse multiple entries in some format */
	if (!cmdline)
		return -1;

	return simple_strtol(cmdline, NULL, 0);
}

943
static int fsl_rio_get_cmdline(char *s)
M
Matt Porter 已提交
944 945 946 947 948 949 950 951
{
	if (!s)
		return 0;

	cmdline = s;
	return 1;
}

952
__setup("riohdid=", fsl_rio_get_cmdline);
M
Matt Porter 已提交
953

954 955 956 957 958 959 960 961 962 963 964 965 966 967
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";
968
			break;
969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995
		}
		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 已提交
996
/**
997 998
 * fsl_rio_setup - Setup Freescale PowerPC RapidIO interface
 * @dev: of_device pointer
M
Matt Porter 已提交
999 1000 1001 1002 1003
 *
 * Initializes MPC85xx RapidIO hardware interface, configures
 * master port with system-specific info, and registers the
 * master port with the RapidIO subsystem.
 */
1004
int fsl_rio_setup(struct of_device *dev)
M
Matt Porter 已提交
1005 1006 1007
{
	struct rio_ops *ops;
	struct rio_mport *port;
1008 1009 1010 1011 1012
	struct rio_priv *priv;
	int rc = 0;
	const u32 *dt_range, *cell;
	struct resource regs;
	int rlen;
1013
	u32 ccsr;
1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028
	u64 law_start, law_size;
	int paw, aw, sw;

	if (!dev->node) {
		dev_err(&dev->dev, "Device OF-Node is NULL");
		return -EFAULT;
	}

	rc = of_address_to_resource(dev->node, 0, &regs);
	if (rc) {
		dev_err(&dev->dev, "Can't get %s property 'reg'\n",
				dev->node->full_name);
		return -EFAULT;
	}
	dev_info(&dev->dev, "Of-device full name %s\n", dev->node->full_name);
1029
	dev_info(&dev->dev, "Regs: %pR\n", &regs);
1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057

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

	/* Get node address wide */
	cell = of_get_property(dev->node, "#address-cells", NULL);
	if (cell)
		aw = *cell;
	else
		aw = of_n_addr_cells(dev->node);
	/* Get node size wide */
	cell = of_get_property(dev->node, "#size-cells", NULL);
	if (cell)
		sw = *cell;
	else
		sw = of_n_size_cells(dev->node);
	/* Get parent address wide wide */
	paw = of_n_addr_cells(dev->node);

	law_start = of_read_number(dt_range + aw, paw);
	law_size = of_read_number(dt_range + aw + paw, sw);

	dev_info(&dev->dev, "LAW start 0x%016llx, size 0x%016llx.\n",
			law_start, law_size);
M
Matt Porter 已提交
1058 1059

	ops = kmalloc(sizeof(struct rio_ops), GFP_KERNEL);
1060 1061 1062 1063
	if (!ops) {
		rc = -ENOMEM;
		goto err_ops;
	}
1064 1065 1066 1067 1068
	ops->lcread = fsl_local_config_read;
	ops->lcwrite = fsl_local_config_write;
	ops->cread = fsl_rio_config_read;
	ops->cwrite = fsl_rio_config_write;
	ops->dsend = fsl_rio_doorbell_send;
M
Matt Porter 已提交
1069

1070
	port = kzalloc(sizeof(struct rio_mport), GFP_KERNEL);
1071 1072 1073 1074
	if (!port) {
		rc = -ENOMEM;
		goto err_port;
	}
M
Matt Porter 已提交
1075 1076
	port->id = 0;
	port->index = 0;
1077 1078 1079 1080 1081

	priv = kzalloc(sizeof(struct rio_priv), GFP_KERNEL);
	if (!priv) {
		printk(KERN_ERR "Can't alloc memory for 'priv'\n");
		rc = -ENOMEM;
1082
		goto err_priv;
1083 1084
	}

M
Matt Porter 已提交
1085 1086
	INIT_LIST_HEAD(&port->dbells);
	port->iores.start = law_start;
1087
	port->iores.end = law_start + law_size - 1;
M
Matt Porter 已提交
1088
	port->iores.flags = IORESOURCE_MEM;
1089
	port->iores.name = "rio_io_win";
M
Matt Porter 已提交
1090

1091 1092 1093 1094 1095 1096
	priv->bellirq = irq_of_parse_and_map(dev->node, 2);
	priv->txirq = irq_of_parse_and_map(dev->node, 3);
	priv->rxirq = irq_of_parse_and_map(dev->node, 4);
	dev_info(&dev->dev, "bellirq: %d, txirq: %d, rxirq %d\n", priv->bellirq,
				priv->txirq, priv->rxirq);

M
Matt Porter 已提交
1097 1098 1099 1100 1101
	rio_init_dbell_res(&port->riores[RIO_DOORBELL_RESOURCE], 0, 0xffff);
	rio_init_mbox_res(&port->riores[RIO_INB_MBOX_RESOURCE], 0, 0);
	rio_init_mbox_res(&port->riores[RIO_OUTB_MBOX_RESOURCE], 0, 0);
	strcpy(port->name, "RIO0 mport");

1102 1103
	priv->dev = &dev->dev;

M
Matt Porter 已提交
1104
	port->ops = ops;
1105
	port->host_deviceid = fsl_rio_get_hdid(port->id);
M
Matt Porter 已提交
1106

1107
	port->priv = priv;
M
Matt Porter 已提交
1108 1109
	rio_register_mport(port);

1110
	priv->regs_win = ioremap(regs.start, regs.end - regs.start + 1);
1111

1112 1113 1114 1115 1116 1117 1118
	/* Probe the master port phy type */
	ccsr = in_be32(priv->regs_win + RIO_CCSR);
	port->phy_type = (ccsr & 1) ? RIO_PHY_SERIAL : RIO_PHY_PARALLEL;
	dev_info(&dev->dev, "RapidIO PHY type: %s\n",
			(port->phy_type == RIO_PHY_PARALLEL) ? "parallel" :
			((port->phy_type == RIO_PHY_SERIAL) ? "serial" :
			 "unknown"));
1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147
	/* Checking the port training status */
	if (in_be32((priv->regs_win + RIO_ESCSR)) & 1) {
		dev_err(&dev->dev, "Port is not ready. "
				   "Try to restart connection...\n");
		switch (port->phy_type) {
		case RIO_PHY_SERIAL:
			/* Disable ports */
			out_be32(priv->regs_win + RIO_CCSR, 0);
			/* Set 1x lane */
			setbits32(priv->regs_win + RIO_CCSR, 0x02000000);
			/* Enable ports */
			setbits32(priv->regs_win + RIO_CCSR, 0x00600000);
			break;
		case RIO_PHY_PARALLEL:
			/* Disable ports */
			out_be32(priv->regs_win + RIO_CCSR, 0x22000000);
			/* Enable ports */
			out_be32(priv->regs_win + RIO_CCSR, 0x44000000);
			break;
		}
		msleep(100);
		if (in_be32((priv->regs_win + RIO_ESCSR)) & 1) {
			dev_err(&dev->dev, "Port restart failed.\n");
			rc = -ENOLINK;
			goto err;
		}
		dev_info(&dev->dev, "Port restart success!\n");
	}
	fsl_rio_info(&dev->dev, ccsr);
1148

1149 1150 1151 1152 1153
	port->sys_size = (in_be32((priv->regs_win + RIO_PEF_CAR))
					& RIO_PEF_CTLS) >> 4;
	dev_info(&dev->dev, "RapidIO Common Transport System size: %d\n",
			port->sys_size ? 65536 : 256);

1154 1155 1156 1157
	priv->atmu_regs = (struct rio_atmu_regs *)(priv->regs_win
					+ RIO_ATMU_REGS_OFFSET);
	priv->maint_atmu_regs = priv->atmu_regs + 1;
	priv->dbell_atmu_regs = priv->atmu_regs + 2;
1158 1159 1160 1161 1162 1163 1164
	priv->msg_regs = (struct rio_msg_regs *)(priv->regs_win +
				((port->phy_type == RIO_PHY_SERIAL) ?
				RIO_S_MSG_REGS_OFFSET : RIO_P_MSG_REGS_OFFSET));

	/* 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), RIO_ISR_AACR_AA);
M
Matt Porter 已提交
1165 1166

	/* Configure maintenance transaction window */
1167 1168
	out_be32(&priv->maint_atmu_regs->rowbar, law_start >> 12);
	out_be32(&priv->maint_atmu_regs->rowar, 0x80077015);	/* 4M */
M
Matt Porter 已提交
1169

1170
	priv->maint_win = ioremap(law_start, RIO_MAINT_WIN_SIZE);
M
Matt Porter 已提交
1171 1172

	/* Configure outbound doorbell window */
1173 1174 1175
	out_be32(&priv->dbell_atmu_regs->rowbar,
			(law_start + RIO_MAINT_WIN_SIZE) >> 12);
	out_be32(&priv->dbell_atmu_regs->rowar, 0x8004200b);	/* 4k */
1176
	fsl_rio_doorbell_init(port);
1177

1178
	return 0;
1179
err:
1180
	iounmap(priv->regs_win);
1181
	kfree(priv);
1182
err_priv:
1183
	kfree(port);
1184 1185 1186
err_port:
	kfree(ops);
err_ops:
1187
	return rc;
M
Matt Porter 已提交
1188
}
1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227

/* The probe function for RapidIO peer-to-peer network.
 */
static int __devinit fsl_of_rio_rpn_probe(struct of_device *dev,
				     const struct of_device_id *match)
{
	int rc;
	printk(KERN_INFO "Setting up RapidIO peer-to-peer network %s\n",
			dev->node->full_name);

	rc = fsl_rio_setup(dev);
	if (rc)
		goto out;

	/* Enumerate all registered ports */
	rc = rio_init_mports();
out:
	return rc;
};

static const struct of_device_id fsl_of_rio_rpn_ids[] = {
	{
		.compatible = "fsl,rapidio-delta",
	},
	{},
};

static struct of_platform_driver fsl_of_rio_rpn_driver = {
	.name = "fsl-of-rio",
	.match_table = fsl_of_rio_rpn_ids,
	.probe = fsl_of_rio_rpn_probe,
};

static __init int fsl_of_rio_rpn_init(void)
{
	return of_register_platform_driver(&fsl_of_rio_rpn_driver);
}

subsys_initcall(fsl_of_rio_rpn_init);