fsl_rio.c 46.0 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 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>
M
Matt Porter 已提交
31 32
#include <linux/rio.h>
#include <linux/rio_drv.h>
33
#include <linux/of_platform.h>
34
#include <linux/delay.h>
35
#include <linux/slab.h>
36
#include <linux/kfifo.h>
M
Matt Porter 已提交
37 38

#include <asm/io.h>
39 40
#include <asm/machdep.h>
#include <asm/uaccess.h>
M
Matt Porter 已提交
41

42 43
#undef DEBUG_PW	/* Port-Write debugging */

44 45 46 47
/* 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)
48
#define IRQ_RIO_PW(m)		(((struct rio_priv *)(m->priv))->pwirq)
49

50 51 52 53 54 55 56
#define IPWSR_CLEAR		0x98
#define OMSR_CLEAR		0x1cb3
#define IMSR_CLEAR		0x491
#define IDSR_CLEAR		0x91
#define ODSR_CLEAR		0x1c00
#define LTLEECSR_ENABLE_ALL	0xFFC000FC
#define ESCSR_CLEAR		0x07120204
57
#define IECSR_CLEAR		0x80000000
58 59 60 61 62 63 64 65 66 67

#define RIO_PORT1_EDCSR		0x0640
#define RIO_PORT2_EDCSR		0x0680
#define RIO_PORT1_IECSR		0x10130
#define RIO_PORT2_IECSR		0x101B0
#define RIO_IM0SR		0x13064
#define RIO_IM1SR		0x13164
#define RIO_OM0SR		0x13004
#define RIO_OM1SR		0x13104

M
Matt Porter 已提交
68
#define RIO_ATMU_REGS_OFFSET	0x10c00
69 70
#define RIO_P_MSG_REGS_OFFSET	0x11000
#define RIO_S_MSG_REGS_OFFSET	0x13000
71
#define RIO_GCCSR		0x13c
72
#define RIO_ESCSR		0x158
73
#define RIO_PORT2_ESCSR		0x178
74
#define RIO_CCSR		0x15c
75
#define RIO_LTLEDCSR		0x0608
76 77
#define RIO_LTLEDCSR_IER	0x80000000
#define RIO_LTLEDCSR_PRT	0x01000000
78 79
#define RIO_LTLEECSR		0x060c
#define RIO_EPWISR		0x10010
80 81
#define RIO_ISR_AACR		0x10120
#define RIO_ISR_AACR_AA		0x1	/* Accept All ID */
M
Matt Porter 已提交
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
#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

98 99 100 101 102 103 104 105 106 107 108 109
#define RIO_IPWMR_SEN		0x00100000
#define RIO_IPWMR_QFIE		0x00000100
#define RIO_IPWMR_EIE		0x00000020
#define RIO_IPWMR_CQ		0x00000002
#define RIO_IPWMR_PWE		0x00000001

#define RIO_IPWSR_QF		0x00100000
#define RIO_IPWSR_TE		0x00000080
#define RIO_IPWSR_QFI		0x00000010
#define RIO_IPWSR_PWD		0x00000008
#define RIO_IPWSR_PWB		0x00000004

110 111 112 113
/* EPWISR Error match value */
#define RIO_EPWISR_PINT1	0x80000000
#define RIO_EPWISR_PINT2	0x40000000
#define RIO_EPWISR_MU		0x00000002
114 115
#define RIO_EPWISR_PW		0x00000001

M
Matt Porter 已提交
116 117 118 119 120 121 122 123 124 125 126
#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
127 128
#define DOORBELL_TID_OFFSET	0x02
#define DOORBELL_SID_OFFSET	0x04
M
Matt Porter 已提交
129 130 131
#define DOORBELL_INFO_OFFSET	0x06

#define DOORBELL_MESSAGE_SIZE	0x08
132 133
#define DBELL_SID(x)		(*(u16 *)(x + DOORBELL_SID_OFFSET))
#define DBELL_TID(x)		(*(u16 *)(x + DOORBELL_TID_OFFSET))
M
Matt Porter 已提交
134 135 136 137
#define DBELL_INF(x)		(*(u16 *)(x + DOORBELL_INFO_OFFSET))

struct rio_atmu_regs {
	u32 rowtar;
138
	u32 rowtear;
M
Matt Porter 已提交
139 140 141 142 143 144 145
	u32 rowbar;
	u32 pad2;
	u32 rowar;
	u32 pad3[3];
};

struct rio_msg_regs {
146 147
	u32 omr;	/* 0xD_3000 - Outbound message 0 mode register */
	u32 osr;	/* 0xD_3004 - Outbound message 0 status register */
M
Matt Porter 已提交
148
	u32 pad1;
149 150
	u32 odqdpar;	/* 0xD_300C - Outbound message 0 descriptor queue
			   dequeue pointer address register */
M
Matt Porter 已提交
151
	u32 pad2;
152 153 154 155 156 157 158 159
	u32 osar;	/* 0xD_3014 - Outbound message 0 source address
			   register */
	u32 odpr;	/* 0xD_3018 - Outbound message 0 destination port
			   register */
	u32 odatr;	/* 0xD_301C - Outbound message 0 destination attributes
			   Register*/
	u32 odcr;	/* 0xD_3020 - Outbound message 0 double-word count
			   register */
M
Matt Porter 已提交
160
	u32 pad3;
161 162
	u32 odqepar;	/* 0xD_3028 - Outbound message 0 descriptor queue
			   enqueue pointer address register */
M
Matt Porter 已提交
163
	u32 pad4[13];
164 165
	u32 imr;	/* 0xD_3060 - Inbound message 0 mode register */
	u32 isr;	/* 0xD_3064 - Inbound message 0 status register */
M
Matt Porter 已提交
166
	u32 pad5;
167 168
	u32 ifqdpar;	/* 0xD_306C - Inbound message 0 frame queue dequeue
			   pointer address register*/
M
Matt Porter 已提交
169
	u32 pad6;
170 171
	u32 ifqepar;	/* 0xD_3074 - Inbound message 0 frame queue enqueue
			   pointer address register */
172
	u32 pad7[226];
173 174
	u32 odmr;	/* 0xD_3400 - Outbound doorbell mode register */
	u32 odsr;	/* 0xD_3404 - Outbound doorbell status register */
175
	u32 res0[4];
176 177 178 179
	u32 oddpr;	/* 0xD_3418 - Outbound doorbell destination port
			   register */
	u32 oddatr;	/* 0xD_341c - Outbound doorbell destination attributes
			   register */
180
	u32 res1[3];
181 182
	u32 odretcr;	/* 0xD_342C - Outbound doorbell retry error threshold
			   configuration register */
183
	u32 res2[12];
184 185
	u32 dmr;	/* 0xD_3460 - Inbound doorbell mode register */
	u32 dsr;	/* 0xD_3464 - Inbound doorbell status register */
M
Matt Porter 已提交
186
	u32 pad8;
187 188
	u32 dqdpar;	/* 0xD_346C - Inbound doorbell queue dequeue Pointer
			   address register */
M
Matt Porter 已提交
189
	u32 pad9;
190 191
	u32 dqepar;	/* 0xD_3474 - Inbound doorbell Queue enqueue pointer
			   address register */
M
Matt Porter 已提交
192
	u32 pad10[26];
193 194 195 196 197 198
	u32 pwmr;	/* 0xD_34E0 - Inbound port-write mode register */
	u32 pwsr;	/* 0xD_34E4 - Inbound port-write status register */
	u32 epwqbar;	/* 0xD_34E8 - Extended Port-Write Queue Base Address
			   register */
	u32 pwqbar;	/* 0xD_34EC - Inbound port-write queue base address
			   register */
M
Matt Porter 已提交
199 200 201 202 203 204 205 206 207 208 209 210 211
};

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

212
struct rio_dbell_ring {
M
Matt Porter 已提交
213 214
	void *virt;
	dma_addr_t phys;
215
};
M
Matt Porter 已提交
216

217
struct rio_msg_tx_ring {
M
Matt Porter 已提交
218 219 220 221 222 223
	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;
224
	void *dev_id;
225
};
M
Matt Porter 已提交
226

227
struct rio_msg_rx_ring {
M
Matt Porter 已提交
228 229 230 231 232
	void *virt;
	dma_addr_t phys;
	void *virt_buffer[RIO_MAX_RX_RING_SIZE];
	int rx_slot;
	int size;
233
	void *dev_id;
234 235
};

236 237 238 239 240 241 242 243
struct rio_port_write_msg {
	void *virt;
	dma_addr_t phys;
	u32 msg_count;
	u32 err_count;
	u32 discard_count;
};

244
struct rio_priv {
245
	struct device *dev;
246 247 248 249 250 251 252 253 254 255
	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;
256
	struct rio_port_write_msg port_write_msg;
257 258 259
	int bellirq;
	int txirq;
	int rxirq;
260 261 262 263
	int pwirq;
	struct work_struct pw_work;
	struct kfifo pw_fifo;
	spinlock_t pw_fifo_lock;
264
};
M
Matt Porter 已提交
265

266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283
#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"		\
		"	.align 2\n"			\
		"	.long 1b,3b\n"			\
		".text"					\
		: "=r" (err), "=r" (x)			\
		: "b" (addr), "i" (-EFAULT), "0" (err))

static void __iomem *rio_regs_win;

L
Li Yang 已提交
284
#ifdef CONFIG_E500
285
int fsl_rio_mcheck_exception(struct pt_regs *regs)
286
{
287 288
	const struct exception_table_entry *entry;
	unsigned long reason;
289

290 291 292 293 294 295 296 297 298 299 300 301 302 303 304
	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;
305 306 307
		}
	}

308
	return 0;
309
}
310
EXPORT_SYMBOL_GPL(fsl_rio_mcheck_exception);
L
Li Yang 已提交
311
#endif
312

M
Matt Porter 已提交
313
/**
314
 * fsl_rio_doorbell_send - Send a MPC85xx doorbell message
315
 * @mport: RapidIO master port info
M
Matt Porter 已提交
316 317 318 319 320 321 322
 * @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.
 */
323 324
static int fsl_rio_doorbell_send(struct rio_mport *mport,
				int index, u16 destid, u16 data)
M
Matt Porter 已提交
325
{
326
	struct rio_priv *priv = mport->priv;
327
	pr_debug("fsl_doorbell_send: index %d destid %4.4x data %4.4x\n",
M
Matt Porter 已提交
328
		 index, destid, data);
329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344
	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 已提交
345 346 347 348 349

	return 0;
}

/**
350
 * fsl_local_config_read - Generate a MPC85xx local config space read
351
 * @mport: RapidIO master port info
M
Matt Porter 已提交
352 353 354 355 356 357 358 359
 * @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.
 */
360 361
static int fsl_local_config_read(struct rio_mport *mport,
				int index, u32 offset, int len, u32 *data)
M
Matt Porter 已提交
362
{
363
	struct rio_priv *priv = mport->priv;
364
	pr_debug("fsl_local_config_read: index %d offset %8.8x\n", index,
M
Matt Porter 已提交
365
		 offset);
366
	*data = in_be32(priv->regs_win + offset);
M
Matt Porter 已提交
367 368 369 370 371

	return 0;
}

/**
372
 * fsl_local_config_write - Generate a MPC85xx local config space write
373
 * @mport: RapidIO master port info
M
Matt Porter 已提交
374 375 376 377 378 379 380 381
 * @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.
 */
382 383
static int fsl_local_config_write(struct rio_mport *mport,
				int index, u32 offset, int len, u32 data)
M
Matt Porter 已提交
384
{
385
	struct rio_priv *priv = mport->priv;
M
Matt Porter 已提交
386
	pr_debug
387
	    ("fsl_local_config_write: index %d offset %8.8x data %8.8x\n",
M
Matt Porter 已提交
388
	     index, offset, data);
389
	out_be32(priv->regs_win + offset, data);
M
Matt Porter 已提交
390 391 392 393 394

	return 0;
}

/**
395
 * fsl_rio_config_read - Generate a MPC85xx read maintenance transaction
396
 * @mport: RapidIO master port info
M
Matt Porter 已提交
397 398 399 400 401 402 403 404 405 406 407
 * @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
408 409
fsl_rio_config_read(struct rio_mport *mport, int index, u16 destid,
			u8 hopcount, u32 offset, int len, u32 *val)
M
Matt Porter 已提交
410
{
411
	struct rio_priv *priv = mport->priv;
M
Matt Porter 已提交
412
	u8 *data;
413
	u32 rval, err = 0;
M
Matt Porter 已提交
414 415

	pr_debug
416
	    ("fsl_rio_config_read: index %d destid %d hopcount %d offset %8.8x len %d\n",
M
Matt Porter 已提交
417
	     index, destid, hopcount, offset, len);
418 419 420 421 422 423

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

424
	out_be32(&priv->maint_atmu_regs->rowtar,
425 426
		 (destid << 22) | (hopcount << 12) | (offset >> 12));
	out_be32(&priv->maint_atmu_regs->rowtear,  (destid >> 10));
M
Matt Porter 已提交
427

428
	data = (u8 *) priv->maint_win + (offset & (RIO_MAINT_WIN_SIZE - 1));
M
Matt Porter 已提交
429 430
	switch (len) {
	case 1:
431
		__fsl_read_rio_config(rval, data, err, "lbz");
M
Matt Porter 已提交
432 433
		break;
	case 2:
434
		__fsl_read_rio_config(rval, data, err, "lhz");
M
Matt Porter 已提交
435
		break;
436
	case 4:
437
		__fsl_read_rio_config(rval, data, err, "lwz");
M
Matt Porter 已提交
438
		break;
439 440
	default:
		return -EINVAL;
M
Matt Porter 已提交
441 442
	}

443 444 445 446 447 448 449 450
	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 已提交
451 452 453
}

/**
454
 * fsl_rio_config_write - Generate a MPC85xx write maintenance transaction
455
 * @mport: RapidIO master port info
M
Matt Porter 已提交
456 457 458 459 460 461 462 463 464 465 466
 * @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
467 468
fsl_rio_config_write(struct rio_mport *mport, int index, u16 destid,
			u8 hopcount, u32 offset, int len, u32 val)
M
Matt Porter 已提交
469
{
470
	struct rio_priv *priv = mport->priv;
M
Matt Porter 已提交
471 472
	u8 *data;
	pr_debug
473
	    ("fsl_rio_config_write: index %d destid %d hopcount %d offset %8.8x len %d val %8.8x\n",
M
Matt Porter 已提交
474
	     index, destid, hopcount, offset, len, val);
475 476 477 478 479 480

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

481
	out_be32(&priv->maint_atmu_regs->rowtar,
482 483
		 (destid << 22) | (hopcount << 12) | (offset >> 12));
	out_be32(&priv->maint_atmu_regs->rowtear,  (destid >> 10));
M
Matt Porter 已提交
484

485
	data = (u8 *) priv->maint_win + (offset & (RIO_MAINT_WIN_SIZE - 1));
M
Matt Porter 已提交
486 487 488 489 490 491 492
	switch (len) {
	case 1:
		out_8((u8 *) data, val);
		break;
	case 2:
		out_be16((u16 *) data, val);
		break;
493
	case 4:
M
Matt Porter 已提交
494 495
		out_be32((u32 *) data, val);
		break;
496 497
	default:
		return -EINVAL;
M
Matt Porter 已提交
498 499 500 501 502 503
	}

	return 0;
}

/**
504
 * fsl_add_outb_message - Add message to the MPC85xx outbound message queue
M
Matt Porter 已提交
505 506 507 508 509 510 511 512 513
 * @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.
 */
514 515
static int
fsl_add_outb_message(struct rio_mport *mport, struct rio_dev *rdev, int mbox,
M
Matt Porter 已提交
516 517
			void *buffer, size_t len)
{
518
	struct rio_priv *priv = mport->priv;
M
Matt Porter 已提交
519
	u32 omr;
520 521
	struct rio_tx_desc *desc = (struct rio_tx_desc *)priv->msg_tx_ring.virt
					+ priv->msg_tx_ring.tx_slot;
M
Matt Porter 已提交
522 523
	int ret = 0;

524 525
	pr_debug("RIO: fsl_add_outb_message(): destid %4.4x mbox %d buffer " \
		 "%8.8x len %8.8x\n", rdev->destid, mbox, (int)buffer, len);
M
Matt Porter 已提交
526 527 528 529 530 531 532

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

	/* Copy and clear rest of buffer */
533 534
	memcpy(priv->msg_tx_ring.virt_buffer[priv->msg_tx_ring.tx_slot], buffer,
			len);
M
Matt Porter 已提交
535
	if (len < (RIO_MAX_MSG_SIZE - 4))
536 537
		memset(priv->msg_tx_ring.virt_buffer[priv->msg_tx_ring.tx_slot]
				+ len, 0, RIO_MAX_MSG_SIZE - len);
M
Matt Porter 已提交
538

539 540 541 542
	switch (mport->phy_type) {
	case RIO_PHY_PARALLEL:
		/* Set mbox field for message */
		desc->dport = mbox & 0x3;
M
Matt Porter 已提交
543

544 545 546 547 548 549 550 551 552 553 554
		/* 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 已提交
555 556 557 558 559

	/* 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 */
560 561
	desc->saddr = 0x00000004
		| priv->msg_tx_ring.phys_buffer[priv->msg_tx_ring.tx_slot];
M
Matt Porter 已提交
562 563

	/* Increment enqueue pointer */
564 565
	omr = in_be32(&priv->msg_regs->omr);
	out_be32(&priv->msg_regs->omr, omr | RIO_MSG_OMR_MUI);
M
Matt Porter 已提交
566 567

	/* Go to next descriptor */
568 569
	if (++priv->msg_tx_ring.tx_slot == priv->msg_tx_ring.size)
		priv->msg_tx_ring.tx_slot = 0;
M
Matt Porter 已提交
570 571 572 573 574 575

      out:
	return ret;
}

/**
576
 * fsl_rio_tx_handler - MPC85xx outbound message interrupt handler
M
Matt Porter 已提交
577 578 579 580
 * @irq: Linux interrupt number
 * @dev_instance: Pointer to interrupt-specific data
 *
 * Handles outbound message interrupts. Executes a register outbound
581
 * mailbox event handler and acks the interrupt occurrence.
M
Matt Porter 已提交
582 583
 */
static irqreturn_t
584
fsl_rio_tx_handler(int irq, void *dev_instance)
M
Matt Porter 已提交
585 586 587
{
	int osr;
	struct rio_mport *port = (struct rio_mport *)dev_instance;
588
	struct rio_priv *priv = port->priv;
M
Matt Porter 已提交
589

590
	osr = in_be32(&priv->msg_regs->osr);
M
Matt Porter 已提交
591 592 593

	if (osr & RIO_MSG_OSR_TE) {
		pr_info("RIO: outbound message transmission error\n");
594
		out_be32(&priv->msg_regs->osr, RIO_MSG_OSR_TE);
M
Matt Porter 已提交
595 596 597 598 599
		goto out;
	}

	if (osr & RIO_MSG_OSR_QOI) {
		pr_info("RIO: outbound message queue overflow\n");
600
		out_be32(&priv->msg_regs->osr, RIO_MSG_OSR_QOI);
M
Matt Porter 已提交
601 602 603 604
		goto out;
	}

	if (osr & RIO_MSG_OSR_EOMI) {
605 606 607 608
		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 已提交
609 610

		/* Ack the end-of-message interrupt */
611
		out_be32(&priv->msg_regs->osr, RIO_MSG_OSR_EOMI);
M
Matt Porter 已提交
612 613 614 615 616 617 618
	}

      out:
	return IRQ_HANDLED;
}

/**
619
 * fsl_open_outb_mbox - Initialize MPC85xx outbound mailbox
M
Matt Porter 已提交
620
 * @mport: Master port implementing the outbound message unit
621
 * @dev_id: Device specific pointer to pass on event
M
Matt Porter 已提交
622 623 624 625 626 627 628
 * @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.
 */
629 630
static int
fsl_open_outb_mbox(struct rio_mport *mport, void *dev_id, int mbox, int entries)
M
Matt Porter 已提交
631 632
{
	int i, j, rc = 0;
633
	struct rio_priv *priv = mport->priv;
M
Matt Porter 已提交
634 635 636 637 638 639 640 641

	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 */
642 643 644 645 646
	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] =
647
			dma_alloc_coherent(priv->dev, RIO_MSG_BUFFER_SIZE,
648 649
				&priv->msg_tx_ring.phys_buffer[i], GFP_KERNEL);
		if (!priv->msg_tx_ring.virt_buffer[i]) {
M
Matt Porter 已提交
650
			rc = -ENOMEM;
651 652
			for (j = 0; j < priv->msg_tx_ring.size; j++)
				if (priv->msg_tx_ring.virt_buffer[j])
653
					dma_free_coherent(priv->dev,
654 655 656 657 658
							RIO_MSG_BUFFER_SIZE,
							priv->msg_tx_ring.
							virt_buffer[j],
							priv->msg_tx_ring.
							phys_buffer[j]);
M
Matt Porter 已提交
659 660 661 662 663
			goto out;
		}
	}

	/* Initialize outbound message descriptor ring */
664
	priv->msg_tx_ring.virt = dma_alloc_coherent(priv->dev,
665 666 667
				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 已提交
668 669 670
		rc = -ENOMEM;
		goto out_dma;
	}
671 672 673
	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 已提交
674 675

	/* Point dequeue/enqueue pointers at first entry in ring */
676 677
	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 已提交
678 679

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

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

	/* Hook up outbound message handler */
686 687 688
	rc = request_irq(IRQ_RIO_TX(mport), fsl_rio_tx_handler, 0,
			 "msg_tx", (void *)mport);
	if (rc < 0)
M
Matt Porter 已提交
689 690 691 692 693 694 695 696 697
		goto out_irq;

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

	/* Set number of entries */
701 702
	out_be32(&priv->msg_regs->omr,
		 in_be32(&priv->msg_regs->omr) |
M
Matt Porter 已提交
703 704 705
		 ((get_bitmask_order(entries) - 2) << 12));

	/* Now enable the unit */
706
	out_be32(&priv->msg_regs->omr, in_be32(&priv->msg_regs->omr) | 0x1);
M
Matt Porter 已提交
707 708 709 710 711

      out:
	return rc;

      out_irq:
712 713
	dma_free_coherent(priv->dev,
			  priv->msg_tx_ring.size * RIO_MSG_DESC_SIZE,
714
			  priv->msg_tx_ring.virt, priv->msg_tx_ring.phys);
M
Matt Porter 已提交
715 716

      out_dma:
717
	for (i = 0; i < priv->msg_tx_ring.size; i++)
718
		dma_free_coherent(priv->dev, RIO_MSG_BUFFER_SIZE,
719 720
				  priv->msg_tx_ring.virt_buffer[i],
				  priv->msg_tx_ring.phys_buffer[i]);
M
Matt Porter 已提交
721 722 723 724 725

	return rc;
}

/**
726
 * fsl_close_outb_mbox - Shut down MPC85xx outbound mailbox
M
Matt Porter 已提交
727 728 729 730 731 732
 * @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.
 */
733
static void fsl_close_outb_mbox(struct rio_mport *mport, int mbox)
M
Matt Porter 已提交
734
{
735
	struct rio_priv *priv = mport->priv;
M
Matt Porter 已提交
736
	/* Disable inbound message unit */
737
	out_be32(&priv->msg_regs->omr, 0);
M
Matt Porter 已提交
738 739

	/* Free ring */
740 741
	dma_free_coherent(priv->dev,
			  priv->msg_tx_ring.size * RIO_MSG_DESC_SIZE,
742
			  priv->msg_tx_ring.virt, priv->msg_tx_ring.phys);
M
Matt Porter 已提交
743 744

	/* Free interrupt */
745
	free_irq(IRQ_RIO_TX(mport), (void *)mport);
M
Matt Porter 已提交
746 747 748
}

/**
749
 * fsl_rio_rx_handler - MPC85xx inbound message interrupt handler
M
Matt Porter 已提交
750 751 752 753
 * @irq: Linux interrupt number
 * @dev_instance: Pointer to interrupt-specific data
 *
 * Handles inbound message interrupts. Executes a registered inbound
754
 * mailbox event handler and acks the interrupt occurrence.
M
Matt Porter 已提交
755 756
 */
static irqreturn_t
757
fsl_rio_rx_handler(int irq, void *dev_instance)
M
Matt Porter 已提交
758 759 760
{
	int isr;
	struct rio_mport *port = (struct rio_mport *)dev_instance;
761
	struct rio_priv *priv = port->priv;
M
Matt Porter 已提交
762

763
	isr = in_be32(&priv->msg_regs->isr);
M
Matt Porter 已提交
764 765 766

	if (isr & RIO_MSG_ISR_TE) {
		pr_info("RIO: inbound message reception error\n");
767
		out_be32((void *)&priv->msg_regs->isr, RIO_MSG_ISR_TE);
M
Matt Porter 已提交
768 769 770 771 772 773 774 775 776 777 778
		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.
		 */
779
		port->inb_msg[0].mcback(port, priv->msg_rx_ring.dev_id, -1, -1);
M
Matt Porter 已提交
780 781

		/* Ack the queueing interrupt */
782
		out_be32(&priv->msg_regs->isr, RIO_MSG_ISR_DIQI);
M
Matt Porter 已提交
783 784 785 786 787 788 789
	}

      out:
	return IRQ_HANDLED;
}

/**
790
 * fsl_open_inb_mbox - Initialize MPC85xx inbound mailbox
M
Matt Porter 已提交
791
 * @mport: Master port implementing the inbound message unit
792
 * @dev_id: Device specific pointer to pass on event
M
Matt Porter 已提交
793 794 795 796 797 798 799
 * @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.
 */
800 801
static int
fsl_open_inb_mbox(struct rio_mport *mport, void *dev_id, int mbox, int entries)
M
Matt Porter 已提交
802 803
{
	int i, rc = 0;
804
	struct rio_priv *priv = mport->priv;
M
Matt Porter 已提交
805 806 807 808 809 810 811 812

	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 */
813 814 815 816 817
	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 已提交
818 819

	/* Initialize inbound message ring */
820
	priv->msg_rx_ring.virt = dma_alloc_coherent(priv->dev,
821 822 823
				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 已提交
824 825 826 827 828
		rc = -ENOMEM;
		goto out;
	}

	/* Point dequeue/enqueue pointers at first entry in ring */
829 830
	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 已提交
831 832

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

	/* Hook up inbound message handler */
836 837 838
	rc = request_irq(IRQ_RIO_RX(mport), fsl_rio_rx_handler, 0,
			 "msg_rx", (void *)mport);
	if (rc < 0) {
839
		dma_free_coherent(priv->dev, RIO_MSG_BUFFER_SIZE,
840 841
				  priv->msg_tx_ring.virt_buffer[i],
				  priv->msg_tx_ring.phys_buffer[i]);
M
Matt Porter 已提交
842 843 844 845 846 847 848 849 850 851
		goto out;
	}

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

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

	/* Now enable the unit */
858
	setbits32(&priv->msg_regs->imr, 0x1);
M
Matt Porter 已提交
859 860 861 862 863 864

      out:
	return rc;
}

/**
865
 * fsl_close_inb_mbox - Shut down MPC85xx inbound mailbox
M
Matt Porter 已提交
866 867 868 869 870 871
 * @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.
 */
872
static void fsl_close_inb_mbox(struct rio_mport *mport, int mbox)
M
Matt Porter 已提交
873
{
874
	struct rio_priv *priv = mport->priv;
M
Matt Porter 已提交
875
	/* Disable inbound message unit */
876
	out_be32(&priv->msg_regs->imr, 0);
M
Matt Porter 已提交
877 878

	/* Free ring */
879
	dma_free_coherent(priv->dev, priv->msg_rx_ring.size * RIO_MAX_MSG_SIZE,
880
			  priv->msg_rx_ring.virt, priv->msg_rx_ring.phys);
M
Matt Porter 已提交
881 882

	/* Free interrupt */
883
	free_irq(IRQ_RIO_RX(mport), (void *)mport);
M
Matt Porter 已提交
884 885 886
}

/**
887
 * fsl_add_inb_buffer - Add buffer to the MPC85xx inbound message queue
M
Matt Porter 已提交
888 889 890 891 892 893 894
 * @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.
 */
895
static int fsl_add_inb_buffer(struct rio_mport *mport, int mbox, void *buf)
M
Matt Porter 已提交
896 897
{
	int rc = 0;
898
	struct rio_priv *priv = mport->priv;
M
Matt Porter 已提交
899

900
	pr_debug("RIO: fsl_add_inb_buffer(), msg_rx_ring.rx_slot %d\n",
901
		 priv->msg_rx_ring.rx_slot);
M
Matt Porter 已提交
902

903
	if (priv->msg_rx_ring.virt_buffer[priv->msg_rx_ring.rx_slot]) {
M
Matt Porter 已提交
904 905
		printk(KERN_ERR
		       "RIO: error adding inbound buffer %d, buffer exists\n",
906
		       priv->msg_rx_ring.rx_slot);
M
Matt Porter 已提交
907 908 909 910
		rc = -EINVAL;
		goto out;
	}

911 912 913
	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 已提交
914 915 916 917 918 919

      out:
	return rc;
}

/**
920
 * fsl_get_inb_message - Fetch inbound message from the MPC85xx message unit
M
Matt Porter 已提交
921 922 923 924 925 926
 * @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.
 */
927
static void *fsl_get_inb_message(struct rio_mport *mport, int mbox)
M
Matt Porter 已提交
928
{
929
	struct rio_priv *priv = mport->priv;
M
Matt Porter 已提交
930 931 932 933
	u32 phys_buf, virt_buf;
	void *buf = NULL;
	int buf_idx;

934
	phys_buf = in_be32(&priv->msg_regs->ifqdpar);
M
Matt Porter 已提交
935 936

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

940 941 942 943
	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 已提交
944 945 946 947 948 949 950 951 952 953 954

	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 */
955
	priv->msg_rx_ring.virt_buffer[buf_idx] = NULL;
M
Matt Porter 已提交
956 957

      out1:
958
	setbits32(&priv->msg_regs->imr, RIO_MSG_IMR_MI);
M
Matt Porter 已提交
959 960 961 962 963 964

      out2:
	return buf;
}

/**
965
 * fsl_rio_dbell_handler - MPC85xx doorbell interrupt handler
M
Matt Porter 已提交
966 967 968 969 970 971 972
 * @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
973
fsl_rio_dbell_handler(int irq, void *dev_instance)
M
Matt Porter 已提交
974 975 976
{
	int dsr;
	struct rio_mport *port = (struct rio_mport *)dev_instance;
977
	struct rio_priv *priv = port->priv;
M
Matt Porter 已提交
978

979
	dsr = in_be32(&priv->msg_regs->dsr);
M
Matt Porter 已提交
980 981 982

	if (dsr & DOORBELL_DSR_TE) {
		pr_info("RIO: doorbell reception error\n");
983
		out_be32(&priv->msg_regs->dsr, DOORBELL_DSR_TE);
M
Matt Porter 已提交
984 985 986 987 988
		goto out;
	}

	if (dsr & DOORBELL_DSR_QFI) {
		pr_info("RIO: doorbell queue full\n");
989
		out_be32(&priv->msg_regs->dsr, DOORBELL_DSR_QFI);
M
Matt Porter 已提交
990 991 992 993 994
	}

	/* XXX Need to check/dispatch until queue empty */
	if (dsr & DOORBELL_DSR_DIQI) {
		u32 dmsg =
995 996
		    (u32) priv->dbell_ring.virt +
		    (in_be32(&priv->msg_regs->dqdpar) & 0xfff);
M
Matt Porter 已提交
997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011
		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) {
1012
			dbell->dinb(port, dbell->dev_id, DBELL_SID(dmsg), DBELL_TID(dmsg),
M
Matt Porter 已提交
1013 1014 1015 1016 1017 1018
				    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));
		}
1019 1020
		setbits32(&priv->msg_regs->dmr, DOORBELL_DMR_DI);
		out_be32(&priv->msg_regs->dsr, DOORBELL_DSR_DIQI);
M
Matt Porter 已提交
1021 1022 1023 1024 1025 1026 1027
	}

      out:
	return IRQ_HANDLED;
}

/**
1028
 * fsl_rio_doorbell_init - MPC85xx doorbell interface init
M
Matt Porter 已提交
1029 1030 1031
 * @mport: Master port implementing the inbound doorbell unit
 *
 * Initializes doorbell unit hardware and inbound DMA buffer
1032
 * ring. Called from fsl_rio_setup(). Returns %0 on success
M
Matt Porter 已提交
1033 1034
 * or %-ENOMEM on failure.
 */
1035
static int fsl_rio_doorbell_init(struct rio_mport *mport)
M
Matt Porter 已提交
1036
{
1037
	struct rio_priv *priv = mport->priv;
M
Matt Porter 已提交
1038 1039 1040
	int rc = 0;

	/* Map outbound doorbell window immediately after maintenance window */
1041 1042 1043
	priv->dbell_win = ioremap(mport->iores.start + RIO_MAINT_WIN_SIZE,
			    RIO_DBELL_WIN_SIZE);
	if (!priv->dbell_win) {
M
Matt Porter 已提交
1044 1045 1046 1047 1048 1049 1050
		printk(KERN_ERR
		       "RIO: unable to map outbound doorbell window\n");
		rc = -ENOMEM;
		goto out;
	}

	/* Initialize inbound doorbells */
1051
	priv->dbell_ring.virt = dma_alloc_coherent(priv->dev, 512 *
1052 1053
		    DOORBELL_MESSAGE_SIZE, &priv->dbell_ring.phys, GFP_KERNEL);
	if (!priv->dbell_ring.virt) {
M
Matt Porter 已提交
1054 1055
		printk(KERN_ERR "RIO: unable allocate inbound doorbell ring\n");
		rc = -ENOMEM;
1056
		iounmap(priv->dbell_win);
M
Matt Porter 已提交
1057 1058 1059 1060
		goto out;
	}

	/* Point dequeue/enqueue pointers at first entry in ring */
1061 1062
	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 已提交
1063 1064

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

	/* Hook up doorbell handler */
1068 1069 1070 1071
	rc = request_irq(IRQ_RIO_BELL(mport), fsl_rio_dbell_handler, 0,
			 "dbell_rx", (void *)mport);
	if (rc < 0) {
		iounmap(priv->dbell_win);
1072
		dma_free_coherent(priv->dev, 512 * DOORBELL_MESSAGE_SIZE,
1073
				  priv->dbell_ring.virt, priv->dbell_ring.phys);
M
Matt Porter 已提交
1074 1075 1076 1077 1078 1079
		printk(KERN_ERR
		       "MPC85xx RIO: unable to request inbound doorbell irq");
		goto out;
	}

	/* Configure doorbells for snooping, 512 entries, and enable */
1080
	out_be32(&priv->msg_regs->dmr, 0x00108161);
M
Matt Porter 已提交
1081 1082 1083 1084 1085

      out:
	return rc;
}

1086 1087 1088 1089 1090 1091 1092
static void port_error_handler(struct rio_mport *port, int offset)
{
	/*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);
1093
		out_be32((u32 *)(rio_regs_win + RIO_PORT1_IECSR), IECSR_CLEAR);
1094 1095 1096
		out_be32((u32 *)(rio_regs_win + RIO_ESCSR), ESCSR_CLEAR);
	} else {
		out_be32((u32 *)(rio_regs_win + RIO_PORT2_EDCSR), 0);
1097
		out_be32((u32 *)(rio_regs_win + RIO_PORT2_IECSR), IECSR_CLEAR);
1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119
		out_be32((u32 *)(rio_regs_win + RIO_PORT2_ESCSR), ESCSR_CLEAR);
	}
}

static void msg_unit_error_handler(struct rio_mport *port)
{
	struct rio_priv *priv = port->priv;

	/*XXX: Error recovery is not implemented, we just clear errors */
	out_be32((u32 *)(rio_regs_win + RIO_LTLEDCSR), 0);

	out_be32((u32 *)(rio_regs_win + RIO_IM0SR), IMSR_CLEAR);
	out_be32((u32 *)(rio_regs_win + RIO_IM1SR), IMSR_CLEAR);
	out_be32((u32 *)(rio_regs_win + RIO_OM0SR), OMSR_CLEAR);
	out_be32((u32 *)(rio_regs_win + RIO_OM1SR), OMSR_CLEAR);

	out_be32(&priv->msg_regs->odsr, ODSR_CLEAR);
	out_be32(&priv->msg_regs->dsr, IDSR_CLEAR);

	out_be32(&priv->msg_regs->pwsr, IPWSR_CLEAR);
}

1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136
/**
 * fsl_rio_port_write_handler - MPC85xx port write interrupt handler
 * @irq: Linux interrupt number
 * @dev_instance: Pointer to interrupt-specific data
 *
 * Handles port write interrupts. Parses a list of registered
 * port write event handlers and executes a matching event handler.
 */
static irqreturn_t
fsl_rio_port_write_handler(int irq, void *dev_instance)
{
	u32 ipwmr, ipwsr;
	struct rio_mport *port = (struct rio_mport *)dev_instance;
	struct rio_priv *priv = port->priv;
	u32 epwisr, tmp;

	epwisr = in_be32(priv->regs_win + RIO_EPWISR);
1137 1138
	if (!(epwisr & RIO_EPWISR_PW))
		goto pw_done;
1139

1140 1141
	ipwmr = in_be32(&priv->msg_regs->pwmr);
	ipwsr = in_be32(&priv->msg_regs->pwsr);
1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167

#ifdef DEBUG_PW
	pr_debug("PW Int->IPWMR: 0x%08x IPWSR: 0x%08x (", ipwmr, ipwsr);
	if (ipwsr & RIO_IPWSR_QF)
		pr_debug(" QF");
	if (ipwsr & RIO_IPWSR_TE)
		pr_debug(" TE");
	if (ipwsr & RIO_IPWSR_QFI)
		pr_debug(" QFI");
	if (ipwsr & RIO_IPWSR_PWD)
		pr_debug(" PWD");
	if (ipwsr & RIO_IPWSR_PWB)
		pr_debug(" PWB");
	pr_debug(" )\n");
#endif
	/* Schedule deferred processing if PW was received */
	if (ipwsr & RIO_IPWSR_QFI) {
		/* Save PW message (if there is room in FIFO),
		 * otherwise discard it.
		 */
		if (kfifo_avail(&priv->pw_fifo) >= RIO_PW_MSG_SIZE) {
			priv->port_write_msg.msg_count++;
			kfifo_in(&priv->pw_fifo, priv->port_write_msg.virt,
				 RIO_PW_MSG_SIZE);
		} else {
			priv->port_write_msg.discard_count++;
1168
			pr_debug("RIO: ISR Discarded Port-Write Msg(s) (%d)\n",
1169 1170
				 priv->port_write_msg.discard_count);
		}
1171 1172 1173 1174 1175 1176
		/* Clear interrupt and issue Clear Queue command. This allows
		 * another port-write to be received.
		 */
		out_be32(&priv->msg_regs->pwsr,	RIO_IPWSR_QFI);
		out_be32(&priv->msg_regs->pwmr, ipwmr | RIO_IPWMR_CQ);

1177 1178 1179
		schedule_work(&priv->pw_work);
	}

1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199
	if ((ipwmr & RIO_IPWMR_EIE) && (ipwsr & RIO_IPWSR_TE)) {
		priv->port_write_msg.err_count++;
		pr_debug("RIO: Port-Write Transaction Err (%d)\n",
			 priv->port_write_msg.err_count);
		/* Clear Transaction Error: port-write controller should be
		 * disabled when clearing this error
		 */
		out_be32(&priv->msg_regs->pwmr, ipwmr & ~RIO_IPWMR_PWE);
		out_be32(&priv->msg_regs->pwsr,	RIO_IPWSR_TE);
		out_be32(&priv->msg_regs->pwmr, ipwmr);
	}

	if (ipwsr & RIO_IPWSR_PWD) {
		priv->port_write_msg.discard_count++;
		pr_debug("RIO: Port Discarded Port-Write Msg(s) (%d)\n",
			 priv->port_write_msg.discard_count);
		out_be32(&priv->msg_regs->pwsr, RIO_IPWSR_PWD);
	}

pw_done:
1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212
	if (epwisr & RIO_EPWISR_PINT1) {
		tmp = in_be32(priv->regs_win + RIO_LTLEDCSR);
		pr_debug("RIO_LTLEDCSR = 0x%x\n", tmp);
		port_error_handler(port, 0);
	}

	if (epwisr & RIO_EPWISR_PINT2) {
		tmp = in_be32(priv->regs_win + RIO_LTLEDCSR);
		pr_debug("RIO_LTLEDCSR = 0x%x\n", tmp);
		port_error_handler(port, 1);
	}

	if (epwisr & RIO_EPWISR_MU) {
1213 1214
		tmp = in_be32(priv->regs_win + RIO_LTLEDCSR);
		pr_debug("RIO_LTLEDCSR = 0x%x\n", tmp);
1215
		msg_unit_error_handler(port);
1216
	}
1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325

	return IRQ_HANDLED;
}

static void fsl_pw_dpc(struct work_struct *work)
{
	struct rio_priv *priv = container_of(work, struct rio_priv, pw_work);
	unsigned long flags;
	u32 msg_buffer[RIO_PW_MSG_SIZE/sizeof(u32)];

	/*
	 * Process port-write messages
	 */
	spin_lock_irqsave(&priv->pw_fifo_lock, flags);
	while (kfifo_out(&priv->pw_fifo, (unsigned char *)msg_buffer,
			 RIO_PW_MSG_SIZE)) {
		/* Process one message */
		spin_unlock_irqrestore(&priv->pw_fifo_lock, flags);
#ifdef DEBUG_PW
		{
		u32 i;
		pr_debug("%s : Port-Write Message:", __func__);
		for (i = 0; i < RIO_PW_MSG_SIZE/sizeof(u32); i++) {
			if ((i%4) == 0)
				pr_debug("\n0x%02x: 0x%08x", i*4,
					 msg_buffer[i]);
			else
				pr_debug(" 0x%08x", msg_buffer[i]);
		}
		pr_debug("\n");
		}
#endif
		/* Pass the port-write message to RIO core for processing */
		rio_inb_pwrite_handler((union rio_pw_msg *)msg_buffer);
		spin_lock_irqsave(&priv->pw_fifo_lock, flags);
	}
	spin_unlock_irqrestore(&priv->pw_fifo_lock, flags);
}

/**
 * fsl_rio_pw_enable - enable/disable port-write interface init
 * @mport: Master port implementing the port write unit
 * @enable:    1=enable; 0=disable port-write message handling
 */
static int fsl_rio_pw_enable(struct rio_mport *mport, int enable)
{
	struct rio_priv *priv = mport->priv;
	u32 rval;

	rval = in_be32(&priv->msg_regs->pwmr);

	if (enable)
		rval |= RIO_IPWMR_PWE;
	else
		rval &= ~RIO_IPWMR_PWE;

	out_be32(&priv->msg_regs->pwmr, rval);

	return 0;
}

/**
 * fsl_rio_port_write_init - MPC85xx port write interface init
 * @mport: Master port implementing the port write unit
 *
 * Initializes port write unit hardware and DMA buffer
 * ring. Called from fsl_rio_setup(). Returns %0 on success
 * or %-ENOMEM on failure.
 */
static int fsl_rio_port_write_init(struct rio_mport *mport)
{
	struct rio_priv *priv = mport->priv;
	int rc = 0;

	/* Following configurations require a disabled port write controller */
	out_be32(&priv->msg_regs->pwmr,
		 in_be32(&priv->msg_regs->pwmr) & ~RIO_IPWMR_PWE);

	/* Initialize port write */
	priv->port_write_msg.virt = dma_alloc_coherent(priv->dev,
					RIO_PW_MSG_SIZE,
					&priv->port_write_msg.phys, GFP_KERNEL);
	if (!priv->port_write_msg.virt) {
		pr_err("RIO: unable allocate port write queue\n");
		return -ENOMEM;
	}

	priv->port_write_msg.err_count = 0;
	priv->port_write_msg.discard_count = 0;

	/* Point dequeue/enqueue pointers at first entry */
	out_be32(&priv->msg_regs->epwqbar, 0);
	out_be32(&priv->msg_regs->pwqbar, (u32) priv->port_write_msg.phys);

	pr_debug("EIPWQBAR: 0x%08x IPWQBAR: 0x%08x\n",
		 in_be32(&priv->msg_regs->epwqbar),
		 in_be32(&priv->msg_regs->pwqbar));

	/* Clear interrupt status IPWSR */
	out_be32(&priv->msg_regs->pwsr,
		 (RIO_IPWSR_TE | RIO_IPWSR_QFI | RIO_IPWSR_PWD));

	/* Configure port write contoller for snooping enable all reporting,
	   clear queue full */
	out_be32(&priv->msg_regs->pwmr,
		 RIO_IPWMR_SEN | RIO_IPWMR_QFIE | RIO_IPWMR_EIE | RIO_IPWMR_CQ);


	/* Hook up port-write handler */
1326 1327
	rc = request_irq(IRQ_RIO_PW(mport), fsl_rio_port_write_handler,
			IRQF_SHARED, "port-write", (void *)mport);
1328 1329 1330 1331
	if (rc < 0) {
		pr_err("MPC85xx RIO: unable to request inbound doorbell irq");
		goto err_out;
	}
1332 1333
	/* Enable Error Interrupt */
	out_be32((u32 *)(rio_regs_win + RIO_LTLEECSR), LTLEECSR_ENABLE_ALL);
1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357

	INIT_WORK(&priv->pw_work, fsl_pw_dpc);
	spin_lock_init(&priv->pw_fifo_lock);
	if (kfifo_alloc(&priv->pw_fifo, RIO_PW_MSG_SIZE * 32, GFP_KERNEL)) {
		pr_err("FIFO allocation failed\n");
		rc = -ENOMEM;
		goto err_out_irq;
	}

	pr_debug("IPWMR: 0x%08x IPWSR: 0x%08x\n",
		 in_be32(&priv->msg_regs->pwmr),
		 in_be32(&priv->msg_regs->pwsr));

	return rc;

err_out_irq:
	free_irq(IRQ_RIO_PW(mport), (void *)mport);
err_out:
	dma_free_coherent(priv->dev, RIO_PW_MSG_SIZE,
			  priv->port_write_msg.virt,
			  priv->port_write_msg.phys);
	return rc;
}

1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371
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";
1372
			break;
1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399
		}
		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 已提交
1400
/**
1401
 * fsl_rio_setup - Setup Freescale PowerPC RapidIO interface
1402
 * @dev: platform_device pointer
M
Matt Porter 已提交
1403 1404 1405 1406 1407
 *
 * Initializes MPC85xx RapidIO hardware interface, configures
 * master port with system-specific info, and registers the
 * master port with the RapidIO subsystem.
 */
1408
int fsl_rio_setup(struct platform_device *dev)
M
Matt Porter 已提交
1409 1410 1411
{
	struct rio_ops *ops;
	struct rio_mport *port;
1412 1413 1414 1415 1416
	struct rio_priv *priv;
	int rc = 0;
	const u32 *dt_range, *cell;
	struct resource regs;
	int rlen;
1417
	u32 ccsr;
1418 1419 1420
	u64 law_start, law_size;
	int paw, aw, sw;

1421
	if (!dev->dev.of_node) {
1422 1423 1424 1425
		dev_err(&dev->dev, "Device OF-Node is NULL");
		return -EFAULT;
	}

1426
	rc = of_address_to_resource(dev->dev.of_node, 0, &regs);
1427 1428
	if (rc) {
		dev_err(&dev->dev, "Can't get %s property 'reg'\n",
1429
				dev->dev.of_node->full_name);
1430 1431
		return -EFAULT;
	}
1432
	dev_info(&dev->dev, "Of-device full name %s\n", dev->dev.of_node->full_name);
1433
	dev_info(&dev->dev, "Regs: %pR\n", &regs);
1434

1435
	dt_range = of_get_property(dev->dev.of_node, "ranges", &rlen);
1436 1437
	if (!dt_range) {
		dev_err(&dev->dev, "Can't get %s property 'ranges'\n",
1438
				dev->dev.of_node->full_name);
1439 1440 1441 1442
		return -EFAULT;
	}

	/* Get node address wide */
1443
	cell = of_get_property(dev->dev.of_node, "#address-cells", NULL);
1444 1445 1446
	if (cell)
		aw = *cell;
	else
1447
		aw = of_n_addr_cells(dev->dev.of_node);
1448
	/* Get node size wide */
1449
	cell = of_get_property(dev->dev.of_node, "#size-cells", NULL);
1450 1451 1452
	if (cell)
		sw = *cell;
	else
1453
		sw = of_n_size_cells(dev->dev.of_node);
1454
	/* Get parent address wide wide */
1455
	paw = of_n_addr_cells(dev->dev.of_node);
1456 1457 1458 1459 1460 1461

	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 已提交
1462

1463
	ops = kzalloc(sizeof(struct rio_ops), GFP_KERNEL);
1464 1465 1466 1467
	if (!ops) {
		rc = -ENOMEM;
		goto err_ops;
	}
1468 1469 1470 1471 1472
	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;
1473
	ops->pwenable = fsl_rio_pw_enable;
1474 1475 1476 1477 1478 1479 1480
	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;
M
Matt Porter 已提交
1481

1482
	port = kzalloc(sizeof(struct rio_mport), GFP_KERNEL);
1483 1484 1485 1486
	if (!port) {
		rc = -ENOMEM;
		goto err_port;
	}
M
Matt Porter 已提交
1487
	port->index = 0;
1488 1489 1490 1491 1492

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

M
Matt Porter 已提交
1496 1497
	INIT_LIST_HEAD(&port->dbells);
	port->iores.start = law_start;
1498
	port->iores.end = law_start + law_size - 1;
M
Matt Porter 已提交
1499
	port->iores.flags = IORESOURCE_MEM;
1500
	port->iores.name = "rio_io_win";
M
Matt Porter 已提交
1501

1502 1503 1504 1505 1506 1507 1508 1509
	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);
			rc = -ENOMEM;
			goto err_res;
	}

1510
	priv->pwirq   = irq_of_parse_and_map(dev->dev.of_node, 0);
1511 1512 1513
	priv->bellirq = irq_of_parse_and_map(dev->dev.of_node, 2);
	priv->txirq = irq_of_parse_and_map(dev->dev.of_node, 3);
	priv->rxirq = irq_of_parse_and_map(dev->dev.of_node, 4);
1514 1515
	dev_info(&dev->dev, "pwirq: %d, bellirq: %d, txirq: %d, rxirq %d\n",
		 priv->pwirq, priv->bellirq, priv->txirq, priv->rxirq);
1516

M
Matt Porter 已提交
1517 1518 1519 1520 1521
	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");

1522 1523
	priv->dev = &dev->dev;

M
Matt Porter 已提交
1524
	port->ops = ops;
1525
	port->priv = priv;
1526
	port->phys_efptr = 0x100;
M
Matt Porter 已提交
1527

1528
	priv->regs_win = ioremap(regs.start, resource_size(&regs));
1529
	rio_regs_win = priv->regs_win;
1530

1531 1532 1533 1534 1535 1536 1537
	/* 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"));
1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566
	/* 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);
1567

1568 1569 1570 1571 1572
	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);

1573 1574 1575
	if (rio_register_mport(port))
		goto err;

1576 1577 1578 1579 1580 1581
	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, 0x00000000);

1582 1583 1584 1585
	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;
1586 1587 1588 1589 1590 1591 1592
	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 已提交
1593 1594

	/* Configure maintenance transaction window */
1595
	out_be32(&priv->maint_atmu_regs->rowbar, law_start >> 12);
1596 1597
	out_be32(&priv->maint_atmu_regs->rowar,
		 0x80077000 | (ilog2(RIO_MAINT_WIN_SIZE) - 1));
M
Matt Porter 已提交
1598

1599
	priv->maint_win = ioremap(law_start, RIO_MAINT_WIN_SIZE);
M
Matt Porter 已提交
1600 1601

	/* Configure outbound doorbell window */
1602 1603 1604
	out_be32(&priv->dbell_atmu_regs->rowbar,
			(law_start + RIO_MAINT_WIN_SIZE) >> 12);
	out_be32(&priv->dbell_atmu_regs->rowar, 0x8004200b);	/* 4k */
1605
	fsl_rio_doorbell_init(port);
1606
	fsl_rio_port_write_init(port);
1607

1608
	return 0;
1609
err:
1610
	iounmap(priv->regs_win);
1611
	release_resource(&port->iores);
1612
err_res:
1613
	kfree(priv);
1614
err_priv:
1615
	kfree(port);
1616 1617 1618
err_port:
	kfree(ops);
err_ops:
1619
	return rc;
M
Matt Porter 已提交
1620
}
1621 1622 1623

/* The probe function for RapidIO peer-to-peer network.
 */
1624
static int __devinit fsl_of_rio_rpn_probe(struct platform_device *dev)
1625 1626
{
	printk(KERN_INFO "Setting up RapidIO peer-to-peer network %s\n",
1627
			dev->dev.of_node->full_name);
1628

1629
	return fsl_rio_setup(dev);
1630 1631 1632 1633 1634 1635 1636 1637 1638
};

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

1639
static struct platform_driver fsl_of_rio_rpn_driver = {
1640 1641 1642 1643 1644
	.driver = {
		.name = "fsl-of-rio",
		.owner = THIS_MODULE,
		.of_match_table = fsl_of_rio_rpn_ids,
	},
1645 1646 1647 1648 1649
	.probe = fsl_of_rio_rpn_probe,
};

static __init int fsl_of_rio_rpn_init(void)
{
1650
	return platform_driver_register(&fsl_of_rio_rpn_driver);
1651 1652 1653
}

subsys_initcall(fsl_of_rio_rpn_init);