1*6ec4bedbSLiu Gang /* 2*6ec4bedbSLiu Gang * Freescale MPC85xx/MPC86xx RapidIO RMU support 3*6ec4bedbSLiu Gang * 4*6ec4bedbSLiu Gang * Copyright 2009 Sysgo AG 5*6ec4bedbSLiu Gang * Thomas Moll <thomas.moll@sysgo.com> 6*6ec4bedbSLiu Gang * - fixed maintenance access routines, check for aligned access 7*6ec4bedbSLiu Gang * 8*6ec4bedbSLiu Gang * Copyright 2009 Integrated Device Technology, Inc. 9*6ec4bedbSLiu Gang * Alex Bounine <alexandre.bounine@idt.com> 10*6ec4bedbSLiu Gang * - Added Port-Write message handling 11*6ec4bedbSLiu Gang * - Added Machine Check exception handling 12*6ec4bedbSLiu Gang * 13*6ec4bedbSLiu Gang * Copyright (C) 2007, 2008, 2010, 2011 Freescale Semiconductor, Inc. 14*6ec4bedbSLiu Gang * Zhang Wei <wei.zhang@freescale.com> 15*6ec4bedbSLiu Gang * Lian Minghuan-B31939 <Minghuan.Lian@freescale.com> 16*6ec4bedbSLiu Gang * Liu Gang <Gang.Liu@freescale.com> 17*6ec4bedbSLiu Gang * 18*6ec4bedbSLiu Gang * Copyright 2005 MontaVista Software, Inc. 19*6ec4bedbSLiu Gang * Matt Porter <mporter@kernel.crashing.org> 20*6ec4bedbSLiu Gang * 21*6ec4bedbSLiu Gang * This program is free software; you can redistribute it and/or modify it 22*6ec4bedbSLiu Gang * under the terms of the GNU General Public License as published by the 23*6ec4bedbSLiu Gang * Free Software Foundation; either version 2 of the License, or (at your 24*6ec4bedbSLiu Gang * option) any later version. 25*6ec4bedbSLiu Gang */ 26*6ec4bedbSLiu Gang 27*6ec4bedbSLiu Gang #include <linux/types.h> 28*6ec4bedbSLiu Gang #include <linux/dma-mapping.h> 29*6ec4bedbSLiu Gang #include <linux/interrupt.h> 30*6ec4bedbSLiu Gang #include <linux/of_platform.h> 31*6ec4bedbSLiu Gang #include <linux/slab.h> 32*6ec4bedbSLiu Gang 33*6ec4bedbSLiu Gang #include "fsl_rio.h" 34*6ec4bedbSLiu Gang 35*6ec4bedbSLiu Gang #define GET_RMM_HANDLE(mport) \ 36*6ec4bedbSLiu Gang (((struct rio_priv *)(mport->priv))->rmm_handle) 37*6ec4bedbSLiu Gang 38*6ec4bedbSLiu Gang /* RapidIO definition irq, which read from OF-tree */ 39*6ec4bedbSLiu Gang #define IRQ_RIO_PW(m) (((struct rio_priv *)(m->priv))->pwirq) 40*6ec4bedbSLiu Gang #define IRQ_RIO_BELL(m) (((struct fsl_rmu *)(GET_RMM_HANDLE(m)))->bellirq) 41*6ec4bedbSLiu Gang #define IRQ_RIO_TX(m) (((struct fsl_rmu *)(GET_RMM_HANDLE(m)))->txirq) 42*6ec4bedbSLiu Gang #define IRQ_RIO_RX(m) (((struct fsl_rmu *)(GET_RMM_HANDLE(m)))->rxirq) 43*6ec4bedbSLiu Gang 44*6ec4bedbSLiu Gang #define RIO_MIN_TX_RING_SIZE 2 45*6ec4bedbSLiu Gang #define RIO_MAX_TX_RING_SIZE 2048 46*6ec4bedbSLiu Gang #define RIO_MIN_RX_RING_SIZE 2 47*6ec4bedbSLiu Gang #define RIO_MAX_RX_RING_SIZE 2048 48*6ec4bedbSLiu Gang 49*6ec4bedbSLiu Gang #define RIO_IPWMR_SEN 0x00100000 50*6ec4bedbSLiu Gang #define RIO_IPWMR_QFIE 0x00000100 51*6ec4bedbSLiu Gang #define RIO_IPWMR_EIE 0x00000020 52*6ec4bedbSLiu Gang #define RIO_IPWMR_CQ 0x00000002 53*6ec4bedbSLiu Gang #define RIO_IPWMR_PWE 0x00000001 54*6ec4bedbSLiu Gang 55*6ec4bedbSLiu Gang #define RIO_IPWSR_QF 0x00100000 56*6ec4bedbSLiu Gang #define RIO_IPWSR_TE 0x00000080 57*6ec4bedbSLiu Gang #define RIO_IPWSR_QFI 0x00000010 58*6ec4bedbSLiu Gang #define RIO_IPWSR_PWD 0x00000008 59*6ec4bedbSLiu Gang #define RIO_IPWSR_PWB 0x00000004 60*6ec4bedbSLiu Gang 61*6ec4bedbSLiu Gang #define RIO_EPWISR 0x10010 62*6ec4bedbSLiu Gang /* EPWISR Error match value */ 63*6ec4bedbSLiu Gang #define RIO_EPWISR_PINT1 0x80000000 64*6ec4bedbSLiu Gang #define RIO_EPWISR_PINT2 0x40000000 65*6ec4bedbSLiu Gang #define RIO_EPWISR_MU 0x00000002 66*6ec4bedbSLiu Gang #define RIO_EPWISR_PW 0x00000001 67*6ec4bedbSLiu Gang 68*6ec4bedbSLiu Gang #define IPWSR_CLEAR 0x98 69*6ec4bedbSLiu Gang #define OMSR_CLEAR 0x1cb3 70*6ec4bedbSLiu Gang #define IMSR_CLEAR 0x491 71*6ec4bedbSLiu Gang #define IDSR_CLEAR 0x91 72*6ec4bedbSLiu Gang #define ODSR_CLEAR 0x1c00 73*6ec4bedbSLiu Gang #define LTLEECSR_ENABLE_ALL 0xFFC000FC 74*6ec4bedbSLiu Gang #define RIO_LTLEECSR 0x060c 75*6ec4bedbSLiu Gang 76*6ec4bedbSLiu Gang #define RIO_IM0SR 0x13064 77*6ec4bedbSLiu Gang #define RIO_IM1SR 0x13164 78*6ec4bedbSLiu Gang #define RIO_OM0SR 0x13004 79*6ec4bedbSLiu Gang #define RIO_OM1SR 0x13104 80*6ec4bedbSLiu Gang 81*6ec4bedbSLiu Gang #define RIO_P_MSG_REGS_OFFSET 0x11000 82*6ec4bedbSLiu Gang #define RIO_S_MSG_REGS_OFFSET 0x13000 83*6ec4bedbSLiu Gang 84*6ec4bedbSLiu Gang #define RIO_DBELL_WIN_SIZE 0x1000 85*6ec4bedbSLiu Gang 86*6ec4bedbSLiu Gang #define RIO_MSG_OMR_MUI 0x00000002 87*6ec4bedbSLiu Gang #define RIO_MSG_OSR_TE 0x00000080 88*6ec4bedbSLiu Gang #define RIO_MSG_OSR_QOI 0x00000020 89*6ec4bedbSLiu Gang #define RIO_MSG_OSR_QFI 0x00000010 90*6ec4bedbSLiu Gang #define RIO_MSG_OSR_MUB 0x00000004 91*6ec4bedbSLiu Gang #define RIO_MSG_OSR_EOMI 0x00000002 92*6ec4bedbSLiu Gang #define RIO_MSG_OSR_QEI 0x00000001 93*6ec4bedbSLiu Gang 94*6ec4bedbSLiu Gang #define RIO_MSG_IMR_MI 0x00000002 95*6ec4bedbSLiu Gang #define RIO_MSG_ISR_TE 0x00000080 96*6ec4bedbSLiu Gang #define RIO_MSG_ISR_QFI 0x00000010 97*6ec4bedbSLiu Gang #define RIO_MSG_ISR_DIQI 0x00000001 98*6ec4bedbSLiu Gang 99*6ec4bedbSLiu Gang #define RIO_MSG_DESC_SIZE 32 100*6ec4bedbSLiu Gang #define RIO_MSG_BUFFER_SIZE 4096 101*6ec4bedbSLiu Gang 102*6ec4bedbSLiu Gang #define DOORBELL_DMR_DI 0x00000002 103*6ec4bedbSLiu Gang #define DOORBELL_DSR_TE 0x00000080 104*6ec4bedbSLiu Gang #define DOORBELL_DSR_QFI 0x00000010 105*6ec4bedbSLiu Gang #define DOORBELL_DSR_DIQI 0x00000001 106*6ec4bedbSLiu Gang #define DOORBELL_TID_OFFSET 0x02 107*6ec4bedbSLiu Gang #define DOORBELL_SID_OFFSET 0x04 108*6ec4bedbSLiu Gang #define DOORBELL_INFO_OFFSET 0x06 109*6ec4bedbSLiu Gang 110*6ec4bedbSLiu Gang #define DOORBELL_MESSAGE_SIZE 0x08 111*6ec4bedbSLiu Gang #define DBELL_SID(x) (*(u16 *)(x + DOORBELL_SID_OFFSET)) 112*6ec4bedbSLiu Gang #define DBELL_TID(x) (*(u16 *)(x + DOORBELL_TID_OFFSET)) 113*6ec4bedbSLiu Gang #define DBELL_INF(x) (*(u16 *)(x + DOORBELL_INFO_OFFSET)) 114*6ec4bedbSLiu Gang 115*6ec4bedbSLiu Gang struct rio_msg_regs { 116*6ec4bedbSLiu Gang u32 omr; /* 0xD_3000 - Outbound message 0 mode register */ 117*6ec4bedbSLiu Gang u32 osr; /* 0xD_3004 - Outbound message 0 status register */ 118*6ec4bedbSLiu Gang u32 pad1; 119*6ec4bedbSLiu Gang u32 odqdpar; /* 0xD_300C - Outbound message 0 descriptor queue 120*6ec4bedbSLiu Gang dequeue pointer address register */ 121*6ec4bedbSLiu Gang u32 pad2; 122*6ec4bedbSLiu Gang u32 osar; /* 0xD_3014 - Outbound message 0 source address 123*6ec4bedbSLiu Gang register */ 124*6ec4bedbSLiu Gang u32 odpr; /* 0xD_3018 - Outbound message 0 destination port 125*6ec4bedbSLiu Gang register */ 126*6ec4bedbSLiu Gang u32 odatr; /* 0xD_301C - Outbound message 0 destination attributes 127*6ec4bedbSLiu Gang Register*/ 128*6ec4bedbSLiu Gang u32 odcr; /* 0xD_3020 - Outbound message 0 double-word count 129*6ec4bedbSLiu Gang register */ 130*6ec4bedbSLiu Gang u32 pad3; 131*6ec4bedbSLiu Gang u32 odqepar; /* 0xD_3028 - Outbound message 0 descriptor queue 132*6ec4bedbSLiu Gang enqueue pointer address register */ 133*6ec4bedbSLiu Gang u32 pad4[13]; 134*6ec4bedbSLiu Gang u32 imr; /* 0xD_3060 - Inbound message 0 mode register */ 135*6ec4bedbSLiu Gang u32 isr; /* 0xD_3064 - Inbound message 0 status register */ 136*6ec4bedbSLiu Gang u32 pad5; 137*6ec4bedbSLiu Gang u32 ifqdpar; /* 0xD_306C - Inbound message 0 frame queue dequeue 138*6ec4bedbSLiu Gang pointer address register*/ 139*6ec4bedbSLiu Gang u32 pad6; 140*6ec4bedbSLiu Gang u32 ifqepar; /* 0xD_3074 - Inbound message 0 frame queue enqueue 141*6ec4bedbSLiu Gang pointer address register */ 142*6ec4bedbSLiu Gang u32 pad7[226]; 143*6ec4bedbSLiu Gang u32 odmr; /* 0xD_3400 - Outbound doorbell mode register */ 144*6ec4bedbSLiu Gang u32 odsr; /* 0xD_3404 - Outbound doorbell status register */ 145*6ec4bedbSLiu Gang u32 res0[4]; 146*6ec4bedbSLiu Gang u32 oddpr; /* 0xD_3418 - Outbound doorbell destination port 147*6ec4bedbSLiu Gang register */ 148*6ec4bedbSLiu Gang u32 oddatr; /* 0xD_341c - Outbound doorbell destination attributes 149*6ec4bedbSLiu Gang register */ 150*6ec4bedbSLiu Gang u32 res1[3]; 151*6ec4bedbSLiu Gang u32 odretcr; /* 0xD_342C - Outbound doorbell retry error threshold 152*6ec4bedbSLiu Gang configuration register */ 153*6ec4bedbSLiu Gang u32 res2[12]; 154*6ec4bedbSLiu Gang u32 dmr; /* 0xD_3460 - Inbound doorbell mode register */ 155*6ec4bedbSLiu Gang u32 dsr; /* 0xD_3464 - Inbound doorbell status register */ 156*6ec4bedbSLiu Gang u32 pad8; 157*6ec4bedbSLiu Gang u32 dqdpar; /* 0xD_346C - Inbound doorbell queue dequeue Pointer 158*6ec4bedbSLiu Gang address register */ 159*6ec4bedbSLiu Gang u32 pad9; 160*6ec4bedbSLiu Gang u32 dqepar; /* 0xD_3474 - Inbound doorbell Queue enqueue pointer 161*6ec4bedbSLiu Gang address register */ 162*6ec4bedbSLiu Gang u32 pad10[26]; 163*6ec4bedbSLiu Gang u32 pwmr; /* 0xD_34E0 - Inbound port-write mode register */ 164*6ec4bedbSLiu Gang u32 pwsr; /* 0xD_34E4 - Inbound port-write status register */ 165*6ec4bedbSLiu Gang u32 epwqbar; /* 0xD_34E8 - Extended Port-Write Queue Base Address 166*6ec4bedbSLiu Gang register */ 167*6ec4bedbSLiu Gang u32 pwqbar; /* 0xD_34EC - Inbound port-write queue base address 168*6ec4bedbSLiu Gang register */ 169*6ec4bedbSLiu Gang }; 170*6ec4bedbSLiu Gang 171*6ec4bedbSLiu Gang struct rio_tx_desc { 172*6ec4bedbSLiu Gang u32 res1; 173*6ec4bedbSLiu Gang u32 saddr; 174*6ec4bedbSLiu Gang u32 dport; 175*6ec4bedbSLiu Gang u32 dattr; 176*6ec4bedbSLiu Gang u32 res2; 177*6ec4bedbSLiu Gang u32 res3; 178*6ec4bedbSLiu Gang u32 dwcnt; 179*6ec4bedbSLiu Gang u32 res4; 180*6ec4bedbSLiu Gang }; 181*6ec4bedbSLiu Gang 182*6ec4bedbSLiu Gang struct rio_dbell_ring { 183*6ec4bedbSLiu Gang void *virt; 184*6ec4bedbSLiu Gang dma_addr_t phys; 185*6ec4bedbSLiu Gang }; 186*6ec4bedbSLiu Gang 187*6ec4bedbSLiu Gang struct rio_msg_tx_ring { 188*6ec4bedbSLiu Gang void *virt; 189*6ec4bedbSLiu Gang dma_addr_t phys; 190*6ec4bedbSLiu Gang void *virt_buffer[RIO_MAX_TX_RING_SIZE]; 191*6ec4bedbSLiu Gang dma_addr_t phys_buffer[RIO_MAX_TX_RING_SIZE]; 192*6ec4bedbSLiu Gang int tx_slot; 193*6ec4bedbSLiu Gang int size; 194*6ec4bedbSLiu Gang void *dev_id; 195*6ec4bedbSLiu Gang }; 196*6ec4bedbSLiu Gang 197*6ec4bedbSLiu Gang struct rio_msg_rx_ring { 198*6ec4bedbSLiu Gang void *virt; 199*6ec4bedbSLiu Gang dma_addr_t phys; 200*6ec4bedbSLiu Gang void *virt_buffer[RIO_MAX_RX_RING_SIZE]; 201*6ec4bedbSLiu Gang int rx_slot; 202*6ec4bedbSLiu Gang int size; 203*6ec4bedbSLiu Gang void *dev_id; 204*6ec4bedbSLiu Gang }; 205*6ec4bedbSLiu Gang 206*6ec4bedbSLiu Gang struct fsl_rmu { 207*6ec4bedbSLiu Gang struct rio_atmu_regs __iomem *dbell_atmu_regs; 208*6ec4bedbSLiu Gang void __iomem *dbell_win; 209*6ec4bedbSLiu Gang struct rio_msg_regs __iomem *msg_regs; 210*6ec4bedbSLiu Gang struct rio_dbell_ring dbell_ring; 211*6ec4bedbSLiu Gang struct rio_msg_tx_ring msg_tx_ring; 212*6ec4bedbSLiu Gang struct rio_msg_rx_ring msg_rx_ring; 213*6ec4bedbSLiu Gang int bellirq; 214*6ec4bedbSLiu Gang int txirq; 215*6ec4bedbSLiu Gang int rxirq; 216*6ec4bedbSLiu Gang }; 217*6ec4bedbSLiu Gang 218*6ec4bedbSLiu Gang /** 219*6ec4bedbSLiu Gang * fsl_rio_tx_handler - MPC85xx outbound message interrupt handler 220*6ec4bedbSLiu Gang * @irq: Linux interrupt number 221*6ec4bedbSLiu Gang * @dev_instance: Pointer to interrupt-specific data 222*6ec4bedbSLiu Gang * 223*6ec4bedbSLiu Gang * Handles outbound message interrupts. Executes a register outbound 224*6ec4bedbSLiu Gang * mailbox event handler and acks the interrupt occurrence. 225*6ec4bedbSLiu Gang */ 226*6ec4bedbSLiu Gang static irqreturn_t 227*6ec4bedbSLiu Gang fsl_rio_tx_handler(int irq, void *dev_instance) 228*6ec4bedbSLiu Gang { 229*6ec4bedbSLiu Gang int osr; 230*6ec4bedbSLiu Gang struct rio_mport *port = (struct rio_mport *)dev_instance; 231*6ec4bedbSLiu Gang struct fsl_rmu *rmu = GET_RMM_HANDLE(port); 232*6ec4bedbSLiu Gang 233*6ec4bedbSLiu Gang osr = in_be32(&rmu->msg_regs->osr); 234*6ec4bedbSLiu Gang 235*6ec4bedbSLiu Gang if (osr & RIO_MSG_OSR_TE) { 236*6ec4bedbSLiu Gang pr_info("RIO: outbound message transmission error\n"); 237*6ec4bedbSLiu Gang out_be32(&rmu->msg_regs->osr, RIO_MSG_OSR_TE); 238*6ec4bedbSLiu Gang goto out; 239*6ec4bedbSLiu Gang } 240*6ec4bedbSLiu Gang 241*6ec4bedbSLiu Gang if (osr & RIO_MSG_OSR_QOI) { 242*6ec4bedbSLiu Gang pr_info("RIO: outbound message queue overflow\n"); 243*6ec4bedbSLiu Gang out_be32(&rmu->msg_regs->osr, RIO_MSG_OSR_QOI); 244*6ec4bedbSLiu Gang goto out; 245*6ec4bedbSLiu Gang } 246*6ec4bedbSLiu Gang 247*6ec4bedbSLiu Gang if (osr & RIO_MSG_OSR_EOMI) { 248*6ec4bedbSLiu Gang u32 dqp = in_be32(&rmu->msg_regs->odqdpar); 249*6ec4bedbSLiu Gang int slot = (dqp - rmu->msg_tx_ring.phys) >> 5; 250*6ec4bedbSLiu Gang port->outb_msg[0].mcback(port, rmu->msg_tx_ring.dev_id, -1, 251*6ec4bedbSLiu Gang slot); 252*6ec4bedbSLiu Gang 253*6ec4bedbSLiu Gang /* Ack the end-of-message interrupt */ 254*6ec4bedbSLiu Gang out_be32(&rmu->msg_regs->osr, RIO_MSG_OSR_EOMI); 255*6ec4bedbSLiu Gang } 256*6ec4bedbSLiu Gang 257*6ec4bedbSLiu Gang out: 258*6ec4bedbSLiu Gang return IRQ_HANDLED; 259*6ec4bedbSLiu Gang } 260*6ec4bedbSLiu Gang 261*6ec4bedbSLiu Gang /** 262*6ec4bedbSLiu Gang * fsl_rio_rx_handler - MPC85xx inbound message interrupt handler 263*6ec4bedbSLiu Gang * @irq: Linux interrupt number 264*6ec4bedbSLiu Gang * @dev_instance: Pointer to interrupt-specific data 265*6ec4bedbSLiu Gang * 266*6ec4bedbSLiu Gang * Handles inbound message interrupts. Executes a registered inbound 267*6ec4bedbSLiu Gang * mailbox event handler and acks the interrupt occurrence. 268*6ec4bedbSLiu Gang */ 269*6ec4bedbSLiu Gang static irqreturn_t 270*6ec4bedbSLiu Gang fsl_rio_rx_handler(int irq, void *dev_instance) 271*6ec4bedbSLiu Gang { 272*6ec4bedbSLiu Gang int isr; 273*6ec4bedbSLiu Gang struct rio_mport *port = (struct rio_mport *)dev_instance; 274*6ec4bedbSLiu Gang struct fsl_rmu *rmu = GET_RMM_HANDLE(port); 275*6ec4bedbSLiu Gang 276*6ec4bedbSLiu Gang isr = in_be32(&rmu->msg_regs->isr); 277*6ec4bedbSLiu Gang 278*6ec4bedbSLiu Gang if (isr & RIO_MSG_ISR_TE) { 279*6ec4bedbSLiu Gang pr_info("RIO: inbound message reception error\n"); 280*6ec4bedbSLiu Gang out_be32((void *)&rmu->msg_regs->isr, RIO_MSG_ISR_TE); 281*6ec4bedbSLiu Gang goto out; 282*6ec4bedbSLiu Gang } 283*6ec4bedbSLiu Gang 284*6ec4bedbSLiu Gang /* XXX Need to check/dispatch until queue empty */ 285*6ec4bedbSLiu Gang if (isr & RIO_MSG_ISR_DIQI) { 286*6ec4bedbSLiu Gang /* 287*6ec4bedbSLiu Gang * We implement *only* mailbox 0, but can receive messages 288*6ec4bedbSLiu Gang * for any mailbox/letter to that mailbox destination. So, 289*6ec4bedbSLiu Gang * make the callback with an unknown/invalid mailbox number 290*6ec4bedbSLiu Gang * argument. 291*6ec4bedbSLiu Gang */ 292*6ec4bedbSLiu Gang port->inb_msg[0].mcback(port, rmu->msg_rx_ring.dev_id, -1, -1); 293*6ec4bedbSLiu Gang 294*6ec4bedbSLiu Gang /* Ack the queueing interrupt */ 295*6ec4bedbSLiu Gang out_be32(&rmu->msg_regs->isr, RIO_MSG_ISR_DIQI); 296*6ec4bedbSLiu Gang } 297*6ec4bedbSLiu Gang 298*6ec4bedbSLiu Gang out: 299*6ec4bedbSLiu Gang return IRQ_HANDLED; 300*6ec4bedbSLiu Gang } 301*6ec4bedbSLiu Gang 302*6ec4bedbSLiu Gang /** 303*6ec4bedbSLiu Gang * fsl_rio_dbell_handler - MPC85xx doorbell interrupt handler 304*6ec4bedbSLiu Gang * @irq: Linux interrupt number 305*6ec4bedbSLiu Gang * @dev_instance: Pointer to interrupt-specific data 306*6ec4bedbSLiu Gang * 307*6ec4bedbSLiu Gang * Handles doorbell interrupts. Parses a list of registered 308*6ec4bedbSLiu Gang * doorbell event handlers and executes a matching event handler. 309*6ec4bedbSLiu Gang */ 310*6ec4bedbSLiu Gang static irqreturn_t 311*6ec4bedbSLiu Gang fsl_rio_dbell_handler(int irq, void *dev_instance) 312*6ec4bedbSLiu Gang { 313*6ec4bedbSLiu Gang int dsr; 314*6ec4bedbSLiu Gang struct rio_mport *port = (struct rio_mport *)dev_instance; 315*6ec4bedbSLiu Gang struct fsl_rmu *rmu = GET_RMM_HANDLE(port); 316*6ec4bedbSLiu Gang 317*6ec4bedbSLiu Gang dsr = in_be32(&rmu->msg_regs->dsr); 318*6ec4bedbSLiu Gang 319*6ec4bedbSLiu Gang if (dsr & DOORBELL_DSR_TE) { 320*6ec4bedbSLiu Gang pr_info("RIO: doorbell reception error\n"); 321*6ec4bedbSLiu Gang out_be32(&rmu->msg_regs->dsr, DOORBELL_DSR_TE); 322*6ec4bedbSLiu Gang goto out; 323*6ec4bedbSLiu Gang } 324*6ec4bedbSLiu Gang 325*6ec4bedbSLiu Gang if (dsr & DOORBELL_DSR_QFI) { 326*6ec4bedbSLiu Gang pr_info("RIO: doorbell queue full\n"); 327*6ec4bedbSLiu Gang out_be32(&rmu->msg_regs->dsr, DOORBELL_DSR_QFI); 328*6ec4bedbSLiu Gang } 329*6ec4bedbSLiu Gang 330*6ec4bedbSLiu Gang /* XXX Need to check/dispatch until queue empty */ 331*6ec4bedbSLiu Gang if (dsr & DOORBELL_DSR_DIQI) { 332*6ec4bedbSLiu Gang u32 dmsg = 333*6ec4bedbSLiu Gang (u32) rmu->dbell_ring.virt + 334*6ec4bedbSLiu Gang (in_be32(&rmu->msg_regs->dqdpar) & 0xfff); 335*6ec4bedbSLiu Gang struct rio_dbell *dbell; 336*6ec4bedbSLiu Gang int found = 0; 337*6ec4bedbSLiu Gang 338*6ec4bedbSLiu Gang pr_debug 339*6ec4bedbSLiu Gang ("RIO: processing doorbell," 340*6ec4bedbSLiu Gang " sid %2.2x tid %2.2x info %4.4x\n", 341*6ec4bedbSLiu Gang DBELL_SID(dmsg), DBELL_TID(dmsg), DBELL_INF(dmsg)); 342*6ec4bedbSLiu Gang 343*6ec4bedbSLiu Gang list_for_each_entry(dbell, &port->dbells, node) { 344*6ec4bedbSLiu Gang if ((dbell->res->start <= DBELL_INF(dmsg)) && 345*6ec4bedbSLiu Gang (dbell->res->end >= DBELL_INF(dmsg))) { 346*6ec4bedbSLiu Gang found = 1; 347*6ec4bedbSLiu Gang break; 348*6ec4bedbSLiu Gang } 349*6ec4bedbSLiu Gang } 350*6ec4bedbSLiu Gang if (found) { 351*6ec4bedbSLiu Gang dbell->dinb(port, dbell->dev_id, 352*6ec4bedbSLiu Gang DBELL_SID(dmsg), 353*6ec4bedbSLiu Gang DBELL_TID(dmsg), DBELL_INF(dmsg)); 354*6ec4bedbSLiu Gang } else { 355*6ec4bedbSLiu Gang pr_debug 356*6ec4bedbSLiu Gang ("RIO: spurious doorbell," 357*6ec4bedbSLiu Gang " sid %2.2x tid %2.2x info %4.4x\n", 358*6ec4bedbSLiu Gang DBELL_SID(dmsg), DBELL_TID(dmsg), 359*6ec4bedbSLiu Gang DBELL_INF(dmsg)); 360*6ec4bedbSLiu Gang } 361*6ec4bedbSLiu Gang setbits32(&rmu->msg_regs->dmr, DOORBELL_DMR_DI); 362*6ec4bedbSLiu Gang out_be32(&rmu->msg_regs->dsr, DOORBELL_DSR_DIQI); 363*6ec4bedbSLiu Gang } 364*6ec4bedbSLiu Gang 365*6ec4bedbSLiu Gang out: 366*6ec4bedbSLiu Gang return IRQ_HANDLED; 367*6ec4bedbSLiu Gang } 368*6ec4bedbSLiu Gang 369*6ec4bedbSLiu Gang void msg_unit_error_handler(struct rio_mport *port) 370*6ec4bedbSLiu Gang { 371*6ec4bedbSLiu Gang struct fsl_rmu *rmu = GET_RMM_HANDLE(port); 372*6ec4bedbSLiu Gang 373*6ec4bedbSLiu Gang /*XXX: Error recovery is not implemented, we just clear errors */ 374*6ec4bedbSLiu Gang out_be32((u32 *)(rio_regs_win + RIO_LTLEDCSR), 0); 375*6ec4bedbSLiu Gang 376*6ec4bedbSLiu Gang out_be32((u32 *)(rio_regs_win + RIO_IM0SR), IMSR_CLEAR); 377*6ec4bedbSLiu Gang out_be32((u32 *)(rio_regs_win + RIO_IM1SR), IMSR_CLEAR); 378*6ec4bedbSLiu Gang out_be32((u32 *)(rio_regs_win + RIO_OM0SR), OMSR_CLEAR); 379*6ec4bedbSLiu Gang out_be32((u32 *)(rio_regs_win + RIO_OM1SR), OMSR_CLEAR); 380*6ec4bedbSLiu Gang 381*6ec4bedbSLiu Gang out_be32(&rmu->msg_regs->odsr, ODSR_CLEAR); 382*6ec4bedbSLiu Gang out_be32(&rmu->msg_regs->dsr, IDSR_CLEAR); 383*6ec4bedbSLiu Gang 384*6ec4bedbSLiu Gang out_be32(&rmu->msg_regs->pwsr, IPWSR_CLEAR); 385*6ec4bedbSLiu Gang } 386*6ec4bedbSLiu Gang 387*6ec4bedbSLiu Gang /** 388*6ec4bedbSLiu Gang * fsl_rio_port_write_handler - MPC85xx port write interrupt handler 389*6ec4bedbSLiu Gang * @irq: Linux interrupt number 390*6ec4bedbSLiu Gang * @dev_instance: Pointer to interrupt-specific data 391*6ec4bedbSLiu Gang * 392*6ec4bedbSLiu Gang * Handles port write interrupts. Parses a list of registered 393*6ec4bedbSLiu Gang * port write event handlers and executes a matching event handler. 394*6ec4bedbSLiu Gang */ 395*6ec4bedbSLiu Gang static irqreturn_t 396*6ec4bedbSLiu Gang fsl_rio_port_write_handler(int irq, void *dev_instance) 397*6ec4bedbSLiu Gang { 398*6ec4bedbSLiu Gang u32 ipwmr, ipwsr; 399*6ec4bedbSLiu Gang struct rio_mport *port = (struct rio_mport *)dev_instance; 400*6ec4bedbSLiu Gang struct rio_priv *priv = port->priv; 401*6ec4bedbSLiu Gang struct fsl_rmu *rmu; 402*6ec4bedbSLiu Gang u32 epwisr, tmp; 403*6ec4bedbSLiu Gang 404*6ec4bedbSLiu Gang rmu = GET_RMM_HANDLE(port); 405*6ec4bedbSLiu Gang epwisr = in_be32(priv->regs_win + RIO_EPWISR); 406*6ec4bedbSLiu Gang if (!(epwisr & RIO_EPWISR_PW)) 407*6ec4bedbSLiu Gang goto pw_done; 408*6ec4bedbSLiu Gang 409*6ec4bedbSLiu Gang ipwmr = in_be32(&rmu->msg_regs->pwmr); 410*6ec4bedbSLiu Gang ipwsr = in_be32(&rmu->msg_regs->pwsr); 411*6ec4bedbSLiu Gang 412*6ec4bedbSLiu Gang #ifdef DEBUG_PW 413*6ec4bedbSLiu Gang pr_debug("PW Int->IPWMR: 0x%08x IPWSR: 0x%08x (", ipwmr, ipwsr); 414*6ec4bedbSLiu Gang if (ipwsr & RIO_IPWSR_QF) 415*6ec4bedbSLiu Gang pr_debug(" QF"); 416*6ec4bedbSLiu Gang if (ipwsr & RIO_IPWSR_TE) 417*6ec4bedbSLiu Gang pr_debug(" TE"); 418*6ec4bedbSLiu Gang if (ipwsr & RIO_IPWSR_QFI) 419*6ec4bedbSLiu Gang pr_debug(" QFI"); 420*6ec4bedbSLiu Gang if (ipwsr & RIO_IPWSR_PWD) 421*6ec4bedbSLiu Gang pr_debug(" PWD"); 422*6ec4bedbSLiu Gang if (ipwsr & RIO_IPWSR_PWB) 423*6ec4bedbSLiu Gang pr_debug(" PWB"); 424*6ec4bedbSLiu Gang pr_debug(" )\n"); 425*6ec4bedbSLiu Gang #endif 426*6ec4bedbSLiu Gang /* Schedule deferred processing if PW was received */ 427*6ec4bedbSLiu Gang if (ipwsr & RIO_IPWSR_QFI) { 428*6ec4bedbSLiu Gang /* Save PW message (if there is room in FIFO), 429*6ec4bedbSLiu Gang * otherwise discard it. 430*6ec4bedbSLiu Gang */ 431*6ec4bedbSLiu Gang if (kfifo_avail(&priv->pw_fifo) >= RIO_PW_MSG_SIZE) { 432*6ec4bedbSLiu Gang priv->port_write_msg.msg_count++; 433*6ec4bedbSLiu Gang kfifo_in(&priv->pw_fifo, priv->port_write_msg.virt, 434*6ec4bedbSLiu Gang RIO_PW_MSG_SIZE); 435*6ec4bedbSLiu Gang } else { 436*6ec4bedbSLiu Gang priv->port_write_msg.discard_count++; 437*6ec4bedbSLiu Gang pr_debug("RIO: ISR Discarded Port-Write Msg(s) (%d)\n", 438*6ec4bedbSLiu Gang priv->port_write_msg.discard_count); 439*6ec4bedbSLiu Gang } 440*6ec4bedbSLiu Gang /* Clear interrupt and issue Clear Queue command. This allows 441*6ec4bedbSLiu Gang * another port-write to be received. 442*6ec4bedbSLiu Gang */ 443*6ec4bedbSLiu Gang out_be32(&rmu->msg_regs->pwsr, RIO_IPWSR_QFI); 444*6ec4bedbSLiu Gang out_be32(&rmu->msg_regs->pwmr, ipwmr | RIO_IPWMR_CQ); 445*6ec4bedbSLiu Gang 446*6ec4bedbSLiu Gang schedule_work(&priv->pw_work); 447*6ec4bedbSLiu Gang } 448*6ec4bedbSLiu Gang 449*6ec4bedbSLiu Gang if ((ipwmr & RIO_IPWMR_EIE) && (ipwsr & RIO_IPWSR_TE)) { 450*6ec4bedbSLiu Gang priv->port_write_msg.err_count++; 451*6ec4bedbSLiu Gang pr_debug("RIO: Port-Write Transaction Err (%d)\n", 452*6ec4bedbSLiu Gang priv->port_write_msg.err_count); 453*6ec4bedbSLiu Gang /* Clear Transaction Error: port-write controller should be 454*6ec4bedbSLiu Gang * disabled when clearing this error 455*6ec4bedbSLiu Gang */ 456*6ec4bedbSLiu Gang out_be32(&rmu->msg_regs->pwmr, ipwmr & ~RIO_IPWMR_PWE); 457*6ec4bedbSLiu Gang out_be32(&rmu->msg_regs->pwsr, RIO_IPWSR_TE); 458*6ec4bedbSLiu Gang out_be32(&rmu->msg_regs->pwmr, ipwmr); 459*6ec4bedbSLiu Gang } 460*6ec4bedbSLiu Gang 461*6ec4bedbSLiu Gang if (ipwsr & RIO_IPWSR_PWD) { 462*6ec4bedbSLiu Gang priv->port_write_msg.discard_count++; 463*6ec4bedbSLiu Gang pr_debug("RIO: Port Discarded Port-Write Msg(s) (%d)\n", 464*6ec4bedbSLiu Gang priv->port_write_msg.discard_count); 465*6ec4bedbSLiu Gang out_be32(&rmu->msg_regs->pwsr, RIO_IPWSR_PWD); 466*6ec4bedbSLiu Gang } 467*6ec4bedbSLiu Gang 468*6ec4bedbSLiu Gang pw_done: 469*6ec4bedbSLiu Gang if (epwisr & RIO_EPWISR_PINT1) { 470*6ec4bedbSLiu Gang tmp = in_be32(priv->regs_win + RIO_LTLEDCSR); 471*6ec4bedbSLiu Gang pr_debug("RIO_LTLEDCSR = 0x%x\n", tmp); 472*6ec4bedbSLiu Gang fsl_rio_port_error_handler(port, 0); 473*6ec4bedbSLiu Gang } 474*6ec4bedbSLiu Gang 475*6ec4bedbSLiu Gang if (epwisr & RIO_EPWISR_PINT2) { 476*6ec4bedbSLiu Gang tmp = in_be32(priv->regs_win + RIO_LTLEDCSR); 477*6ec4bedbSLiu Gang pr_debug("RIO_LTLEDCSR = 0x%x\n", tmp); 478*6ec4bedbSLiu Gang fsl_rio_port_error_handler(port, 1); 479*6ec4bedbSLiu Gang } 480*6ec4bedbSLiu Gang 481*6ec4bedbSLiu Gang if (epwisr & RIO_EPWISR_MU) { 482*6ec4bedbSLiu Gang tmp = in_be32(priv->regs_win + RIO_LTLEDCSR); 483*6ec4bedbSLiu Gang pr_debug("RIO_LTLEDCSR = 0x%x\n", tmp); 484*6ec4bedbSLiu Gang msg_unit_error_handler(port); 485*6ec4bedbSLiu Gang } 486*6ec4bedbSLiu Gang 487*6ec4bedbSLiu Gang return IRQ_HANDLED; 488*6ec4bedbSLiu Gang } 489*6ec4bedbSLiu Gang 490*6ec4bedbSLiu Gang static void fsl_pw_dpc(struct work_struct *work) 491*6ec4bedbSLiu Gang { 492*6ec4bedbSLiu Gang struct rio_priv *priv = container_of(work, struct rio_priv, pw_work); 493*6ec4bedbSLiu Gang unsigned long flags; 494*6ec4bedbSLiu Gang u32 msg_buffer[RIO_PW_MSG_SIZE/sizeof(u32)]; 495*6ec4bedbSLiu Gang 496*6ec4bedbSLiu Gang /* 497*6ec4bedbSLiu Gang * Process port-write messages 498*6ec4bedbSLiu Gang */ 499*6ec4bedbSLiu Gang spin_lock_irqsave(&priv->pw_fifo_lock, flags); 500*6ec4bedbSLiu Gang while (kfifo_out(&priv->pw_fifo, (unsigned char *)msg_buffer, 501*6ec4bedbSLiu Gang RIO_PW_MSG_SIZE)) { 502*6ec4bedbSLiu Gang /* Process one message */ 503*6ec4bedbSLiu Gang spin_unlock_irqrestore(&priv->pw_fifo_lock, flags); 504*6ec4bedbSLiu Gang #ifdef DEBUG_PW 505*6ec4bedbSLiu Gang { 506*6ec4bedbSLiu Gang u32 i; 507*6ec4bedbSLiu Gang pr_debug("%s : Port-Write Message:", __func__); 508*6ec4bedbSLiu Gang for (i = 0; i < RIO_PW_MSG_SIZE/sizeof(u32); i++) { 509*6ec4bedbSLiu Gang if ((i%4) == 0) 510*6ec4bedbSLiu Gang pr_debug("\n0x%02x: 0x%08x", i*4, 511*6ec4bedbSLiu Gang msg_buffer[i]); 512*6ec4bedbSLiu Gang else 513*6ec4bedbSLiu Gang pr_debug(" 0x%08x", msg_buffer[i]); 514*6ec4bedbSLiu Gang } 515*6ec4bedbSLiu Gang pr_debug("\n"); 516*6ec4bedbSLiu Gang } 517*6ec4bedbSLiu Gang #endif 518*6ec4bedbSLiu Gang /* Pass the port-write message to RIO core for processing */ 519*6ec4bedbSLiu Gang rio_inb_pwrite_handler((union rio_pw_msg *)msg_buffer); 520*6ec4bedbSLiu Gang spin_lock_irqsave(&priv->pw_fifo_lock, flags); 521*6ec4bedbSLiu Gang } 522*6ec4bedbSLiu Gang spin_unlock_irqrestore(&priv->pw_fifo_lock, flags); 523*6ec4bedbSLiu Gang } 524*6ec4bedbSLiu Gang 525*6ec4bedbSLiu Gang /** 526*6ec4bedbSLiu Gang * fsl_rio_pw_enable - enable/disable port-write interface init 527*6ec4bedbSLiu Gang * @mport: Master port implementing the port write unit 528*6ec4bedbSLiu Gang * @enable: 1=enable; 0=disable port-write message handling 529*6ec4bedbSLiu Gang */ 530*6ec4bedbSLiu Gang int fsl_rio_pw_enable(struct rio_mport *mport, int enable) 531*6ec4bedbSLiu Gang { 532*6ec4bedbSLiu Gang struct fsl_rmu *rmu; 533*6ec4bedbSLiu Gang u32 rval; 534*6ec4bedbSLiu Gang 535*6ec4bedbSLiu Gang rmu = GET_RMM_HANDLE(mport); 536*6ec4bedbSLiu Gang 537*6ec4bedbSLiu Gang rval = in_be32(&rmu->msg_regs->pwmr); 538*6ec4bedbSLiu Gang 539*6ec4bedbSLiu Gang if (enable) 540*6ec4bedbSLiu Gang rval |= RIO_IPWMR_PWE; 541*6ec4bedbSLiu Gang else 542*6ec4bedbSLiu Gang rval &= ~RIO_IPWMR_PWE; 543*6ec4bedbSLiu Gang 544*6ec4bedbSLiu Gang out_be32(&rmu->msg_regs->pwmr, rval); 545*6ec4bedbSLiu Gang 546*6ec4bedbSLiu Gang return 0; 547*6ec4bedbSLiu Gang } 548*6ec4bedbSLiu Gang 549*6ec4bedbSLiu Gang /** 550*6ec4bedbSLiu Gang * fsl_rio_port_write_init - MPC85xx port write interface init 551*6ec4bedbSLiu Gang * @mport: Master port implementing the port write unit 552*6ec4bedbSLiu Gang * 553*6ec4bedbSLiu Gang * Initializes port write unit hardware and DMA buffer 554*6ec4bedbSLiu Gang * ring. Called from fsl_rio_setup(). Returns %0 on success 555*6ec4bedbSLiu Gang * or %-ENOMEM on failure. 556*6ec4bedbSLiu Gang */ 557*6ec4bedbSLiu Gang 558*6ec4bedbSLiu Gang int fsl_rio_port_write_init(struct rio_mport *mport) 559*6ec4bedbSLiu Gang { 560*6ec4bedbSLiu Gang struct rio_priv *priv = mport->priv; 561*6ec4bedbSLiu Gang struct fsl_rmu *rmu; 562*6ec4bedbSLiu Gang int rc = 0; 563*6ec4bedbSLiu Gang 564*6ec4bedbSLiu Gang rmu = GET_RMM_HANDLE(mport); 565*6ec4bedbSLiu Gang 566*6ec4bedbSLiu Gang /* Following configurations require a disabled port write controller */ 567*6ec4bedbSLiu Gang out_be32(&rmu->msg_regs->pwmr, 568*6ec4bedbSLiu Gang in_be32(&rmu->msg_regs->pwmr) & ~RIO_IPWMR_PWE); 569*6ec4bedbSLiu Gang 570*6ec4bedbSLiu Gang /* Initialize port write */ 571*6ec4bedbSLiu Gang priv->port_write_msg.virt = dma_alloc_coherent(priv->dev, 572*6ec4bedbSLiu Gang RIO_PW_MSG_SIZE, 573*6ec4bedbSLiu Gang &priv->port_write_msg.phys, GFP_KERNEL); 574*6ec4bedbSLiu Gang if (!priv->port_write_msg.virt) { 575*6ec4bedbSLiu Gang pr_err("RIO: unable allocate port write queue\n"); 576*6ec4bedbSLiu Gang return -ENOMEM; 577*6ec4bedbSLiu Gang } 578*6ec4bedbSLiu Gang 579*6ec4bedbSLiu Gang priv->port_write_msg.err_count = 0; 580*6ec4bedbSLiu Gang priv->port_write_msg.discard_count = 0; 581*6ec4bedbSLiu Gang 582*6ec4bedbSLiu Gang /* Point dequeue/enqueue pointers at first entry */ 583*6ec4bedbSLiu Gang out_be32(&rmu->msg_regs->epwqbar, 0); 584*6ec4bedbSLiu Gang out_be32(&rmu->msg_regs->pwqbar, (u32) priv->port_write_msg.phys); 585*6ec4bedbSLiu Gang 586*6ec4bedbSLiu Gang pr_debug("EIPWQBAR: 0x%08x IPWQBAR: 0x%08x\n", 587*6ec4bedbSLiu Gang in_be32(&rmu->msg_regs->epwqbar), 588*6ec4bedbSLiu Gang in_be32(&rmu->msg_regs->pwqbar)); 589*6ec4bedbSLiu Gang 590*6ec4bedbSLiu Gang /* Clear interrupt status IPWSR */ 591*6ec4bedbSLiu Gang out_be32(&rmu->msg_regs->pwsr, 592*6ec4bedbSLiu Gang (RIO_IPWSR_TE | RIO_IPWSR_QFI | RIO_IPWSR_PWD)); 593*6ec4bedbSLiu Gang 594*6ec4bedbSLiu Gang /* Configure port write contoller for snooping enable all reporting, 595*6ec4bedbSLiu Gang clear queue full */ 596*6ec4bedbSLiu Gang out_be32(&rmu->msg_regs->pwmr, 597*6ec4bedbSLiu Gang RIO_IPWMR_SEN | RIO_IPWMR_QFIE | RIO_IPWMR_EIE | RIO_IPWMR_CQ); 598*6ec4bedbSLiu Gang 599*6ec4bedbSLiu Gang 600*6ec4bedbSLiu Gang /* Hook up port-write handler */ 601*6ec4bedbSLiu Gang rc = request_irq(IRQ_RIO_PW(mport), fsl_rio_port_write_handler, 602*6ec4bedbSLiu Gang IRQF_SHARED, "port-write", (void *)mport); 603*6ec4bedbSLiu Gang if (rc < 0) { 604*6ec4bedbSLiu Gang pr_err("MPC85xx RIO: unable to request inbound doorbell irq"); 605*6ec4bedbSLiu Gang goto err_out; 606*6ec4bedbSLiu Gang } 607*6ec4bedbSLiu Gang /* Enable Error Interrupt */ 608*6ec4bedbSLiu Gang out_be32((u32 *)(rio_regs_win + RIO_LTLEECSR), LTLEECSR_ENABLE_ALL); 609*6ec4bedbSLiu Gang 610*6ec4bedbSLiu Gang INIT_WORK(&priv->pw_work, fsl_pw_dpc); 611*6ec4bedbSLiu Gang spin_lock_init(&priv->pw_fifo_lock); 612*6ec4bedbSLiu Gang if (kfifo_alloc(&priv->pw_fifo, RIO_PW_MSG_SIZE * 32, GFP_KERNEL)) { 613*6ec4bedbSLiu Gang pr_err("FIFO allocation failed\n"); 614*6ec4bedbSLiu Gang rc = -ENOMEM; 615*6ec4bedbSLiu Gang goto err_out_irq; 616*6ec4bedbSLiu Gang } 617*6ec4bedbSLiu Gang 618*6ec4bedbSLiu Gang pr_debug("IPWMR: 0x%08x IPWSR: 0x%08x\n", 619*6ec4bedbSLiu Gang in_be32(&rmu->msg_regs->pwmr), 620*6ec4bedbSLiu Gang in_be32(&rmu->msg_regs->pwsr)); 621*6ec4bedbSLiu Gang 622*6ec4bedbSLiu Gang return rc; 623*6ec4bedbSLiu Gang 624*6ec4bedbSLiu Gang err_out_irq: 625*6ec4bedbSLiu Gang free_irq(IRQ_RIO_PW(mport), (void *)mport); 626*6ec4bedbSLiu Gang err_out: 627*6ec4bedbSLiu Gang dma_free_coherent(priv->dev, RIO_PW_MSG_SIZE, 628*6ec4bedbSLiu Gang priv->port_write_msg.virt, 629*6ec4bedbSLiu Gang priv->port_write_msg.phys); 630*6ec4bedbSLiu Gang return rc; 631*6ec4bedbSLiu Gang } 632*6ec4bedbSLiu Gang 633*6ec4bedbSLiu Gang /** 634*6ec4bedbSLiu Gang * fsl_rio_doorbell_send - Send a MPC85xx doorbell message 635*6ec4bedbSLiu Gang * @mport: RapidIO master port info 636*6ec4bedbSLiu Gang * @index: ID of RapidIO interface 637*6ec4bedbSLiu Gang * @destid: Destination ID of target device 638*6ec4bedbSLiu Gang * @data: 16-bit info field of RapidIO doorbell message 639*6ec4bedbSLiu Gang * 640*6ec4bedbSLiu Gang * Sends a MPC85xx doorbell message. Returns %0 on success or 641*6ec4bedbSLiu Gang * %-EINVAL on failure. 642*6ec4bedbSLiu Gang */ 643*6ec4bedbSLiu Gang static int fsl_rio_doorbell_send(struct rio_mport *mport, 644*6ec4bedbSLiu Gang int index, u16 destid, u16 data) 645*6ec4bedbSLiu Gang { 646*6ec4bedbSLiu Gang struct fsl_rmu *rmu = GET_RMM_HANDLE(mport); 647*6ec4bedbSLiu Gang 648*6ec4bedbSLiu Gang pr_debug("fsl_doorbell_send: index %d destid %4.4x data %4.4x\n", 649*6ec4bedbSLiu Gang index, destid, data); 650*6ec4bedbSLiu Gang switch (mport->phy_type) { 651*6ec4bedbSLiu Gang case RIO_PHY_PARALLEL: 652*6ec4bedbSLiu Gang out_be32(&rmu->dbell_atmu_regs->rowtar, destid << 22); 653*6ec4bedbSLiu Gang out_be16(rmu->dbell_win, data); 654*6ec4bedbSLiu Gang break; 655*6ec4bedbSLiu Gang case RIO_PHY_SERIAL: 656*6ec4bedbSLiu Gang /* In the serial version silicons, such as MPC8548, MPC8641, 657*6ec4bedbSLiu Gang * below operations is must be. 658*6ec4bedbSLiu Gang */ 659*6ec4bedbSLiu Gang out_be32(&rmu->msg_regs->odmr, 0x00000000); 660*6ec4bedbSLiu Gang out_be32(&rmu->msg_regs->odretcr, 0x00000004); 661*6ec4bedbSLiu Gang out_be32(&rmu->msg_regs->oddpr, destid << 16); 662*6ec4bedbSLiu Gang out_be32(&rmu->msg_regs->oddatr, data); 663*6ec4bedbSLiu Gang out_be32(&rmu->msg_regs->odmr, 0x00000001); 664*6ec4bedbSLiu Gang break; 665*6ec4bedbSLiu Gang } 666*6ec4bedbSLiu Gang 667*6ec4bedbSLiu Gang return 0; 668*6ec4bedbSLiu Gang } 669*6ec4bedbSLiu Gang 670*6ec4bedbSLiu Gang /** 671*6ec4bedbSLiu Gang * fsl_add_outb_message - Add message to the MPC85xx outbound message queue 672*6ec4bedbSLiu Gang * @mport: Master port with outbound message queue 673*6ec4bedbSLiu Gang * @rdev: Target of outbound message 674*6ec4bedbSLiu Gang * @mbox: Outbound mailbox 675*6ec4bedbSLiu Gang * @buffer: Message to add to outbound queue 676*6ec4bedbSLiu Gang * @len: Length of message 677*6ec4bedbSLiu Gang * 678*6ec4bedbSLiu Gang * Adds the @buffer message to the MPC85xx outbound message queue. Returns 679*6ec4bedbSLiu Gang * %0 on success or %-EINVAL on failure. 680*6ec4bedbSLiu Gang */ 681*6ec4bedbSLiu Gang static int 682*6ec4bedbSLiu Gang fsl_add_outb_message(struct rio_mport *mport, struct rio_dev *rdev, int mbox, 683*6ec4bedbSLiu Gang void *buffer, size_t len) 684*6ec4bedbSLiu Gang { 685*6ec4bedbSLiu Gang struct fsl_rmu *rmu = GET_RMM_HANDLE(mport); 686*6ec4bedbSLiu Gang u32 omr; 687*6ec4bedbSLiu Gang struct rio_tx_desc *desc = (struct rio_tx_desc *)rmu->msg_tx_ring.virt 688*6ec4bedbSLiu Gang + rmu->msg_tx_ring.tx_slot; 689*6ec4bedbSLiu Gang int ret = 0; 690*6ec4bedbSLiu Gang 691*6ec4bedbSLiu Gang pr_debug("RIO: fsl_add_outb_message(): destid %4.4x mbox %d buffer " \ 692*6ec4bedbSLiu Gang "%8.8x len %8.8x\n", rdev->destid, mbox, (int)buffer, len); 693*6ec4bedbSLiu Gang 694*6ec4bedbSLiu Gang if ((len < 8) || (len > RIO_MAX_MSG_SIZE)) { 695*6ec4bedbSLiu Gang ret = -EINVAL; 696*6ec4bedbSLiu Gang goto out; 697*6ec4bedbSLiu Gang } 698*6ec4bedbSLiu Gang 699*6ec4bedbSLiu Gang /* Copy and clear rest of buffer */ 700*6ec4bedbSLiu Gang memcpy(rmu->msg_tx_ring.virt_buffer[rmu->msg_tx_ring.tx_slot], buffer, 701*6ec4bedbSLiu Gang len); 702*6ec4bedbSLiu Gang if (len < (RIO_MAX_MSG_SIZE - 4)) 703*6ec4bedbSLiu Gang memset(rmu->msg_tx_ring.virt_buffer[rmu->msg_tx_ring.tx_slot] 704*6ec4bedbSLiu Gang + len, 0, RIO_MAX_MSG_SIZE - len); 705*6ec4bedbSLiu Gang 706*6ec4bedbSLiu Gang switch (mport->phy_type) { 707*6ec4bedbSLiu Gang case RIO_PHY_PARALLEL: 708*6ec4bedbSLiu Gang /* Set mbox field for message */ 709*6ec4bedbSLiu Gang desc->dport = mbox & 0x3; 710*6ec4bedbSLiu Gang 711*6ec4bedbSLiu Gang /* Enable EOMI interrupt, set priority, and set destid */ 712*6ec4bedbSLiu Gang desc->dattr = 0x28000000 | (rdev->destid << 2); 713*6ec4bedbSLiu Gang break; 714*6ec4bedbSLiu Gang case RIO_PHY_SERIAL: 715*6ec4bedbSLiu Gang /* Set mbox field for message, and set destid */ 716*6ec4bedbSLiu Gang desc->dport = (rdev->destid << 16) | (mbox & 0x3); 717*6ec4bedbSLiu Gang 718*6ec4bedbSLiu Gang /* Enable EOMI interrupt and priority */ 719*6ec4bedbSLiu Gang desc->dattr = 0x28000000; 720*6ec4bedbSLiu Gang break; 721*6ec4bedbSLiu Gang } 722*6ec4bedbSLiu Gang 723*6ec4bedbSLiu Gang /* Set transfer size aligned to next power of 2 (in double words) */ 724*6ec4bedbSLiu Gang desc->dwcnt = is_power_of_2(len) ? len : 1 << get_bitmask_order(len); 725*6ec4bedbSLiu Gang 726*6ec4bedbSLiu Gang /* Set snooping and source buffer address */ 727*6ec4bedbSLiu Gang desc->saddr = 0x00000004 728*6ec4bedbSLiu Gang | rmu->msg_tx_ring.phys_buffer[rmu->msg_tx_ring.tx_slot]; 729*6ec4bedbSLiu Gang 730*6ec4bedbSLiu Gang /* Increment enqueue pointer */ 731*6ec4bedbSLiu Gang omr = in_be32(&rmu->msg_regs->omr); 732*6ec4bedbSLiu Gang out_be32(&rmu->msg_regs->omr, omr | RIO_MSG_OMR_MUI); 733*6ec4bedbSLiu Gang 734*6ec4bedbSLiu Gang /* Go to next descriptor */ 735*6ec4bedbSLiu Gang if (++rmu->msg_tx_ring.tx_slot == rmu->msg_tx_ring.size) 736*6ec4bedbSLiu Gang rmu->msg_tx_ring.tx_slot = 0; 737*6ec4bedbSLiu Gang 738*6ec4bedbSLiu Gang out: 739*6ec4bedbSLiu Gang return ret; 740*6ec4bedbSLiu Gang } 741*6ec4bedbSLiu Gang 742*6ec4bedbSLiu Gang /** 743*6ec4bedbSLiu Gang * fsl_open_outb_mbox - Initialize MPC85xx outbound mailbox 744*6ec4bedbSLiu Gang * @mport: Master port implementing the outbound message unit 745*6ec4bedbSLiu Gang * @dev_id: Device specific pointer to pass on event 746*6ec4bedbSLiu Gang * @mbox: Mailbox to open 747*6ec4bedbSLiu Gang * @entries: Number of entries in the outbound mailbox ring 748*6ec4bedbSLiu Gang * 749*6ec4bedbSLiu Gang * Initializes buffer ring, request the outbound message interrupt, 750*6ec4bedbSLiu Gang * and enables the outbound message unit. Returns %0 on success and 751*6ec4bedbSLiu Gang * %-EINVAL or %-ENOMEM on failure. 752*6ec4bedbSLiu Gang */ 753*6ec4bedbSLiu Gang static int 754*6ec4bedbSLiu Gang fsl_open_outb_mbox(struct rio_mport *mport, void *dev_id, int mbox, int entries) 755*6ec4bedbSLiu Gang { 756*6ec4bedbSLiu Gang int i, j, rc = 0; 757*6ec4bedbSLiu Gang struct rio_priv *priv = mport->priv; 758*6ec4bedbSLiu Gang struct fsl_rmu *rmu = GET_RMM_HANDLE(mport); 759*6ec4bedbSLiu Gang 760*6ec4bedbSLiu Gang if ((entries < RIO_MIN_TX_RING_SIZE) || 761*6ec4bedbSLiu Gang (entries > RIO_MAX_TX_RING_SIZE) || (!is_power_of_2(entries))) { 762*6ec4bedbSLiu Gang rc = -EINVAL; 763*6ec4bedbSLiu Gang goto out; 764*6ec4bedbSLiu Gang } 765*6ec4bedbSLiu Gang 766*6ec4bedbSLiu Gang /* Initialize shadow copy ring */ 767*6ec4bedbSLiu Gang rmu->msg_tx_ring.dev_id = dev_id; 768*6ec4bedbSLiu Gang rmu->msg_tx_ring.size = entries; 769*6ec4bedbSLiu Gang 770*6ec4bedbSLiu Gang for (i = 0; i < rmu->msg_tx_ring.size; i++) { 771*6ec4bedbSLiu Gang rmu->msg_tx_ring.virt_buffer[i] = 772*6ec4bedbSLiu Gang dma_alloc_coherent(priv->dev, RIO_MSG_BUFFER_SIZE, 773*6ec4bedbSLiu Gang &rmu->msg_tx_ring.phys_buffer[i], GFP_KERNEL); 774*6ec4bedbSLiu Gang if (!rmu->msg_tx_ring.virt_buffer[i]) { 775*6ec4bedbSLiu Gang rc = -ENOMEM; 776*6ec4bedbSLiu Gang for (j = 0; j < rmu->msg_tx_ring.size; j++) 777*6ec4bedbSLiu Gang if (rmu->msg_tx_ring.virt_buffer[j]) 778*6ec4bedbSLiu Gang dma_free_coherent(priv->dev, 779*6ec4bedbSLiu Gang RIO_MSG_BUFFER_SIZE, 780*6ec4bedbSLiu Gang rmu->msg_tx_ring. 781*6ec4bedbSLiu Gang virt_buffer[j], 782*6ec4bedbSLiu Gang rmu->msg_tx_ring. 783*6ec4bedbSLiu Gang phys_buffer[j]); 784*6ec4bedbSLiu Gang goto out; 785*6ec4bedbSLiu Gang } 786*6ec4bedbSLiu Gang } 787*6ec4bedbSLiu Gang 788*6ec4bedbSLiu Gang /* Initialize outbound message descriptor ring */ 789*6ec4bedbSLiu Gang rmu->msg_tx_ring.virt = dma_alloc_coherent(priv->dev, 790*6ec4bedbSLiu Gang rmu->msg_tx_ring.size * RIO_MSG_DESC_SIZE, 791*6ec4bedbSLiu Gang &rmu->msg_tx_ring.phys, GFP_KERNEL); 792*6ec4bedbSLiu Gang if (!rmu->msg_tx_ring.virt) { 793*6ec4bedbSLiu Gang rc = -ENOMEM; 794*6ec4bedbSLiu Gang goto out_dma; 795*6ec4bedbSLiu Gang } 796*6ec4bedbSLiu Gang memset(rmu->msg_tx_ring.virt, 0, 797*6ec4bedbSLiu Gang rmu->msg_tx_ring.size * RIO_MSG_DESC_SIZE); 798*6ec4bedbSLiu Gang rmu->msg_tx_ring.tx_slot = 0; 799*6ec4bedbSLiu Gang 800*6ec4bedbSLiu Gang /* Point dequeue/enqueue pointers at first entry in ring */ 801*6ec4bedbSLiu Gang out_be32(&rmu->msg_regs->odqdpar, rmu->msg_tx_ring.phys); 802*6ec4bedbSLiu Gang out_be32(&rmu->msg_regs->odqepar, rmu->msg_tx_ring.phys); 803*6ec4bedbSLiu Gang 804*6ec4bedbSLiu Gang /* Configure for snooping */ 805*6ec4bedbSLiu Gang out_be32(&rmu->msg_regs->osar, 0x00000004); 806*6ec4bedbSLiu Gang 807*6ec4bedbSLiu Gang /* Clear interrupt status */ 808*6ec4bedbSLiu Gang out_be32(&rmu->msg_regs->osr, 0x000000b3); 809*6ec4bedbSLiu Gang 810*6ec4bedbSLiu Gang /* Hook up outbound message handler */ 811*6ec4bedbSLiu Gang rc = request_irq(IRQ_RIO_TX(mport), fsl_rio_tx_handler, 0, 812*6ec4bedbSLiu Gang "msg_tx", (void *)mport); 813*6ec4bedbSLiu Gang if (rc < 0) 814*6ec4bedbSLiu Gang goto out_irq; 815*6ec4bedbSLiu Gang 816*6ec4bedbSLiu Gang /* 817*6ec4bedbSLiu Gang * Configure outbound message unit 818*6ec4bedbSLiu Gang * Snooping 819*6ec4bedbSLiu Gang * Interrupts (all enabled, except QEIE) 820*6ec4bedbSLiu Gang * Chaining mode 821*6ec4bedbSLiu Gang * Disable 822*6ec4bedbSLiu Gang */ 823*6ec4bedbSLiu Gang out_be32(&rmu->msg_regs->omr, 0x00100220); 824*6ec4bedbSLiu Gang 825*6ec4bedbSLiu Gang /* Set number of entries */ 826*6ec4bedbSLiu Gang out_be32(&rmu->msg_regs->omr, 827*6ec4bedbSLiu Gang in_be32(&rmu->msg_regs->omr) | 828*6ec4bedbSLiu Gang ((get_bitmask_order(entries) - 2) << 12)); 829*6ec4bedbSLiu Gang 830*6ec4bedbSLiu Gang /* Now enable the unit */ 831*6ec4bedbSLiu Gang out_be32(&rmu->msg_regs->omr, in_be32(&rmu->msg_regs->omr) | 0x1); 832*6ec4bedbSLiu Gang 833*6ec4bedbSLiu Gang out: 834*6ec4bedbSLiu Gang return rc; 835*6ec4bedbSLiu Gang 836*6ec4bedbSLiu Gang out_irq: 837*6ec4bedbSLiu Gang dma_free_coherent(priv->dev, 838*6ec4bedbSLiu Gang rmu->msg_tx_ring.size * RIO_MSG_DESC_SIZE, 839*6ec4bedbSLiu Gang rmu->msg_tx_ring.virt, rmu->msg_tx_ring.phys); 840*6ec4bedbSLiu Gang 841*6ec4bedbSLiu Gang out_dma: 842*6ec4bedbSLiu Gang for (i = 0; i < rmu->msg_tx_ring.size; i++) 843*6ec4bedbSLiu Gang dma_free_coherent(priv->dev, RIO_MSG_BUFFER_SIZE, 844*6ec4bedbSLiu Gang rmu->msg_tx_ring.virt_buffer[i], 845*6ec4bedbSLiu Gang rmu->msg_tx_ring.phys_buffer[i]); 846*6ec4bedbSLiu Gang 847*6ec4bedbSLiu Gang return rc; 848*6ec4bedbSLiu Gang } 849*6ec4bedbSLiu Gang 850*6ec4bedbSLiu Gang /** 851*6ec4bedbSLiu Gang * fsl_close_outb_mbox - Shut down MPC85xx outbound mailbox 852*6ec4bedbSLiu Gang * @mport: Master port implementing the outbound message unit 853*6ec4bedbSLiu Gang * @mbox: Mailbox to close 854*6ec4bedbSLiu Gang * 855*6ec4bedbSLiu Gang * Disables the outbound message unit, free all buffers, and 856*6ec4bedbSLiu Gang * frees the outbound message interrupt. 857*6ec4bedbSLiu Gang */ 858*6ec4bedbSLiu Gang static void fsl_close_outb_mbox(struct rio_mport *mport, int mbox) 859*6ec4bedbSLiu Gang { 860*6ec4bedbSLiu Gang struct rio_priv *priv = mport->priv; 861*6ec4bedbSLiu Gang struct fsl_rmu *rmu = GET_RMM_HANDLE(mport); 862*6ec4bedbSLiu Gang 863*6ec4bedbSLiu Gang /* Disable inbound message unit */ 864*6ec4bedbSLiu Gang out_be32(&rmu->msg_regs->omr, 0); 865*6ec4bedbSLiu Gang 866*6ec4bedbSLiu Gang /* Free ring */ 867*6ec4bedbSLiu Gang dma_free_coherent(priv->dev, 868*6ec4bedbSLiu Gang rmu->msg_tx_ring.size * RIO_MSG_DESC_SIZE, 869*6ec4bedbSLiu Gang rmu->msg_tx_ring.virt, rmu->msg_tx_ring.phys); 870*6ec4bedbSLiu Gang 871*6ec4bedbSLiu Gang /* Free interrupt */ 872*6ec4bedbSLiu Gang free_irq(IRQ_RIO_TX(mport), (void *)mport); 873*6ec4bedbSLiu Gang } 874*6ec4bedbSLiu Gang 875*6ec4bedbSLiu Gang /** 876*6ec4bedbSLiu Gang * fsl_open_inb_mbox - Initialize MPC85xx inbound mailbox 877*6ec4bedbSLiu Gang * @mport: Master port implementing the inbound message unit 878*6ec4bedbSLiu Gang * @dev_id: Device specific pointer to pass on event 879*6ec4bedbSLiu Gang * @mbox: Mailbox to open 880*6ec4bedbSLiu Gang * @entries: Number of entries in the inbound mailbox ring 881*6ec4bedbSLiu Gang * 882*6ec4bedbSLiu Gang * Initializes buffer ring, request the inbound message interrupt, 883*6ec4bedbSLiu Gang * and enables the inbound message unit. Returns %0 on success 884*6ec4bedbSLiu Gang * and %-EINVAL or %-ENOMEM on failure. 885*6ec4bedbSLiu Gang */ 886*6ec4bedbSLiu Gang static int 887*6ec4bedbSLiu Gang fsl_open_inb_mbox(struct rio_mport *mport, void *dev_id, int mbox, int entries) 888*6ec4bedbSLiu Gang { 889*6ec4bedbSLiu Gang int i, rc = 0; 890*6ec4bedbSLiu Gang struct rio_priv *priv = mport->priv; 891*6ec4bedbSLiu Gang struct fsl_rmu *rmu = GET_RMM_HANDLE(mport); 892*6ec4bedbSLiu Gang 893*6ec4bedbSLiu Gang if ((entries < RIO_MIN_RX_RING_SIZE) || 894*6ec4bedbSLiu Gang (entries > RIO_MAX_RX_RING_SIZE) || (!is_power_of_2(entries))) { 895*6ec4bedbSLiu Gang rc = -EINVAL; 896*6ec4bedbSLiu Gang goto out; 897*6ec4bedbSLiu Gang } 898*6ec4bedbSLiu Gang 899*6ec4bedbSLiu Gang /* Initialize client buffer ring */ 900*6ec4bedbSLiu Gang rmu->msg_rx_ring.dev_id = dev_id; 901*6ec4bedbSLiu Gang rmu->msg_rx_ring.size = entries; 902*6ec4bedbSLiu Gang rmu->msg_rx_ring.rx_slot = 0; 903*6ec4bedbSLiu Gang for (i = 0; i < rmu->msg_rx_ring.size; i++) 904*6ec4bedbSLiu Gang rmu->msg_rx_ring.virt_buffer[i] = NULL; 905*6ec4bedbSLiu Gang 906*6ec4bedbSLiu Gang /* Initialize inbound message ring */ 907*6ec4bedbSLiu Gang rmu->msg_rx_ring.virt = dma_alloc_coherent(priv->dev, 908*6ec4bedbSLiu Gang rmu->msg_rx_ring.size * RIO_MAX_MSG_SIZE, 909*6ec4bedbSLiu Gang &rmu->msg_rx_ring.phys, GFP_KERNEL); 910*6ec4bedbSLiu Gang if (!rmu->msg_rx_ring.virt) { 911*6ec4bedbSLiu Gang rc = -ENOMEM; 912*6ec4bedbSLiu Gang goto out; 913*6ec4bedbSLiu Gang } 914*6ec4bedbSLiu Gang 915*6ec4bedbSLiu Gang /* Point dequeue/enqueue pointers at first entry in ring */ 916*6ec4bedbSLiu Gang out_be32(&rmu->msg_regs->ifqdpar, (u32) rmu->msg_rx_ring.phys); 917*6ec4bedbSLiu Gang out_be32(&rmu->msg_regs->ifqepar, (u32) rmu->msg_rx_ring.phys); 918*6ec4bedbSLiu Gang 919*6ec4bedbSLiu Gang /* Clear interrupt status */ 920*6ec4bedbSLiu Gang out_be32(&rmu->msg_regs->isr, 0x00000091); 921*6ec4bedbSLiu Gang 922*6ec4bedbSLiu Gang /* Hook up inbound message handler */ 923*6ec4bedbSLiu Gang rc = request_irq(IRQ_RIO_RX(mport), fsl_rio_rx_handler, 0, 924*6ec4bedbSLiu Gang "msg_rx", (void *)mport); 925*6ec4bedbSLiu Gang if (rc < 0) { 926*6ec4bedbSLiu Gang dma_free_coherent(priv->dev, RIO_MSG_BUFFER_SIZE, 927*6ec4bedbSLiu Gang rmu->msg_tx_ring.virt_buffer[i], 928*6ec4bedbSLiu Gang rmu->msg_tx_ring.phys_buffer[i]); 929*6ec4bedbSLiu Gang goto out; 930*6ec4bedbSLiu Gang } 931*6ec4bedbSLiu Gang 932*6ec4bedbSLiu Gang /* 933*6ec4bedbSLiu Gang * Configure inbound message unit: 934*6ec4bedbSLiu Gang * Snooping 935*6ec4bedbSLiu Gang * 4KB max message size 936*6ec4bedbSLiu Gang * Unmask all interrupt sources 937*6ec4bedbSLiu Gang * Disable 938*6ec4bedbSLiu Gang */ 939*6ec4bedbSLiu Gang out_be32(&rmu->msg_regs->imr, 0x001b0060); 940*6ec4bedbSLiu Gang 941*6ec4bedbSLiu Gang /* Set number of queue entries */ 942*6ec4bedbSLiu Gang setbits32(&rmu->msg_regs->imr, (get_bitmask_order(entries) - 2) << 12); 943*6ec4bedbSLiu Gang 944*6ec4bedbSLiu Gang /* Now enable the unit */ 945*6ec4bedbSLiu Gang setbits32(&rmu->msg_regs->imr, 0x1); 946*6ec4bedbSLiu Gang 947*6ec4bedbSLiu Gang out: 948*6ec4bedbSLiu Gang return rc; 949*6ec4bedbSLiu Gang } 950*6ec4bedbSLiu Gang 951*6ec4bedbSLiu Gang /** 952*6ec4bedbSLiu Gang * fsl_close_inb_mbox - Shut down MPC85xx inbound mailbox 953*6ec4bedbSLiu Gang * @mport: Master port implementing the inbound message unit 954*6ec4bedbSLiu Gang * @mbox: Mailbox to close 955*6ec4bedbSLiu Gang * 956*6ec4bedbSLiu Gang * Disables the inbound message unit, free all buffers, and 957*6ec4bedbSLiu Gang * frees the inbound message interrupt. 958*6ec4bedbSLiu Gang */ 959*6ec4bedbSLiu Gang static void fsl_close_inb_mbox(struct rio_mport *mport, int mbox) 960*6ec4bedbSLiu Gang { 961*6ec4bedbSLiu Gang struct rio_priv *priv = mport->priv; 962*6ec4bedbSLiu Gang struct fsl_rmu *rmu = GET_RMM_HANDLE(mport); 963*6ec4bedbSLiu Gang 964*6ec4bedbSLiu Gang /* Disable inbound message unit */ 965*6ec4bedbSLiu Gang out_be32(&rmu->msg_regs->imr, 0); 966*6ec4bedbSLiu Gang 967*6ec4bedbSLiu Gang /* Free ring */ 968*6ec4bedbSLiu Gang dma_free_coherent(priv->dev, rmu->msg_rx_ring.size * RIO_MAX_MSG_SIZE, 969*6ec4bedbSLiu Gang rmu->msg_rx_ring.virt, rmu->msg_rx_ring.phys); 970*6ec4bedbSLiu Gang 971*6ec4bedbSLiu Gang /* Free interrupt */ 972*6ec4bedbSLiu Gang free_irq(IRQ_RIO_RX(mport), (void *)mport); 973*6ec4bedbSLiu Gang } 974*6ec4bedbSLiu Gang 975*6ec4bedbSLiu Gang /** 976*6ec4bedbSLiu Gang * fsl_add_inb_buffer - Add buffer to the MPC85xx inbound message queue 977*6ec4bedbSLiu Gang * @mport: Master port implementing the inbound message unit 978*6ec4bedbSLiu Gang * @mbox: Inbound mailbox number 979*6ec4bedbSLiu Gang * @buf: Buffer to add to inbound queue 980*6ec4bedbSLiu Gang * 981*6ec4bedbSLiu Gang * Adds the @buf buffer to the MPC85xx inbound message queue. Returns 982*6ec4bedbSLiu Gang * %0 on success or %-EINVAL on failure. 983*6ec4bedbSLiu Gang */ 984*6ec4bedbSLiu Gang static int fsl_add_inb_buffer(struct rio_mport *mport, int mbox, void *buf) 985*6ec4bedbSLiu Gang { 986*6ec4bedbSLiu Gang int rc = 0; 987*6ec4bedbSLiu Gang struct fsl_rmu *rmu = GET_RMM_HANDLE(mport); 988*6ec4bedbSLiu Gang 989*6ec4bedbSLiu Gang pr_debug("RIO: fsl_add_inb_buffer(), msg_rx_ring.rx_slot %d\n", 990*6ec4bedbSLiu Gang rmu->msg_rx_ring.rx_slot); 991*6ec4bedbSLiu Gang 992*6ec4bedbSLiu Gang if (rmu->msg_rx_ring.virt_buffer[rmu->msg_rx_ring.rx_slot]) { 993*6ec4bedbSLiu Gang printk(KERN_ERR 994*6ec4bedbSLiu Gang "RIO: error adding inbound buffer %d, buffer exists\n", 995*6ec4bedbSLiu Gang rmu->msg_rx_ring.rx_slot); 996*6ec4bedbSLiu Gang rc = -EINVAL; 997*6ec4bedbSLiu Gang goto out; 998*6ec4bedbSLiu Gang } 999*6ec4bedbSLiu Gang 1000*6ec4bedbSLiu Gang rmu->msg_rx_ring.virt_buffer[rmu->msg_rx_ring.rx_slot] = buf; 1001*6ec4bedbSLiu Gang if (++rmu->msg_rx_ring.rx_slot == rmu->msg_rx_ring.size) 1002*6ec4bedbSLiu Gang rmu->msg_rx_ring.rx_slot = 0; 1003*6ec4bedbSLiu Gang 1004*6ec4bedbSLiu Gang out: 1005*6ec4bedbSLiu Gang return rc; 1006*6ec4bedbSLiu Gang } 1007*6ec4bedbSLiu Gang 1008*6ec4bedbSLiu Gang /** 1009*6ec4bedbSLiu Gang * fsl_get_inb_message - Fetch inbound message from the MPC85xx message unit 1010*6ec4bedbSLiu Gang * @mport: Master port implementing the inbound message unit 1011*6ec4bedbSLiu Gang * @mbox: Inbound mailbox number 1012*6ec4bedbSLiu Gang * 1013*6ec4bedbSLiu Gang * Gets the next available inbound message from the inbound message queue. 1014*6ec4bedbSLiu Gang * A pointer to the message is returned on success or NULL on failure. 1015*6ec4bedbSLiu Gang */ 1016*6ec4bedbSLiu Gang static void *fsl_get_inb_message(struct rio_mport *mport, int mbox) 1017*6ec4bedbSLiu Gang { 1018*6ec4bedbSLiu Gang struct fsl_rmu *rmu = GET_RMM_HANDLE(mport); 1019*6ec4bedbSLiu Gang u32 phys_buf, virt_buf; 1020*6ec4bedbSLiu Gang void *buf = NULL; 1021*6ec4bedbSLiu Gang int buf_idx; 1022*6ec4bedbSLiu Gang 1023*6ec4bedbSLiu Gang phys_buf = in_be32(&rmu->msg_regs->ifqdpar); 1024*6ec4bedbSLiu Gang 1025*6ec4bedbSLiu Gang /* If no more messages, then bail out */ 1026*6ec4bedbSLiu Gang if (phys_buf == in_be32(&rmu->msg_regs->ifqepar)) 1027*6ec4bedbSLiu Gang goto out2; 1028*6ec4bedbSLiu Gang 1029*6ec4bedbSLiu Gang virt_buf = (u32) rmu->msg_rx_ring.virt + (phys_buf 1030*6ec4bedbSLiu Gang - rmu->msg_rx_ring.phys); 1031*6ec4bedbSLiu Gang buf_idx = (phys_buf - rmu->msg_rx_ring.phys) / RIO_MAX_MSG_SIZE; 1032*6ec4bedbSLiu Gang buf = rmu->msg_rx_ring.virt_buffer[buf_idx]; 1033*6ec4bedbSLiu Gang 1034*6ec4bedbSLiu Gang if (!buf) { 1035*6ec4bedbSLiu Gang printk(KERN_ERR 1036*6ec4bedbSLiu Gang "RIO: inbound message copy failed, no buffers\n"); 1037*6ec4bedbSLiu Gang goto out1; 1038*6ec4bedbSLiu Gang } 1039*6ec4bedbSLiu Gang 1040*6ec4bedbSLiu Gang /* Copy max message size, caller is expected to allocate that big */ 1041*6ec4bedbSLiu Gang memcpy(buf, (void *)virt_buf, RIO_MAX_MSG_SIZE); 1042*6ec4bedbSLiu Gang 1043*6ec4bedbSLiu Gang /* Clear the available buffer */ 1044*6ec4bedbSLiu Gang rmu->msg_rx_ring.virt_buffer[buf_idx] = NULL; 1045*6ec4bedbSLiu Gang 1046*6ec4bedbSLiu Gang out1: 1047*6ec4bedbSLiu Gang setbits32(&rmu->msg_regs->imr, RIO_MSG_IMR_MI); 1048*6ec4bedbSLiu Gang 1049*6ec4bedbSLiu Gang out2: 1050*6ec4bedbSLiu Gang return buf; 1051*6ec4bedbSLiu Gang } 1052*6ec4bedbSLiu Gang 1053*6ec4bedbSLiu Gang /** 1054*6ec4bedbSLiu Gang * fsl_rio_doorbell_init - MPC85xx doorbell interface init 1055*6ec4bedbSLiu Gang * @mport: Master port implementing the inbound doorbell unit 1056*6ec4bedbSLiu Gang * 1057*6ec4bedbSLiu Gang * Initializes doorbell unit hardware and inbound DMA buffer 1058*6ec4bedbSLiu Gang * ring. Called from fsl_rio_setup(). Returns %0 on success 1059*6ec4bedbSLiu Gang * or %-ENOMEM on failure. 1060*6ec4bedbSLiu Gang */ 1061*6ec4bedbSLiu Gang static int fsl_rio_doorbell_init(struct rio_mport *mport) 1062*6ec4bedbSLiu Gang { 1063*6ec4bedbSLiu Gang struct rio_priv *priv = mport->priv; 1064*6ec4bedbSLiu Gang struct fsl_rmu *rmu = GET_RMM_HANDLE(mport); 1065*6ec4bedbSLiu Gang int rc = 0; 1066*6ec4bedbSLiu Gang 1067*6ec4bedbSLiu Gang /* Map outbound doorbell window immediately after maintenance window */ 1068*6ec4bedbSLiu Gang rmu->dbell_win = ioremap(mport->iores.start + RIO_MAINT_WIN_SIZE, 1069*6ec4bedbSLiu Gang RIO_DBELL_WIN_SIZE); 1070*6ec4bedbSLiu Gang if (!rmu->dbell_win) { 1071*6ec4bedbSLiu Gang printk(KERN_ERR 1072*6ec4bedbSLiu Gang "RIO: unable to map outbound doorbell window\n"); 1073*6ec4bedbSLiu Gang rc = -ENOMEM; 1074*6ec4bedbSLiu Gang goto out; 1075*6ec4bedbSLiu Gang } 1076*6ec4bedbSLiu Gang 1077*6ec4bedbSLiu Gang /* Initialize inbound doorbells */ 1078*6ec4bedbSLiu Gang rmu->dbell_ring.virt = dma_alloc_coherent(priv->dev, 512 * 1079*6ec4bedbSLiu Gang DOORBELL_MESSAGE_SIZE, &rmu->dbell_ring.phys, GFP_KERNEL); 1080*6ec4bedbSLiu Gang if (!rmu->dbell_ring.virt) { 1081*6ec4bedbSLiu Gang printk(KERN_ERR "RIO: unable allocate inbound doorbell ring\n"); 1082*6ec4bedbSLiu Gang rc = -ENOMEM; 1083*6ec4bedbSLiu Gang iounmap(rmu->dbell_win); 1084*6ec4bedbSLiu Gang goto out; 1085*6ec4bedbSLiu Gang } 1086*6ec4bedbSLiu Gang 1087*6ec4bedbSLiu Gang /* Point dequeue/enqueue pointers at first entry in ring */ 1088*6ec4bedbSLiu Gang out_be32(&rmu->msg_regs->dqdpar, (u32) rmu->dbell_ring.phys); 1089*6ec4bedbSLiu Gang out_be32(&rmu->msg_regs->dqepar, (u32) rmu->dbell_ring.phys); 1090*6ec4bedbSLiu Gang 1091*6ec4bedbSLiu Gang /* Clear interrupt status */ 1092*6ec4bedbSLiu Gang out_be32(&rmu->msg_regs->dsr, 0x00000091); 1093*6ec4bedbSLiu Gang 1094*6ec4bedbSLiu Gang /* Hook up doorbell handler */ 1095*6ec4bedbSLiu Gang rc = request_irq(IRQ_RIO_BELL(mport), fsl_rio_dbell_handler, 0, 1096*6ec4bedbSLiu Gang "dbell_rx", (void *)mport); 1097*6ec4bedbSLiu Gang if (rc < 0) { 1098*6ec4bedbSLiu Gang iounmap(rmu->dbell_win); 1099*6ec4bedbSLiu Gang dma_free_coherent(priv->dev, 512 * DOORBELL_MESSAGE_SIZE, 1100*6ec4bedbSLiu Gang rmu->dbell_ring.virt, rmu->dbell_ring.phys); 1101*6ec4bedbSLiu Gang printk(KERN_ERR 1102*6ec4bedbSLiu Gang "MPC85xx RIO: unable to request inbound doorbell irq"); 1103*6ec4bedbSLiu Gang goto out; 1104*6ec4bedbSLiu Gang } 1105*6ec4bedbSLiu Gang 1106*6ec4bedbSLiu Gang /* Configure doorbells for snooping, 512 entries, and enable */ 1107*6ec4bedbSLiu Gang out_be32(&rmu->msg_regs->dmr, 0x00108161); 1108*6ec4bedbSLiu Gang 1109*6ec4bedbSLiu Gang out: 1110*6ec4bedbSLiu Gang return rc; 1111*6ec4bedbSLiu Gang } 1112*6ec4bedbSLiu Gang 1113*6ec4bedbSLiu Gang int fsl_rio_setup_rmu(struct rio_mport *mport, struct device_node *node) 1114*6ec4bedbSLiu Gang { 1115*6ec4bedbSLiu Gang struct rio_priv *priv; 1116*6ec4bedbSLiu Gang struct fsl_rmu *rmu; 1117*6ec4bedbSLiu Gang struct rio_ops *ops; 1118*6ec4bedbSLiu Gang 1119*6ec4bedbSLiu Gang if (!mport || !mport->priv || !node) 1120*6ec4bedbSLiu Gang return -1; 1121*6ec4bedbSLiu Gang 1122*6ec4bedbSLiu Gang rmu = kzalloc(sizeof(struct fsl_rmu), GFP_KERNEL); 1123*6ec4bedbSLiu Gang if (!rmu) 1124*6ec4bedbSLiu Gang return -ENOMEM; 1125*6ec4bedbSLiu Gang 1126*6ec4bedbSLiu Gang priv = mport->priv; 1127*6ec4bedbSLiu Gang priv->rmm_handle = rmu; 1128*6ec4bedbSLiu Gang rmu->dbell_atmu_regs = priv->atmu_regs + 2; 1129*6ec4bedbSLiu Gang rmu->msg_regs = (struct rio_msg_regs *)(priv->regs_win + 1130*6ec4bedbSLiu Gang ((mport->phy_type == RIO_PHY_SERIAL) ? 1131*6ec4bedbSLiu Gang RIO_S_MSG_REGS_OFFSET : RIO_P_MSG_REGS_OFFSET)); 1132*6ec4bedbSLiu Gang 1133*6ec4bedbSLiu Gang rmu->bellirq = irq_of_parse_and_map(node, 2); 1134*6ec4bedbSLiu Gang rmu->txirq = irq_of_parse_and_map(node, 3); 1135*6ec4bedbSLiu Gang rmu->rxirq = irq_of_parse_and_map(node, 4); 1136*6ec4bedbSLiu Gang dev_info(priv->dev, "bellirq: %d, txirq: %d, rxirq %d\n", 1137*6ec4bedbSLiu Gang rmu->bellirq, rmu->txirq, rmu->rxirq); 1138*6ec4bedbSLiu Gang 1139*6ec4bedbSLiu Gang ops = mport->ops; 1140*6ec4bedbSLiu Gang 1141*6ec4bedbSLiu Gang ops->dsend = fsl_rio_doorbell_send; 1142*6ec4bedbSLiu Gang ops->open_outb_mbox = fsl_open_outb_mbox; 1143*6ec4bedbSLiu Gang ops->open_inb_mbox = fsl_open_inb_mbox; 1144*6ec4bedbSLiu Gang ops->close_outb_mbox = fsl_close_outb_mbox; 1145*6ec4bedbSLiu Gang ops->close_inb_mbox = fsl_close_inb_mbox; 1146*6ec4bedbSLiu Gang ops->add_outb_message = fsl_add_outb_message; 1147*6ec4bedbSLiu Gang ops->add_inb_buffer = fsl_add_inb_buffer; 1148*6ec4bedbSLiu Gang ops->get_inb_message = fsl_get_inb_message; 1149*6ec4bedbSLiu Gang 1150*6ec4bedbSLiu Gang rio_init_dbell_res(&mport->riores[RIO_DOORBELL_RESOURCE], 0, 0xffff); 1151*6ec4bedbSLiu Gang rio_init_mbox_res(&mport->riores[RIO_INB_MBOX_RESOURCE], 0, 0); 1152*6ec4bedbSLiu Gang rio_init_mbox_res(&mport->riores[RIO_OUTB_MBOX_RESOURCE], 0, 0); 1153*6ec4bedbSLiu Gang 1154*6ec4bedbSLiu Gang /* Configure outbound doorbell window */ 1155*6ec4bedbSLiu Gang out_be32(&rmu->dbell_atmu_regs->rowbar, 1156*6ec4bedbSLiu Gang (mport->iores.start + RIO_MAINT_WIN_SIZE) >> 12); 1157*6ec4bedbSLiu Gang /* 4k window size */ 1158*6ec4bedbSLiu Gang out_be32(&rmu->dbell_atmu_regs->rowar, 0x8004200b); 1159*6ec4bedbSLiu Gang 1160*6ec4bedbSLiu Gang fsl_rio_doorbell_init(mport); 1161*6ec4bedbSLiu Gang 1162*6ec4bedbSLiu Gang return 0; 1163*6ec4bedbSLiu Gang } 1164