Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

powerpc/fsl-rio: add support for mapping inbound windows

Add support for mapping and unmapping of inbound rapidio windows. This
allows for drivers to open up a part of local memory on the rapidio
network. Also applications can use this and tranfer blocks of data
over the network.

Signed-off-by: Martijn de Gouw <martijn.de.gouw@prodrive-technologies.com>
[scottwood@freescale.com: updated commit message based on review]
Signed-off-by: Scott Wood <scottwood@freescale.com>

authored by

Martijn de Gouw and committed by
Scott Wood
e6a546fd e327fff4

+117
+104
arch/powerpc/sysdev/fsl_rio.c
··· 58 58 #define RIO_ISR_AACR 0x10120 59 59 #define RIO_ISR_AACR_AA 0x1 /* Accept All ID */ 60 60 61 + #define RIWTAR_TRAD_VAL_SHIFT 12 62 + #define RIWTAR_TRAD_MASK 0x00FFFFFF 63 + #define RIWBAR_BADD_VAL_SHIFT 12 64 + #define RIWBAR_BADD_MASK 0x003FFFFF 65 + #define RIWAR_ENABLE 0x80000000 66 + #define RIWAR_TGINT_LOCAL 0x00F00000 67 + #define RIWAR_RDTYP_NO_SNOOP 0x00040000 68 + #define RIWAR_RDTYP_SNOOP 0x00050000 69 + #define RIWAR_WRTYP_NO_SNOOP 0x00004000 70 + #define RIWAR_WRTYP_SNOOP 0x00005000 71 + #define RIWAR_WRTYP_ALLOC 0x00006000 72 + #define RIWAR_SIZE_MASK 0x0000003F 73 + 61 74 #define __fsl_read_rio_config(x, addr, err, op) \ 62 75 __asm__ __volatile__( \ 63 76 "1: "op" %1,0(%2)\n" \ ··· 279 266 return 0; 280 267 } 281 268 269 + static void fsl_rio_inbound_mem_init(struct rio_priv *priv) 270 + { 271 + int i; 272 + 273 + /* close inbound windows */ 274 + for (i = 0; i < RIO_INB_ATMU_COUNT; i++) 275 + out_be32(&priv->inb_atmu_regs[i].riwar, 0); 276 + } 277 + 278 + int fsl_map_inb_mem(struct rio_mport *mport, dma_addr_t lstart, 279 + u64 rstart, u32 size, u32 flags) 280 + { 281 + struct rio_priv *priv = mport->priv; 282 + u32 base_size; 283 + unsigned int base_size_log; 284 + u64 win_start, win_end; 285 + u32 riwar; 286 + int i; 287 + 288 + if ((size & (size - 1)) != 0) 289 + return -EINVAL; 290 + 291 + base_size_log = ilog2(size); 292 + base_size = 1 << base_size_log; 293 + 294 + /* check if addresses are aligned with the window size */ 295 + if (lstart & (base_size - 1)) 296 + return -EINVAL; 297 + if (rstart & (base_size - 1)) 298 + return -EINVAL; 299 + 300 + /* check for conflicting ranges */ 301 + for (i = 0; i < RIO_INB_ATMU_COUNT; i++) { 302 + riwar = in_be32(&priv->inb_atmu_regs[i].riwar); 303 + if ((riwar & RIWAR_ENABLE) == 0) 304 + continue; 305 + win_start = ((u64)(in_be32(&priv->inb_atmu_regs[i].riwbar) & RIWBAR_BADD_MASK)) 306 + << RIWBAR_BADD_VAL_SHIFT; 307 + win_end = win_start + ((1 << ((riwar & RIWAR_SIZE_MASK) + 1)) - 1); 308 + if (rstart < win_end && (rstart + size) > win_start) 309 + return -EINVAL; 310 + } 311 + 312 + /* find unused atmu */ 313 + for (i = 0; i < RIO_INB_ATMU_COUNT; i++) { 314 + riwar = in_be32(&priv->inb_atmu_regs[i].riwar); 315 + if ((riwar & RIWAR_ENABLE) == 0) 316 + break; 317 + } 318 + if (i >= RIO_INB_ATMU_COUNT) 319 + return -ENOMEM; 320 + 321 + out_be32(&priv->inb_atmu_regs[i].riwtar, lstart >> RIWTAR_TRAD_VAL_SHIFT); 322 + out_be32(&priv->inb_atmu_regs[i].riwbar, rstart >> RIWBAR_BADD_VAL_SHIFT); 323 + out_be32(&priv->inb_atmu_regs[i].riwar, RIWAR_ENABLE | RIWAR_TGINT_LOCAL | 324 + RIWAR_RDTYP_SNOOP | RIWAR_WRTYP_SNOOP | (base_size_log - 1)); 325 + 326 + return 0; 327 + } 328 + 329 + void fsl_unmap_inb_mem(struct rio_mport *mport, dma_addr_t lstart) 330 + { 331 + u32 win_start_shift, base_start_shift; 332 + struct rio_priv *priv = mport->priv; 333 + u32 riwar, riwtar; 334 + int i; 335 + 336 + /* skip default window */ 337 + base_start_shift = lstart >> RIWTAR_TRAD_VAL_SHIFT; 338 + for (i = 0; i < RIO_INB_ATMU_COUNT; i++) { 339 + riwar = in_be32(&priv->inb_atmu_regs[i].riwar); 340 + if ((riwar & RIWAR_ENABLE) == 0) 341 + continue; 342 + 343 + riwtar = in_be32(&priv->inb_atmu_regs[i].riwtar); 344 + win_start_shift = riwtar & RIWTAR_TRAD_MASK; 345 + if (win_start_shift == base_start_shift) { 346 + out_be32(&priv->inb_atmu_regs[i].riwar, riwar & ~RIWAR_ENABLE); 347 + return; 348 + } 349 + } 350 + } 351 + 282 352 void fsl_rio_port_error_handler(int offset) 283 353 { 284 354 /*XXX: Error recovery is not implemented, we just clear errors */ ··· 485 389 ops->add_outb_message = fsl_add_outb_message; 486 390 ops->add_inb_buffer = fsl_add_inb_buffer; 487 391 ops->get_inb_message = fsl_get_inb_message; 392 + ops->map_inb = fsl_map_inb_mem; 393 + ops->unmap_inb = fsl_unmap_inb_mem; 488 394 489 395 rmu_node = of_parse_phandle(dev->dev.of_node, "fsl,srio-rmu-handle", 0); 490 396 if (!rmu_node) { ··· 700 602 RIO_ATMU_REGS_PORT2_OFFSET)); 701 603 702 604 priv->maint_atmu_regs = priv->atmu_regs + 1; 605 + priv->inb_atmu_regs = (struct rio_inb_atmu_regs __iomem *) 606 + (priv->regs_win + 607 + ((i == 0) ? RIO_INB_ATMU_REGS_PORT1_OFFSET : 608 + RIO_INB_ATMU_REGS_PORT2_OFFSET)); 609 + 703 610 704 611 /* Set to receive any dist ID for serial RapidIO controller. */ 705 612 if (port->phy_type == RIO_PHY_SERIAL) ··· 723 620 rio_law_start = range_start; 724 621 725 622 fsl_rio_setup_rmu(port, rmu_np[i]); 623 + fsl_rio_inbound_mem_init(priv); 726 624 727 625 dbell->mport[i] = port; 728 626
+13
arch/powerpc/sysdev/fsl_rio.h
··· 50 50 #define RIO_S_DBELL_REGS_OFFSET 0x13400 51 51 #define RIO_S_PW_REGS_OFFSET 0x134e0 52 52 #define RIO_ATMU_REGS_DBELL_OFFSET 0x10C40 53 + #define RIO_INB_ATMU_REGS_PORT1_OFFSET 0x10d60 54 + #define RIO_INB_ATMU_REGS_PORT2_OFFSET 0x10f60 53 55 54 56 #define MAX_MSG_UNIT_NUM 2 55 57 #define MAX_PORT_NUM 4 58 + #define RIO_INB_ATMU_COUNT 4 56 59 57 60 struct rio_atmu_regs { 58 61 u32 rowtar; ··· 64 61 u32 pad1; 65 62 u32 rowar; 66 63 u32 pad2[3]; 64 + }; 65 + 66 + struct rio_inb_atmu_regs { 67 + u32 riwtar; 68 + u32 pad1; 69 + u32 riwbar; 70 + u32 pad2; 71 + u32 riwar; 72 + u32 pad3[3]; 67 73 }; 68 74 69 75 struct rio_dbell_ring { ··· 111 99 void __iomem *regs_win; 112 100 struct rio_atmu_regs __iomem *atmu_regs; 113 101 struct rio_atmu_regs __iomem *maint_atmu_regs; 102 + struct rio_inb_atmu_regs __iomem *inb_atmu_regs; 114 103 void __iomem *maint_win; 115 104 void *rmm_handle; /* RapidIO message manager(unit) Handle */ 116 105 };