12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 2de3c8d41SKumar Gala /* 3d02443a6SZhang Wei * Freescale MPC85xx/MPC86xx RapidIO support 4de3c8d41SKumar Gala * 5bd4fb654SThomas Moll * Copyright 2009 Sysgo AG 6bd4fb654SThomas Moll * Thomas Moll <thomas.moll@sysgo.com> 7bd4fb654SThomas Moll * - fixed maintenance access routines, check for aligned access 8bd4fb654SThomas Moll * 95b2074aeSAlexandre Bounine * Copyright 2009 Integrated Device Technology, Inc. 105b2074aeSAlexandre Bounine * Alex Bounine <alexandre.bounine@idt.com> 115b2074aeSAlexandre Bounine * - Added Port-Write message handling 125b2074aeSAlexandre Bounine * - Added Machine Check exception handling 135b2074aeSAlexandre Bounine * 146ec4bedbSLiu Gang * Copyright (C) 2007, 2008, 2010, 2011 Freescale Semiconductor, Inc. 15ad1e9380SZhang Wei * Zhang Wei <wei.zhang@freescale.com> 16ad1e9380SZhang Wei * 17de3c8d41SKumar Gala * Copyright 2005 MontaVista Software, Inc. 18de3c8d41SKumar Gala * Matt Porter <mporter@kernel.crashing.org> 19de3c8d41SKumar Gala */ 20de3c8d41SKumar Gala 21de3c8d41SKumar Gala #include <linux/init.h> 228a39b05fSPaul Gortmaker #include <linux/extable.h> 23de3c8d41SKumar Gala #include <linux/types.h> 24de3c8d41SKumar Gala #include <linux/dma-mapping.h> 25de3c8d41SKumar Gala #include <linux/interrupt.h> 260dbbbf1aSAnton Vorontsov #include <linux/device.h> 2726a2056eSRob Herring #include <linux/of_address.h> 2826a2056eSRob Herring #include <linux/of_irq.h> 29cc2bb696SZhang Wei #include <linux/of_platform.h> 3061b26917SZhang Wei #include <linux/delay.h> 315a0e3ad6STejun Heo #include <linux/slab.h> 32de3c8d41SKumar Gala 336ec4bedbSLiu Gang #include <linux/io.h> 346ec4bedbSLiu Gang #include <linux/uaccess.h> 35a52c8f52SAlexandre Bounine #include <asm/machdep.h> 366ec4bedbSLiu Gang 376ec4bedbSLiu Gang #include "fsl_rio.h" 38de3c8d41SKumar Gala 395b2074aeSAlexandre Bounine #undef DEBUG_PW /* Port-Write debugging */ 405b2074aeSAlexandre Bounine 416ff31453SShaohui Xie #define RIO_PORT1_EDCSR 0x0640 426ff31453SShaohui Xie #define RIO_PORT2_EDCSR 0x0680 436ff31453SShaohui Xie #define RIO_PORT1_IECSR 0x10130 446ff31453SShaohui Xie #define RIO_PORT2_IECSR 0x101B0 456ff31453SShaohui Xie 46af84ca38SAlexandre Bounine #define RIO_GCCSR 0x13c 4761b26917SZhang Wei #define RIO_ESCSR 0x158 486ec4bedbSLiu Gang #define ESCSR_CLEAR 0x07120204 496ff31453SShaohui Xie #define RIO_PORT2_ESCSR 0x178 5061b26917SZhang Wei #define RIO_CCSR 0x15c 51a52c8f52SAlexandre Bounine #define RIO_LTLEDCSR_IER 0x80000000 52a52c8f52SAlexandre Bounine #define RIO_LTLEDCSR_PRT 0x01000000 536ec4bedbSLiu Gang #define IECSR_CLEAR 0x80000000 5461b26917SZhang Wei #define RIO_ISR_AACR 0x10120 5561b26917SZhang Wei #define RIO_ISR_AACR_AA 0x1 /* Accept All ID */ 56de3c8d41SKumar Gala 57e6a546fdSMartijn de Gouw #define RIWTAR_TRAD_VAL_SHIFT 12 58e6a546fdSMartijn de Gouw #define RIWTAR_TRAD_MASK 0x00FFFFFF 59e6a546fdSMartijn de Gouw #define RIWBAR_BADD_VAL_SHIFT 12 60e6a546fdSMartijn de Gouw #define RIWBAR_BADD_MASK 0x003FFFFF 61e6a546fdSMartijn de Gouw #define RIWAR_ENABLE 0x80000000 62e6a546fdSMartijn de Gouw #define RIWAR_TGINT_LOCAL 0x00F00000 63e6a546fdSMartijn de Gouw #define RIWAR_RDTYP_NO_SNOOP 0x00040000 64e6a546fdSMartijn de Gouw #define RIWAR_RDTYP_SNOOP 0x00050000 65e6a546fdSMartijn de Gouw #define RIWAR_WRTYP_NO_SNOOP 0x00004000 66e6a546fdSMartijn de Gouw #define RIWAR_WRTYP_SNOOP 0x00005000 67e6a546fdSMartijn de Gouw #define RIWAR_WRTYP_ALLOC 0x00006000 68e6a546fdSMartijn de Gouw #define RIWAR_SIZE_MASK 0x0000003F 69e6a546fdSMartijn de Gouw 7031d1e130SIoan Nicu static DEFINE_SPINLOCK(fsl_rio_config_lock); 7131d1e130SIoan Nicu 72a52c8f52SAlexandre Bounine #define __fsl_read_rio_config(x, addr, err, op) \ 73a52c8f52SAlexandre Bounine __asm__ __volatile__( \ 74a52c8f52SAlexandre Bounine "1: "op" %1,0(%2)\n" \ 75a52c8f52SAlexandre Bounine " eieio\n" \ 76a52c8f52SAlexandre Bounine "2:\n" \ 77a52c8f52SAlexandre Bounine ".section .fixup,\"ax\"\n" \ 78a52c8f52SAlexandre Bounine "3: li %1,-1\n" \ 79a52c8f52SAlexandre Bounine " li %0,%3\n" \ 80a52c8f52SAlexandre Bounine " b 2b\n" \ 8124bfa6a9SNicholas Piggin ".previous\n" \ 8224bfa6a9SNicholas Piggin EX_TABLE(1b, 3b) \ 83a52c8f52SAlexandre Bounine : "=r" (err), "=r" (x) \ 84a52c8f52SAlexandre Bounine : "b" (addr), "i" (-EFAULT), "0" (err)) 85a52c8f52SAlexandre Bounine 866ec4bedbSLiu Gang void __iomem *rio_regs_win; 87abc3aeaeSLiu Gang void __iomem *rmu_regs_win; 88abc3aeaeSLiu Gang resource_size_t rio_law_start; 89abc3aeaeSLiu Gang 90abc3aeaeSLiu Gang struct fsl_rio_dbell *dbell; 91abc3aeaeSLiu Gang struct fsl_rio_pw *pw; 92a52c8f52SAlexandre Bounine 93ff33f182SLi Yang #ifdef CONFIG_E500 94cce1f106SShaohui Xie int fsl_rio_mcheck_exception(struct pt_regs *regs) 95a52c8f52SAlexandre Bounine { 9682a9a480SScott Wood const struct exception_table_entry *entry; 9782a9a480SScott Wood unsigned long reason; 98a52c8f52SAlexandre Bounine 9982a9a480SScott Wood if (!rio_regs_win) 10082a9a480SScott Wood return 0; 10182a9a480SScott Wood 102a52c8f52SAlexandre Bounine reason = in_be32((u32 *)(rio_regs_win + RIO_LTLEDCSR)); 103a52c8f52SAlexandre Bounine if (reason & (RIO_LTLEDCSR_IER | RIO_LTLEDCSR_PRT)) { 104a52c8f52SAlexandre Bounine /* Check if we are prepared to handle this fault */ 105a52c8f52SAlexandre Bounine entry = search_exception_tables(regs->nip); 106a52c8f52SAlexandre Bounine if (entry) { 107a52c8f52SAlexandre Bounine pr_debug("RIO: %s - MC Exception handled\n", 108a52c8f52SAlexandre Bounine __func__); 109a52c8f52SAlexandre Bounine out_be32((u32 *)(rio_regs_win + RIO_LTLEDCSR), 110a52c8f52SAlexandre Bounine 0); 111806c0e6eSChristophe Leroy regs_set_recoverable(regs); 11259dc5bfcSNicholas Piggin regs_set_return_ip(regs, extable_fixup(entry)); 113a52c8f52SAlexandre Bounine return 1; 114a52c8f52SAlexandre Bounine } 115a52c8f52SAlexandre Bounine } 116a52c8f52SAlexandre Bounine 117cce1f106SShaohui Xie return 0; 118a52c8f52SAlexandre Bounine } 119cce1f106SShaohui Xie EXPORT_SYMBOL_GPL(fsl_rio_mcheck_exception); 120ff33f182SLi Yang #endif 121a52c8f52SAlexandre Bounine 122de3c8d41SKumar Gala /** 123d02443a6SZhang Wei * fsl_local_config_read - Generate a MPC85xx local config space read 1249941d945SRandy Dunlap * @mport: RapidIO master port info 125de3c8d41SKumar Gala * @index: ID of RapdiIO interface 126de3c8d41SKumar Gala * @offset: Offset into configuration space 127de3c8d41SKumar Gala * @len: Length (in bytes) of the maintenance transaction 128de3c8d41SKumar Gala * @data: Value to be read into 129de3c8d41SKumar Gala * 130de3c8d41SKumar Gala * Generates a MPC85xx local configuration space read. Returns %0 on 131de3c8d41SKumar Gala * success or %-EINVAL on failure. 132de3c8d41SKumar Gala */ 133ad1e9380SZhang Wei static int fsl_local_config_read(struct rio_mport *mport, 134ad1e9380SZhang Wei int index, u32 offset, int len, u32 *data) 135de3c8d41SKumar Gala { 136ad1e9380SZhang Wei struct rio_priv *priv = mport->priv; 137d02443a6SZhang Wei pr_debug("fsl_local_config_read: index %d offset %8.8x\n", index, 138de3c8d41SKumar Gala offset); 139ad1e9380SZhang Wei *data = in_be32(priv->regs_win + offset); 140de3c8d41SKumar Gala 141de3c8d41SKumar Gala return 0; 142de3c8d41SKumar Gala } 143de3c8d41SKumar Gala 144de3c8d41SKumar Gala /** 145d02443a6SZhang Wei * fsl_local_config_write - Generate a MPC85xx local config space write 1469941d945SRandy Dunlap * @mport: RapidIO master port info 147de3c8d41SKumar Gala * @index: ID of RapdiIO interface 148de3c8d41SKumar Gala * @offset: Offset into configuration space 149de3c8d41SKumar Gala * @len: Length (in bytes) of the maintenance transaction 150de3c8d41SKumar Gala * @data: Value to be written 151de3c8d41SKumar Gala * 152de3c8d41SKumar Gala * Generates a MPC85xx local configuration space write. Returns %0 on 153de3c8d41SKumar Gala * success or %-EINVAL on failure. 154de3c8d41SKumar Gala */ 155ad1e9380SZhang Wei static int fsl_local_config_write(struct rio_mport *mport, 156ad1e9380SZhang Wei int index, u32 offset, int len, u32 data) 157de3c8d41SKumar Gala { 158ad1e9380SZhang Wei struct rio_priv *priv = mport->priv; 159de3c8d41SKumar Gala pr_debug 160d02443a6SZhang Wei ("fsl_local_config_write: index %d offset %8.8x data %8.8x\n", 161de3c8d41SKumar Gala index, offset, data); 162ad1e9380SZhang Wei out_be32(priv->regs_win + offset, data); 163de3c8d41SKumar Gala 164de3c8d41SKumar Gala return 0; 165de3c8d41SKumar Gala } 166de3c8d41SKumar Gala 167de3c8d41SKumar Gala /** 168d02443a6SZhang Wei * fsl_rio_config_read - Generate a MPC85xx read maintenance transaction 1699941d945SRandy Dunlap * @mport: RapidIO master port info 170de3c8d41SKumar Gala * @index: ID of RapdiIO interface 171de3c8d41SKumar Gala * @destid: Destination ID of transaction 172de3c8d41SKumar Gala * @hopcount: Number of hops to target device 173de3c8d41SKumar Gala * @offset: Offset into configuration space 174de3c8d41SKumar Gala * @len: Length (in bytes) of the maintenance transaction 175de3c8d41SKumar Gala * @val: Location to be read into 176de3c8d41SKumar Gala * 177de3c8d41SKumar Gala * Generates a MPC85xx read maintenance transaction. Returns %0 on 178de3c8d41SKumar Gala * success or %-EINVAL on failure. 179de3c8d41SKumar Gala */ 180de3c8d41SKumar Gala static int 181ad1e9380SZhang Wei fsl_rio_config_read(struct rio_mport *mport, int index, u16 destid, 182ad1e9380SZhang Wei u8 hopcount, u32 offset, int len, u32 *val) 183de3c8d41SKumar Gala { 184ad1e9380SZhang Wei struct rio_priv *priv = mport->priv; 18531d1e130SIoan Nicu unsigned long flags; 186de3c8d41SKumar Gala u8 *data; 187a52c8f52SAlexandre Bounine u32 rval, err = 0; 188de3c8d41SKumar Gala 189de3c8d41SKumar Gala pr_debug 1906ec4bedbSLiu Gang ("fsl_rio_config_read:" 1916ec4bedbSLiu Gang " index %d destid %d hopcount %d offset %8.8x len %d\n", 192de3c8d41SKumar Gala index, destid, hopcount, offset, len); 193de3c8d41SKumar Gala 194bd4fb654SThomas Moll /* 16MB maintenance window possible */ 195bd4fb654SThomas Moll /* allow only aligned access to maintenance registers */ 196bd4fb654SThomas Moll if (offset > (0x1000000 - len) || !IS_ALIGNED(offset, len)) 197bd4fb654SThomas Moll return -EINVAL; 198bd4fb654SThomas Moll 19931d1e130SIoan Nicu spin_lock_irqsave(&fsl_rio_config_lock, flags); 20031d1e130SIoan Nicu 201bd4fb654SThomas Moll out_be32(&priv->maint_atmu_regs->rowtar, 202bd4fb654SThomas Moll (destid << 22) | (hopcount << 12) | (offset >> 12)); 203bd4fb654SThomas Moll out_be32(&priv->maint_atmu_regs->rowtear, (destid >> 10)); 204bd4fb654SThomas Moll 205bd4fb654SThomas Moll data = (u8 *) priv->maint_win + (offset & (RIO_MAINT_WIN_SIZE - 1)); 206de3c8d41SKumar Gala switch (len) { 207de3c8d41SKumar Gala case 1: 208a52c8f52SAlexandre Bounine __fsl_read_rio_config(rval, data, err, "lbz"); 209de3c8d41SKumar Gala break; 210de3c8d41SKumar Gala case 2: 211a52c8f52SAlexandre Bounine __fsl_read_rio_config(rval, data, err, "lhz"); 212de3c8d41SKumar Gala break; 213bd4fb654SThomas Moll case 4: 214a52c8f52SAlexandre Bounine __fsl_read_rio_config(rval, data, err, "lwz"); 215de3c8d41SKumar Gala break; 216bd4fb654SThomas Moll default: 21731d1e130SIoan Nicu spin_unlock_irqrestore(&fsl_rio_config_lock, flags); 218bd4fb654SThomas Moll return -EINVAL; 219de3c8d41SKumar Gala } 220de3c8d41SKumar Gala 221a52c8f52SAlexandre Bounine if (err) { 222a52c8f52SAlexandre Bounine pr_debug("RIO: cfg_read error %d for %x:%x:%x\n", 223a52c8f52SAlexandre Bounine err, destid, hopcount, offset); 224a52c8f52SAlexandre Bounine } 225a52c8f52SAlexandre Bounine 22631d1e130SIoan Nicu spin_unlock_irqrestore(&fsl_rio_config_lock, flags); 227a52c8f52SAlexandre Bounine *val = rval; 228a52c8f52SAlexandre Bounine 229a52c8f52SAlexandre Bounine return err; 230de3c8d41SKumar Gala } 231de3c8d41SKumar Gala 232de3c8d41SKumar Gala /** 233d02443a6SZhang Wei * fsl_rio_config_write - Generate a MPC85xx write maintenance transaction 2349941d945SRandy Dunlap * @mport: RapidIO master port info 235de3c8d41SKumar Gala * @index: ID of RapdiIO interface 236de3c8d41SKumar Gala * @destid: Destination ID of transaction 237de3c8d41SKumar Gala * @hopcount: Number of hops to target device 238de3c8d41SKumar Gala * @offset: Offset into configuration space 239de3c8d41SKumar Gala * @len: Length (in bytes) of the maintenance transaction 240de3c8d41SKumar Gala * @val: Value to be written 241de3c8d41SKumar Gala * 242de3c8d41SKumar Gala * Generates an MPC85xx write maintenance transaction. Returns %0 on 243de3c8d41SKumar Gala * success or %-EINVAL on failure. 244de3c8d41SKumar Gala */ 245de3c8d41SKumar Gala static int 246ad1e9380SZhang Wei fsl_rio_config_write(struct rio_mport *mport, int index, u16 destid, 247ad1e9380SZhang Wei u8 hopcount, u32 offset, int len, u32 val) 248de3c8d41SKumar Gala { 249ad1e9380SZhang Wei struct rio_priv *priv = mport->priv; 25031d1e130SIoan Nicu unsigned long flags; 251de3c8d41SKumar Gala u8 *data; 25231d1e130SIoan Nicu int ret = 0; 25331d1e130SIoan Nicu 254de3c8d41SKumar Gala pr_debug 2556ec4bedbSLiu Gang ("fsl_rio_config_write:" 2566ec4bedbSLiu Gang " index %d destid %d hopcount %d offset %8.8x len %d val %8.8x\n", 257de3c8d41SKumar Gala index, destid, hopcount, offset, len, val); 258de3c8d41SKumar Gala 259bd4fb654SThomas Moll /* 16MB maintenance windows possible */ 260bd4fb654SThomas Moll /* allow only aligned access to maintenance registers */ 261bd4fb654SThomas Moll if (offset > (0x1000000 - len) || !IS_ALIGNED(offset, len)) 262bd4fb654SThomas Moll return -EINVAL; 263bd4fb654SThomas Moll 26431d1e130SIoan Nicu spin_lock_irqsave(&fsl_rio_config_lock, flags); 26531d1e130SIoan Nicu 266bd4fb654SThomas Moll out_be32(&priv->maint_atmu_regs->rowtar, 267bd4fb654SThomas Moll (destid << 22) | (hopcount << 12) | (offset >> 12)); 268bd4fb654SThomas Moll out_be32(&priv->maint_atmu_regs->rowtear, (destid >> 10)); 269bd4fb654SThomas Moll 270bd4fb654SThomas Moll data = (u8 *) priv->maint_win + (offset & (RIO_MAINT_WIN_SIZE - 1)); 271de3c8d41SKumar Gala switch (len) { 272de3c8d41SKumar Gala case 1: 273de3c8d41SKumar Gala out_8((u8 *) data, val); 274de3c8d41SKumar Gala break; 275de3c8d41SKumar Gala case 2: 276de3c8d41SKumar Gala out_be16((u16 *) data, val); 277de3c8d41SKumar Gala break; 278bd4fb654SThomas Moll case 4: 279de3c8d41SKumar Gala out_be32((u32 *) data, val); 280de3c8d41SKumar Gala break; 281bd4fb654SThomas Moll default: 28231d1e130SIoan Nicu ret = -EINVAL; 283de3c8d41SKumar Gala } 28431d1e130SIoan Nicu spin_unlock_irqrestore(&fsl_rio_config_lock, flags); 285de3c8d41SKumar Gala 28631d1e130SIoan Nicu return ret; 287de3c8d41SKumar Gala } 288de3c8d41SKumar Gala 289e6a546fdSMartijn de Gouw static void fsl_rio_inbound_mem_init(struct rio_priv *priv) 290e6a546fdSMartijn de Gouw { 291e6a546fdSMartijn de Gouw int i; 292e6a546fdSMartijn de Gouw 293e6a546fdSMartijn de Gouw /* close inbound windows */ 294e6a546fdSMartijn de Gouw for (i = 0; i < RIO_INB_ATMU_COUNT; i++) 295e6a546fdSMartijn de Gouw out_be32(&priv->inb_atmu_regs[i].riwar, 0); 296e6a546fdSMartijn de Gouw } 297e6a546fdSMartijn de Gouw 298e6a546fdSMartijn de Gouw int fsl_map_inb_mem(struct rio_mport *mport, dma_addr_t lstart, 299a057a52eSAlexandre Bounine u64 rstart, u64 size, u32 flags) 300e6a546fdSMartijn de Gouw { 301e6a546fdSMartijn de Gouw struct rio_priv *priv = mport->priv; 302e6a546fdSMartijn de Gouw u32 base_size; 303e6a546fdSMartijn de Gouw unsigned int base_size_log; 304e6a546fdSMartijn de Gouw u64 win_start, win_end; 305e6a546fdSMartijn de Gouw u32 riwar; 306e6a546fdSMartijn de Gouw int i; 307e6a546fdSMartijn de Gouw 308a057a52eSAlexandre Bounine if ((size & (size - 1)) != 0 || size > 0x400000000ULL) 309e6a546fdSMartijn de Gouw return -EINVAL; 310e6a546fdSMartijn de Gouw 311e6a546fdSMartijn de Gouw base_size_log = ilog2(size); 312e6a546fdSMartijn de Gouw base_size = 1 << base_size_log; 313e6a546fdSMartijn de Gouw 314e6a546fdSMartijn de Gouw /* check if addresses are aligned with the window size */ 315e6a546fdSMartijn de Gouw if (lstart & (base_size - 1)) 316e6a546fdSMartijn de Gouw return -EINVAL; 317e6a546fdSMartijn de Gouw if (rstart & (base_size - 1)) 318e6a546fdSMartijn de Gouw return -EINVAL; 319e6a546fdSMartijn de Gouw 320e6a546fdSMartijn de Gouw /* check for conflicting ranges */ 321e6a546fdSMartijn de Gouw for (i = 0; i < RIO_INB_ATMU_COUNT; i++) { 322e6a546fdSMartijn de Gouw riwar = in_be32(&priv->inb_atmu_regs[i].riwar); 323e6a546fdSMartijn de Gouw if ((riwar & RIWAR_ENABLE) == 0) 324e6a546fdSMartijn de Gouw continue; 325e6a546fdSMartijn de Gouw win_start = ((u64)(in_be32(&priv->inb_atmu_regs[i].riwbar) & RIWBAR_BADD_MASK)) 326e6a546fdSMartijn de Gouw << RIWBAR_BADD_VAL_SHIFT; 327e6a546fdSMartijn de Gouw win_end = win_start + ((1 << ((riwar & RIWAR_SIZE_MASK) + 1)) - 1); 328e6a546fdSMartijn de Gouw if (rstart < win_end && (rstart + size) > win_start) 329e6a546fdSMartijn de Gouw return -EINVAL; 330e6a546fdSMartijn de Gouw } 331e6a546fdSMartijn de Gouw 332e6a546fdSMartijn de Gouw /* find unused atmu */ 333e6a546fdSMartijn de Gouw for (i = 0; i < RIO_INB_ATMU_COUNT; i++) { 334e6a546fdSMartijn de Gouw riwar = in_be32(&priv->inb_atmu_regs[i].riwar); 335e6a546fdSMartijn de Gouw if ((riwar & RIWAR_ENABLE) == 0) 336e6a546fdSMartijn de Gouw break; 337e6a546fdSMartijn de Gouw } 338e6a546fdSMartijn de Gouw if (i >= RIO_INB_ATMU_COUNT) 339e6a546fdSMartijn de Gouw return -ENOMEM; 340e6a546fdSMartijn de Gouw 341e6a546fdSMartijn de Gouw out_be32(&priv->inb_atmu_regs[i].riwtar, lstart >> RIWTAR_TRAD_VAL_SHIFT); 342e6a546fdSMartijn de Gouw out_be32(&priv->inb_atmu_regs[i].riwbar, rstart >> RIWBAR_BADD_VAL_SHIFT); 343e6a546fdSMartijn de Gouw out_be32(&priv->inb_atmu_regs[i].riwar, RIWAR_ENABLE | RIWAR_TGINT_LOCAL | 344e6a546fdSMartijn de Gouw RIWAR_RDTYP_SNOOP | RIWAR_WRTYP_SNOOP | (base_size_log - 1)); 345e6a546fdSMartijn de Gouw 346e6a546fdSMartijn de Gouw return 0; 347e6a546fdSMartijn de Gouw } 348e6a546fdSMartijn de Gouw 349e6a546fdSMartijn de Gouw void fsl_unmap_inb_mem(struct rio_mport *mport, dma_addr_t lstart) 350e6a546fdSMartijn de Gouw { 351e6a546fdSMartijn de Gouw u32 win_start_shift, base_start_shift; 352e6a546fdSMartijn de Gouw struct rio_priv *priv = mport->priv; 353e6a546fdSMartijn de Gouw u32 riwar, riwtar; 354e6a546fdSMartijn de Gouw int i; 355e6a546fdSMartijn de Gouw 356e6a546fdSMartijn de Gouw /* skip default window */ 357e6a546fdSMartijn de Gouw base_start_shift = lstart >> RIWTAR_TRAD_VAL_SHIFT; 358e6a546fdSMartijn de Gouw for (i = 0; i < RIO_INB_ATMU_COUNT; i++) { 359e6a546fdSMartijn de Gouw riwar = in_be32(&priv->inb_atmu_regs[i].riwar); 360e6a546fdSMartijn de Gouw if ((riwar & RIWAR_ENABLE) == 0) 361e6a546fdSMartijn de Gouw continue; 362e6a546fdSMartijn de Gouw 363e6a546fdSMartijn de Gouw riwtar = in_be32(&priv->inb_atmu_regs[i].riwtar); 364e6a546fdSMartijn de Gouw win_start_shift = riwtar & RIWTAR_TRAD_MASK; 365e6a546fdSMartijn de Gouw if (win_start_shift == base_start_shift) { 366e6a546fdSMartijn de Gouw out_be32(&priv->inb_atmu_regs[i].riwar, riwar & ~RIWAR_ENABLE); 367e6a546fdSMartijn de Gouw return; 368e6a546fdSMartijn de Gouw } 369e6a546fdSMartijn de Gouw } 370e6a546fdSMartijn de Gouw } 371e6a546fdSMartijn de Gouw 372abc3aeaeSLiu Gang void fsl_rio_port_error_handler(int offset) 3736ff31453SShaohui Xie { 3746ff31453SShaohui Xie /*XXX: Error recovery is not implemented, we just clear errors */ 3756ff31453SShaohui Xie out_be32((u32 *)(rio_regs_win + RIO_LTLEDCSR), 0); 3766ff31453SShaohui Xie 3776ff31453SShaohui Xie if (offset == 0) { 3786ff31453SShaohui Xie out_be32((u32 *)(rio_regs_win + RIO_PORT1_EDCSR), 0); 379671ee7f0SLiu Gang-B34182 out_be32((u32 *)(rio_regs_win + RIO_PORT1_IECSR), IECSR_CLEAR); 3806ff31453SShaohui Xie out_be32((u32 *)(rio_regs_win + RIO_ESCSR), ESCSR_CLEAR); 3816ff31453SShaohui Xie } else { 3826ff31453SShaohui Xie out_be32((u32 *)(rio_regs_win + RIO_PORT2_EDCSR), 0); 383671ee7f0SLiu Gang-B34182 out_be32((u32 *)(rio_regs_win + RIO_PORT2_IECSR), IECSR_CLEAR); 3846ff31453SShaohui Xie out_be32((u32 *)(rio_regs_win + RIO_PORT2_ESCSR), ESCSR_CLEAR); 3856ff31453SShaohui Xie } 3866ff31453SShaohui Xie } 3877f620df8SZhang Wei static inline void fsl_rio_info(struct device *dev, u32 ccsr) 3887f620df8SZhang Wei { 3897f620df8SZhang Wei const char *str; 3907f620df8SZhang Wei if (ccsr & 1) { 3917f620df8SZhang Wei /* Serial phy */ 3927f620df8SZhang Wei switch (ccsr >> 30) { 3937f620df8SZhang Wei case 0: 3947f620df8SZhang Wei str = "1"; 3957f620df8SZhang Wei break; 3967f620df8SZhang Wei case 1: 3977f620df8SZhang Wei str = "4"; 3987f620df8SZhang Wei break; 3997f620df8SZhang Wei default: 4007f620df8SZhang Wei str = "Unknown"; 401d258e64eSJoe Perches break; 4027f620df8SZhang Wei } 4037f620df8SZhang Wei dev_info(dev, "Hardware port width: %s\n", str); 4047f620df8SZhang Wei 4057f620df8SZhang Wei switch ((ccsr >> 27) & 7) { 4067f620df8SZhang Wei case 0: 4077f620df8SZhang Wei str = "Single-lane 0"; 4087f620df8SZhang Wei break; 4097f620df8SZhang Wei case 1: 4107f620df8SZhang Wei str = "Single-lane 2"; 4117f620df8SZhang Wei break; 4127f620df8SZhang Wei case 2: 4137f620df8SZhang Wei str = "Four-lane"; 4147f620df8SZhang Wei break; 4157f620df8SZhang Wei default: 4167f620df8SZhang Wei str = "Unknown"; 4177f620df8SZhang Wei break; 4187f620df8SZhang Wei } 4197f620df8SZhang Wei dev_info(dev, "Training connection status: %s\n", str); 4207f620df8SZhang Wei } else { 4217f620df8SZhang Wei /* Parallel phy */ 4227f620df8SZhang Wei if (!(ccsr & 0x80000000)) 4237f620df8SZhang Wei dev_info(dev, "Output port operating in 8-bit mode\n"); 4247f620df8SZhang Wei if (!(ccsr & 0x08000000)) 4257f620df8SZhang Wei dev_info(dev, "Input port operating in 8-bit mode\n"); 4267f620df8SZhang Wei } 4277f620df8SZhang Wei } 4287f620df8SZhang Wei 429de3c8d41SKumar Gala /** 4309941d945SRandy Dunlap * fsl_rio_setup - Setup Freescale PowerPC RapidIO interface 4312dc11581SGrant Likely * @dev: platform_device pointer 432de3c8d41SKumar Gala * 433de3c8d41SKumar Gala * Initializes MPC85xx RapidIO hardware interface, configures 434de3c8d41SKumar Gala * master port with system-specific info, and registers the 435de3c8d41SKumar Gala * master port with the RapidIO subsystem. 436de3c8d41SKumar Gala */ 437a454dc50SGrant Likely int fsl_rio_setup(struct platform_device *dev) 438de3c8d41SKumar Gala { 439de3c8d41SKumar Gala struct rio_ops *ops; 440de3c8d41SKumar Gala struct rio_mport *port; 441cc2bb696SZhang Wei struct rio_priv *priv; 442cc2bb696SZhang Wei int rc = 0; 443abc3aeaeSLiu Gang const u32 *dt_range, *cell, *port_index; 444abc3aeaeSLiu Gang u32 active_ports = 0; 445abc3aeaeSLiu Gang struct resource regs, rmu_regs; 446abc3aeaeSLiu Gang struct device_node *np, *rmu_node; 447cc2bb696SZhang Wei int rlen; 44861b26917SZhang Wei u32 ccsr; 449abc3aeaeSLiu Gang u64 range_start, range_size; 450cc2bb696SZhang Wei int paw, aw, sw; 451abc3aeaeSLiu Gang u32 i; 452abc3aeaeSLiu Gang static int tmp; 453abc3aeaeSLiu Gang struct device_node *rmu_np[MAX_MSG_UNIT_NUM] = {NULL}; 454cc2bb696SZhang Wei 45561c7a080SGrant Likely if (!dev->dev.of_node) { 456cc2bb696SZhang Wei dev_err(&dev->dev, "Device OF-Node is NULL"); 457abc3aeaeSLiu Gang return -ENODEV; 458cc2bb696SZhang Wei } 459cc2bb696SZhang Wei 46061c7a080SGrant Likely rc = of_address_to_resource(dev->dev.of_node, 0, ®s); 461cc2bb696SZhang Wei if (rc) { 462b7c670d6SRob Herring dev_err(&dev->dev, "Can't get %pOF property 'reg'\n", 463b7c670d6SRob Herring dev->dev.of_node); 464cc2bb696SZhang Wei return -EFAULT; 465cc2bb696SZhang Wei } 466b7c670d6SRob Herring dev_info(&dev->dev, "Of-device full name %pOF\n", 467b7c670d6SRob Herring dev->dev.of_node); 468fc274a15SKumar Gala dev_info(&dev->dev, "Regs: %pR\n", ®s); 469cc2bb696SZhang Wei 470abc3aeaeSLiu Gang rio_regs_win = ioremap(regs.start, resource_size(®s)); 471abc3aeaeSLiu Gang if (!rio_regs_win) { 472abc3aeaeSLiu Gang dev_err(&dev->dev, "Unable to map rio register window\n"); 473abc3aeaeSLiu Gang rc = -ENOMEM; 474abc3aeaeSLiu Gang goto err_rio_regs; 475cc2bb696SZhang Wei } 476cc2bb696SZhang Wei 477e5cabeb3SAlexandre Bounine ops = kzalloc(sizeof(struct rio_ops), GFP_KERNEL); 4786c75933cSJulia Lawall if (!ops) { 4796c75933cSJulia Lawall rc = -ENOMEM; 4806c75933cSJulia Lawall goto err_ops; 4816c75933cSJulia Lawall } 482d02443a6SZhang Wei ops->lcread = fsl_local_config_read; 483d02443a6SZhang Wei ops->lcwrite = fsl_local_config_write; 484d02443a6SZhang Wei ops->cread = fsl_rio_config_read; 485d02443a6SZhang Wei ops->cwrite = fsl_rio_config_write; 486abc3aeaeSLiu Gang ops->dsend = fsl_rio_doorbell_send; 4875b2074aeSAlexandre Bounine ops->pwenable = fsl_rio_pw_enable; 488abc3aeaeSLiu Gang ops->open_outb_mbox = fsl_open_outb_mbox; 489abc3aeaeSLiu Gang ops->open_inb_mbox = fsl_open_inb_mbox; 490abc3aeaeSLiu Gang ops->close_outb_mbox = fsl_close_outb_mbox; 491abc3aeaeSLiu Gang ops->close_inb_mbox = fsl_close_inb_mbox; 492abc3aeaeSLiu Gang ops->add_outb_message = fsl_add_outb_message; 493abc3aeaeSLiu Gang ops->add_inb_buffer = fsl_add_inb_buffer; 494abc3aeaeSLiu Gang ops->get_inb_message = fsl_get_inb_message; 495e6a546fdSMartijn de Gouw ops->map_inb = fsl_map_inb_mem; 496e6a546fdSMartijn de Gouw ops->unmap_inb = fsl_unmap_inb_mem; 497abc3aeaeSLiu Gang 498abc3aeaeSLiu Gang rmu_node = of_parse_phandle(dev->dev.of_node, "fsl,srio-rmu-handle", 0); 499a614db9aSScott Wood if (!rmu_node) { 500a614db9aSScott Wood dev_err(&dev->dev, "No valid fsl,srio-rmu-handle property\n"); 501380afa36SDan Carpenter rc = -ENOENT; 502abc3aeaeSLiu Gang goto err_rmu; 503a614db9aSScott Wood } 504abc3aeaeSLiu Gang rc = of_address_to_resource(rmu_node, 0, &rmu_regs); 505abc3aeaeSLiu Gang if (rc) { 506b7c670d6SRob Herring dev_err(&dev->dev, "Can't get %pOF property 'reg'\n", 507b7c670d6SRob Herring rmu_node); 508*fcee9692SMiaoqian Lin of_node_put(rmu_node); 509abc3aeaeSLiu Gang goto err_rmu; 510abc3aeaeSLiu Gang } 511*fcee9692SMiaoqian Lin of_node_put(rmu_node); 512abc3aeaeSLiu Gang rmu_regs_win = ioremap(rmu_regs.start, resource_size(&rmu_regs)); 513abc3aeaeSLiu Gang if (!rmu_regs_win) { 514abc3aeaeSLiu Gang dev_err(&dev->dev, "Unable to map rmu register window\n"); 515abc3aeaeSLiu Gang rc = -ENOMEM; 516abc3aeaeSLiu Gang goto err_rmu; 517abc3aeaeSLiu Gang } 518abc3aeaeSLiu Gang for_each_compatible_node(np, NULL, "fsl,srio-msg-unit") { 519abc3aeaeSLiu Gang rmu_np[tmp] = np; 520abc3aeaeSLiu Gang tmp++; 521abc3aeaeSLiu Gang } 522abc3aeaeSLiu Gang 523abc3aeaeSLiu Gang /*set up doobell node*/ 524abc3aeaeSLiu Gang np = of_find_compatible_node(NULL, NULL, "fsl,srio-dbell-unit"); 525abc3aeaeSLiu Gang if (!np) { 526a614db9aSScott Wood dev_err(&dev->dev, "No fsl,srio-dbell-unit node\n"); 527abc3aeaeSLiu Gang rc = -ENODEV; 528abc3aeaeSLiu Gang goto err_dbell; 529abc3aeaeSLiu Gang } 530abc3aeaeSLiu Gang dbell = kzalloc(sizeof(struct fsl_rio_dbell), GFP_KERNEL); 531abc3aeaeSLiu Gang if (!(dbell)) { 532abc3aeaeSLiu Gang dev_err(&dev->dev, "Can't alloc memory for 'fsl_rio_dbell'\n"); 533abc3aeaeSLiu Gang rc = -ENOMEM; 534abc3aeaeSLiu Gang goto err_dbell; 535abc3aeaeSLiu Gang } 536abc3aeaeSLiu Gang dbell->dev = &dev->dev; 537abc3aeaeSLiu Gang dbell->bellirq = irq_of_parse_and_map(np, 1); 538abc3aeaeSLiu Gang dev_info(&dev->dev, "bellirq: %d\n", dbell->bellirq); 539abc3aeaeSLiu Gang 540abc3aeaeSLiu Gang aw = of_n_addr_cells(np); 541abc3aeaeSLiu Gang dt_range = of_get_property(np, "reg", &rlen); 542abc3aeaeSLiu Gang if (!dt_range) { 543b7c670d6SRob Herring pr_err("%pOF: unable to find 'reg' property\n", 544b7c670d6SRob Herring np); 545abc3aeaeSLiu Gang rc = -ENOMEM; 546abc3aeaeSLiu Gang goto err_pw; 547abc3aeaeSLiu Gang } 548abc3aeaeSLiu Gang range_start = of_read_number(dt_range, aw); 549abc3aeaeSLiu Gang dbell->dbell_regs = (struct rio_dbell_regs *)(rmu_regs_win + 550abc3aeaeSLiu Gang (u32)range_start); 551abc3aeaeSLiu Gang 552abc3aeaeSLiu Gang /*set up port write node*/ 553abc3aeaeSLiu Gang np = of_find_compatible_node(NULL, NULL, "fsl,srio-port-write-unit"); 554abc3aeaeSLiu Gang if (!np) { 555a614db9aSScott Wood dev_err(&dev->dev, "No fsl,srio-port-write-unit node\n"); 556abc3aeaeSLiu Gang rc = -ENODEV; 557abc3aeaeSLiu Gang goto err_pw; 558abc3aeaeSLiu Gang } 559abc3aeaeSLiu Gang pw = kzalloc(sizeof(struct fsl_rio_pw), GFP_KERNEL); 560abc3aeaeSLiu Gang if (!(pw)) { 561abc3aeaeSLiu Gang dev_err(&dev->dev, "Can't alloc memory for 'fsl_rio_pw'\n"); 562abc3aeaeSLiu Gang rc = -ENOMEM; 563abc3aeaeSLiu Gang goto err_pw; 564abc3aeaeSLiu Gang } 565abc3aeaeSLiu Gang pw->dev = &dev->dev; 566abc3aeaeSLiu Gang pw->pwirq = irq_of_parse_and_map(np, 0); 567abc3aeaeSLiu Gang dev_info(&dev->dev, "pwirq: %d\n", pw->pwirq); 568abc3aeaeSLiu Gang aw = of_n_addr_cells(np); 569abc3aeaeSLiu Gang dt_range = of_get_property(np, "reg", &rlen); 570abc3aeaeSLiu Gang if (!dt_range) { 571b7c670d6SRob Herring pr_err("%pOF: unable to find 'reg' property\n", 572b7c670d6SRob Herring np); 573abc3aeaeSLiu Gang rc = -ENOMEM; 574abc3aeaeSLiu Gang goto err; 575abc3aeaeSLiu Gang } 576abc3aeaeSLiu Gang range_start = of_read_number(dt_range, aw); 577abc3aeaeSLiu Gang pw->pw_regs = (struct rio_pw_regs *)(rmu_regs_win + (u32)range_start); 578abc3aeaeSLiu Gang 579abc3aeaeSLiu Gang /*set up ports node*/ 580abc3aeaeSLiu Gang for_each_child_of_node(dev->dev.of_node, np) { 581abc3aeaeSLiu Gang port_index = of_get_property(np, "cell-index", NULL); 582abc3aeaeSLiu Gang if (!port_index) { 583b7c670d6SRob Herring dev_err(&dev->dev, "Can't get %pOF property 'cell-index'\n", 584b7c670d6SRob Herring np); 585abc3aeaeSLiu Gang continue; 586abc3aeaeSLiu Gang } 587abc3aeaeSLiu Gang 588abc3aeaeSLiu Gang dt_range = of_get_property(np, "ranges", &rlen); 589abc3aeaeSLiu Gang if (!dt_range) { 590b7c670d6SRob Herring dev_err(&dev->dev, "Can't get %pOF property 'ranges'\n", 591b7c670d6SRob Herring np); 592abc3aeaeSLiu Gang continue; 593abc3aeaeSLiu Gang } 594abc3aeaeSLiu Gang 595abc3aeaeSLiu Gang /* Get node address wide */ 596abc3aeaeSLiu Gang cell = of_get_property(np, "#address-cells", NULL); 597abc3aeaeSLiu Gang if (cell) 598abc3aeaeSLiu Gang aw = *cell; 599abc3aeaeSLiu Gang else 600abc3aeaeSLiu Gang aw = of_n_addr_cells(np); 601abc3aeaeSLiu Gang /* Get node size wide */ 602abc3aeaeSLiu Gang cell = of_get_property(np, "#size-cells", NULL); 603abc3aeaeSLiu Gang if (cell) 604abc3aeaeSLiu Gang sw = *cell; 605abc3aeaeSLiu Gang else 606abc3aeaeSLiu Gang sw = of_n_size_cells(np); 607abc3aeaeSLiu Gang /* Get parent address wide wide */ 608abc3aeaeSLiu Gang paw = of_n_addr_cells(np); 609abc3aeaeSLiu Gang range_start = of_read_number(dt_range + aw, paw); 610abc3aeaeSLiu Gang range_size = of_read_number(dt_range + aw + paw, sw); 611abc3aeaeSLiu Gang 612b7c670d6SRob Herring dev_info(&dev->dev, "%pOF: LAW start 0x%016llx, size 0x%016llx.\n", 613b7c670d6SRob Herring np, range_start, range_size); 614de3c8d41SKumar Gala 615ad1e9380SZhang Wei port = kzalloc(sizeof(struct rio_mport), GFP_KERNEL); 616abc3aeaeSLiu Gang if (!port) 617abc3aeaeSLiu Gang continue; 618abc3aeaeSLiu Gang 619dd64f4feSAlexandre Bounine rc = rio_mport_initialize(port); 620dd64f4feSAlexandre Bounine if (rc) { 621dd64f4feSAlexandre Bounine kfree(port); 622dd64f4feSAlexandre Bounine continue; 623dd64f4feSAlexandre Bounine } 624dd64f4feSAlexandre Bounine 625abc3aeaeSLiu Gang i = *port_index - 1; 626abc3aeaeSLiu Gang port->index = (unsigned char)i; 627ad1e9380SZhang Wei 628ad1e9380SZhang Wei priv = kzalloc(sizeof(struct rio_priv), GFP_KERNEL); 629ad1e9380SZhang Wei if (!priv) { 630abc3aeaeSLiu Gang dev_err(&dev->dev, "Can't alloc memory for 'priv'\n"); 631abc3aeaeSLiu Gang kfree(port); 632abc3aeaeSLiu Gang continue; 633ad1e9380SZhang Wei } 634ad1e9380SZhang Wei 635de3c8d41SKumar Gala INIT_LIST_HEAD(&port->dbells); 636abc3aeaeSLiu Gang port->iores.start = range_start; 637abc3aeaeSLiu Gang port->iores.end = port->iores.start + range_size - 1; 638de3c8d41SKumar Gala port->iores.flags = IORESOURCE_MEM; 639186e74b9SLi Yang port->iores.name = "rio_io_win"; 640de3c8d41SKumar Gala 641c1256ebeSAlexandre Bounine if (request_resource(&iomem_resource, &port->iores) < 0) { 642c1256ebeSAlexandre Bounine dev_err(&dev->dev, "RIO: Error requesting master port region" 643c1256ebeSAlexandre Bounine " 0x%016llx-0x%016llx\n", 644c1256ebeSAlexandre Bounine (u64)port->iores.start, (u64)port->iores.end); 645abc3aeaeSLiu Gang kfree(priv); 646abc3aeaeSLiu Gang kfree(port); 647abc3aeaeSLiu Gang continue; 648c1256ebeSAlexandre Bounine } 649abc3aeaeSLiu Gang sprintf(port->name, "RIO mport %d", i); 650de3c8d41SKumar Gala 6510dbbbf1aSAnton Vorontsov priv->dev = &dev->dev; 6522aaf308bSAlexandre Bounine port->dev.parent = &dev->dev; 653de3c8d41SKumar Gala port->ops = ops; 654ad1e9380SZhang Wei port->priv = priv; 655af84ca38SAlexandre Bounine port->phys_efptr = 0x100; 656adff1649SAlexandre Bounine port->phys_rmap = 1; 657abc3aeaeSLiu Gang priv->regs_win = rio_regs_win; 658e0423236SZhang Wei 659abc3aeaeSLiu Gang ccsr = in_be32(priv->regs_win + RIO_CCSR + i*0x20); 660adff1649SAlexandre Bounine 6617f620df8SZhang Wei /* Checking the port training status */ 662abc3aeaeSLiu Gang if (in_be32((priv->regs_win + RIO_ESCSR + i*0x20)) & 1) { 663abc3aeaeSLiu Gang dev_err(&dev->dev, "Port %d is not ready. " 664abc3aeaeSLiu Gang "Try to restart connection...\n", i); 6657f620df8SZhang Wei /* Disable ports */ 666abc3aeaeSLiu Gang out_be32(priv->regs_win 667abc3aeaeSLiu Gang + RIO_CCSR + i*0x20, 0); 6687f620df8SZhang Wei /* Set 1x lane */ 669abc3aeaeSLiu Gang setbits32(priv->regs_win 670abc3aeaeSLiu Gang + RIO_CCSR + i*0x20, 0x02000000); 6717f620df8SZhang Wei /* Enable ports */ 672abc3aeaeSLiu Gang setbits32(priv->regs_win 673abc3aeaeSLiu Gang + RIO_CCSR + i*0x20, 0x00600000); 6747f620df8SZhang Wei msleep(100); 675abc3aeaeSLiu Gang if (in_be32((priv->regs_win 676abc3aeaeSLiu Gang + RIO_ESCSR + i*0x20)) & 1) { 677abc3aeaeSLiu Gang dev_err(&dev->dev, 678abc3aeaeSLiu Gang "Port %d restart failed.\n", i); 679abc3aeaeSLiu Gang release_resource(&port->iores); 680abc3aeaeSLiu Gang kfree(priv); 681abc3aeaeSLiu Gang kfree(port); 682abc3aeaeSLiu Gang continue; 6837f620df8SZhang Wei } 684abc3aeaeSLiu Gang dev_info(&dev->dev, "Port %d restart success!\n", i); 6857f620df8SZhang Wei } 6867f620df8SZhang Wei fsl_rio_info(&dev->dev, ccsr); 68761b26917SZhang Wei 688e0423236SZhang Wei port->sys_size = (in_be32((priv->regs_win + RIO_PEF_CAR)) 689e0423236SZhang Wei & RIO_PEF_CTLS) >> 4; 690e0423236SZhang Wei dev_info(&dev->dev, "RapidIO Common Transport System size: %d\n", 691e0423236SZhang Wei port->sys_size ? 65536 : 256); 692e0423236SZhang Wei 693af84ca38SAlexandre Bounine if (port->host_deviceid >= 0) 694af84ca38SAlexandre Bounine out_be32(priv->regs_win + RIO_GCCSR, RIO_PORT_GEN_HOST | 695af84ca38SAlexandre Bounine RIO_PORT_GEN_MASTER | RIO_PORT_GEN_DISCOVERED); 696af84ca38SAlexandre Bounine else 697abc3aeaeSLiu Gang out_be32(priv->regs_win + RIO_GCCSR, 698abc3aeaeSLiu Gang RIO_PORT_GEN_MASTER); 699af84ca38SAlexandre Bounine 700ad1e9380SZhang Wei priv->atmu_regs = (struct rio_atmu_regs *)(priv->regs_win 701abc3aeaeSLiu Gang + ((i == 0) ? RIO_ATMU_REGS_PORT1_OFFSET : 702abc3aeaeSLiu Gang RIO_ATMU_REGS_PORT2_OFFSET)); 703abc3aeaeSLiu Gang 704ad1e9380SZhang Wei priv->maint_atmu_regs = priv->atmu_regs + 1; 705e6a546fdSMartijn de Gouw priv->inb_atmu_regs = (struct rio_inb_atmu_regs __iomem *) 706e6a546fdSMartijn de Gouw (priv->regs_win + 707e6a546fdSMartijn de Gouw ((i == 0) ? RIO_INB_ATMU_REGS_PORT1_OFFSET : 708e6a546fdSMartijn de Gouw RIO_INB_ATMU_REGS_PORT2_OFFSET)); 709e6a546fdSMartijn de Gouw 710adff1649SAlexandre Bounine /* Set to receive packets with any dest ID */ 711adff1649SAlexandre Bounine out_be32((priv->regs_win + RIO_ISR_AACR + i*0x80), 712adff1649SAlexandre Bounine RIO_ISR_AACR_AA); 713de3c8d41SKumar Gala 714de3c8d41SKumar Gala /* Configure maintenance transaction window */ 715abc3aeaeSLiu Gang out_be32(&priv->maint_atmu_regs->rowbar, 716abc3aeaeSLiu Gang port->iores.start >> 12); 717bd4fb654SThomas Moll out_be32(&priv->maint_atmu_regs->rowar, 718bd4fb654SThomas Moll 0x80077000 | (ilog2(RIO_MAINT_WIN_SIZE) - 1)); 719de3c8d41SKumar Gala 720abc3aeaeSLiu Gang priv->maint_win = ioremap(port->iores.start, 721abc3aeaeSLiu Gang RIO_MAINT_WIN_SIZE); 722de3c8d41SKumar Gala 723abc3aeaeSLiu Gang rio_law_start = range_start; 7246ec4bedbSLiu Gang 725abc3aeaeSLiu Gang fsl_rio_setup_rmu(port, rmu_np[i]); 726e6a546fdSMartijn de Gouw fsl_rio_inbound_mem_init(priv); 727abc3aeaeSLiu Gang 728abc3aeaeSLiu Gang dbell->mport[i] = port; 7299a0b0627SAlexandre Bounine pw->mport[i] = port; 730abc3aeaeSLiu Gang 731dd64f4feSAlexandre Bounine if (rio_register_mport(port)) { 732dd64f4feSAlexandre Bounine release_resource(&port->iores); 733dd64f4feSAlexandre Bounine kfree(priv); 734dd64f4feSAlexandre Bounine kfree(port); 735dd64f4feSAlexandre Bounine continue; 736dd64f4feSAlexandre Bounine } 737abc3aeaeSLiu Gang active_ports++; 738abc3aeaeSLiu Gang } 739abc3aeaeSLiu Gang 740abc3aeaeSLiu Gang if (!active_ports) { 741abc3aeaeSLiu Gang rc = -ENOLINK; 742abc3aeaeSLiu Gang goto err; 743abc3aeaeSLiu Gang } 744abc3aeaeSLiu Gang 745abc3aeaeSLiu Gang fsl_rio_doorbell_init(dbell); 746abc3aeaeSLiu Gang fsl_rio_port_write_init(pw); 747ad1e9380SZhang Wei 748cc2bb696SZhang Wei return 0; 749ad1e9380SZhang Wei err: 750abc3aeaeSLiu Gang kfree(pw); 751a614db9aSScott Wood pw = NULL; 752abc3aeaeSLiu Gang err_pw: 753abc3aeaeSLiu Gang kfree(dbell); 754a614db9aSScott Wood dbell = NULL; 755abc3aeaeSLiu Gang err_dbell: 756abc3aeaeSLiu Gang iounmap(rmu_regs_win); 757a614db9aSScott Wood rmu_regs_win = NULL; 758abc3aeaeSLiu Gang err_rmu: 7596c75933cSJulia Lawall kfree(ops); 7606c75933cSJulia Lawall err_ops: 761abc3aeaeSLiu Gang iounmap(rio_regs_win); 762a614db9aSScott Wood rio_regs_win = NULL; 763abc3aeaeSLiu Gang err_rio_regs: 764cc2bb696SZhang Wei return rc; 765de3c8d41SKumar Gala } 766cc2bb696SZhang Wei 767cc2bb696SZhang Wei /* The probe function for RapidIO peer-to-peer network. 768cc2bb696SZhang Wei */ 769cad5cef6SGreg Kroah-Hartman static int fsl_of_rio_rpn_probe(struct platform_device *dev) 770cc2bb696SZhang Wei { 771b7c670d6SRob Herring printk(KERN_INFO "Setting up RapidIO peer-to-peer network %pOF\n", 772b7c670d6SRob Herring dev->dev.of_node); 773cc2bb696SZhang Wei 7742f809985SAlexandre Bounine return fsl_rio_setup(dev); 775cc2bb696SZhang Wei }; 776cc2bb696SZhang Wei 777cc2bb696SZhang Wei static const struct of_device_id fsl_of_rio_rpn_ids[] = { 778cc2bb696SZhang Wei { 779abc3aeaeSLiu Gang .compatible = "fsl,srio", 780cc2bb696SZhang Wei }, 781cc2bb696SZhang Wei {}, 782cc2bb696SZhang Wei }; 783cc2bb696SZhang Wei 78400006124SGrant Likely static struct platform_driver fsl_of_rio_rpn_driver = { 7854018294bSGrant Likely .driver = { 786cc2bb696SZhang Wei .name = "fsl-of-rio", 7874018294bSGrant Likely .of_match_table = fsl_of_rio_rpn_ids, 7884018294bSGrant Likely }, 789cc2bb696SZhang Wei .probe = fsl_of_rio_rpn_probe, 790cc2bb696SZhang Wei }; 791cc2bb696SZhang Wei 792cc2bb696SZhang Wei static __init int fsl_of_rio_rpn_init(void) 793cc2bb696SZhang Wei { 79400006124SGrant Likely return platform_driver_register(&fsl_of_rio_rpn_driver); 795cc2bb696SZhang Wei } 796cc2bb696SZhang Wei 797cc2bb696SZhang Wei subsys_initcall(fsl_of_rio_rpn_init); 798