12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
26ec4bedbSLiu Gang /*
36ec4bedbSLiu Gang * Freescale MPC85xx/MPC86xx RapidIO RMU support
46ec4bedbSLiu Gang *
56ec4bedbSLiu Gang * Copyright 2009 Sysgo AG
66ec4bedbSLiu Gang * Thomas Moll <thomas.moll@sysgo.com>
76ec4bedbSLiu Gang * - fixed maintenance access routines, check for aligned access
86ec4bedbSLiu Gang *
96ec4bedbSLiu Gang * Copyright 2009 Integrated Device Technology, Inc.
106ec4bedbSLiu Gang * Alex Bounine <alexandre.bounine@idt.com>
116ec4bedbSLiu Gang * - Added Port-Write message handling
126ec4bedbSLiu Gang * - Added Machine Check exception handling
136ec4bedbSLiu Gang *
146ec4bedbSLiu Gang * Copyright (C) 2007, 2008, 2010, 2011 Freescale Semiconductor, Inc.
156ec4bedbSLiu Gang * Zhang Wei <wei.zhang@freescale.com>
166ec4bedbSLiu Gang * Lian Minghuan-B31939 <Minghuan.Lian@freescale.com>
176ec4bedbSLiu Gang * Liu Gang <Gang.Liu@freescale.com>
186ec4bedbSLiu Gang *
196ec4bedbSLiu Gang * Copyright 2005 MontaVista Software, Inc.
206ec4bedbSLiu Gang * Matt Porter <mporter@kernel.crashing.org>
216ec4bedbSLiu Gang */
226ec4bedbSLiu Gang
236ec4bedbSLiu Gang #include <linux/types.h>
246ec4bedbSLiu Gang #include <linux/dma-mapping.h>
256ec4bedbSLiu Gang #include <linux/interrupt.h>
26f892ac77SRob Herring #include <linux/of_address.h>
2726a2056eSRob Herring #include <linux/of_irq.h>
286ec4bedbSLiu Gang #include <linux/slab.h>
296ec4bedbSLiu Gang
306ec4bedbSLiu Gang #include "fsl_rio.h"
316ec4bedbSLiu Gang
326ec4bedbSLiu Gang #define GET_RMM_HANDLE(mport) \
336ec4bedbSLiu Gang (((struct rio_priv *)(mport->priv))->rmm_handle)
346ec4bedbSLiu Gang
356ec4bedbSLiu Gang /* RapidIO definition irq, which read from OF-tree */
36abc3aeaeSLiu Gang #define IRQ_RIO_PW(m) (((struct fsl_rio_pw *)(m))->pwirq)
37abc3aeaeSLiu Gang #define IRQ_RIO_BELL(m) (((struct fsl_rio_dbell *)(m))->bellirq)
386ec4bedbSLiu Gang #define IRQ_RIO_TX(m) (((struct fsl_rmu *)(GET_RMM_HANDLE(m)))->txirq)
396ec4bedbSLiu Gang #define IRQ_RIO_RX(m) (((struct fsl_rmu *)(GET_RMM_HANDLE(m)))->rxirq)
406ec4bedbSLiu Gang
416ec4bedbSLiu Gang #define RIO_MIN_TX_RING_SIZE 2
426ec4bedbSLiu Gang #define RIO_MAX_TX_RING_SIZE 2048
436ec4bedbSLiu Gang #define RIO_MIN_RX_RING_SIZE 2
446ec4bedbSLiu Gang #define RIO_MAX_RX_RING_SIZE 2048
456ec4bedbSLiu Gang
466ec4bedbSLiu Gang #define RIO_IPWMR_SEN 0x00100000
476ec4bedbSLiu Gang #define RIO_IPWMR_QFIE 0x00000100
486ec4bedbSLiu Gang #define RIO_IPWMR_EIE 0x00000020
496ec4bedbSLiu Gang #define RIO_IPWMR_CQ 0x00000002
506ec4bedbSLiu Gang #define RIO_IPWMR_PWE 0x00000001
516ec4bedbSLiu Gang
526ec4bedbSLiu Gang #define RIO_IPWSR_QF 0x00100000
536ec4bedbSLiu Gang #define RIO_IPWSR_TE 0x00000080
546ec4bedbSLiu Gang #define RIO_IPWSR_QFI 0x00000010
556ec4bedbSLiu Gang #define RIO_IPWSR_PWD 0x00000008
566ec4bedbSLiu Gang #define RIO_IPWSR_PWB 0x00000004
576ec4bedbSLiu Gang
586ec4bedbSLiu Gang #define RIO_EPWISR 0x10010
596ec4bedbSLiu Gang /* EPWISR Error match value */
606ec4bedbSLiu Gang #define RIO_EPWISR_PINT1 0x80000000
616ec4bedbSLiu Gang #define RIO_EPWISR_PINT2 0x40000000
626ec4bedbSLiu Gang #define RIO_EPWISR_MU 0x00000002
636ec4bedbSLiu Gang #define RIO_EPWISR_PW 0x00000001
646ec4bedbSLiu Gang
656ec4bedbSLiu Gang #define IPWSR_CLEAR 0x98
666ec4bedbSLiu Gang #define OMSR_CLEAR 0x1cb3
676ec4bedbSLiu Gang #define IMSR_CLEAR 0x491
686ec4bedbSLiu Gang #define IDSR_CLEAR 0x91
696ec4bedbSLiu Gang #define ODSR_CLEAR 0x1c00
706ec4bedbSLiu Gang #define LTLEECSR_ENABLE_ALL 0xFFC000FC
716ec4bedbSLiu Gang #define RIO_LTLEECSR 0x060c
726ec4bedbSLiu Gang
73abc3aeaeSLiu Gang #define RIO_IM0SR 0x64
74abc3aeaeSLiu Gang #define RIO_IM1SR 0x164
75abc3aeaeSLiu Gang #define RIO_OM0SR 0x4
76abc3aeaeSLiu Gang #define RIO_OM1SR 0x104
776ec4bedbSLiu Gang
786ec4bedbSLiu Gang #define RIO_DBELL_WIN_SIZE 0x1000
796ec4bedbSLiu Gang
806ec4bedbSLiu Gang #define RIO_MSG_OMR_MUI 0x00000002
816ec4bedbSLiu Gang #define RIO_MSG_OSR_TE 0x00000080
826ec4bedbSLiu Gang #define RIO_MSG_OSR_QOI 0x00000020
836ec4bedbSLiu Gang #define RIO_MSG_OSR_QFI 0x00000010
846ec4bedbSLiu Gang #define RIO_MSG_OSR_MUB 0x00000004
856ec4bedbSLiu Gang #define RIO_MSG_OSR_EOMI 0x00000002
866ec4bedbSLiu Gang #define RIO_MSG_OSR_QEI 0x00000001
876ec4bedbSLiu Gang
886ec4bedbSLiu Gang #define RIO_MSG_IMR_MI 0x00000002
896ec4bedbSLiu Gang #define RIO_MSG_ISR_TE 0x00000080
906ec4bedbSLiu Gang #define RIO_MSG_ISR_QFI 0x00000010
916ec4bedbSLiu Gang #define RIO_MSG_ISR_DIQI 0x00000001
926ec4bedbSLiu Gang
936ec4bedbSLiu Gang #define RIO_MSG_DESC_SIZE 32
946ec4bedbSLiu Gang #define RIO_MSG_BUFFER_SIZE 4096
956ec4bedbSLiu Gang
966ec4bedbSLiu Gang #define DOORBELL_DMR_DI 0x00000002
976ec4bedbSLiu Gang #define DOORBELL_DSR_TE 0x00000080
986ec4bedbSLiu Gang #define DOORBELL_DSR_QFI 0x00000010
996ec4bedbSLiu Gang #define DOORBELL_DSR_DIQI 0x00000001
1006ec4bedbSLiu Gang
1016ec4bedbSLiu Gang #define DOORBELL_MESSAGE_SIZE 0x08
1026ec4bedbSLiu Gang
10331d1e130SIoan Nicu static DEFINE_SPINLOCK(fsl_rio_doorbell_lock);
10431d1e130SIoan Nicu
1056ec4bedbSLiu Gang struct rio_msg_regs {
106abc3aeaeSLiu Gang u32 omr;
107abc3aeaeSLiu Gang u32 osr;
1086ec4bedbSLiu Gang u32 pad1;
109abc3aeaeSLiu Gang u32 odqdpar;
1106ec4bedbSLiu Gang u32 pad2;
111abc3aeaeSLiu Gang u32 osar;
112abc3aeaeSLiu Gang u32 odpr;
113abc3aeaeSLiu Gang u32 odatr;
114abc3aeaeSLiu Gang u32 odcr;
1156ec4bedbSLiu Gang u32 pad3;
116abc3aeaeSLiu Gang u32 odqepar;
1176ec4bedbSLiu Gang u32 pad4[13];
118abc3aeaeSLiu Gang u32 imr;
119abc3aeaeSLiu Gang u32 isr;
1206ec4bedbSLiu Gang u32 pad5;
121abc3aeaeSLiu Gang u32 ifqdpar;
1226ec4bedbSLiu Gang u32 pad6;
123abc3aeaeSLiu Gang u32 ifqepar;
1246ec4bedbSLiu Gang };
1256ec4bedbSLiu Gang
126abc3aeaeSLiu Gang struct rio_dbell_regs {
127abc3aeaeSLiu Gang u32 odmr;
128abc3aeaeSLiu Gang u32 odsr;
129abc3aeaeSLiu Gang u32 pad1[4];
130abc3aeaeSLiu Gang u32 oddpr;
131abc3aeaeSLiu Gang u32 oddatr;
132abc3aeaeSLiu Gang u32 pad2[3];
133abc3aeaeSLiu Gang u32 odretcr;
134abc3aeaeSLiu Gang u32 pad3[12];
135abc3aeaeSLiu Gang u32 dmr;
136abc3aeaeSLiu Gang u32 dsr;
137abc3aeaeSLiu Gang u32 pad4;
138abc3aeaeSLiu Gang u32 dqdpar;
139abc3aeaeSLiu Gang u32 pad5;
140abc3aeaeSLiu Gang u32 dqepar;
141abc3aeaeSLiu Gang };
142abc3aeaeSLiu Gang
143abc3aeaeSLiu Gang struct rio_pw_regs {
144abc3aeaeSLiu Gang u32 pwmr;
145abc3aeaeSLiu Gang u32 pwsr;
146abc3aeaeSLiu Gang u32 epwqbar;
147abc3aeaeSLiu Gang u32 pwqbar;
148abc3aeaeSLiu Gang };
149abc3aeaeSLiu Gang
150abc3aeaeSLiu Gang
1516ec4bedbSLiu Gang struct rio_tx_desc {
152abc3aeaeSLiu Gang u32 pad1;
1536ec4bedbSLiu Gang u32 saddr;
1546ec4bedbSLiu Gang u32 dport;
1556ec4bedbSLiu Gang u32 dattr;
156abc3aeaeSLiu Gang u32 pad2;
157abc3aeaeSLiu Gang u32 pad3;
1586ec4bedbSLiu Gang u32 dwcnt;
159abc3aeaeSLiu Gang u32 pad4;
1606ec4bedbSLiu Gang };
1616ec4bedbSLiu Gang
1626ec4bedbSLiu Gang struct rio_msg_tx_ring {
1636ec4bedbSLiu Gang void *virt;
1646ec4bedbSLiu Gang dma_addr_t phys;
1656ec4bedbSLiu Gang void *virt_buffer[RIO_MAX_TX_RING_SIZE];
1666ec4bedbSLiu Gang dma_addr_t phys_buffer[RIO_MAX_TX_RING_SIZE];
1676ec4bedbSLiu Gang int tx_slot;
1686ec4bedbSLiu Gang int size;
1696ec4bedbSLiu Gang void *dev_id;
1706ec4bedbSLiu Gang };
1716ec4bedbSLiu Gang
1726ec4bedbSLiu Gang struct rio_msg_rx_ring {
1736ec4bedbSLiu Gang void *virt;
1746ec4bedbSLiu Gang dma_addr_t phys;
1756ec4bedbSLiu Gang void *virt_buffer[RIO_MAX_RX_RING_SIZE];
1766ec4bedbSLiu Gang int rx_slot;
1776ec4bedbSLiu Gang int size;
1786ec4bedbSLiu Gang void *dev_id;
1796ec4bedbSLiu Gang };
1806ec4bedbSLiu Gang
1816ec4bedbSLiu Gang struct fsl_rmu {
1826ec4bedbSLiu Gang struct rio_msg_regs __iomem *msg_regs;
1836ec4bedbSLiu Gang struct rio_msg_tx_ring msg_tx_ring;
1846ec4bedbSLiu Gang struct rio_msg_rx_ring msg_rx_ring;
1856ec4bedbSLiu Gang int txirq;
1866ec4bedbSLiu Gang int rxirq;
1876ec4bedbSLiu Gang };
1886ec4bedbSLiu Gang
1892a2383daSLiu Gang struct rio_dbell_msg {
1902a2383daSLiu Gang u16 pad1;
1912a2383daSLiu Gang u16 tid;
1922a2383daSLiu Gang u16 sid;
1932a2383daSLiu Gang u16 info;
1942a2383daSLiu Gang };
1952a2383daSLiu Gang
1966ec4bedbSLiu Gang /**
1976ec4bedbSLiu Gang * fsl_rio_tx_handler - MPC85xx outbound message interrupt handler
1986ec4bedbSLiu Gang * @irq: Linux interrupt number
1996ec4bedbSLiu Gang * @dev_instance: Pointer to interrupt-specific data
2006ec4bedbSLiu Gang *
2016ec4bedbSLiu Gang * Handles outbound message interrupts. Executes a register outbound
2026ec4bedbSLiu Gang * mailbox event handler and acks the interrupt occurrence.
2036ec4bedbSLiu Gang */
2046ec4bedbSLiu Gang static irqreturn_t
fsl_rio_tx_handler(int irq,void * dev_instance)2056ec4bedbSLiu Gang fsl_rio_tx_handler(int irq, void *dev_instance)
2066ec4bedbSLiu Gang {
2076ec4bedbSLiu Gang int osr;
2086ec4bedbSLiu Gang struct rio_mport *port = (struct rio_mport *)dev_instance;
2096ec4bedbSLiu Gang struct fsl_rmu *rmu = GET_RMM_HANDLE(port);
2106ec4bedbSLiu Gang
2116ec4bedbSLiu Gang osr = in_be32(&rmu->msg_regs->osr);
2126ec4bedbSLiu Gang
2136ec4bedbSLiu Gang if (osr & RIO_MSG_OSR_TE) {
2146ec4bedbSLiu Gang pr_info("RIO: outbound message transmission error\n");
2156ec4bedbSLiu Gang out_be32(&rmu->msg_regs->osr, RIO_MSG_OSR_TE);
2166ec4bedbSLiu Gang goto out;
2176ec4bedbSLiu Gang }
2186ec4bedbSLiu Gang
2196ec4bedbSLiu Gang if (osr & RIO_MSG_OSR_QOI) {
2206ec4bedbSLiu Gang pr_info("RIO: outbound message queue overflow\n");
2216ec4bedbSLiu Gang out_be32(&rmu->msg_regs->osr, RIO_MSG_OSR_QOI);
2226ec4bedbSLiu Gang goto out;
2236ec4bedbSLiu Gang }
2246ec4bedbSLiu Gang
2256ec4bedbSLiu Gang if (osr & RIO_MSG_OSR_EOMI) {
2266ec4bedbSLiu Gang u32 dqp = in_be32(&rmu->msg_regs->odqdpar);
2276ec4bedbSLiu Gang int slot = (dqp - rmu->msg_tx_ring.phys) >> 5;
228abc3aeaeSLiu Gang if (port->outb_msg[0].mcback != NULL) {
229abc3aeaeSLiu Gang port->outb_msg[0].mcback(port, rmu->msg_tx_ring.dev_id,
230abc3aeaeSLiu Gang -1,
2316ec4bedbSLiu Gang slot);
232abc3aeaeSLiu Gang }
2336ec4bedbSLiu Gang /* Ack the end-of-message interrupt */
2346ec4bedbSLiu Gang out_be32(&rmu->msg_regs->osr, RIO_MSG_OSR_EOMI);
2356ec4bedbSLiu Gang }
2366ec4bedbSLiu Gang
2376ec4bedbSLiu Gang out:
2386ec4bedbSLiu Gang return IRQ_HANDLED;
2396ec4bedbSLiu Gang }
2406ec4bedbSLiu Gang
2416ec4bedbSLiu Gang /**
2426ec4bedbSLiu Gang * fsl_rio_rx_handler - MPC85xx inbound message interrupt handler
2436ec4bedbSLiu Gang * @irq: Linux interrupt number
2446ec4bedbSLiu Gang * @dev_instance: Pointer to interrupt-specific data
2456ec4bedbSLiu Gang *
2466ec4bedbSLiu Gang * Handles inbound message interrupts. Executes a registered inbound
2476ec4bedbSLiu Gang * mailbox event handler and acks the interrupt occurrence.
2486ec4bedbSLiu Gang */
2496ec4bedbSLiu Gang static irqreturn_t
fsl_rio_rx_handler(int irq,void * dev_instance)2506ec4bedbSLiu Gang fsl_rio_rx_handler(int irq, void *dev_instance)
2516ec4bedbSLiu Gang {
2526ec4bedbSLiu Gang int isr;
2536ec4bedbSLiu Gang struct rio_mport *port = (struct rio_mport *)dev_instance;
2546ec4bedbSLiu Gang struct fsl_rmu *rmu = GET_RMM_HANDLE(port);
2556ec4bedbSLiu Gang
2566ec4bedbSLiu Gang isr = in_be32(&rmu->msg_regs->isr);
2576ec4bedbSLiu Gang
2586ec4bedbSLiu Gang if (isr & RIO_MSG_ISR_TE) {
2596ec4bedbSLiu Gang pr_info("RIO: inbound message reception error\n");
2606ec4bedbSLiu Gang out_be32((void *)&rmu->msg_regs->isr, RIO_MSG_ISR_TE);
2616ec4bedbSLiu Gang goto out;
2626ec4bedbSLiu Gang }
2636ec4bedbSLiu Gang
2646ec4bedbSLiu Gang /* XXX Need to check/dispatch until queue empty */
2656ec4bedbSLiu Gang if (isr & RIO_MSG_ISR_DIQI) {
2666ec4bedbSLiu Gang /*
267abc3aeaeSLiu Gang * Can receive messages for any mailbox/letter to that
268abc3aeaeSLiu Gang * mailbox destination. So, make the callback with an
269abc3aeaeSLiu Gang * unknown/invalid mailbox number argument.
2706ec4bedbSLiu Gang */
271abc3aeaeSLiu Gang if (port->inb_msg[0].mcback != NULL)
272abc3aeaeSLiu Gang port->inb_msg[0].mcback(port, rmu->msg_rx_ring.dev_id,
273abc3aeaeSLiu Gang -1,
274abc3aeaeSLiu Gang -1);
2756ec4bedbSLiu Gang
2766ec4bedbSLiu Gang /* Ack the queueing interrupt */
2776ec4bedbSLiu Gang out_be32(&rmu->msg_regs->isr, RIO_MSG_ISR_DIQI);
2786ec4bedbSLiu Gang }
2796ec4bedbSLiu Gang
2806ec4bedbSLiu Gang out:
2816ec4bedbSLiu Gang return IRQ_HANDLED;
2826ec4bedbSLiu Gang }
2836ec4bedbSLiu Gang
2846ec4bedbSLiu Gang /**
2856ec4bedbSLiu Gang * fsl_rio_dbell_handler - MPC85xx doorbell interrupt handler
2866ec4bedbSLiu Gang * @irq: Linux interrupt number
2876ec4bedbSLiu Gang * @dev_instance: Pointer to interrupt-specific data
2886ec4bedbSLiu Gang *
2896ec4bedbSLiu Gang * Handles doorbell interrupts. Parses a list of registered
2906ec4bedbSLiu Gang * doorbell event handlers and executes a matching event handler.
2916ec4bedbSLiu Gang */
2926ec4bedbSLiu Gang static irqreturn_t
fsl_rio_dbell_handler(int irq,void * dev_instance)2936ec4bedbSLiu Gang fsl_rio_dbell_handler(int irq, void *dev_instance)
2946ec4bedbSLiu Gang {
2956ec4bedbSLiu Gang int dsr;
296abc3aeaeSLiu Gang struct fsl_rio_dbell *fsl_dbell = (struct fsl_rio_dbell *)dev_instance;
297abc3aeaeSLiu Gang int i;
2986ec4bedbSLiu Gang
299abc3aeaeSLiu Gang dsr = in_be32(&fsl_dbell->dbell_regs->dsr);
3006ec4bedbSLiu Gang
3016ec4bedbSLiu Gang if (dsr & DOORBELL_DSR_TE) {
3026ec4bedbSLiu Gang pr_info("RIO: doorbell reception error\n");
303abc3aeaeSLiu Gang out_be32(&fsl_dbell->dbell_regs->dsr, DOORBELL_DSR_TE);
3046ec4bedbSLiu Gang goto out;
3056ec4bedbSLiu Gang }
3066ec4bedbSLiu Gang
3076ec4bedbSLiu Gang if (dsr & DOORBELL_DSR_QFI) {
3086ec4bedbSLiu Gang pr_info("RIO: doorbell queue full\n");
309abc3aeaeSLiu Gang out_be32(&fsl_dbell->dbell_regs->dsr, DOORBELL_DSR_QFI);
3106ec4bedbSLiu Gang }
3116ec4bedbSLiu Gang
3126ec4bedbSLiu Gang /* XXX Need to check/dispatch until queue empty */
3136ec4bedbSLiu Gang if (dsr & DOORBELL_DSR_DIQI) {
3142a2383daSLiu Gang struct rio_dbell_msg *dmsg =
3152a2383daSLiu Gang fsl_dbell->dbell_ring.virt +
316abc3aeaeSLiu Gang (in_be32(&fsl_dbell->dbell_regs->dqdpar) & 0xfff);
3176ec4bedbSLiu Gang struct rio_dbell *dbell;
3186ec4bedbSLiu Gang int found = 0;
3196ec4bedbSLiu Gang
3206ec4bedbSLiu Gang pr_debug
3216ec4bedbSLiu Gang ("RIO: processing doorbell,"
3226ec4bedbSLiu Gang " sid %2.2x tid %2.2x info %4.4x\n",
3232a2383daSLiu Gang dmsg->sid, dmsg->tid, dmsg->info);
3246ec4bedbSLiu Gang
325abc3aeaeSLiu Gang for (i = 0; i < MAX_PORT_NUM; i++) {
326abc3aeaeSLiu Gang if (fsl_dbell->mport[i]) {
327abc3aeaeSLiu Gang list_for_each_entry(dbell,
328abc3aeaeSLiu Gang &fsl_dbell->mport[i]->dbells, node) {
329abc3aeaeSLiu Gang if ((dbell->res->start
3302a2383daSLiu Gang <= dmsg->info)
331abc3aeaeSLiu Gang && (dbell->res->end
3322a2383daSLiu Gang >= dmsg->info)) {
3336ec4bedbSLiu Gang found = 1;
3346ec4bedbSLiu Gang break;
3356ec4bedbSLiu Gang }
3366ec4bedbSLiu Gang }
337abc3aeaeSLiu Gang if (found && dbell->dinb) {
338abc3aeaeSLiu Gang dbell->dinb(fsl_dbell->mport[i],
3392a2383daSLiu Gang dbell->dev_id, dmsg->sid,
3402a2383daSLiu Gang dmsg->tid,
3412a2383daSLiu Gang dmsg->info);
342abc3aeaeSLiu Gang break;
343abc3aeaeSLiu Gang }
344abc3aeaeSLiu Gang }
345abc3aeaeSLiu Gang }
346abc3aeaeSLiu Gang
347abc3aeaeSLiu Gang if (!found) {
3486ec4bedbSLiu Gang pr_debug
3496ec4bedbSLiu Gang ("RIO: spurious doorbell,"
3506ec4bedbSLiu Gang " sid %2.2x tid %2.2x info %4.4x\n",
3512a2383daSLiu Gang dmsg->sid, dmsg->tid,
3522a2383daSLiu Gang dmsg->info);
3536ec4bedbSLiu Gang }
354abc3aeaeSLiu Gang setbits32(&fsl_dbell->dbell_regs->dmr, DOORBELL_DMR_DI);
355abc3aeaeSLiu Gang out_be32(&fsl_dbell->dbell_regs->dsr, DOORBELL_DSR_DIQI);
3566ec4bedbSLiu Gang }
3576ec4bedbSLiu Gang
3586ec4bedbSLiu Gang out:
3596ec4bedbSLiu Gang return IRQ_HANDLED;
3606ec4bedbSLiu Gang }
3616ec4bedbSLiu Gang
msg_unit_error_handler(void)362*c265735fSChristophe Leroy static void msg_unit_error_handler(void)
3636ec4bedbSLiu Gang {
3646ec4bedbSLiu Gang
3656ec4bedbSLiu Gang /*XXX: Error recovery is not implemented, we just clear errors */
3666ec4bedbSLiu Gang out_be32((u32 *)(rio_regs_win + RIO_LTLEDCSR), 0);
3676ec4bedbSLiu Gang
368abc3aeaeSLiu Gang out_be32((u32 *)(rmu_regs_win + RIO_IM0SR), IMSR_CLEAR);
369abc3aeaeSLiu Gang out_be32((u32 *)(rmu_regs_win + RIO_IM1SR), IMSR_CLEAR);
370abc3aeaeSLiu Gang out_be32((u32 *)(rmu_regs_win + RIO_OM0SR), OMSR_CLEAR);
371abc3aeaeSLiu Gang out_be32((u32 *)(rmu_regs_win + RIO_OM1SR), OMSR_CLEAR);
3726ec4bedbSLiu Gang
373abc3aeaeSLiu Gang out_be32(&dbell->dbell_regs->odsr, ODSR_CLEAR);
374abc3aeaeSLiu Gang out_be32(&dbell->dbell_regs->dsr, IDSR_CLEAR);
3756ec4bedbSLiu Gang
376abc3aeaeSLiu Gang out_be32(&pw->pw_regs->pwsr, IPWSR_CLEAR);
3776ec4bedbSLiu Gang }
3786ec4bedbSLiu Gang
3796ec4bedbSLiu Gang /**
3806ec4bedbSLiu Gang * fsl_rio_port_write_handler - MPC85xx port write interrupt handler
3816ec4bedbSLiu Gang * @irq: Linux interrupt number
3826ec4bedbSLiu Gang * @dev_instance: Pointer to interrupt-specific data
3836ec4bedbSLiu Gang *
3846ec4bedbSLiu Gang * Handles port write interrupts. Parses a list of registered
3856ec4bedbSLiu Gang * port write event handlers and executes a matching event handler.
3866ec4bedbSLiu Gang */
3876ec4bedbSLiu Gang static irqreturn_t
fsl_rio_port_write_handler(int irq,void * dev_instance)3886ec4bedbSLiu Gang fsl_rio_port_write_handler(int irq, void *dev_instance)
3896ec4bedbSLiu Gang {
3906ec4bedbSLiu Gang u32 ipwmr, ipwsr;
391abc3aeaeSLiu Gang struct fsl_rio_pw *pw = (struct fsl_rio_pw *)dev_instance;
3926ec4bedbSLiu Gang u32 epwisr, tmp;
3936ec4bedbSLiu Gang
394abc3aeaeSLiu Gang epwisr = in_be32(rio_regs_win + RIO_EPWISR);
3956ec4bedbSLiu Gang if (!(epwisr & RIO_EPWISR_PW))
3966ec4bedbSLiu Gang goto pw_done;
3976ec4bedbSLiu Gang
398abc3aeaeSLiu Gang ipwmr = in_be32(&pw->pw_regs->pwmr);
399abc3aeaeSLiu Gang ipwsr = in_be32(&pw->pw_regs->pwsr);
4006ec4bedbSLiu Gang
4016ec4bedbSLiu Gang #ifdef DEBUG_PW
4026ec4bedbSLiu Gang pr_debug("PW Int->IPWMR: 0x%08x IPWSR: 0x%08x (", ipwmr, ipwsr);
4036ec4bedbSLiu Gang if (ipwsr & RIO_IPWSR_QF)
4046ec4bedbSLiu Gang pr_debug(" QF");
4056ec4bedbSLiu Gang if (ipwsr & RIO_IPWSR_TE)
4066ec4bedbSLiu Gang pr_debug(" TE");
4076ec4bedbSLiu Gang if (ipwsr & RIO_IPWSR_QFI)
4086ec4bedbSLiu Gang pr_debug(" QFI");
4096ec4bedbSLiu Gang if (ipwsr & RIO_IPWSR_PWD)
4106ec4bedbSLiu Gang pr_debug(" PWD");
4116ec4bedbSLiu Gang if (ipwsr & RIO_IPWSR_PWB)
4126ec4bedbSLiu Gang pr_debug(" PWB");
4136ec4bedbSLiu Gang pr_debug(" )\n");
4146ec4bedbSLiu Gang #endif
4156ec4bedbSLiu Gang /* Schedule deferred processing if PW was received */
4166ec4bedbSLiu Gang if (ipwsr & RIO_IPWSR_QFI) {
4176ec4bedbSLiu Gang /* Save PW message (if there is room in FIFO),
4186ec4bedbSLiu Gang * otherwise discard it.
4196ec4bedbSLiu Gang */
420abc3aeaeSLiu Gang if (kfifo_avail(&pw->pw_fifo) >= RIO_PW_MSG_SIZE) {
421abc3aeaeSLiu Gang pw->port_write_msg.msg_count++;
422abc3aeaeSLiu Gang kfifo_in(&pw->pw_fifo, pw->port_write_msg.virt,
4236ec4bedbSLiu Gang RIO_PW_MSG_SIZE);
4246ec4bedbSLiu Gang } else {
425abc3aeaeSLiu Gang pw->port_write_msg.discard_count++;
4266ec4bedbSLiu Gang pr_debug("RIO: ISR Discarded Port-Write Msg(s) (%d)\n",
427abc3aeaeSLiu Gang pw->port_write_msg.discard_count);
4286ec4bedbSLiu Gang }
4296ec4bedbSLiu Gang /* Clear interrupt and issue Clear Queue command. This allows
4306ec4bedbSLiu Gang * another port-write to be received.
4316ec4bedbSLiu Gang */
432abc3aeaeSLiu Gang out_be32(&pw->pw_regs->pwsr, RIO_IPWSR_QFI);
433abc3aeaeSLiu Gang out_be32(&pw->pw_regs->pwmr, ipwmr | RIO_IPWMR_CQ);
4346ec4bedbSLiu Gang
435abc3aeaeSLiu Gang schedule_work(&pw->pw_work);
4366ec4bedbSLiu Gang }
4376ec4bedbSLiu Gang
4386ec4bedbSLiu Gang if ((ipwmr & RIO_IPWMR_EIE) && (ipwsr & RIO_IPWSR_TE)) {
439abc3aeaeSLiu Gang pw->port_write_msg.err_count++;
4406ec4bedbSLiu Gang pr_debug("RIO: Port-Write Transaction Err (%d)\n",
441abc3aeaeSLiu Gang pw->port_write_msg.err_count);
4426ec4bedbSLiu Gang /* Clear Transaction Error: port-write controller should be
4436ec4bedbSLiu Gang * disabled when clearing this error
4446ec4bedbSLiu Gang */
445abc3aeaeSLiu Gang out_be32(&pw->pw_regs->pwmr, ipwmr & ~RIO_IPWMR_PWE);
446abc3aeaeSLiu Gang out_be32(&pw->pw_regs->pwsr, RIO_IPWSR_TE);
447abc3aeaeSLiu Gang out_be32(&pw->pw_regs->pwmr, ipwmr);
4486ec4bedbSLiu Gang }
4496ec4bedbSLiu Gang
4506ec4bedbSLiu Gang if (ipwsr & RIO_IPWSR_PWD) {
451abc3aeaeSLiu Gang pw->port_write_msg.discard_count++;
4526ec4bedbSLiu Gang pr_debug("RIO: Port Discarded Port-Write Msg(s) (%d)\n",
453abc3aeaeSLiu Gang pw->port_write_msg.discard_count);
454abc3aeaeSLiu Gang out_be32(&pw->pw_regs->pwsr, RIO_IPWSR_PWD);
4556ec4bedbSLiu Gang }
4566ec4bedbSLiu Gang
4576ec4bedbSLiu Gang pw_done:
4586ec4bedbSLiu Gang if (epwisr & RIO_EPWISR_PINT1) {
459abc3aeaeSLiu Gang tmp = in_be32(rio_regs_win + RIO_LTLEDCSR);
4606ec4bedbSLiu Gang pr_debug("RIO_LTLEDCSR = 0x%x\n", tmp);
461abc3aeaeSLiu Gang fsl_rio_port_error_handler(0);
4626ec4bedbSLiu Gang }
4636ec4bedbSLiu Gang
4646ec4bedbSLiu Gang if (epwisr & RIO_EPWISR_PINT2) {
465abc3aeaeSLiu Gang tmp = in_be32(rio_regs_win + RIO_LTLEDCSR);
4666ec4bedbSLiu Gang pr_debug("RIO_LTLEDCSR = 0x%x\n", tmp);
467abc3aeaeSLiu Gang fsl_rio_port_error_handler(1);
4686ec4bedbSLiu Gang }
4696ec4bedbSLiu Gang
4706ec4bedbSLiu Gang if (epwisr & RIO_EPWISR_MU) {
471abc3aeaeSLiu Gang tmp = in_be32(rio_regs_win + RIO_LTLEDCSR);
4726ec4bedbSLiu Gang pr_debug("RIO_LTLEDCSR = 0x%x\n", tmp);
473abc3aeaeSLiu Gang msg_unit_error_handler();
4746ec4bedbSLiu Gang }
4756ec4bedbSLiu Gang
4766ec4bedbSLiu Gang return IRQ_HANDLED;
4776ec4bedbSLiu Gang }
4786ec4bedbSLiu Gang
fsl_pw_dpc(struct work_struct * work)4796ec4bedbSLiu Gang static void fsl_pw_dpc(struct work_struct *work)
4806ec4bedbSLiu Gang {
481abc3aeaeSLiu Gang struct fsl_rio_pw *pw = container_of(work, struct fsl_rio_pw, pw_work);
4829a0b0627SAlexandre Bounine union rio_pw_msg msg_buffer;
4839a0b0627SAlexandre Bounine int i;
4846ec4bedbSLiu Gang
4856ec4bedbSLiu Gang /*
4866ec4bedbSLiu Gang * Process port-write messages
4876ec4bedbSLiu Gang */
4889a0b0627SAlexandre Bounine while (kfifo_out_spinlocked(&pw->pw_fifo, (unsigned char *)&msg_buffer,
489abc3aeaeSLiu Gang RIO_PW_MSG_SIZE, &pw->pw_fifo_lock)) {
4906ec4bedbSLiu Gang #ifdef DEBUG_PW
4916ec4bedbSLiu Gang {
4926ec4bedbSLiu Gang u32 i;
4936ec4bedbSLiu Gang pr_debug("%s : Port-Write Message:", __func__);
4946ec4bedbSLiu Gang for (i = 0; i < RIO_PW_MSG_SIZE/sizeof(u32); i++) {
4956ec4bedbSLiu Gang if ((i%4) == 0)
4966ec4bedbSLiu Gang pr_debug("\n0x%02x: 0x%08x", i*4,
4979a0b0627SAlexandre Bounine msg_buffer.raw[i]);
4986ec4bedbSLiu Gang else
4999a0b0627SAlexandre Bounine pr_debug(" 0x%08x", msg_buffer.raw[i]);
5006ec4bedbSLiu Gang }
5016ec4bedbSLiu Gang pr_debug("\n");
5026ec4bedbSLiu Gang }
5036ec4bedbSLiu Gang #endif
5046ec4bedbSLiu Gang /* Pass the port-write message to RIO core for processing */
5059a0b0627SAlexandre Bounine for (i = 0; i < MAX_PORT_NUM; i++) {
5069a0b0627SAlexandre Bounine if (pw->mport[i])
5079a0b0627SAlexandre Bounine rio_inb_pwrite_handler(pw->mport[i],
5089a0b0627SAlexandre Bounine &msg_buffer);
5099a0b0627SAlexandre Bounine }
5106ec4bedbSLiu Gang }
5116ec4bedbSLiu Gang }
5126ec4bedbSLiu Gang
5136ec4bedbSLiu Gang /**
5146ec4bedbSLiu Gang * fsl_rio_pw_enable - enable/disable port-write interface init
5156ec4bedbSLiu Gang * @mport: Master port implementing the port write unit
5166ec4bedbSLiu Gang * @enable: 1=enable; 0=disable port-write message handling
5176ec4bedbSLiu Gang */
fsl_rio_pw_enable(struct rio_mport * mport,int enable)5186ec4bedbSLiu Gang int fsl_rio_pw_enable(struct rio_mport *mport, int enable)
5196ec4bedbSLiu Gang {
5206ec4bedbSLiu Gang u32 rval;
5216ec4bedbSLiu Gang
522abc3aeaeSLiu Gang rval = in_be32(&pw->pw_regs->pwmr);
5236ec4bedbSLiu Gang
5246ec4bedbSLiu Gang if (enable)
5256ec4bedbSLiu Gang rval |= RIO_IPWMR_PWE;
5266ec4bedbSLiu Gang else
5276ec4bedbSLiu Gang rval &= ~RIO_IPWMR_PWE;
5286ec4bedbSLiu Gang
529abc3aeaeSLiu Gang out_be32(&pw->pw_regs->pwmr, rval);
5306ec4bedbSLiu Gang
5316ec4bedbSLiu Gang return 0;
5326ec4bedbSLiu Gang }
5336ec4bedbSLiu Gang
5346ec4bedbSLiu Gang /**
5356ec4bedbSLiu Gang * fsl_rio_port_write_init - MPC85xx port write interface init
5366ec4bedbSLiu Gang * @mport: Master port implementing the port write unit
5376ec4bedbSLiu Gang *
5386ec4bedbSLiu Gang * Initializes port write unit hardware and DMA buffer
5396ec4bedbSLiu Gang * ring. Called from fsl_rio_setup(). Returns %0 on success
5406ec4bedbSLiu Gang * or %-ENOMEM on failure.
5416ec4bedbSLiu Gang */
5426ec4bedbSLiu Gang
fsl_rio_port_write_init(struct fsl_rio_pw * pw)543abc3aeaeSLiu Gang int fsl_rio_port_write_init(struct fsl_rio_pw *pw)
5446ec4bedbSLiu Gang {
5456ec4bedbSLiu Gang int rc = 0;
5466ec4bedbSLiu Gang
5476ec4bedbSLiu Gang /* Following configurations require a disabled port write controller */
548abc3aeaeSLiu Gang out_be32(&pw->pw_regs->pwmr,
549abc3aeaeSLiu Gang in_be32(&pw->pw_regs->pwmr) & ~RIO_IPWMR_PWE);
5506ec4bedbSLiu Gang
5516ec4bedbSLiu Gang /* Initialize port write */
552abc3aeaeSLiu Gang pw->port_write_msg.virt = dma_alloc_coherent(pw->dev,
5536ec4bedbSLiu Gang RIO_PW_MSG_SIZE,
554abc3aeaeSLiu Gang &pw->port_write_msg.phys, GFP_KERNEL);
555abc3aeaeSLiu Gang if (!pw->port_write_msg.virt) {
5566ec4bedbSLiu Gang pr_err("RIO: unable allocate port write queue\n");
5576ec4bedbSLiu Gang return -ENOMEM;
5586ec4bedbSLiu Gang }
5596ec4bedbSLiu Gang
560abc3aeaeSLiu Gang pw->port_write_msg.err_count = 0;
561abc3aeaeSLiu Gang pw->port_write_msg.discard_count = 0;
5626ec4bedbSLiu Gang
5636ec4bedbSLiu Gang /* Point dequeue/enqueue pointers at first entry */
564abc3aeaeSLiu Gang out_be32(&pw->pw_regs->epwqbar, 0);
565abc3aeaeSLiu Gang out_be32(&pw->pw_regs->pwqbar, (u32) pw->port_write_msg.phys);
5666ec4bedbSLiu Gang
5676ec4bedbSLiu Gang pr_debug("EIPWQBAR: 0x%08x IPWQBAR: 0x%08x\n",
568abc3aeaeSLiu Gang in_be32(&pw->pw_regs->epwqbar),
569abc3aeaeSLiu Gang in_be32(&pw->pw_regs->pwqbar));
5706ec4bedbSLiu Gang
5716ec4bedbSLiu Gang /* Clear interrupt status IPWSR */
572abc3aeaeSLiu Gang out_be32(&pw->pw_regs->pwsr,
5736ec4bedbSLiu Gang (RIO_IPWSR_TE | RIO_IPWSR_QFI | RIO_IPWSR_PWD));
5746ec4bedbSLiu Gang
575446957baSAdam Buchbinder /* Configure port write controller for snooping enable all reporting,
5766ec4bedbSLiu Gang clear queue full */
577abc3aeaeSLiu Gang out_be32(&pw->pw_regs->pwmr,
5786ec4bedbSLiu Gang RIO_IPWMR_SEN | RIO_IPWMR_QFIE | RIO_IPWMR_EIE | RIO_IPWMR_CQ);
5796ec4bedbSLiu Gang
5806ec4bedbSLiu Gang
5816ec4bedbSLiu Gang /* Hook up port-write handler */
582abc3aeaeSLiu Gang rc = request_irq(IRQ_RIO_PW(pw), fsl_rio_port_write_handler,
583abc3aeaeSLiu Gang IRQF_SHARED, "port-write", (void *)pw);
5846ec4bedbSLiu Gang if (rc < 0) {
5856ec4bedbSLiu Gang pr_err("MPC85xx RIO: unable to request inbound doorbell irq");
5866ec4bedbSLiu Gang goto err_out;
5876ec4bedbSLiu Gang }
5886ec4bedbSLiu Gang /* Enable Error Interrupt */
5896ec4bedbSLiu Gang out_be32((u32 *)(rio_regs_win + RIO_LTLEECSR), LTLEECSR_ENABLE_ALL);
5906ec4bedbSLiu Gang
591abc3aeaeSLiu Gang INIT_WORK(&pw->pw_work, fsl_pw_dpc);
592abc3aeaeSLiu Gang spin_lock_init(&pw->pw_fifo_lock);
593abc3aeaeSLiu Gang if (kfifo_alloc(&pw->pw_fifo, RIO_PW_MSG_SIZE * 32, GFP_KERNEL)) {
5946ec4bedbSLiu Gang pr_err("FIFO allocation failed\n");
5956ec4bedbSLiu Gang rc = -ENOMEM;
5966ec4bedbSLiu Gang goto err_out_irq;
5976ec4bedbSLiu Gang }
5986ec4bedbSLiu Gang
5996ec4bedbSLiu Gang pr_debug("IPWMR: 0x%08x IPWSR: 0x%08x\n",
600abc3aeaeSLiu Gang in_be32(&pw->pw_regs->pwmr),
601abc3aeaeSLiu Gang in_be32(&pw->pw_regs->pwsr));
6026ec4bedbSLiu Gang
6036ec4bedbSLiu Gang return rc;
6046ec4bedbSLiu Gang
6056ec4bedbSLiu Gang err_out_irq:
606abc3aeaeSLiu Gang free_irq(IRQ_RIO_PW(pw), (void *)pw);
6076ec4bedbSLiu Gang err_out:
608abc3aeaeSLiu Gang dma_free_coherent(pw->dev, RIO_PW_MSG_SIZE,
609abc3aeaeSLiu Gang pw->port_write_msg.virt,
610abc3aeaeSLiu Gang pw->port_write_msg.phys);
6116ec4bedbSLiu Gang return rc;
6126ec4bedbSLiu Gang }
6136ec4bedbSLiu Gang
6146ec4bedbSLiu Gang /**
6156ec4bedbSLiu Gang * fsl_rio_doorbell_send - Send a MPC85xx doorbell message
6166ec4bedbSLiu Gang * @mport: RapidIO master port info
6176ec4bedbSLiu Gang * @index: ID of RapidIO interface
6186ec4bedbSLiu Gang * @destid: Destination ID of target device
6196ec4bedbSLiu Gang * @data: 16-bit info field of RapidIO doorbell message
6206ec4bedbSLiu Gang *
6216ec4bedbSLiu Gang * Sends a MPC85xx doorbell message. Returns %0 on success or
6226ec4bedbSLiu Gang * %-EINVAL on failure.
6236ec4bedbSLiu Gang */
fsl_rio_doorbell_send(struct rio_mport * mport,int index,u16 destid,u16 data)624abc3aeaeSLiu Gang int fsl_rio_doorbell_send(struct rio_mport *mport,
6256ec4bedbSLiu Gang int index, u16 destid, u16 data)
6266ec4bedbSLiu Gang {
62731d1e130SIoan Nicu unsigned long flags;
62831d1e130SIoan Nicu
6296ec4bedbSLiu Gang pr_debug("fsl_doorbell_send: index %d destid %4.4x data %4.4x\n",
6306ec4bedbSLiu Gang index, destid, data);
631abc3aeaeSLiu Gang
63231d1e130SIoan Nicu spin_lock_irqsave(&fsl_rio_doorbell_lock, flags);
63331d1e130SIoan Nicu
6346ec4bedbSLiu Gang /* In the serial version silicons, such as MPC8548, MPC8641,
6356ec4bedbSLiu Gang * below operations is must be.
6366ec4bedbSLiu Gang */
637abc3aeaeSLiu Gang out_be32(&dbell->dbell_regs->odmr, 0x00000000);
638abc3aeaeSLiu Gang out_be32(&dbell->dbell_regs->odretcr, 0x00000004);
639abc3aeaeSLiu Gang out_be32(&dbell->dbell_regs->oddpr, destid << 16);
640abc3aeaeSLiu Gang out_be32(&dbell->dbell_regs->oddatr, (index << 20) | data);
641abc3aeaeSLiu Gang out_be32(&dbell->dbell_regs->odmr, 0x00000001);
6426ec4bedbSLiu Gang
64331d1e130SIoan Nicu spin_unlock_irqrestore(&fsl_rio_doorbell_lock, flags);
64431d1e130SIoan Nicu
6456ec4bedbSLiu Gang return 0;
6466ec4bedbSLiu Gang }
6476ec4bedbSLiu Gang
6486ec4bedbSLiu Gang /**
6496ec4bedbSLiu Gang * fsl_add_outb_message - Add message to the MPC85xx outbound message queue
6506ec4bedbSLiu Gang * @mport: Master port with outbound message queue
6516ec4bedbSLiu Gang * @rdev: Target of outbound message
6526ec4bedbSLiu Gang * @mbox: Outbound mailbox
6536ec4bedbSLiu Gang * @buffer: Message to add to outbound queue
6546ec4bedbSLiu Gang * @len: Length of message
6556ec4bedbSLiu Gang *
6566ec4bedbSLiu Gang * Adds the @buffer message to the MPC85xx outbound message queue. Returns
6576ec4bedbSLiu Gang * %0 on success or %-EINVAL on failure.
6586ec4bedbSLiu Gang */
659abc3aeaeSLiu Gang int
fsl_add_outb_message(struct rio_mport * mport,struct rio_dev * rdev,int mbox,void * buffer,size_t len)6606ec4bedbSLiu Gang fsl_add_outb_message(struct rio_mport *mport, struct rio_dev *rdev, int mbox,
6616ec4bedbSLiu Gang void *buffer, size_t len)
6626ec4bedbSLiu Gang {
6636ec4bedbSLiu Gang struct fsl_rmu *rmu = GET_RMM_HANDLE(mport);
6646ec4bedbSLiu Gang u32 omr;
6656ec4bedbSLiu Gang struct rio_tx_desc *desc = (struct rio_tx_desc *)rmu->msg_tx_ring.virt
6666ec4bedbSLiu Gang + rmu->msg_tx_ring.tx_slot;
6676ec4bedbSLiu Gang int ret = 0;
6686ec4bedbSLiu Gang
6696ec4bedbSLiu Gang pr_debug("RIO: fsl_add_outb_message(): destid %4.4x mbox %d buffer " \
6702a2383daSLiu Gang "%p len %8.8zx\n", rdev->destid, mbox, buffer, len);
6716ec4bedbSLiu Gang if ((len < 8) || (len > RIO_MAX_MSG_SIZE)) {
6726ec4bedbSLiu Gang ret = -EINVAL;
6736ec4bedbSLiu Gang goto out;
6746ec4bedbSLiu Gang }
6756ec4bedbSLiu Gang
6766ec4bedbSLiu Gang /* Copy and clear rest of buffer */
6776ec4bedbSLiu Gang memcpy(rmu->msg_tx_ring.virt_buffer[rmu->msg_tx_ring.tx_slot], buffer,
6786ec4bedbSLiu Gang len);
6796ec4bedbSLiu Gang if (len < (RIO_MAX_MSG_SIZE - 4))
6806ec4bedbSLiu Gang memset(rmu->msg_tx_ring.virt_buffer[rmu->msg_tx_ring.tx_slot]
6816ec4bedbSLiu Gang + len, 0, RIO_MAX_MSG_SIZE - len);
6826ec4bedbSLiu Gang
6836ec4bedbSLiu Gang /* Set mbox field for message, and set destid */
6846ec4bedbSLiu Gang desc->dport = (rdev->destid << 16) | (mbox & 0x3);
6856ec4bedbSLiu Gang
6866ec4bedbSLiu Gang /* Enable EOMI interrupt and priority */
687abc3aeaeSLiu Gang desc->dattr = 0x28000000 | ((mport->index) << 20);
6886ec4bedbSLiu Gang
6896ec4bedbSLiu Gang /* Set transfer size aligned to next power of 2 (in double words) */
6906ec4bedbSLiu Gang desc->dwcnt = is_power_of_2(len) ? len : 1 << get_bitmask_order(len);
6916ec4bedbSLiu Gang
6926ec4bedbSLiu Gang /* Set snooping and source buffer address */
6936ec4bedbSLiu Gang desc->saddr = 0x00000004
6946ec4bedbSLiu Gang | rmu->msg_tx_ring.phys_buffer[rmu->msg_tx_ring.tx_slot];
6956ec4bedbSLiu Gang
6966ec4bedbSLiu Gang /* Increment enqueue pointer */
6976ec4bedbSLiu Gang omr = in_be32(&rmu->msg_regs->omr);
6986ec4bedbSLiu Gang out_be32(&rmu->msg_regs->omr, omr | RIO_MSG_OMR_MUI);
6996ec4bedbSLiu Gang
7006ec4bedbSLiu Gang /* Go to next descriptor */
7016ec4bedbSLiu Gang if (++rmu->msg_tx_ring.tx_slot == rmu->msg_tx_ring.size)
7026ec4bedbSLiu Gang rmu->msg_tx_ring.tx_slot = 0;
7036ec4bedbSLiu Gang
7046ec4bedbSLiu Gang out:
7056ec4bedbSLiu Gang return ret;
7066ec4bedbSLiu Gang }
7076ec4bedbSLiu Gang
7086ec4bedbSLiu Gang /**
7096ec4bedbSLiu Gang * fsl_open_outb_mbox - Initialize MPC85xx outbound mailbox
7106ec4bedbSLiu Gang * @mport: Master port implementing the outbound message unit
7116ec4bedbSLiu Gang * @dev_id: Device specific pointer to pass on event
7126ec4bedbSLiu Gang * @mbox: Mailbox to open
7136ec4bedbSLiu Gang * @entries: Number of entries in the outbound mailbox ring
7146ec4bedbSLiu Gang *
7156ec4bedbSLiu Gang * Initializes buffer ring, request the outbound message interrupt,
7166ec4bedbSLiu Gang * and enables the outbound message unit. Returns %0 on success and
7176ec4bedbSLiu Gang * %-EINVAL or %-ENOMEM on failure.
7186ec4bedbSLiu Gang */
719abc3aeaeSLiu Gang int
fsl_open_outb_mbox(struct rio_mport * mport,void * dev_id,int mbox,int entries)7206ec4bedbSLiu Gang fsl_open_outb_mbox(struct rio_mport *mport, void *dev_id, int mbox, int entries)
7216ec4bedbSLiu Gang {
7226ec4bedbSLiu Gang int i, j, rc = 0;
7236ec4bedbSLiu Gang struct rio_priv *priv = mport->priv;
7246ec4bedbSLiu Gang struct fsl_rmu *rmu = GET_RMM_HANDLE(mport);
7256ec4bedbSLiu Gang
7266ec4bedbSLiu Gang if ((entries < RIO_MIN_TX_RING_SIZE) ||
7276ec4bedbSLiu Gang (entries > RIO_MAX_TX_RING_SIZE) || (!is_power_of_2(entries))) {
7286ec4bedbSLiu Gang rc = -EINVAL;
7296ec4bedbSLiu Gang goto out;
7306ec4bedbSLiu Gang }
7316ec4bedbSLiu Gang
7326ec4bedbSLiu Gang /* Initialize shadow copy ring */
7336ec4bedbSLiu Gang rmu->msg_tx_ring.dev_id = dev_id;
7346ec4bedbSLiu Gang rmu->msg_tx_ring.size = entries;
7356ec4bedbSLiu Gang
7366ec4bedbSLiu Gang for (i = 0; i < rmu->msg_tx_ring.size; i++) {
7376ec4bedbSLiu Gang rmu->msg_tx_ring.virt_buffer[i] =
7386ec4bedbSLiu Gang dma_alloc_coherent(priv->dev, RIO_MSG_BUFFER_SIZE,
7396ec4bedbSLiu Gang &rmu->msg_tx_ring.phys_buffer[i], GFP_KERNEL);
7406ec4bedbSLiu Gang if (!rmu->msg_tx_ring.virt_buffer[i]) {
7416ec4bedbSLiu Gang rc = -ENOMEM;
7426ec4bedbSLiu Gang for (j = 0; j < rmu->msg_tx_ring.size; j++)
7436ec4bedbSLiu Gang if (rmu->msg_tx_ring.virt_buffer[j])
7446ec4bedbSLiu Gang dma_free_coherent(priv->dev,
7456ec4bedbSLiu Gang RIO_MSG_BUFFER_SIZE,
7466ec4bedbSLiu Gang rmu->msg_tx_ring.
7476ec4bedbSLiu Gang virt_buffer[j],
7486ec4bedbSLiu Gang rmu->msg_tx_ring.
7496ec4bedbSLiu Gang phys_buffer[j]);
7506ec4bedbSLiu Gang goto out;
7516ec4bedbSLiu Gang }
7526ec4bedbSLiu Gang }
7536ec4bedbSLiu Gang
7546ec4bedbSLiu Gang /* Initialize outbound message descriptor ring */
755750afb08SLuis Chamberlain rmu->msg_tx_ring.virt = dma_alloc_coherent(priv->dev,
7566ec4bedbSLiu Gang rmu->msg_tx_ring.size * RIO_MSG_DESC_SIZE,
757750afb08SLuis Chamberlain &rmu->msg_tx_ring.phys,
758750afb08SLuis Chamberlain GFP_KERNEL);
7596ec4bedbSLiu Gang if (!rmu->msg_tx_ring.virt) {
7606ec4bedbSLiu Gang rc = -ENOMEM;
7616ec4bedbSLiu Gang goto out_dma;
7626ec4bedbSLiu Gang }
7636ec4bedbSLiu Gang rmu->msg_tx_ring.tx_slot = 0;
7646ec4bedbSLiu Gang
7656ec4bedbSLiu Gang /* Point dequeue/enqueue pointers at first entry in ring */
7666ec4bedbSLiu Gang out_be32(&rmu->msg_regs->odqdpar, rmu->msg_tx_ring.phys);
7676ec4bedbSLiu Gang out_be32(&rmu->msg_regs->odqepar, rmu->msg_tx_ring.phys);
7686ec4bedbSLiu Gang
7696ec4bedbSLiu Gang /* Configure for snooping */
7706ec4bedbSLiu Gang out_be32(&rmu->msg_regs->osar, 0x00000004);
7716ec4bedbSLiu Gang
7726ec4bedbSLiu Gang /* Clear interrupt status */
7736ec4bedbSLiu Gang out_be32(&rmu->msg_regs->osr, 0x000000b3);
7746ec4bedbSLiu Gang
7756ec4bedbSLiu Gang /* Hook up outbound message handler */
7766ec4bedbSLiu Gang rc = request_irq(IRQ_RIO_TX(mport), fsl_rio_tx_handler, 0,
7776ec4bedbSLiu Gang "msg_tx", (void *)mport);
7786ec4bedbSLiu Gang if (rc < 0)
7796ec4bedbSLiu Gang goto out_irq;
7806ec4bedbSLiu Gang
7816ec4bedbSLiu Gang /*
7826ec4bedbSLiu Gang * Configure outbound message unit
7836ec4bedbSLiu Gang * Snooping
7846ec4bedbSLiu Gang * Interrupts (all enabled, except QEIE)
7856ec4bedbSLiu Gang * Chaining mode
7866ec4bedbSLiu Gang * Disable
7876ec4bedbSLiu Gang */
7886ec4bedbSLiu Gang out_be32(&rmu->msg_regs->omr, 0x00100220);
7896ec4bedbSLiu Gang
7906ec4bedbSLiu Gang /* Set number of entries */
7916ec4bedbSLiu Gang out_be32(&rmu->msg_regs->omr,
7926ec4bedbSLiu Gang in_be32(&rmu->msg_regs->omr) |
7936ec4bedbSLiu Gang ((get_bitmask_order(entries) - 2) << 12));
7946ec4bedbSLiu Gang
7956ec4bedbSLiu Gang /* Now enable the unit */
7966ec4bedbSLiu Gang out_be32(&rmu->msg_regs->omr, in_be32(&rmu->msg_regs->omr) | 0x1);
7976ec4bedbSLiu Gang
7986ec4bedbSLiu Gang out:
7996ec4bedbSLiu Gang return rc;
8006ec4bedbSLiu Gang
8016ec4bedbSLiu Gang out_irq:
8026ec4bedbSLiu Gang dma_free_coherent(priv->dev,
8036ec4bedbSLiu Gang rmu->msg_tx_ring.size * RIO_MSG_DESC_SIZE,
8046ec4bedbSLiu Gang rmu->msg_tx_ring.virt, rmu->msg_tx_ring.phys);
8056ec4bedbSLiu Gang
8066ec4bedbSLiu Gang out_dma:
8076ec4bedbSLiu Gang for (i = 0; i < rmu->msg_tx_ring.size; i++)
8086ec4bedbSLiu Gang dma_free_coherent(priv->dev, RIO_MSG_BUFFER_SIZE,
8096ec4bedbSLiu Gang rmu->msg_tx_ring.virt_buffer[i],
8106ec4bedbSLiu Gang rmu->msg_tx_ring.phys_buffer[i]);
8116ec4bedbSLiu Gang
8126ec4bedbSLiu Gang return rc;
8136ec4bedbSLiu Gang }
8146ec4bedbSLiu Gang
8156ec4bedbSLiu Gang /**
8166ec4bedbSLiu Gang * fsl_close_outb_mbox - Shut down MPC85xx outbound mailbox
8176ec4bedbSLiu Gang * @mport: Master port implementing the outbound message unit
8186ec4bedbSLiu Gang * @mbox: Mailbox to close
8196ec4bedbSLiu Gang *
8206ec4bedbSLiu Gang * Disables the outbound message unit, free all buffers, and
8216ec4bedbSLiu Gang * frees the outbound message interrupt.
8226ec4bedbSLiu Gang */
fsl_close_outb_mbox(struct rio_mport * mport,int mbox)823abc3aeaeSLiu Gang void fsl_close_outb_mbox(struct rio_mport *mport, int mbox)
8246ec4bedbSLiu Gang {
8256ec4bedbSLiu Gang struct rio_priv *priv = mport->priv;
8266ec4bedbSLiu Gang struct fsl_rmu *rmu = GET_RMM_HANDLE(mport);
8276ec4bedbSLiu Gang
8286ec4bedbSLiu Gang /* Disable inbound message unit */
8296ec4bedbSLiu Gang out_be32(&rmu->msg_regs->omr, 0);
8306ec4bedbSLiu Gang
8316ec4bedbSLiu Gang /* Free ring */
8326ec4bedbSLiu Gang dma_free_coherent(priv->dev,
8336ec4bedbSLiu Gang rmu->msg_tx_ring.size * RIO_MSG_DESC_SIZE,
8346ec4bedbSLiu Gang rmu->msg_tx_ring.virt, rmu->msg_tx_ring.phys);
8356ec4bedbSLiu Gang
8366ec4bedbSLiu Gang /* Free interrupt */
8376ec4bedbSLiu Gang free_irq(IRQ_RIO_TX(mport), (void *)mport);
8386ec4bedbSLiu Gang }
8396ec4bedbSLiu Gang
8406ec4bedbSLiu Gang /**
8416ec4bedbSLiu Gang * fsl_open_inb_mbox - Initialize MPC85xx inbound mailbox
8426ec4bedbSLiu Gang * @mport: Master port implementing the inbound message unit
8436ec4bedbSLiu Gang * @dev_id: Device specific pointer to pass on event
8446ec4bedbSLiu Gang * @mbox: Mailbox to open
8456ec4bedbSLiu Gang * @entries: Number of entries in the inbound mailbox ring
8466ec4bedbSLiu Gang *
8476ec4bedbSLiu Gang * Initializes buffer ring, request the inbound message interrupt,
8486ec4bedbSLiu Gang * and enables the inbound message unit. Returns %0 on success
8496ec4bedbSLiu Gang * and %-EINVAL or %-ENOMEM on failure.
8506ec4bedbSLiu Gang */
851abc3aeaeSLiu Gang int
fsl_open_inb_mbox(struct rio_mport * mport,void * dev_id,int mbox,int entries)8526ec4bedbSLiu Gang fsl_open_inb_mbox(struct rio_mport *mport, void *dev_id, int mbox, int entries)
8536ec4bedbSLiu Gang {
8546ec4bedbSLiu Gang int i, rc = 0;
8556ec4bedbSLiu Gang struct rio_priv *priv = mport->priv;
8566ec4bedbSLiu Gang struct fsl_rmu *rmu = GET_RMM_HANDLE(mport);
8576ec4bedbSLiu Gang
8586ec4bedbSLiu Gang if ((entries < RIO_MIN_RX_RING_SIZE) ||
8596ec4bedbSLiu Gang (entries > RIO_MAX_RX_RING_SIZE) || (!is_power_of_2(entries))) {
8606ec4bedbSLiu Gang rc = -EINVAL;
8616ec4bedbSLiu Gang goto out;
8626ec4bedbSLiu Gang }
8636ec4bedbSLiu Gang
8646ec4bedbSLiu Gang /* Initialize client buffer ring */
8656ec4bedbSLiu Gang rmu->msg_rx_ring.dev_id = dev_id;
8666ec4bedbSLiu Gang rmu->msg_rx_ring.size = entries;
8676ec4bedbSLiu Gang rmu->msg_rx_ring.rx_slot = 0;
8686ec4bedbSLiu Gang for (i = 0; i < rmu->msg_rx_ring.size; i++)
8696ec4bedbSLiu Gang rmu->msg_rx_ring.virt_buffer[i] = NULL;
8706ec4bedbSLiu Gang
8716ec4bedbSLiu Gang /* Initialize inbound message ring */
8726ec4bedbSLiu Gang rmu->msg_rx_ring.virt = dma_alloc_coherent(priv->dev,
8736ec4bedbSLiu Gang rmu->msg_rx_ring.size * RIO_MAX_MSG_SIZE,
8746ec4bedbSLiu Gang &rmu->msg_rx_ring.phys, GFP_KERNEL);
8756ec4bedbSLiu Gang if (!rmu->msg_rx_ring.virt) {
8766ec4bedbSLiu Gang rc = -ENOMEM;
8776ec4bedbSLiu Gang goto out;
8786ec4bedbSLiu Gang }
8796ec4bedbSLiu Gang
8806ec4bedbSLiu Gang /* Point dequeue/enqueue pointers at first entry in ring */
8816ec4bedbSLiu Gang out_be32(&rmu->msg_regs->ifqdpar, (u32) rmu->msg_rx_ring.phys);
8826ec4bedbSLiu Gang out_be32(&rmu->msg_regs->ifqepar, (u32) rmu->msg_rx_ring.phys);
8836ec4bedbSLiu Gang
8846ec4bedbSLiu Gang /* Clear interrupt status */
8856ec4bedbSLiu Gang out_be32(&rmu->msg_regs->isr, 0x00000091);
8866ec4bedbSLiu Gang
8876ec4bedbSLiu Gang /* Hook up inbound message handler */
8886ec4bedbSLiu Gang rc = request_irq(IRQ_RIO_RX(mport), fsl_rio_rx_handler, 0,
8896ec4bedbSLiu Gang "msg_rx", (void *)mport);
8906ec4bedbSLiu Gang if (rc < 0) {
8911c075f95SLiu Gang dma_free_coherent(priv->dev,
8921c075f95SLiu Gang rmu->msg_rx_ring.size * RIO_MAX_MSG_SIZE,
8931c075f95SLiu Gang rmu->msg_rx_ring.virt, rmu->msg_rx_ring.phys);
8946ec4bedbSLiu Gang goto out;
8956ec4bedbSLiu Gang }
8966ec4bedbSLiu Gang
8976ec4bedbSLiu Gang /*
8986ec4bedbSLiu Gang * Configure inbound message unit:
8996ec4bedbSLiu Gang * Snooping
9006ec4bedbSLiu Gang * 4KB max message size
9016ec4bedbSLiu Gang * Unmask all interrupt sources
9026ec4bedbSLiu Gang * Disable
9036ec4bedbSLiu Gang */
9046ec4bedbSLiu Gang out_be32(&rmu->msg_regs->imr, 0x001b0060);
9056ec4bedbSLiu Gang
9066ec4bedbSLiu Gang /* Set number of queue entries */
9076ec4bedbSLiu Gang setbits32(&rmu->msg_regs->imr, (get_bitmask_order(entries) - 2) << 12);
9086ec4bedbSLiu Gang
9096ec4bedbSLiu Gang /* Now enable the unit */
9106ec4bedbSLiu Gang setbits32(&rmu->msg_regs->imr, 0x1);
9116ec4bedbSLiu Gang
9126ec4bedbSLiu Gang out:
9136ec4bedbSLiu Gang return rc;
9146ec4bedbSLiu Gang }
9156ec4bedbSLiu Gang
9166ec4bedbSLiu Gang /**
9176ec4bedbSLiu Gang * fsl_close_inb_mbox - Shut down MPC85xx inbound mailbox
9186ec4bedbSLiu Gang * @mport: Master port implementing the inbound message unit
9196ec4bedbSLiu Gang * @mbox: Mailbox to close
9206ec4bedbSLiu Gang *
9216ec4bedbSLiu Gang * Disables the inbound message unit, free all buffers, and
9226ec4bedbSLiu Gang * frees the inbound message interrupt.
9236ec4bedbSLiu Gang */
fsl_close_inb_mbox(struct rio_mport * mport,int mbox)924abc3aeaeSLiu Gang void fsl_close_inb_mbox(struct rio_mport *mport, int mbox)
9256ec4bedbSLiu Gang {
9266ec4bedbSLiu Gang struct rio_priv *priv = mport->priv;
9276ec4bedbSLiu Gang struct fsl_rmu *rmu = GET_RMM_HANDLE(mport);
9286ec4bedbSLiu Gang
9296ec4bedbSLiu Gang /* Disable inbound message unit */
9306ec4bedbSLiu Gang out_be32(&rmu->msg_regs->imr, 0);
9316ec4bedbSLiu Gang
9326ec4bedbSLiu Gang /* Free ring */
9336ec4bedbSLiu Gang dma_free_coherent(priv->dev, rmu->msg_rx_ring.size * RIO_MAX_MSG_SIZE,
9346ec4bedbSLiu Gang rmu->msg_rx_ring.virt, rmu->msg_rx_ring.phys);
9356ec4bedbSLiu Gang
9366ec4bedbSLiu Gang /* Free interrupt */
9376ec4bedbSLiu Gang free_irq(IRQ_RIO_RX(mport), (void *)mport);
9386ec4bedbSLiu Gang }
9396ec4bedbSLiu Gang
9406ec4bedbSLiu Gang /**
9416ec4bedbSLiu Gang * fsl_add_inb_buffer - Add buffer to the MPC85xx inbound message queue
9426ec4bedbSLiu Gang * @mport: Master port implementing the inbound message unit
9436ec4bedbSLiu Gang * @mbox: Inbound mailbox number
9446ec4bedbSLiu Gang * @buf: Buffer to add to inbound queue
9456ec4bedbSLiu Gang *
9466ec4bedbSLiu Gang * Adds the @buf buffer to the MPC85xx inbound message queue. Returns
9476ec4bedbSLiu Gang * %0 on success or %-EINVAL on failure.
9486ec4bedbSLiu Gang */
fsl_add_inb_buffer(struct rio_mport * mport,int mbox,void * buf)949abc3aeaeSLiu Gang int fsl_add_inb_buffer(struct rio_mport *mport, int mbox, void *buf)
9506ec4bedbSLiu Gang {
9516ec4bedbSLiu Gang int rc = 0;
9526ec4bedbSLiu Gang struct fsl_rmu *rmu = GET_RMM_HANDLE(mport);
9536ec4bedbSLiu Gang
9546ec4bedbSLiu Gang pr_debug("RIO: fsl_add_inb_buffer(), msg_rx_ring.rx_slot %d\n",
9556ec4bedbSLiu Gang rmu->msg_rx_ring.rx_slot);
9566ec4bedbSLiu Gang
9576ec4bedbSLiu Gang if (rmu->msg_rx_ring.virt_buffer[rmu->msg_rx_ring.rx_slot]) {
9586ec4bedbSLiu Gang printk(KERN_ERR
9596ec4bedbSLiu Gang "RIO: error adding inbound buffer %d, buffer exists\n",
9606ec4bedbSLiu Gang rmu->msg_rx_ring.rx_slot);
9616ec4bedbSLiu Gang rc = -EINVAL;
9626ec4bedbSLiu Gang goto out;
9636ec4bedbSLiu Gang }
9646ec4bedbSLiu Gang
9656ec4bedbSLiu Gang rmu->msg_rx_ring.virt_buffer[rmu->msg_rx_ring.rx_slot] = buf;
9666ec4bedbSLiu Gang if (++rmu->msg_rx_ring.rx_slot == rmu->msg_rx_ring.size)
9676ec4bedbSLiu Gang rmu->msg_rx_ring.rx_slot = 0;
9686ec4bedbSLiu Gang
9696ec4bedbSLiu Gang out:
9706ec4bedbSLiu Gang return rc;
9716ec4bedbSLiu Gang }
9726ec4bedbSLiu Gang
9736ec4bedbSLiu Gang /**
9746ec4bedbSLiu Gang * fsl_get_inb_message - Fetch inbound message from the MPC85xx message unit
9756ec4bedbSLiu Gang * @mport: Master port implementing the inbound message unit
9766ec4bedbSLiu Gang * @mbox: Inbound mailbox number
9776ec4bedbSLiu Gang *
9786ec4bedbSLiu Gang * Gets the next available inbound message from the inbound message queue.
9796ec4bedbSLiu Gang * A pointer to the message is returned on success or NULL on failure.
9806ec4bedbSLiu Gang */
fsl_get_inb_message(struct rio_mport * mport,int mbox)981abc3aeaeSLiu Gang void *fsl_get_inb_message(struct rio_mport *mport, int mbox)
9826ec4bedbSLiu Gang {
9836ec4bedbSLiu Gang struct fsl_rmu *rmu = GET_RMM_HANDLE(mport);
9842a2383daSLiu Gang u32 phys_buf;
9852a2383daSLiu Gang void *virt_buf;
9866ec4bedbSLiu Gang void *buf = NULL;
9876ec4bedbSLiu Gang int buf_idx;
9886ec4bedbSLiu Gang
9896ec4bedbSLiu Gang phys_buf = in_be32(&rmu->msg_regs->ifqdpar);
9906ec4bedbSLiu Gang
9916ec4bedbSLiu Gang /* If no more messages, then bail out */
9926ec4bedbSLiu Gang if (phys_buf == in_be32(&rmu->msg_regs->ifqepar))
9936ec4bedbSLiu Gang goto out2;
9946ec4bedbSLiu Gang
9952a2383daSLiu Gang virt_buf = rmu->msg_rx_ring.virt + (phys_buf
9966ec4bedbSLiu Gang - rmu->msg_rx_ring.phys);
9976ec4bedbSLiu Gang buf_idx = (phys_buf - rmu->msg_rx_ring.phys) / RIO_MAX_MSG_SIZE;
9986ec4bedbSLiu Gang buf = rmu->msg_rx_ring.virt_buffer[buf_idx];
9996ec4bedbSLiu Gang
10006ec4bedbSLiu Gang if (!buf) {
10016ec4bedbSLiu Gang printk(KERN_ERR
10026ec4bedbSLiu Gang "RIO: inbound message copy failed, no buffers\n");
10036ec4bedbSLiu Gang goto out1;
10046ec4bedbSLiu Gang }
10056ec4bedbSLiu Gang
10066ec4bedbSLiu Gang /* Copy max message size, caller is expected to allocate that big */
10072a2383daSLiu Gang memcpy(buf, virt_buf, RIO_MAX_MSG_SIZE);
10086ec4bedbSLiu Gang
10096ec4bedbSLiu Gang /* Clear the available buffer */
10106ec4bedbSLiu Gang rmu->msg_rx_ring.virt_buffer[buf_idx] = NULL;
10116ec4bedbSLiu Gang
10126ec4bedbSLiu Gang out1:
10136ec4bedbSLiu Gang setbits32(&rmu->msg_regs->imr, RIO_MSG_IMR_MI);
10146ec4bedbSLiu Gang
10156ec4bedbSLiu Gang out2:
10166ec4bedbSLiu Gang return buf;
10176ec4bedbSLiu Gang }
10186ec4bedbSLiu Gang
10196ec4bedbSLiu Gang /**
10206ec4bedbSLiu Gang * fsl_rio_doorbell_init - MPC85xx doorbell interface init
10216ec4bedbSLiu Gang * @mport: Master port implementing the inbound doorbell unit
10226ec4bedbSLiu Gang *
10236ec4bedbSLiu Gang * Initializes doorbell unit hardware and inbound DMA buffer
10246ec4bedbSLiu Gang * ring. Called from fsl_rio_setup(). Returns %0 on success
10256ec4bedbSLiu Gang * or %-ENOMEM on failure.
10266ec4bedbSLiu Gang */
fsl_rio_doorbell_init(struct fsl_rio_dbell * dbell)1027abc3aeaeSLiu Gang int fsl_rio_doorbell_init(struct fsl_rio_dbell *dbell)
10286ec4bedbSLiu Gang {
10296ec4bedbSLiu Gang int rc = 0;
10306ec4bedbSLiu Gang
10316ec4bedbSLiu Gang /* Initialize inbound doorbells */
1032abc3aeaeSLiu Gang dbell->dbell_ring.virt = dma_alloc_coherent(dbell->dev, 512 *
1033abc3aeaeSLiu Gang DOORBELL_MESSAGE_SIZE, &dbell->dbell_ring.phys, GFP_KERNEL);
1034abc3aeaeSLiu Gang if (!dbell->dbell_ring.virt) {
10356ec4bedbSLiu Gang printk(KERN_ERR "RIO: unable allocate inbound doorbell ring\n");
10366ec4bedbSLiu Gang rc = -ENOMEM;
10376ec4bedbSLiu Gang goto out;
10386ec4bedbSLiu Gang }
10396ec4bedbSLiu Gang
10406ec4bedbSLiu Gang /* Point dequeue/enqueue pointers at first entry in ring */
1041abc3aeaeSLiu Gang out_be32(&dbell->dbell_regs->dqdpar, (u32) dbell->dbell_ring.phys);
1042abc3aeaeSLiu Gang out_be32(&dbell->dbell_regs->dqepar, (u32) dbell->dbell_ring.phys);
10436ec4bedbSLiu Gang
10446ec4bedbSLiu Gang /* Clear interrupt status */
1045abc3aeaeSLiu Gang out_be32(&dbell->dbell_regs->dsr, 0x00000091);
10466ec4bedbSLiu Gang
10476ec4bedbSLiu Gang /* Hook up doorbell handler */
1048abc3aeaeSLiu Gang rc = request_irq(IRQ_RIO_BELL(dbell), fsl_rio_dbell_handler, 0,
1049abc3aeaeSLiu Gang "dbell_rx", (void *)dbell);
10506ec4bedbSLiu Gang if (rc < 0) {
1051abc3aeaeSLiu Gang dma_free_coherent(dbell->dev, 512 * DOORBELL_MESSAGE_SIZE,
1052abc3aeaeSLiu Gang dbell->dbell_ring.virt, dbell->dbell_ring.phys);
10536ec4bedbSLiu Gang printk(KERN_ERR
10546ec4bedbSLiu Gang "MPC85xx RIO: unable to request inbound doorbell irq");
10556ec4bedbSLiu Gang goto out;
10566ec4bedbSLiu Gang }
10576ec4bedbSLiu Gang
10586ec4bedbSLiu Gang /* Configure doorbells for snooping, 512 entries, and enable */
1059abc3aeaeSLiu Gang out_be32(&dbell->dbell_regs->dmr, 0x00108161);
10606ec4bedbSLiu Gang
10616ec4bedbSLiu Gang out:
10626ec4bedbSLiu Gang return rc;
10636ec4bedbSLiu Gang }
10646ec4bedbSLiu Gang
fsl_rio_setup_rmu(struct rio_mport * mport,struct device_node * node)10656ec4bedbSLiu Gang int fsl_rio_setup_rmu(struct rio_mport *mport, struct device_node *node)
10666ec4bedbSLiu Gang {
10676ec4bedbSLiu Gang struct rio_priv *priv;
10686ec4bedbSLiu Gang struct fsl_rmu *rmu;
1069abc3aeaeSLiu Gang u64 msg_start;
10706ec4bedbSLiu Gang
1071abc3aeaeSLiu Gang if (!mport || !mport->priv)
1072abc3aeaeSLiu Gang return -EINVAL;
1073abc3aeaeSLiu Gang
1074abc3aeaeSLiu Gang priv = mport->priv;
1075abc3aeaeSLiu Gang
1076abc3aeaeSLiu Gang if (!node) {
1077b7c670d6SRob Herring dev_warn(priv->dev, "Can't get %pOF property 'fsl,rmu'\n",
1078b7c670d6SRob Herring priv->dev->of_node);
1079abc3aeaeSLiu Gang return -EINVAL;
1080abc3aeaeSLiu Gang }
10816ec4bedbSLiu Gang
10826ec4bedbSLiu Gang rmu = kzalloc(sizeof(struct fsl_rmu), GFP_KERNEL);
10836ec4bedbSLiu Gang if (!rmu)
10846ec4bedbSLiu Gang return -ENOMEM;
10856ec4bedbSLiu Gang
1086f892ac77SRob Herring if (of_property_read_reg(node, 0, &msg_start, NULL)) {
1087b7c670d6SRob Herring pr_err("%pOF: unable to find 'reg' property of message-unit\n",
1088b7c670d6SRob Herring node);
1089c6ca52adSJulia Lawall kfree(rmu);
1090abc3aeaeSLiu Gang return -ENOMEM;
1091abc3aeaeSLiu Gang }
1092abc3aeaeSLiu Gang rmu->msg_regs = (struct rio_msg_regs *)
1093abc3aeaeSLiu Gang (rmu_regs_win + (u32)msg_start);
1094abc3aeaeSLiu Gang
1095abc3aeaeSLiu Gang rmu->txirq = irq_of_parse_and_map(node, 0);
1096abc3aeaeSLiu Gang rmu->rxirq = irq_of_parse_and_map(node, 1);
1097b7c670d6SRob Herring printk(KERN_INFO "%pOF: txirq: %d, rxirq %d\n",
1098b7c670d6SRob Herring node, rmu->txirq, rmu->rxirq);
1099abc3aeaeSLiu Gang
11006ec4bedbSLiu Gang priv->rmm_handle = rmu;
11016ec4bedbSLiu Gang
11026ec4bedbSLiu Gang rio_init_dbell_res(&mport->riores[RIO_DOORBELL_RESOURCE], 0, 0xffff);
11036ec4bedbSLiu Gang rio_init_mbox_res(&mport->riores[RIO_INB_MBOX_RESOURCE], 0, 0);
11046ec4bedbSLiu Gang rio_init_mbox_res(&mport->riores[RIO_OUTB_MBOX_RESOURCE], 0, 0);
11056ec4bedbSLiu Gang
11066ec4bedbSLiu Gang return 0;
11076ec4bedbSLiu Gang }
1108