xref: /openbmc/linux/arch/powerpc/sysdev/fsl_rmu.c (revision 750afb08ca71310fcf0c4e2cb1565c63b8235b60)
16ec4bedbSLiu Gang /*
26ec4bedbSLiu Gang  * Freescale MPC85xx/MPC86xx RapidIO RMU support
36ec4bedbSLiu Gang  *
46ec4bedbSLiu Gang  * Copyright 2009 Sysgo AG
56ec4bedbSLiu Gang  * Thomas Moll <thomas.moll@sysgo.com>
66ec4bedbSLiu Gang  * - fixed maintenance access routines, check for aligned access
76ec4bedbSLiu Gang  *
86ec4bedbSLiu Gang  * Copyright 2009 Integrated Device Technology, Inc.
96ec4bedbSLiu Gang  * Alex Bounine <alexandre.bounine@idt.com>
106ec4bedbSLiu Gang  * - Added Port-Write message handling
116ec4bedbSLiu Gang  * - Added Machine Check exception handling
126ec4bedbSLiu Gang  *
136ec4bedbSLiu Gang  * Copyright (C) 2007, 2008, 2010, 2011 Freescale Semiconductor, Inc.
146ec4bedbSLiu Gang  * Zhang Wei <wei.zhang@freescale.com>
156ec4bedbSLiu Gang  * Lian Minghuan-B31939 <Minghuan.Lian@freescale.com>
166ec4bedbSLiu Gang  * Liu Gang <Gang.Liu@freescale.com>
176ec4bedbSLiu Gang  *
186ec4bedbSLiu Gang  * Copyright 2005 MontaVista Software, Inc.
196ec4bedbSLiu Gang  * Matt Porter <mporter@kernel.crashing.org>
206ec4bedbSLiu Gang  *
216ec4bedbSLiu Gang  * This program is free software; you can redistribute  it and/or modify it
226ec4bedbSLiu Gang  * under  the terms of  the GNU General  Public License as published by the
236ec4bedbSLiu Gang  * Free Software Foundation;  either version 2 of the  License, or (at your
246ec4bedbSLiu Gang  * option) any later version.
256ec4bedbSLiu Gang  */
266ec4bedbSLiu Gang 
276ec4bedbSLiu Gang #include <linux/types.h>
286ec4bedbSLiu Gang #include <linux/dma-mapping.h>
296ec4bedbSLiu Gang #include <linux/interrupt.h>
3026a2056eSRob Herring #include <linux/of_irq.h>
316ec4bedbSLiu Gang #include <linux/of_platform.h>
326ec4bedbSLiu Gang #include <linux/slab.h>
336ec4bedbSLiu Gang 
346ec4bedbSLiu Gang #include "fsl_rio.h"
356ec4bedbSLiu Gang 
366ec4bedbSLiu Gang #define GET_RMM_HANDLE(mport) \
376ec4bedbSLiu Gang 		(((struct rio_priv *)(mport->priv))->rmm_handle)
386ec4bedbSLiu Gang 
396ec4bedbSLiu Gang /* RapidIO definition irq, which read from OF-tree */
40abc3aeaeSLiu Gang #define IRQ_RIO_PW(m)		(((struct fsl_rio_pw *)(m))->pwirq)
41abc3aeaeSLiu Gang #define IRQ_RIO_BELL(m) (((struct fsl_rio_dbell *)(m))->bellirq)
426ec4bedbSLiu Gang #define IRQ_RIO_TX(m) (((struct fsl_rmu *)(GET_RMM_HANDLE(m)))->txirq)
436ec4bedbSLiu Gang #define IRQ_RIO_RX(m) (((struct fsl_rmu *)(GET_RMM_HANDLE(m)))->rxirq)
446ec4bedbSLiu Gang 
456ec4bedbSLiu Gang #define RIO_MIN_TX_RING_SIZE	2
466ec4bedbSLiu Gang #define RIO_MAX_TX_RING_SIZE	2048
476ec4bedbSLiu Gang #define RIO_MIN_RX_RING_SIZE	2
486ec4bedbSLiu Gang #define RIO_MAX_RX_RING_SIZE	2048
496ec4bedbSLiu Gang 
506ec4bedbSLiu Gang #define RIO_IPWMR_SEN		0x00100000
516ec4bedbSLiu Gang #define RIO_IPWMR_QFIE		0x00000100
526ec4bedbSLiu Gang #define RIO_IPWMR_EIE		0x00000020
536ec4bedbSLiu Gang #define RIO_IPWMR_CQ		0x00000002
546ec4bedbSLiu Gang #define RIO_IPWMR_PWE		0x00000001
556ec4bedbSLiu Gang 
566ec4bedbSLiu Gang #define RIO_IPWSR_QF		0x00100000
576ec4bedbSLiu Gang #define RIO_IPWSR_TE		0x00000080
586ec4bedbSLiu Gang #define RIO_IPWSR_QFI		0x00000010
596ec4bedbSLiu Gang #define RIO_IPWSR_PWD		0x00000008
606ec4bedbSLiu Gang #define RIO_IPWSR_PWB		0x00000004
616ec4bedbSLiu Gang 
626ec4bedbSLiu Gang #define RIO_EPWISR		0x10010
636ec4bedbSLiu Gang /* EPWISR Error match value */
646ec4bedbSLiu Gang #define RIO_EPWISR_PINT1	0x80000000
656ec4bedbSLiu Gang #define RIO_EPWISR_PINT2	0x40000000
666ec4bedbSLiu Gang #define RIO_EPWISR_MU		0x00000002
676ec4bedbSLiu Gang #define RIO_EPWISR_PW		0x00000001
686ec4bedbSLiu Gang 
696ec4bedbSLiu Gang #define IPWSR_CLEAR		0x98
706ec4bedbSLiu Gang #define OMSR_CLEAR		0x1cb3
716ec4bedbSLiu Gang #define IMSR_CLEAR		0x491
726ec4bedbSLiu Gang #define IDSR_CLEAR		0x91
736ec4bedbSLiu Gang #define ODSR_CLEAR		0x1c00
746ec4bedbSLiu Gang #define LTLEECSR_ENABLE_ALL	0xFFC000FC
756ec4bedbSLiu Gang #define RIO_LTLEECSR		0x060c
766ec4bedbSLiu Gang 
77abc3aeaeSLiu Gang #define RIO_IM0SR		0x64
78abc3aeaeSLiu Gang #define RIO_IM1SR		0x164
79abc3aeaeSLiu Gang #define RIO_OM0SR		0x4
80abc3aeaeSLiu Gang #define RIO_OM1SR		0x104
816ec4bedbSLiu Gang 
826ec4bedbSLiu Gang #define RIO_DBELL_WIN_SIZE	0x1000
836ec4bedbSLiu Gang 
846ec4bedbSLiu Gang #define RIO_MSG_OMR_MUI		0x00000002
856ec4bedbSLiu Gang #define RIO_MSG_OSR_TE		0x00000080
866ec4bedbSLiu Gang #define RIO_MSG_OSR_QOI		0x00000020
876ec4bedbSLiu Gang #define RIO_MSG_OSR_QFI		0x00000010
886ec4bedbSLiu Gang #define RIO_MSG_OSR_MUB		0x00000004
896ec4bedbSLiu Gang #define RIO_MSG_OSR_EOMI	0x00000002
906ec4bedbSLiu Gang #define RIO_MSG_OSR_QEI		0x00000001
916ec4bedbSLiu Gang 
926ec4bedbSLiu Gang #define RIO_MSG_IMR_MI		0x00000002
936ec4bedbSLiu Gang #define RIO_MSG_ISR_TE		0x00000080
946ec4bedbSLiu Gang #define RIO_MSG_ISR_QFI		0x00000010
956ec4bedbSLiu Gang #define RIO_MSG_ISR_DIQI	0x00000001
966ec4bedbSLiu Gang 
976ec4bedbSLiu Gang #define RIO_MSG_DESC_SIZE	32
986ec4bedbSLiu Gang #define RIO_MSG_BUFFER_SIZE	4096
996ec4bedbSLiu Gang 
1006ec4bedbSLiu Gang #define DOORBELL_DMR_DI		0x00000002
1016ec4bedbSLiu Gang #define DOORBELL_DSR_TE		0x00000080
1026ec4bedbSLiu Gang #define DOORBELL_DSR_QFI	0x00000010
1036ec4bedbSLiu Gang #define DOORBELL_DSR_DIQI	0x00000001
1046ec4bedbSLiu Gang 
1056ec4bedbSLiu Gang #define DOORBELL_MESSAGE_SIZE	0x08
1066ec4bedbSLiu Gang 
10731d1e130SIoan Nicu static DEFINE_SPINLOCK(fsl_rio_doorbell_lock);
10831d1e130SIoan Nicu 
1096ec4bedbSLiu Gang struct rio_msg_regs {
110abc3aeaeSLiu Gang 	u32 omr;
111abc3aeaeSLiu Gang 	u32 osr;
1126ec4bedbSLiu Gang 	u32 pad1;
113abc3aeaeSLiu Gang 	u32 odqdpar;
1146ec4bedbSLiu Gang 	u32 pad2;
115abc3aeaeSLiu Gang 	u32 osar;
116abc3aeaeSLiu Gang 	u32 odpr;
117abc3aeaeSLiu Gang 	u32 odatr;
118abc3aeaeSLiu Gang 	u32 odcr;
1196ec4bedbSLiu Gang 	u32 pad3;
120abc3aeaeSLiu Gang 	u32 odqepar;
1216ec4bedbSLiu Gang 	u32 pad4[13];
122abc3aeaeSLiu Gang 	u32 imr;
123abc3aeaeSLiu Gang 	u32 isr;
1246ec4bedbSLiu Gang 	u32 pad5;
125abc3aeaeSLiu Gang 	u32 ifqdpar;
1266ec4bedbSLiu Gang 	u32 pad6;
127abc3aeaeSLiu Gang 	u32 ifqepar;
1286ec4bedbSLiu Gang };
1296ec4bedbSLiu Gang 
130abc3aeaeSLiu Gang struct rio_dbell_regs {
131abc3aeaeSLiu Gang 	u32 odmr;
132abc3aeaeSLiu Gang 	u32 odsr;
133abc3aeaeSLiu Gang 	u32 pad1[4];
134abc3aeaeSLiu Gang 	u32 oddpr;
135abc3aeaeSLiu Gang 	u32 oddatr;
136abc3aeaeSLiu Gang 	u32 pad2[3];
137abc3aeaeSLiu Gang 	u32 odretcr;
138abc3aeaeSLiu Gang 	u32 pad3[12];
139abc3aeaeSLiu Gang 	u32 dmr;
140abc3aeaeSLiu Gang 	u32 dsr;
141abc3aeaeSLiu Gang 	u32 pad4;
142abc3aeaeSLiu Gang 	u32 dqdpar;
143abc3aeaeSLiu Gang 	u32 pad5;
144abc3aeaeSLiu Gang 	u32 dqepar;
145abc3aeaeSLiu Gang };
146abc3aeaeSLiu Gang 
147abc3aeaeSLiu Gang struct rio_pw_regs {
148abc3aeaeSLiu Gang 	u32 pwmr;
149abc3aeaeSLiu Gang 	u32 pwsr;
150abc3aeaeSLiu Gang 	u32 epwqbar;
151abc3aeaeSLiu Gang 	u32 pwqbar;
152abc3aeaeSLiu Gang };
153abc3aeaeSLiu Gang 
154abc3aeaeSLiu Gang 
1556ec4bedbSLiu Gang struct rio_tx_desc {
156abc3aeaeSLiu Gang 	u32 pad1;
1576ec4bedbSLiu Gang 	u32 saddr;
1586ec4bedbSLiu Gang 	u32 dport;
1596ec4bedbSLiu Gang 	u32 dattr;
160abc3aeaeSLiu Gang 	u32 pad2;
161abc3aeaeSLiu Gang 	u32 pad3;
1626ec4bedbSLiu Gang 	u32 dwcnt;
163abc3aeaeSLiu Gang 	u32 pad4;
1646ec4bedbSLiu Gang };
1656ec4bedbSLiu Gang 
1666ec4bedbSLiu Gang struct rio_msg_tx_ring {
1676ec4bedbSLiu Gang 	void *virt;
1686ec4bedbSLiu Gang 	dma_addr_t phys;
1696ec4bedbSLiu Gang 	void *virt_buffer[RIO_MAX_TX_RING_SIZE];
1706ec4bedbSLiu Gang 	dma_addr_t phys_buffer[RIO_MAX_TX_RING_SIZE];
1716ec4bedbSLiu Gang 	int tx_slot;
1726ec4bedbSLiu Gang 	int size;
1736ec4bedbSLiu Gang 	void *dev_id;
1746ec4bedbSLiu Gang };
1756ec4bedbSLiu Gang 
1766ec4bedbSLiu Gang struct rio_msg_rx_ring {
1776ec4bedbSLiu Gang 	void *virt;
1786ec4bedbSLiu Gang 	dma_addr_t phys;
1796ec4bedbSLiu Gang 	void *virt_buffer[RIO_MAX_RX_RING_SIZE];
1806ec4bedbSLiu Gang 	int rx_slot;
1816ec4bedbSLiu Gang 	int size;
1826ec4bedbSLiu Gang 	void *dev_id;
1836ec4bedbSLiu Gang };
1846ec4bedbSLiu Gang 
1856ec4bedbSLiu Gang struct fsl_rmu {
1866ec4bedbSLiu Gang 	struct rio_msg_regs __iomem *msg_regs;
1876ec4bedbSLiu Gang 	struct rio_msg_tx_ring msg_tx_ring;
1886ec4bedbSLiu Gang 	struct rio_msg_rx_ring msg_rx_ring;
1896ec4bedbSLiu Gang 	int txirq;
1906ec4bedbSLiu Gang 	int rxirq;
1916ec4bedbSLiu Gang };
1926ec4bedbSLiu Gang 
1932a2383daSLiu Gang struct rio_dbell_msg {
1942a2383daSLiu Gang 	u16 pad1;
1952a2383daSLiu Gang 	u16 tid;
1962a2383daSLiu Gang 	u16 sid;
1972a2383daSLiu Gang 	u16 info;
1982a2383daSLiu Gang };
1992a2383daSLiu Gang 
2006ec4bedbSLiu Gang /**
2016ec4bedbSLiu Gang  * fsl_rio_tx_handler - MPC85xx outbound message interrupt handler
2026ec4bedbSLiu Gang  * @irq: Linux interrupt number
2036ec4bedbSLiu Gang  * @dev_instance: Pointer to interrupt-specific data
2046ec4bedbSLiu Gang  *
2056ec4bedbSLiu Gang  * Handles outbound message interrupts. Executes a register outbound
2066ec4bedbSLiu Gang  * mailbox event handler and acks the interrupt occurrence.
2076ec4bedbSLiu Gang  */
2086ec4bedbSLiu Gang static irqreturn_t
2096ec4bedbSLiu Gang fsl_rio_tx_handler(int irq, void *dev_instance)
2106ec4bedbSLiu Gang {
2116ec4bedbSLiu Gang 	int osr;
2126ec4bedbSLiu Gang 	struct rio_mport *port = (struct rio_mport *)dev_instance;
2136ec4bedbSLiu Gang 	struct fsl_rmu *rmu = GET_RMM_HANDLE(port);
2146ec4bedbSLiu Gang 
2156ec4bedbSLiu Gang 	osr = in_be32(&rmu->msg_regs->osr);
2166ec4bedbSLiu Gang 
2176ec4bedbSLiu Gang 	if (osr & RIO_MSG_OSR_TE) {
2186ec4bedbSLiu Gang 		pr_info("RIO: outbound message transmission error\n");
2196ec4bedbSLiu Gang 		out_be32(&rmu->msg_regs->osr, RIO_MSG_OSR_TE);
2206ec4bedbSLiu Gang 		goto out;
2216ec4bedbSLiu Gang 	}
2226ec4bedbSLiu Gang 
2236ec4bedbSLiu Gang 	if (osr & RIO_MSG_OSR_QOI) {
2246ec4bedbSLiu Gang 		pr_info("RIO: outbound message queue overflow\n");
2256ec4bedbSLiu Gang 		out_be32(&rmu->msg_regs->osr, RIO_MSG_OSR_QOI);
2266ec4bedbSLiu Gang 		goto out;
2276ec4bedbSLiu Gang 	}
2286ec4bedbSLiu Gang 
2296ec4bedbSLiu Gang 	if (osr & RIO_MSG_OSR_EOMI) {
2306ec4bedbSLiu Gang 		u32 dqp = in_be32(&rmu->msg_regs->odqdpar);
2316ec4bedbSLiu Gang 		int slot = (dqp - rmu->msg_tx_ring.phys) >> 5;
232abc3aeaeSLiu Gang 		if (port->outb_msg[0].mcback != NULL) {
233abc3aeaeSLiu Gang 			port->outb_msg[0].mcback(port, rmu->msg_tx_ring.dev_id,
234abc3aeaeSLiu Gang 					-1,
2356ec4bedbSLiu Gang 					slot);
236abc3aeaeSLiu Gang 		}
2376ec4bedbSLiu Gang 		/* Ack the end-of-message interrupt */
2386ec4bedbSLiu Gang 		out_be32(&rmu->msg_regs->osr, RIO_MSG_OSR_EOMI);
2396ec4bedbSLiu Gang 	}
2406ec4bedbSLiu Gang 
2416ec4bedbSLiu Gang out:
2426ec4bedbSLiu Gang 	return IRQ_HANDLED;
2436ec4bedbSLiu Gang }
2446ec4bedbSLiu Gang 
2456ec4bedbSLiu Gang /**
2466ec4bedbSLiu Gang  * fsl_rio_rx_handler - MPC85xx inbound message interrupt handler
2476ec4bedbSLiu Gang  * @irq: Linux interrupt number
2486ec4bedbSLiu Gang  * @dev_instance: Pointer to interrupt-specific data
2496ec4bedbSLiu Gang  *
2506ec4bedbSLiu Gang  * Handles inbound message interrupts. Executes a registered inbound
2516ec4bedbSLiu Gang  * mailbox event handler and acks the interrupt occurrence.
2526ec4bedbSLiu Gang  */
2536ec4bedbSLiu Gang static irqreturn_t
2546ec4bedbSLiu Gang fsl_rio_rx_handler(int irq, void *dev_instance)
2556ec4bedbSLiu Gang {
2566ec4bedbSLiu Gang 	int isr;
2576ec4bedbSLiu Gang 	struct rio_mport *port = (struct rio_mport *)dev_instance;
2586ec4bedbSLiu Gang 	struct fsl_rmu *rmu = GET_RMM_HANDLE(port);
2596ec4bedbSLiu Gang 
2606ec4bedbSLiu Gang 	isr = in_be32(&rmu->msg_regs->isr);
2616ec4bedbSLiu Gang 
2626ec4bedbSLiu Gang 	if (isr & RIO_MSG_ISR_TE) {
2636ec4bedbSLiu Gang 		pr_info("RIO: inbound message reception error\n");
2646ec4bedbSLiu Gang 		out_be32((void *)&rmu->msg_regs->isr, RIO_MSG_ISR_TE);
2656ec4bedbSLiu Gang 		goto out;
2666ec4bedbSLiu Gang 	}
2676ec4bedbSLiu Gang 
2686ec4bedbSLiu Gang 	/* XXX Need to check/dispatch until queue empty */
2696ec4bedbSLiu Gang 	if (isr & RIO_MSG_ISR_DIQI) {
2706ec4bedbSLiu Gang 		/*
271abc3aeaeSLiu Gang 		* Can receive messages for any mailbox/letter to that
272abc3aeaeSLiu Gang 		* mailbox destination. So, make the callback with an
273abc3aeaeSLiu Gang 		* unknown/invalid mailbox number argument.
2746ec4bedbSLiu Gang 		*/
275abc3aeaeSLiu Gang 		if (port->inb_msg[0].mcback != NULL)
276abc3aeaeSLiu Gang 			port->inb_msg[0].mcback(port, rmu->msg_rx_ring.dev_id,
277abc3aeaeSLiu Gang 				-1,
278abc3aeaeSLiu Gang 				-1);
2796ec4bedbSLiu Gang 
2806ec4bedbSLiu Gang 		/* Ack the queueing interrupt */
2816ec4bedbSLiu Gang 		out_be32(&rmu->msg_regs->isr, RIO_MSG_ISR_DIQI);
2826ec4bedbSLiu Gang 	}
2836ec4bedbSLiu Gang 
2846ec4bedbSLiu Gang out:
2856ec4bedbSLiu Gang 	return IRQ_HANDLED;
2866ec4bedbSLiu Gang }
2876ec4bedbSLiu Gang 
2886ec4bedbSLiu Gang /**
2896ec4bedbSLiu Gang  * fsl_rio_dbell_handler - MPC85xx doorbell interrupt handler
2906ec4bedbSLiu Gang  * @irq: Linux interrupt number
2916ec4bedbSLiu Gang  * @dev_instance: Pointer to interrupt-specific data
2926ec4bedbSLiu Gang  *
2936ec4bedbSLiu Gang  * Handles doorbell interrupts. Parses a list of registered
2946ec4bedbSLiu Gang  * doorbell event handlers and executes a matching event handler.
2956ec4bedbSLiu Gang  */
2966ec4bedbSLiu Gang static irqreturn_t
2976ec4bedbSLiu Gang fsl_rio_dbell_handler(int irq, void *dev_instance)
2986ec4bedbSLiu Gang {
2996ec4bedbSLiu Gang 	int dsr;
300abc3aeaeSLiu Gang 	struct fsl_rio_dbell *fsl_dbell = (struct fsl_rio_dbell *)dev_instance;
301abc3aeaeSLiu Gang 	int i;
3026ec4bedbSLiu Gang 
303abc3aeaeSLiu Gang 	dsr = in_be32(&fsl_dbell->dbell_regs->dsr);
3046ec4bedbSLiu Gang 
3056ec4bedbSLiu Gang 	if (dsr & DOORBELL_DSR_TE) {
3066ec4bedbSLiu Gang 		pr_info("RIO: doorbell reception error\n");
307abc3aeaeSLiu Gang 		out_be32(&fsl_dbell->dbell_regs->dsr, DOORBELL_DSR_TE);
3086ec4bedbSLiu Gang 		goto out;
3096ec4bedbSLiu Gang 	}
3106ec4bedbSLiu Gang 
3116ec4bedbSLiu Gang 	if (dsr & DOORBELL_DSR_QFI) {
3126ec4bedbSLiu Gang 		pr_info("RIO: doorbell queue full\n");
313abc3aeaeSLiu Gang 		out_be32(&fsl_dbell->dbell_regs->dsr, DOORBELL_DSR_QFI);
3146ec4bedbSLiu Gang 	}
3156ec4bedbSLiu Gang 
3166ec4bedbSLiu Gang 	/* XXX Need to check/dispatch until queue empty */
3176ec4bedbSLiu Gang 	if (dsr & DOORBELL_DSR_DIQI) {
3182a2383daSLiu Gang 		struct rio_dbell_msg *dmsg =
3192a2383daSLiu Gang 			fsl_dbell->dbell_ring.virt +
320abc3aeaeSLiu Gang 			(in_be32(&fsl_dbell->dbell_regs->dqdpar) & 0xfff);
3216ec4bedbSLiu Gang 		struct rio_dbell *dbell;
3226ec4bedbSLiu Gang 		int found = 0;
3236ec4bedbSLiu Gang 
3246ec4bedbSLiu Gang 		pr_debug
3256ec4bedbSLiu Gang 			("RIO: processing doorbell,"
3266ec4bedbSLiu Gang 			" sid %2.2x tid %2.2x info %4.4x\n",
3272a2383daSLiu Gang 			dmsg->sid, dmsg->tid, dmsg->info);
3286ec4bedbSLiu Gang 
329abc3aeaeSLiu Gang 		for (i = 0; i < MAX_PORT_NUM; i++) {
330abc3aeaeSLiu Gang 			if (fsl_dbell->mport[i]) {
331abc3aeaeSLiu Gang 				list_for_each_entry(dbell,
332abc3aeaeSLiu Gang 					&fsl_dbell->mport[i]->dbells, node) {
333abc3aeaeSLiu Gang 					if ((dbell->res->start
3342a2383daSLiu Gang 						<= dmsg->info)
335abc3aeaeSLiu Gang 						&& (dbell->res->end
3362a2383daSLiu Gang 						>= dmsg->info)) {
3376ec4bedbSLiu Gang 						found = 1;
3386ec4bedbSLiu Gang 						break;
3396ec4bedbSLiu Gang 					}
3406ec4bedbSLiu Gang 				}
341abc3aeaeSLiu Gang 				if (found && dbell->dinb) {
342abc3aeaeSLiu Gang 					dbell->dinb(fsl_dbell->mport[i],
3432a2383daSLiu Gang 						dbell->dev_id, dmsg->sid,
3442a2383daSLiu Gang 						dmsg->tid,
3452a2383daSLiu Gang 						dmsg->info);
346abc3aeaeSLiu Gang 					break;
347abc3aeaeSLiu Gang 				}
348abc3aeaeSLiu Gang 			}
349abc3aeaeSLiu Gang 		}
350abc3aeaeSLiu Gang 
351abc3aeaeSLiu Gang 		if (!found) {
3526ec4bedbSLiu Gang 			pr_debug
3536ec4bedbSLiu Gang 				("RIO: spurious doorbell,"
3546ec4bedbSLiu Gang 				" sid %2.2x tid %2.2x info %4.4x\n",
3552a2383daSLiu Gang 				dmsg->sid, dmsg->tid,
3562a2383daSLiu Gang 				dmsg->info);
3576ec4bedbSLiu Gang 		}
358abc3aeaeSLiu Gang 		setbits32(&fsl_dbell->dbell_regs->dmr, DOORBELL_DMR_DI);
359abc3aeaeSLiu Gang 		out_be32(&fsl_dbell->dbell_regs->dsr, DOORBELL_DSR_DIQI);
3606ec4bedbSLiu Gang 	}
3616ec4bedbSLiu Gang 
3626ec4bedbSLiu Gang out:
3636ec4bedbSLiu Gang 	return IRQ_HANDLED;
3646ec4bedbSLiu Gang }
3656ec4bedbSLiu Gang 
366abc3aeaeSLiu Gang void msg_unit_error_handler(void)
3676ec4bedbSLiu Gang {
3686ec4bedbSLiu Gang 
3696ec4bedbSLiu Gang 	/*XXX: Error recovery is not implemented, we just clear errors */
3706ec4bedbSLiu Gang 	out_be32((u32 *)(rio_regs_win + RIO_LTLEDCSR), 0);
3716ec4bedbSLiu Gang 
372abc3aeaeSLiu Gang 	out_be32((u32 *)(rmu_regs_win + RIO_IM0SR), IMSR_CLEAR);
373abc3aeaeSLiu Gang 	out_be32((u32 *)(rmu_regs_win + RIO_IM1SR), IMSR_CLEAR);
374abc3aeaeSLiu Gang 	out_be32((u32 *)(rmu_regs_win + RIO_OM0SR), OMSR_CLEAR);
375abc3aeaeSLiu Gang 	out_be32((u32 *)(rmu_regs_win + RIO_OM1SR), OMSR_CLEAR);
3766ec4bedbSLiu Gang 
377abc3aeaeSLiu Gang 	out_be32(&dbell->dbell_regs->odsr, ODSR_CLEAR);
378abc3aeaeSLiu Gang 	out_be32(&dbell->dbell_regs->dsr, IDSR_CLEAR);
3796ec4bedbSLiu Gang 
380abc3aeaeSLiu Gang 	out_be32(&pw->pw_regs->pwsr, IPWSR_CLEAR);
3816ec4bedbSLiu Gang }
3826ec4bedbSLiu Gang 
3836ec4bedbSLiu Gang /**
3846ec4bedbSLiu Gang  * fsl_rio_port_write_handler - MPC85xx port write interrupt handler
3856ec4bedbSLiu Gang  * @irq: Linux interrupt number
3866ec4bedbSLiu Gang  * @dev_instance: Pointer to interrupt-specific data
3876ec4bedbSLiu Gang  *
3886ec4bedbSLiu Gang  * Handles port write interrupts. Parses a list of registered
3896ec4bedbSLiu Gang  * port write event handlers and executes a matching event handler.
3906ec4bedbSLiu Gang  */
3916ec4bedbSLiu Gang static irqreturn_t
3926ec4bedbSLiu Gang fsl_rio_port_write_handler(int irq, void *dev_instance)
3936ec4bedbSLiu Gang {
3946ec4bedbSLiu Gang 	u32 ipwmr, ipwsr;
395abc3aeaeSLiu Gang 	struct fsl_rio_pw *pw = (struct fsl_rio_pw *)dev_instance;
3966ec4bedbSLiu Gang 	u32 epwisr, tmp;
3976ec4bedbSLiu Gang 
398abc3aeaeSLiu Gang 	epwisr = in_be32(rio_regs_win + RIO_EPWISR);
3996ec4bedbSLiu Gang 	if (!(epwisr & RIO_EPWISR_PW))
4006ec4bedbSLiu Gang 		goto pw_done;
4016ec4bedbSLiu Gang 
402abc3aeaeSLiu Gang 	ipwmr = in_be32(&pw->pw_regs->pwmr);
403abc3aeaeSLiu Gang 	ipwsr = in_be32(&pw->pw_regs->pwsr);
4046ec4bedbSLiu Gang 
4056ec4bedbSLiu Gang #ifdef DEBUG_PW
4066ec4bedbSLiu Gang 	pr_debug("PW Int->IPWMR: 0x%08x IPWSR: 0x%08x (", ipwmr, ipwsr);
4076ec4bedbSLiu Gang 	if (ipwsr & RIO_IPWSR_QF)
4086ec4bedbSLiu Gang 		pr_debug(" QF");
4096ec4bedbSLiu Gang 	if (ipwsr & RIO_IPWSR_TE)
4106ec4bedbSLiu Gang 		pr_debug(" TE");
4116ec4bedbSLiu Gang 	if (ipwsr & RIO_IPWSR_QFI)
4126ec4bedbSLiu Gang 		pr_debug(" QFI");
4136ec4bedbSLiu Gang 	if (ipwsr & RIO_IPWSR_PWD)
4146ec4bedbSLiu Gang 		pr_debug(" PWD");
4156ec4bedbSLiu Gang 	if (ipwsr & RIO_IPWSR_PWB)
4166ec4bedbSLiu Gang 		pr_debug(" PWB");
4176ec4bedbSLiu Gang 	pr_debug(" )\n");
4186ec4bedbSLiu Gang #endif
4196ec4bedbSLiu Gang 	/* Schedule deferred processing if PW was received */
4206ec4bedbSLiu Gang 	if (ipwsr & RIO_IPWSR_QFI) {
4216ec4bedbSLiu Gang 		/* Save PW message (if there is room in FIFO),
4226ec4bedbSLiu Gang 		 * otherwise discard it.
4236ec4bedbSLiu Gang 		 */
424abc3aeaeSLiu Gang 		if (kfifo_avail(&pw->pw_fifo) >= RIO_PW_MSG_SIZE) {
425abc3aeaeSLiu Gang 			pw->port_write_msg.msg_count++;
426abc3aeaeSLiu Gang 			kfifo_in(&pw->pw_fifo, pw->port_write_msg.virt,
4276ec4bedbSLiu Gang 				 RIO_PW_MSG_SIZE);
4286ec4bedbSLiu Gang 		} else {
429abc3aeaeSLiu Gang 			pw->port_write_msg.discard_count++;
4306ec4bedbSLiu Gang 			pr_debug("RIO: ISR Discarded Port-Write Msg(s) (%d)\n",
431abc3aeaeSLiu Gang 				 pw->port_write_msg.discard_count);
4326ec4bedbSLiu Gang 		}
4336ec4bedbSLiu Gang 		/* Clear interrupt and issue Clear Queue command. This allows
4346ec4bedbSLiu Gang 		 * another port-write to be received.
4356ec4bedbSLiu Gang 		 */
436abc3aeaeSLiu Gang 		out_be32(&pw->pw_regs->pwsr,	RIO_IPWSR_QFI);
437abc3aeaeSLiu Gang 		out_be32(&pw->pw_regs->pwmr, ipwmr | RIO_IPWMR_CQ);
4386ec4bedbSLiu Gang 
439abc3aeaeSLiu Gang 		schedule_work(&pw->pw_work);
4406ec4bedbSLiu Gang 	}
4416ec4bedbSLiu Gang 
4426ec4bedbSLiu Gang 	if ((ipwmr & RIO_IPWMR_EIE) && (ipwsr & RIO_IPWSR_TE)) {
443abc3aeaeSLiu Gang 		pw->port_write_msg.err_count++;
4446ec4bedbSLiu Gang 		pr_debug("RIO: Port-Write Transaction Err (%d)\n",
445abc3aeaeSLiu Gang 			 pw->port_write_msg.err_count);
4466ec4bedbSLiu Gang 		/* Clear Transaction Error: port-write controller should be
4476ec4bedbSLiu Gang 		 * disabled when clearing this error
4486ec4bedbSLiu Gang 		 */
449abc3aeaeSLiu Gang 		out_be32(&pw->pw_regs->pwmr, ipwmr & ~RIO_IPWMR_PWE);
450abc3aeaeSLiu Gang 		out_be32(&pw->pw_regs->pwsr,	RIO_IPWSR_TE);
451abc3aeaeSLiu Gang 		out_be32(&pw->pw_regs->pwmr, ipwmr);
4526ec4bedbSLiu Gang 	}
4536ec4bedbSLiu Gang 
4546ec4bedbSLiu Gang 	if (ipwsr & RIO_IPWSR_PWD) {
455abc3aeaeSLiu Gang 		pw->port_write_msg.discard_count++;
4566ec4bedbSLiu Gang 		pr_debug("RIO: Port Discarded Port-Write Msg(s) (%d)\n",
457abc3aeaeSLiu Gang 			 pw->port_write_msg.discard_count);
458abc3aeaeSLiu Gang 		out_be32(&pw->pw_regs->pwsr, RIO_IPWSR_PWD);
4596ec4bedbSLiu Gang 	}
4606ec4bedbSLiu Gang 
4616ec4bedbSLiu Gang pw_done:
4626ec4bedbSLiu Gang 	if (epwisr & RIO_EPWISR_PINT1) {
463abc3aeaeSLiu Gang 		tmp = in_be32(rio_regs_win + RIO_LTLEDCSR);
4646ec4bedbSLiu Gang 		pr_debug("RIO_LTLEDCSR = 0x%x\n", tmp);
465abc3aeaeSLiu Gang 		fsl_rio_port_error_handler(0);
4666ec4bedbSLiu Gang 	}
4676ec4bedbSLiu Gang 
4686ec4bedbSLiu Gang 	if (epwisr & RIO_EPWISR_PINT2) {
469abc3aeaeSLiu Gang 		tmp = in_be32(rio_regs_win + RIO_LTLEDCSR);
4706ec4bedbSLiu Gang 		pr_debug("RIO_LTLEDCSR = 0x%x\n", tmp);
471abc3aeaeSLiu Gang 		fsl_rio_port_error_handler(1);
4726ec4bedbSLiu Gang 	}
4736ec4bedbSLiu Gang 
4746ec4bedbSLiu Gang 	if (epwisr & RIO_EPWISR_MU) {
475abc3aeaeSLiu Gang 		tmp = in_be32(rio_regs_win + RIO_LTLEDCSR);
4766ec4bedbSLiu Gang 		pr_debug("RIO_LTLEDCSR = 0x%x\n", tmp);
477abc3aeaeSLiu Gang 		msg_unit_error_handler();
4786ec4bedbSLiu Gang 	}
4796ec4bedbSLiu Gang 
4806ec4bedbSLiu Gang 	return IRQ_HANDLED;
4816ec4bedbSLiu Gang }
4826ec4bedbSLiu Gang 
4836ec4bedbSLiu Gang static void fsl_pw_dpc(struct work_struct *work)
4846ec4bedbSLiu Gang {
485abc3aeaeSLiu Gang 	struct fsl_rio_pw *pw = container_of(work, struct fsl_rio_pw, pw_work);
4869a0b0627SAlexandre Bounine 	union rio_pw_msg msg_buffer;
4879a0b0627SAlexandre Bounine 	int i;
4886ec4bedbSLiu Gang 
4896ec4bedbSLiu Gang 	/*
4906ec4bedbSLiu Gang 	 * Process port-write messages
4916ec4bedbSLiu Gang 	 */
4929a0b0627SAlexandre Bounine 	while (kfifo_out_spinlocked(&pw->pw_fifo, (unsigned char *)&msg_buffer,
493abc3aeaeSLiu Gang 			 RIO_PW_MSG_SIZE, &pw->pw_fifo_lock)) {
4946ec4bedbSLiu Gang #ifdef DEBUG_PW
4956ec4bedbSLiu Gang 		{
4966ec4bedbSLiu Gang 		u32 i;
4976ec4bedbSLiu Gang 		pr_debug("%s : Port-Write Message:", __func__);
4986ec4bedbSLiu Gang 		for (i = 0; i < RIO_PW_MSG_SIZE/sizeof(u32); i++) {
4996ec4bedbSLiu Gang 			if ((i%4) == 0)
5006ec4bedbSLiu Gang 				pr_debug("\n0x%02x: 0x%08x", i*4,
5019a0b0627SAlexandre Bounine 					 msg_buffer.raw[i]);
5026ec4bedbSLiu Gang 			else
5039a0b0627SAlexandre Bounine 				pr_debug(" 0x%08x", msg_buffer.raw[i]);
5046ec4bedbSLiu Gang 		}
5056ec4bedbSLiu Gang 		pr_debug("\n");
5066ec4bedbSLiu Gang 		}
5076ec4bedbSLiu Gang #endif
5086ec4bedbSLiu Gang 		/* Pass the port-write message to RIO core for processing */
5099a0b0627SAlexandre Bounine 		for (i = 0; i < MAX_PORT_NUM; i++) {
5109a0b0627SAlexandre Bounine 			if (pw->mport[i])
5119a0b0627SAlexandre Bounine 				rio_inb_pwrite_handler(pw->mport[i],
5129a0b0627SAlexandre Bounine 						       &msg_buffer);
5139a0b0627SAlexandre Bounine 		}
5146ec4bedbSLiu Gang 	}
5156ec4bedbSLiu Gang }
5166ec4bedbSLiu Gang 
5176ec4bedbSLiu Gang /**
5186ec4bedbSLiu Gang  * fsl_rio_pw_enable - enable/disable port-write interface init
5196ec4bedbSLiu Gang  * @mport: Master port implementing the port write unit
5206ec4bedbSLiu Gang  * @enable:    1=enable; 0=disable port-write message handling
5216ec4bedbSLiu Gang  */
5226ec4bedbSLiu Gang int fsl_rio_pw_enable(struct rio_mport *mport, int enable)
5236ec4bedbSLiu Gang {
5246ec4bedbSLiu Gang 	u32 rval;
5256ec4bedbSLiu Gang 
526abc3aeaeSLiu Gang 	rval = in_be32(&pw->pw_regs->pwmr);
5276ec4bedbSLiu Gang 
5286ec4bedbSLiu Gang 	if (enable)
5296ec4bedbSLiu Gang 		rval |= RIO_IPWMR_PWE;
5306ec4bedbSLiu Gang 	else
5316ec4bedbSLiu Gang 		rval &= ~RIO_IPWMR_PWE;
5326ec4bedbSLiu Gang 
533abc3aeaeSLiu Gang 	out_be32(&pw->pw_regs->pwmr, rval);
5346ec4bedbSLiu Gang 
5356ec4bedbSLiu Gang 	return 0;
5366ec4bedbSLiu Gang }
5376ec4bedbSLiu Gang 
5386ec4bedbSLiu Gang /**
5396ec4bedbSLiu Gang  * fsl_rio_port_write_init - MPC85xx port write interface init
5406ec4bedbSLiu Gang  * @mport: Master port implementing the port write unit
5416ec4bedbSLiu Gang  *
5426ec4bedbSLiu Gang  * Initializes port write unit hardware and DMA buffer
5436ec4bedbSLiu Gang  * ring. Called from fsl_rio_setup(). Returns %0 on success
5446ec4bedbSLiu Gang  * or %-ENOMEM on failure.
5456ec4bedbSLiu Gang  */
5466ec4bedbSLiu Gang 
547abc3aeaeSLiu Gang int fsl_rio_port_write_init(struct fsl_rio_pw *pw)
5486ec4bedbSLiu Gang {
5496ec4bedbSLiu Gang 	int rc = 0;
5506ec4bedbSLiu Gang 
5516ec4bedbSLiu Gang 	/* Following configurations require a disabled port write controller */
552abc3aeaeSLiu Gang 	out_be32(&pw->pw_regs->pwmr,
553abc3aeaeSLiu Gang 		 in_be32(&pw->pw_regs->pwmr) & ~RIO_IPWMR_PWE);
5546ec4bedbSLiu Gang 
5556ec4bedbSLiu Gang 	/* Initialize port write */
556abc3aeaeSLiu Gang 	pw->port_write_msg.virt = dma_alloc_coherent(pw->dev,
5576ec4bedbSLiu Gang 					RIO_PW_MSG_SIZE,
558abc3aeaeSLiu Gang 					&pw->port_write_msg.phys, GFP_KERNEL);
559abc3aeaeSLiu Gang 	if (!pw->port_write_msg.virt) {
5606ec4bedbSLiu Gang 		pr_err("RIO: unable allocate port write queue\n");
5616ec4bedbSLiu Gang 		return -ENOMEM;
5626ec4bedbSLiu Gang 	}
5636ec4bedbSLiu Gang 
564abc3aeaeSLiu Gang 	pw->port_write_msg.err_count = 0;
565abc3aeaeSLiu Gang 	pw->port_write_msg.discard_count = 0;
5666ec4bedbSLiu Gang 
5676ec4bedbSLiu Gang 	/* Point dequeue/enqueue pointers at first entry */
568abc3aeaeSLiu Gang 	out_be32(&pw->pw_regs->epwqbar, 0);
569abc3aeaeSLiu Gang 	out_be32(&pw->pw_regs->pwqbar, (u32) pw->port_write_msg.phys);
5706ec4bedbSLiu Gang 
5716ec4bedbSLiu Gang 	pr_debug("EIPWQBAR: 0x%08x IPWQBAR: 0x%08x\n",
572abc3aeaeSLiu Gang 		 in_be32(&pw->pw_regs->epwqbar),
573abc3aeaeSLiu Gang 		 in_be32(&pw->pw_regs->pwqbar));
5746ec4bedbSLiu Gang 
5756ec4bedbSLiu Gang 	/* Clear interrupt status IPWSR */
576abc3aeaeSLiu Gang 	out_be32(&pw->pw_regs->pwsr,
5776ec4bedbSLiu Gang 		 (RIO_IPWSR_TE | RIO_IPWSR_QFI | RIO_IPWSR_PWD));
5786ec4bedbSLiu Gang 
579446957baSAdam Buchbinder 	/* Configure port write controller for snooping enable all reporting,
5806ec4bedbSLiu Gang 	   clear queue full */
581abc3aeaeSLiu Gang 	out_be32(&pw->pw_regs->pwmr,
5826ec4bedbSLiu Gang 		 RIO_IPWMR_SEN | RIO_IPWMR_QFIE | RIO_IPWMR_EIE | RIO_IPWMR_CQ);
5836ec4bedbSLiu Gang 
5846ec4bedbSLiu Gang 
5856ec4bedbSLiu Gang 	/* Hook up port-write handler */
586abc3aeaeSLiu Gang 	rc = request_irq(IRQ_RIO_PW(pw), fsl_rio_port_write_handler,
587abc3aeaeSLiu Gang 			IRQF_SHARED, "port-write", (void *)pw);
5886ec4bedbSLiu Gang 	if (rc < 0) {
5896ec4bedbSLiu Gang 		pr_err("MPC85xx RIO: unable to request inbound doorbell irq");
5906ec4bedbSLiu Gang 		goto err_out;
5916ec4bedbSLiu Gang 	}
5926ec4bedbSLiu Gang 	/* Enable Error Interrupt */
5936ec4bedbSLiu Gang 	out_be32((u32 *)(rio_regs_win + RIO_LTLEECSR), LTLEECSR_ENABLE_ALL);
5946ec4bedbSLiu Gang 
595abc3aeaeSLiu Gang 	INIT_WORK(&pw->pw_work, fsl_pw_dpc);
596abc3aeaeSLiu Gang 	spin_lock_init(&pw->pw_fifo_lock);
597abc3aeaeSLiu Gang 	if (kfifo_alloc(&pw->pw_fifo, RIO_PW_MSG_SIZE * 32, GFP_KERNEL)) {
5986ec4bedbSLiu Gang 		pr_err("FIFO allocation failed\n");
5996ec4bedbSLiu Gang 		rc = -ENOMEM;
6006ec4bedbSLiu Gang 		goto err_out_irq;
6016ec4bedbSLiu Gang 	}
6026ec4bedbSLiu Gang 
6036ec4bedbSLiu Gang 	pr_debug("IPWMR: 0x%08x IPWSR: 0x%08x\n",
604abc3aeaeSLiu Gang 		 in_be32(&pw->pw_regs->pwmr),
605abc3aeaeSLiu Gang 		 in_be32(&pw->pw_regs->pwsr));
6066ec4bedbSLiu Gang 
6076ec4bedbSLiu Gang 	return rc;
6086ec4bedbSLiu Gang 
6096ec4bedbSLiu Gang err_out_irq:
610abc3aeaeSLiu Gang 	free_irq(IRQ_RIO_PW(pw), (void *)pw);
6116ec4bedbSLiu Gang err_out:
612abc3aeaeSLiu Gang 	dma_free_coherent(pw->dev, RIO_PW_MSG_SIZE,
613abc3aeaeSLiu Gang 		pw->port_write_msg.virt,
614abc3aeaeSLiu Gang 		pw->port_write_msg.phys);
6156ec4bedbSLiu Gang 	return rc;
6166ec4bedbSLiu Gang }
6176ec4bedbSLiu Gang 
6186ec4bedbSLiu Gang /**
6196ec4bedbSLiu Gang  * fsl_rio_doorbell_send - Send a MPC85xx doorbell message
6206ec4bedbSLiu Gang  * @mport: RapidIO master port info
6216ec4bedbSLiu Gang  * @index: ID of RapidIO interface
6226ec4bedbSLiu Gang  * @destid: Destination ID of target device
6236ec4bedbSLiu Gang  * @data: 16-bit info field of RapidIO doorbell message
6246ec4bedbSLiu Gang  *
6256ec4bedbSLiu Gang  * Sends a MPC85xx doorbell message. Returns %0 on success or
6266ec4bedbSLiu Gang  * %-EINVAL on failure.
6276ec4bedbSLiu Gang  */
628abc3aeaeSLiu Gang int fsl_rio_doorbell_send(struct rio_mport *mport,
6296ec4bedbSLiu Gang 				int index, u16 destid, u16 data)
6306ec4bedbSLiu Gang {
63131d1e130SIoan Nicu 	unsigned long flags;
63231d1e130SIoan Nicu 
6336ec4bedbSLiu Gang 	pr_debug("fsl_doorbell_send: index %d destid %4.4x data %4.4x\n",
6346ec4bedbSLiu Gang 		 index, destid, data);
635abc3aeaeSLiu Gang 
63631d1e130SIoan Nicu 	spin_lock_irqsave(&fsl_rio_doorbell_lock, flags);
63731d1e130SIoan Nicu 
6386ec4bedbSLiu Gang 	/* In the serial version silicons, such as MPC8548, MPC8641,
6396ec4bedbSLiu Gang 	 * below operations is must be.
6406ec4bedbSLiu Gang 	 */
641abc3aeaeSLiu Gang 	out_be32(&dbell->dbell_regs->odmr, 0x00000000);
642abc3aeaeSLiu Gang 	out_be32(&dbell->dbell_regs->odretcr, 0x00000004);
643abc3aeaeSLiu Gang 	out_be32(&dbell->dbell_regs->oddpr, destid << 16);
644abc3aeaeSLiu Gang 	out_be32(&dbell->dbell_regs->oddatr, (index << 20) | data);
645abc3aeaeSLiu Gang 	out_be32(&dbell->dbell_regs->odmr, 0x00000001);
6466ec4bedbSLiu Gang 
64731d1e130SIoan Nicu 	spin_unlock_irqrestore(&fsl_rio_doorbell_lock, flags);
64831d1e130SIoan Nicu 
6496ec4bedbSLiu Gang 	return 0;
6506ec4bedbSLiu Gang }
6516ec4bedbSLiu Gang 
6526ec4bedbSLiu Gang /**
6536ec4bedbSLiu Gang  * fsl_add_outb_message - Add message to the MPC85xx outbound message queue
6546ec4bedbSLiu Gang  * @mport: Master port with outbound message queue
6556ec4bedbSLiu Gang  * @rdev: Target of outbound message
6566ec4bedbSLiu Gang  * @mbox: Outbound mailbox
6576ec4bedbSLiu Gang  * @buffer: Message to add to outbound queue
6586ec4bedbSLiu Gang  * @len: Length of message
6596ec4bedbSLiu Gang  *
6606ec4bedbSLiu Gang  * Adds the @buffer message to the MPC85xx outbound message queue. Returns
6616ec4bedbSLiu Gang  * %0 on success or %-EINVAL on failure.
6626ec4bedbSLiu Gang  */
663abc3aeaeSLiu Gang int
6646ec4bedbSLiu Gang fsl_add_outb_message(struct rio_mport *mport, struct rio_dev *rdev, int mbox,
6656ec4bedbSLiu Gang 			void *buffer, size_t len)
6666ec4bedbSLiu Gang {
6676ec4bedbSLiu Gang 	struct fsl_rmu *rmu = GET_RMM_HANDLE(mport);
6686ec4bedbSLiu Gang 	u32 omr;
6696ec4bedbSLiu Gang 	struct rio_tx_desc *desc = (struct rio_tx_desc *)rmu->msg_tx_ring.virt
6706ec4bedbSLiu Gang 					+ rmu->msg_tx_ring.tx_slot;
6716ec4bedbSLiu Gang 	int ret = 0;
6726ec4bedbSLiu Gang 
6736ec4bedbSLiu Gang 	pr_debug("RIO: fsl_add_outb_message(): destid %4.4x mbox %d buffer " \
6742a2383daSLiu Gang 		 "%p len %8.8zx\n", rdev->destid, mbox, buffer, len);
6756ec4bedbSLiu Gang 	if ((len < 8) || (len > RIO_MAX_MSG_SIZE)) {
6766ec4bedbSLiu Gang 		ret = -EINVAL;
6776ec4bedbSLiu Gang 		goto out;
6786ec4bedbSLiu Gang 	}
6796ec4bedbSLiu Gang 
6806ec4bedbSLiu Gang 	/* Copy and clear rest of buffer */
6816ec4bedbSLiu Gang 	memcpy(rmu->msg_tx_ring.virt_buffer[rmu->msg_tx_ring.tx_slot], buffer,
6826ec4bedbSLiu Gang 			len);
6836ec4bedbSLiu Gang 	if (len < (RIO_MAX_MSG_SIZE - 4))
6846ec4bedbSLiu Gang 		memset(rmu->msg_tx_ring.virt_buffer[rmu->msg_tx_ring.tx_slot]
6856ec4bedbSLiu Gang 				+ len, 0, RIO_MAX_MSG_SIZE - len);
6866ec4bedbSLiu Gang 
6876ec4bedbSLiu Gang 	/* Set mbox field for message, and set destid */
6886ec4bedbSLiu Gang 	desc->dport = (rdev->destid << 16) | (mbox & 0x3);
6896ec4bedbSLiu Gang 
6906ec4bedbSLiu Gang 	/* Enable EOMI interrupt and priority */
691abc3aeaeSLiu Gang 	desc->dattr = 0x28000000 | ((mport->index) << 20);
6926ec4bedbSLiu Gang 
6936ec4bedbSLiu Gang 	/* Set transfer size aligned to next power of 2 (in double words) */
6946ec4bedbSLiu Gang 	desc->dwcnt = is_power_of_2(len) ? len : 1 << get_bitmask_order(len);
6956ec4bedbSLiu Gang 
6966ec4bedbSLiu Gang 	/* Set snooping and source buffer address */
6976ec4bedbSLiu Gang 	desc->saddr = 0x00000004
6986ec4bedbSLiu Gang 		| rmu->msg_tx_ring.phys_buffer[rmu->msg_tx_ring.tx_slot];
6996ec4bedbSLiu Gang 
7006ec4bedbSLiu Gang 	/* Increment enqueue pointer */
7016ec4bedbSLiu Gang 	omr = in_be32(&rmu->msg_regs->omr);
7026ec4bedbSLiu Gang 	out_be32(&rmu->msg_regs->omr, omr | RIO_MSG_OMR_MUI);
7036ec4bedbSLiu Gang 
7046ec4bedbSLiu Gang 	/* Go to next descriptor */
7056ec4bedbSLiu Gang 	if (++rmu->msg_tx_ring.tx_slot == rmu->msg_tx_ring.size)
7066ec4bedbSLiu Gang 		rmu->msg_tx_ring.tx_slot = 0;
7076ec4bedbSLiu Gang 
7086ec4bedbSLiu Gang out:
7096ec4bedbSLiu Gang 	return ret;
7106ec4bedbSLiu Gang }
7116ec4bedbSLiu Gang 
7126ec4bedbSLiu Gang /**
7136ec4bedbSLiu Gang  * fsl_open_outb_mbox - Initialize MPC85xx outbound mailbox
7146ec4bedbSLiu Gang  * @mport: Master port implementing the outbound message unit
7156ec4bedbSLiu Gang  * @dev_id: Device specific pointer to pass on event
7166ec4bedbSLiu Gang  * @mbox: Mailbox to open
7176ec4bedbSLiu Gang  * @entries: Number of entries in the outbound mailbox ring
7186ec4bedbSLiu Gang  *
7196ec4bedbSLiu Gang  * Initializes buffer ring, request the outbound message interrupt,
7206ec4bedbSLiu Gang  * and enables the outbound message unit. Returns %0 on success and
7216ec4bedbSLiu Gang  * %-EINVAL or %-ENOMEM on failure.
7226ec4bedbSLiu Gang  */
723abc3aeaeSLiu Gang int
7246ec4bedbSLiu Gang fsl_open_outb_mbox(struct rio_mport *mport, void *dev_id, int mbox, int entries)
7256ec4bedbSLiu Gang {
7266ec4bedbSLiu Gang 	int i, j, rc = 0;
7276ec4bedbSLiu Gang 	struct rio_priv *priv = mport->priv;
7286ec4bedbSLiu Gang 	struct fsl_rmu *rmu = GET_RMM_HANDLE(mport);
7296ec4bedbSLiu Gang 
7306ec4bedbSLiu Gang 	if ((entries < RIO_MIN_TX_RING_SIZE) ||
7316ec4bedbSLiu Gang 		(entries > RIO_MAX_TX_RING_SIZE) || (!is_power_of_2(entries))) {
7326ec4bedbSLiu Gang 		rc = -EINVAL;
7336ec4bedbSLiu Gang 		goto out;
7346ec4bedbSLiu Gang 	}
7356ec4bedbSLiu Gang 
7366ec4bedbSLiu Gang 	/* Initialize shadow copy ring */
7376ec4bedbSLiu Gang 	rmu->msg_tx_ring.dev_id = dev_id;
7386ec4bedbSLiu Gang 	rmu->msg_tx_ring.size = entries;
7396ec4bedbSLiu Gang 
7406ec4bedbSLiu Gang 	for (i = 0; i < rmu->msg_tx_ring.size; i++) {
7416ec4bedbSLiu Gang 		rmu->msg_tx_ring.virt_buffer[i] =
7426ec4bedbSLiu Gang 			dma_alloc_coherent(priv->dev, RIO_MSG_BUFFER_SIZE,
7436ec4bedbSLiu Gang 				&rmu->msg_tx_ring.phys_buffer[i], GFP_KERNEL);
7446ec4bedbSLiu Gang 		if (!rmu->msg_tx_ring.virt_buffer[i]) {
7456ec4bedbSLiu Gang 			rc = -ENOMEM;
7466ec4bedbSLiu Gang 			for (j = 0; j < rmu->msg_tx_ring.size; j++)
7476ec4bedbSLiu Gang 				if (rmu->msg_tx_ring.virt_buffer[j])
7486ec4bedbSLiu Gang 					dma_free_coherent(priv->dev,
7496ec4bedbSLiu Gang 							RIO_MSG_BUFFER_SIZE,
7506ec4bedbSLiu Gang 							rmu->msg_tx_ring.
7516ec4bedbSLiu Gang 							virt_buffer[j],
7526ec4bedbSLiu Gang 							rmu->msg_tx_ring.
7536ec4bedbSLiu Gang 							phys_buffer[j]);
7546ec4bedbSLiu Gang 			goto out;
7556ec4bedbSLiu Gang 		}
7566ec4bedbSLiu Gang 	}
7576ec4bedbSLiu Gang 
7586ec4bedbSLiu Gang 	/* Initialize outbound message descriptor ring */
759*750afb08SLuis Chamberlain 	rmu->msg_tx_ring.virt = dma_alloc_coherent(priv->dev,
7606ec4bedbSLiu Gang 						   rmu->msg_tx_ring.size * RIO_MSG_DESC_SIZE,
761*750afb08SLuis Chamberlain 						   &rmu->msg_tx_ring.phys,
762*750afb08SLuis Chamberlain 						   GFP_KERNEL);
7636ec4bedbSLiu Gang 	if (!rmu->msg_tx_ring.virt) {
7646ec4bedbSLiu Gang 		rc = -ENOMEM;
7656ec4bedbSLiu Gang 		goto out_dma;
7666ec4bedbSLiu Gang 	}
7676ec4bedbSLiu Gang 	rmu->msg_tx_ring.tx_slot = 0;
7686ec4bedbSLiu Gang 
7696ec4bedbSLiu Gang 	/* Point dequeue/enqueue pointers at first entry in ring */
7706ec4bedbSLiu Gang 	out_be32(&rmu->msg_regs->odqdpar, rmu->msg_tx_ring.phys);
7716ec4bedbSLiu Gang 	out_be32(&rmu->msg_regs->odqepar, rmu->msg_tx_ring.phys);
7726ec4bedbSLiu Gang 
7736ec4bedbSLiu Gang 	/* Configure for snooping */
7746ec4bedbSLiu Gang 	out_be32(&rmu->msg_regs->osar, 0x00000004);
7756ec4bedbSLiu Gang 
7766ec4bedbSLiu Gang 	/* Clear interrupt status */
7776ec4bedbSLiu Gang 	out_be32(&rmu->msg_regs->osr, 0x000000b3);
7786ec4bedbSLiu Gang 
7796ec4bedbSLiu Gang 	/* Hook up outbound message handler */
7806ec4bedbSLiu Gang 	rc = request_irq(IRQ_RIO_TX(mport), fsl_rio_tx_handler, 0,
7816ec4bedbSLiu Gang 			 "msg_tx", (void *)mport);
7826ec4bedbSLiu Gang 	if (rc < 0)
7836ec4bedbSLiu Gang 		goto out_irq;
7846ec4bedbSLiu Gang 
7856ec4bedbSLiu Gang 	/*
7866ec4bedbSLiu Gang 	 * Configure outbound message unit
7876ec4bedbSLiu Gang 	 *      Snooping
7886ec4bedbSLiu Gang 	 *      Interrupts (all enabled, except QEIE)
7896ec4bedbSLiu Gang 	 *      Chaining mode
7906ec4bedbSLiu Gang 	 *      Disable
7916ec4bedbSLiu Gang 	 */
7926ec4bedbSLiu Gang 	out_be32(&rmu->msg_regs->omr, 0x00100220);
7936ec4bedbSLiu Gang 
7946ec4bedbSLiu Gang 	/* Set number of entries */
7956ec4bedbSLiu Gang 	out_be32(&rmu->msg_regs->omr,
7966ec4bedbSLiu Gang 		 in_be32(&rmu->msg_regs->omr) |
7976ec4bedbSLiu Gang 		 ((get_bitmask_order(entries) - 2) << 12));
7986ec4bedbSLiu Gang 
7996ec4bedbSLiu Gang 	/* Now enable the unit */
8006ec4bedbSLiu Gang 	out_be32(&rmu->msg_regs->omr, in_be32(&rmu->msg_regs->omr) | 0x1);
8016ec4bedbSLiu Gang 
8026ec4bedbSLiu Gang out:
8036ec4bedbSLiu Gang 	return rc;
8046ec4bedbSLiu Gang 
8056ec4bedbSLiu Gang out_irq:
8066ec4bedbSLiu Gang 	dma_free_coherent(priv->dev,
8076ec4bedbSLiu Gang 		rmu->msg_tx_ring.size * RIO_MSG_DESC_SIZE,
8086ec4bedbSLiu Gang 		rmu->msg_tx_ring.virt, rmu->msg_tx_ring.phys);
8096ec4bedbSLiu Gang 
8106ec4bedbSLiu Gang out_dma:
8116ec4bedbSLiu Gang 	for (i = 0; i < rmu->msg_tx_ring.size; i++)
8126ec4bedbSLiu Gang 		dma_free_coherent(priv->dev, RIO_MSG_BUFFER_SIZE,
8136ec4bedbSLiu Gang 		rmu->msg_tx_ring.virt_buffer[i],
8146ec4bedbSLiu Gang 		rmu->msg_tx_ring.phys_buffer[i]);
8156ec4bedbSLiu Gang 
8166ec4bedbSLiu Gang 	return rc;
8176ec4bedbSLiu Gang }
8186ec4bedbSLiu Gang 
8196ec4bedbSLiu Gang /**
8206ec4bedbSLiu Gang  * fsl_close_outb_mbox - Shut down MPC85xx outbound mailbox
8216ec4bedbSLiu Gang  * @mport: Master port implementing the outbound message unit
8226ec4bedbSLiu Gang  * @mbox: Mailbox to close
8236ec4bedbSLiu Gang  *
8246ec4bedbSLiu Gang  * Disables the outbound message unit, free all buffers, and
8256ec4bedbSLiu Gang  * frees the outbound message interrupt.
8266ec4bedbSLiu Gang  */
827abc3aeaeSLiu Gang void fsl_close_outb_mbox(struct rio_mport *mport, int mbox)
8286ec4bedbSLiu Gang {
8296ec4bedbSLiu Gang 	struct rio_priv *priv = mport->priv;
8306ec4bedbSLiu Gang 	struct fsl_rmu *rmu = GET_RMM_HANDLE(mport);
8316ec4bedbSLiu Gang 
8326ec4bedbSLiu Gang 	/* Disable inbound message unit */
8336ec4bedbSLiu Gang 	out_be32(&rmu->msg_regs->omr, 0);
8346ec4bedbSLiu Gang 
8356ec4bedbSLiu Gang 	/* Free ring */
8366ec4bedbSLiu Gang 	dma_free_coherent(priv->dev,
8376ec4bedbSLiu Gang 	rmu->msg_tx_ring.size * RIO_MSG_DESC_SIZE,
8386ec4bedbSLiu Gang 	rmu->msg_tx_ring.virt, rmu->msg_tx_ring.phys);
8396ec4bedbSLiu Gang 
8406ec4bedbSLiu Gang 	/* Free interrupt */
8416ec4bedbSLiu Gang 	free_irq(IRQ_RIO_TX(mport), (void *)mport);
8426ec4bedbSLiu Gang }
8436ec4bedbSLiu Gang 
8446ec4bedbSLiu Gang /**
8456ec4bedbSLiu Gang  * fsl_open_inb_mbox - Initialize MPC85xx inbound mailbox
8466ec4bedbSLiu Gang  * @mport: Master port implementing the inbound message unit
8476ec4bedbSLiu Gang  * @dev_id: Device specific pointer to pass on event
8486ec4bedbSLiu Gang  * @mbox: Mailbox to open
8496ec4bedbSLiu Gang  * @entries: Number of entries in the inbound mailbox ring
8506ec4bedbSLiu Gang  *
8516ec4bedbSLiu Gang  * Initializes buffer ring, request the inbound message interrupt,
8526ec4bedbSLiu Gang  * and enables the inbound message unit. Returns %0 on success
8536ec4bedbSLiu Gang  * and %-EINVAL or %-ENOMEM on failure.
8546ec4bedbSLiu Gang  */
855abc3aeaeSLiu Gang int
8566ec4bedbSLiu Gang fsl_open_inb_mbox(struct rio_mport *mport, void *dev_id, int mbox, int entries)
8576ec4bedbSLiu Gang {
8586ec4bedbSLiu Gang 	int i, rc = 0;
8596ec4bedbSLiu Gang 	struct rio_priv *priv = mport->priv;
8606ec4bedbSLiu Gang 	struct fsl_rmu *rmu = GET_RMM_HANDLE(mport);
8616ec4bedbSLiu Gang 
8626ec4bedbSLiu Gang 	if ((entries < RIO_MIN_RX_RING_SIZE) ||
8636ec4bedbSLiu Gang 		(entries > RIO_MAX_RX_RING_SIZE) || (!is_power_of_2(entries))) {
8646ec4bedbSLiu Gang 		rc = -EINVAL;
8656ec4bedbSLiu Gang 		goto out;
8666ec4bedbSLiu Gang 	}
8676ec4bedbSLiu Gang 
8686ec4bedbSLiu Gang 	/* Initialize client buffer ring */
8696ec4bedbSLiu Gang 	rmu->msg_rx_ring.dev_id = dev_id;
8706ec4bedbSLiu Gang 	rmu->msg_rx_ring.size = entries;
8716ec4bedbSLiu Gang 	rmu->msg_rx_ring.rx_slot = 0;
8726ec4bedbSLiu Gang 	for (i = 0; i < rmu->msg_rx_ring.size; i++)
8736ec4bedbSLiu Gang 		rmu->msg_rx_ring.virt_buffer[i] = NULL;
8746ec4bedbSLiu Gang 
8756ec4bedbSLiu Gang 	/* Initialize inbound message ring */
8766ec4bedbSLiu Gang 	rmu->msg_rx_ring.virt = dma_alloc_coherent(priv->dev,
8776ec4bedbSLiu Gang 				rmu->msg_rx_ring.size * RIO_MAX_MSG_SIZE,
8786ec4bedbSLiu Gang 				&rmu->msg_rx_ring.phys, GFP_KERNEL);
8796ec4bedbSLiu Gang 	if (!rmu->msg_rx_ring.virt) {
8806ec4bedbSLiu Gang 		rc = -ENOMEM;
8816ec4bedbSLiu Gang 		goto out;
8826ec4bedbSLiu Gang 	}
8836ec4bedbSLiu Gang 
8846ec4bedbSLiu Gang 	/* Point dequeue/enqueue pointers at first entry in ring */
8856ec4bedbSLiu Gang 	out_be32(&rmu->msg_regs->ifqdpar, (u32) rmu->msg_rx_ring.phys);
8866ec4bedbSLiu Gang 	out_be32(&rmu->msg_regs->ifqepar, (u32) rmu->msg_rx_ring.phys);
8876ec4bedbSLiu Gang 
8886ec4bedbSLiu Gang 	/* Clear interrupt status */
8896ec4bedbSLiu Gang 	out_be32(&rmu->msg_regs->isr, 0x00000091);
8906ec4bedbSLiu Gang 
8916ec4bedbSLiu Gang 	/* Hook up inbound message handler */
8926ec4bedbSLiu Gang 	rc = request_irq(IRQ_RIO_RX(mport), fsl_rio_rx_handler, 0,
8936ec4bedbSLiu Gang 			 "msg_rx", (void *)mport);
8946ec4bedbSLiu Gang 	if (rc < 0) {
8951c075f95SLiu Gang 		dma_free_coherent(priv->dev,
8961c075f95SLiu Gang 			rmu->msg_rx_ring.size * RIO_MAX_MSG_SIZE,
8971c075f95SLiu Gang 			rmu->msg_rx_ring.virt, rmu->msg_rx_ring.phys);
8986ec4bedbSLiu Gang 		goto out;
8996ec4bedbSLiu Gang 	}
9006ec4bedbSLiu Gang 
9016ec4bedbSLiu Gang 	/*
9026ec4bedbSLiu Gang 	 * Configure inbound message unit:
9036ec4bedbSLiu Gang 	 *      Snooping
9046ec4bedbSLiu Gang 	 *      4KB max message size
9056ec4bedbSLiu Gang 	 *      Unmask all interrupt sources
9066ec4bedbSLiu Gang 	 *      Disable
9076ec4bedbSLiu Gang 	 */
9086ec4bedbSLiu Gang 	out_be32(&rmu->msg_regs->imr, 0x001b0060);
9096ec4bedbSLiu Gang 
9106ec4bedbSLiu Gang 	/* Set number of queue entries */
9116ec4bedbSLiu Gang 	setbits32(&rmu->msg_regs->imr, (get_bitmask_order(entries) - 2) << 12);
9126ec4bedbSLiu Gang 
9136ec4bedbSLiu Gang 	/* Now enable the unit */
9146ec4bedbSLiu Gang 	setbits32(&rmu->msg_regs->imr, 0x1);
9156ec4bedbSLiu Gang 
9166ec4bedbSLiu Gang out:
9176ec4bedbSLiu Gang 	return rc;
9186ec4bedbSLiu Gang }
9196ec4bedbSLiu Gang 
9206ec4bedbSLiu Gang /**
9216ec4bedbSLiu Gang  * fsl_close_inb_mbox - Shut down MPC85xx inbound mailbox
9226ec4bedbSLiu Gang  * @mport: Master port implementing the inbound message unit
9236ec4bedbSLiu Gang  * @mbox: Mailbox to close
9246ec4bedbSLiu Gang  *
9256ec4bedbSLiu Gang  * Disables the inbound message unit, free all buffers, and
9266ec4bedbSLiu Gang  * frees the inbound message interrupt.
9276ec4bedbSLiu Gang  */
928abc3aeaeSLiu Gang void fsl_close_inb_mbox(struct rio_mport *mport, int mbox)
9296ec4bedbSLiu Gang {
9306ec4bedbSLiu Gang 	struct rio_priv *priv = mport->priv;
9316ec4bedbSLiu Gang 	struct fsl_rmu *rmu = GET_RMM_HANDLE(mport);
9326ec4bedbSLiu Gang 
9336ec4bedbSLiu Gang 	/* Disable inbound message unit */
9346ec4bedbSLiu Gang 	out_be32(&rmu->msg_regs->imr, 0);
9356ec4bedbSLiu Gang 
9366ec4bedbSLiu Gang 	/* Free ring */
9376ec4bedbSLiu Gang 	dma_free_coherent(priv->dev, rmu->msg_rx_ring.size * RIO_MAX_MSG_SIZE,
9386ec4bedbSLiu Gang 	rmu->msg_rx_ring.virt, rmu->msg_rx_ring.phys);
9396ec4bedbSLiu Gang 
9406ec4bedbSLiu Gang 	/* Free interrupt */
9416ec4bedbSLiu Gang 	free_irq(IRQ_RIO_RX(mport), (void *)mport);
9426ec4bedbSLiu Gang }
9436ec4bedbSLiu Gang 
9446ec4bedbSLiu Gang /**
9456ec4bedbSLiu Gang  * fsl_add_inb_buffer - Add buffer to the MPC85xx inbound message queue
9466ec4bedbSLiu Gang  * @mport: Master port implementing the inbound message unit
9476ec4bedbSLiu Gang  * @mbox: Inbound mailbox number
9486ec4bedbSLiu Gang  * @buf: Buffer to add to inbound queue
9496ec4bedbSLiu Gang  *
9506ec4bedbSLiu Gang  * Adds the @buf buffer to the MPC85xx inbound message queue. Returns
9516ec4bedbSLiu Gang  * %0 on success or %-EINVAL on failure.
9526ec4bedbSLiu Gang  */
953abc3aeaeSLiu Gang int fsl_add_inb_buffer(struct rio_mport *mport, int mbox, void *buf)
9546ec4bedbSLiu Gang {
9556ec4bedbSLiu Gang 	int rc = 0;
9566ec4bedbSLiu Gang 	struct fsl_rmu *rmu = GET_RMM_HANDLE(mport);
9576ec4bedbSLiu Gang 
9586ec4bedbSLiu Gang 	pr_debug("RIO: fsl_add_inb_buffer(), msg_rx_ring.rx_slot %d\n",
9596ec4bedbSLiu Gang 		 rmu->msg_rx_ring.rx_slot);
9606ec4bedbSLiu Gang 
9616ec4bedbSLiu Gang 	if (rmu->msg_rx_ring.virt_buffer[rmu->msg_rx_ring.rx_slot]) {
9626ec4bedbSLiu Gang 		printk(KERN_ERR
9636ec4bedbSLiu Gang 			"RIO: error adding inbound buffer %d, buffer exists\n",
9646ec4bedbSLiu Gang 			rmu->msg_rx_ring.rx_slot);
9656ec4bedbSLiu Gang 		rc = -EINVAL;
9666ec4bedbSLiu Gang 		goto out;
9676ec4bedbSLiu Gang 	}
9686ec4bedbSLiu Gang 
9696ec4bedbSLiu Gang 	rmu->msg_rx_ring.virt_buffer[rmu->msg_rx_ring.rx_slot] = buf;
9706ec4bedbSLiu Gang 	if (++rmu->msg_rx_ring.rx_slot == rmu->msg_rx_ring.size)
9716ec4bedbSLiu Gang 		rmu->msg_rx_ring.rx_slot = 0;
9726ec4bedbSLiu Gang 
9736ec4bedbSLiu Gang out:
9746ec4bedbSLiu Gang 	return rc;
9756ec4bedbSLiu Gang }
9766ec4bedbSLiu Gang 
9776ec4bedbSLiu Gang /**
9786ec4bedbSLiu Gang  * fsl_get_inb_message - Fetch inbound message from the MPC85xx message unit
9796ec4bedbSLiu Gang  * @mport: Master port implementing the inbound message unit
9806ec4bedbSLiu Gang  * @mbox: Inbound mailbox number
9816ec4bedbSLiu Gang  *
9826ec4bedbSLiu Gang  * Gets the next available inbound message from the inbound message queue.
9836ec4bedbSLiu Gang  * A pointer to the message is returned on success or NULL on failure.
9846ec4bedbSLiu Gang  */
985abc3aeaeSLiu Gang void *fsl_get_inb_message(struct rio_mport *mport, int mbox)
9866ec4bedbSLiu Gang {
9876ec4bedbSLiu Gang 	struct fsl_rmu *rmu = GET_RMM_HANDLE(mport);
9882a2383daSLiu Gang 	u32 phys_buf;
9892a2383daSLiu Gang 	void *virt_buf;
9906ec4bedbSLiu Gang 	void *buf = NULL;
9916ec4bedbSLiu Gang 	int buf_idx;
9926ec4bedbSLiu Gang 
9936ec4bedbSLiu Gang 	phys_buf = in_be32(&rmu->msg_regs->ifqdpar);
9946ec4bedbSLiu Gang 
9956ec4bedbSLiu Gang 	/* If no more messages, then bail out */
9966ec4bedbSLiu Gang 	if (phys_buf == in_be32(&rmu->msg_regs->ifqepar))
9976ec4bedbSLiu Gang 		goto out2;
9986ec4bedbSLiu Gang 
9992a2383daSLiu Gang 	virt_buf = rmu->msg_rx_ring.virt + (phys_buf
10006ec4bedbSLiu Gang 						- rmu->msg_rx_ring.phys);
10016ec4bedbSLiu Gang 	buf_idx = (phys_buf - rmu->msg_rx_ring.phys) / RIO_MAX_MSG_SIZE;
10026ec4bedbSLiu Gang 	buf = rmu->msg_rx_ring.virt_buffer[buf_idx];
10036ec4bedbSLiu Gang 
10046ec4bedbSLiu Gang 	if (!buf) {
10056ec4bedbSLiu Gang 		printk(KERN_ERR
10066ec4bedbSLiu Gang 			"RIO: inbound message copy failed, no buffers\n");
10076ec4bedbSLiu Gang 		goto out1;
10086ec4bedbSLiu Gang 	}
10096ec4bedbSLiu Gang 
10106ec4bedbSLiu Gang 	/* Copy max message size, caller is expected to allocate that big */
10112a2383daSLiu Gang 	memcpy(buf, virt_buf, RIO_MAX_MSG_SIZE);
10126ec4bedbSLiu Gang 
10136ec4bedbSLiu Gang 	/* Clear the available buffer */
10146ec4bedbSLiu Gang 	rmu->msg_rx_ring.virt_buffer[buf_idx] = NULL;
10156ec4bedbSLiu Gang 
10166ec4bedbSLiu Gang out1:
10176ec4bedbSLiu Gang 	setbits32(&rmu->msg_regs->imr, RIO_MSG_IMR_MI);
10186ec4bedbSLiu Gang 
10196ec4bedbSLiu Gang out2:
10206ec4bedbSLiu Gang 	return buf;
10216ec4bedbSLiu Gang }
10226ec4bedbSLiu Gang 
10236ec4bedbSLiu Gang /**
10246ec4bedbSLiu Gang  * fsl_rio_doorbell_init - MPC85xx doorbell interface init
10256ec4bedbSLiu Gang  * @mport: Master port implementing the inbound doorbell unit
10266ec4bedbSLiu Gang  *
10276ec4bedbSLiu Gang  * Initializes doorbell unit hardware and inbound DMA buffer
10286ec4bedbSLiu Gang  * ring. Called from fsl_rio_setup(). Returns %0 on success
10296ec4bedbSLiu Gang  * or %-ENOMEM on failure.
10306ec4bedbSLiu Gang  */
1031abc3aeaeSLiu Gang int fsl_rio_doorbell_init(struct fsl_rio_dbell *dbell)
10326ec4bedbSLiu Gang {
10336ec4bedbSLiu Gang 	int rc = 0;
10346ec4bedbSLiu Gang 
10356ec4bedbSLiu Gang 	/* Initialize inbound doorbells */
1036abc3aeaeSLiu Gang 	dbell->dbell_ring.virt = dma_alloc_coherent(dbell->dev, 512 *
1037abc3aeaeSLiu Gang 		DOORBELL_MESSAGE_SIZE, &dbell->dbell_ring.phys, GFP_KERNEL);
1038abc3aeaeSLiu Gang 	if (!dbell->dbell_ring.virt) {
10396ec4bedbSLiu Gang 		printk(KERN_ERR "RIO: unable allocate inbound doorbell ring\n");
10406ec4bedbSLiu Gang 		rc = -ENOMEM;
10416ec4bedbSLiu Gang 		goto out;
10426ec4bedbSLiu Gang 	}
10436ec4bedbSLiu Gang 
10446ec4bedbSLiu Gang 	/* Point dequeue/enqueue pointers at first entry in ring */
1045abc3aeaeSLiu Gang 	out_be32(&dbell->dbell_regs->dqdpar, (u32) dbell->dbell_ring.phys);
1046abc3aeaeSLiu Gang 	out_be32(&dbell->dbell_regs->dqepar, (u32) dbell->dbell_ring.phys);
10476ec4bedbSLiu Gang 
10486ec4bedbSLiu Gang 	/* Clear interrupt status */
1049abc3aeaeSLiu Gang 	out_be32(&dbell->dbell_regs->dsr, 0x00000091);
10506ec4bedbSLiu Gang 
10516ec4bedbSLiu Gang 	/* Hook up doorbell handler */
1052abc3aeaeSLiu Gang 	rc = request_irq(IRQ_RIO_BELL(dbell), fsl_rio_dbell_handler, 0,
1053abc3aeaeSLiu Gang 			 "dbell_rx", (void *)dbell);
10546ec4bedbSLiu Gang 	if (rc < 0) {
1055abc3aeaeSLiu Gang 		dma_free_coherent(dbell->dev, 512 * DOORBELL_MESSAGE_SIZE,
1056abc3aeaeSLiu Gang 			 dbell->dbell_ring.virt, dbell->dbell_ring.phys);
10576ec4bedbSLiu Gang 		printk(KERN_ERR
10586ec4bedbSLiu Gang 			"MPC85xx RIO: unable to request inbound doorbell irq");
10596ec4bedbSLiu Gang 		goto out;
10606ec4bedbSLiu Gang 	}
10616ec4bedbSLiu Gang 
10626ec4bedbSLiu Gang 	/* Configure doorbells for snooping, 512 entries, and enable */
1063abc3aeaeSLiu Gang 	out_be32(&dbell->dbell_regs->dmr, 0x00108161);
10646ec4bedbSLiu Gang 
10656ec4bedbSLiu Gang out:
10666ec4bedbSLiu Gang 	return rc;
10676ec4bedbSLiu Gang }
10686ec4bedbSLiu Gang 
10696ec4bedbSLiu Gang int fsl_rio_setup_rmu(struct rio_mport *mport, struct device_node *node)
10706ec4bedbSLiu Gang {
10716ec4bedbSLiu Gang 	struct rio_priv *priv;
10726ec4bedbSLiu Gang 	struct fsl_rmu *rmu;
1073abc3aeaeSLiu Gang 	u64 msg_start;
1074abc3aeaeSLiu Gang 	const u32 *msg_addr;
1075abc3aeaeSLiu Gang 	int mlen;
1076abc3aeaeSLiu Gang 	int aw;
10776ec4bedbSLiu Gang 
1078abc3aeaeSLiu Gang 	if (!mport || !mport->priv)
1079abc3aeaeSLiu Gang 		return -EINVAL;
1080abc3aeaeSLiu Gang 
1081abc3aeaeSLiu Gang 	priv = mport->priv;
1082abc3aeaeSLiu Gang 
1083abc3aeaeSLiu Gang 	if (!node) {
1084b7c670d6SRob Herring 		dev_warn(priv->dev, "Can't get %pOF property 'fsl,rmu'\n",
1085b7c670d6SRob Herring 			priv->dev->of_node);
1086abc3aeaeSLiu Gang 		return -EINVAL;
1087abc3aeaeSLiu Gang 	}
10886ec4bedbSLiu Gang 
10896ec4bedbSLiu Gang 	rmu = kzalloc(sizeof(struct fsl_rmu), GFP_KERNEL);
10906ec4bedbSLiu Gang 	if (!rmu)
10916ec4bedbSLiu Gang 		return -ENOMEM;
10926ec4bedbSLiu Gang 
1093abc3aeaeSLiu Gang 	aw = of_n_addr_cells(node);
1094abc3aeaeSLiu Gang 	msg_addr = of_get_property(node, "reg", &mlen);
1095abc3aeaeSLiu Gang 	if (!msg_addr) {
1096b7c670d6SRob Herring 		pr_err("%pOF: unable to find 'reg' property of message-unit\n",
1097b7c670d6SRob Herring 			node);
1098c6ca52adSJulia Lawall 		kfree(rmu);
1099abc3aeaeSLiu Gang 		return -ENOMEM;
1100abc3aeaeSLiu Gang 	}
1101abc3aeaeSLiu Gang 	msg_start = of_read_number(msg_addr, aw);
1102abc3aeaeSLiu Gang 
1103abc3aeaeSLiu Gang 	rmu->msg_regs = (struct rio_msg_regs *)
1104abc3aeaeSLiu Gang 			(rmu_regs_win + (u32)msg_start);
1105abc3aeaeSLiu Gang 
1106abc3aeaeSLiu Gang 	rmu->txirq = irq_of_parse_and_map(node, 0);
1107abc3aeaeSLiu Gang 	rmu->rxirq = irq_of_parse_and_map(node, 1);
1108b7c670d6SRob Herring 	printk(KERN_INFO "%pOF: txirq: %d, rxirq %d\n",
1109b7c670d6SRob Herring 		node, rmu->txirq, rmu->rxirq);
1110abc3aeaeSLiu Gang 
11116ec4bedbSLiu Gang 	priv->rmm_handle = rmu;
11126ec4bedbSLiu Gang 
11136ec4bedbSLiu Gang 	rio_init_dbell_res(&mport->riores[RIO_DOORBELL_RESOURCE], 0, 0xffff);
11146ec4bedbSLiu Gang 	rio_init_mbox_res(&mport->riores[RIO_INB_MBOX_RESOURCE], 0, 0);
11156ec4bedbSLiu Gang 	rio_init_mbox_res(&mport->riores[RIO_OUTB_MBOX_RESOURCE], 0, 0);
11166ec4bedbSLiu Gang 
11176ec4bedbSLiu Gang 	return 0;
11186ec4bedbSLiu Gang }
1119