diff options
| author | Martijn de Gouw <martijn.de.gouw@prodrive-technologies.com> | 2014-08-05 09:52:32 -0400 |
|---|---|---|
| committer | Scott Wood <scottwood@freescale.com> | 2014-11-13 00:56:16 -0500 |
| commit | e6a546fd03753ffbd9d2f2883210f8043a8791f7 (patch) | |
| tree | b6c12ed3a97aa9485acaedc17c8372edda522619 /arch/powerpc/sysdev | |
| parent | e327fff47b6778e56f8e1dbd6493c1b0bbad1ae8 (diff) | |
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>
Diffstat (limited to 'arch/powerpc/sysdev')
| -rw-r--r-- | arch/powerpc/sysdev/fsl_rio.c | 104 | ||||
| -rw-r--r-- | arch/powerpc/sysdev/fsl_rio.h | 13 |
2 files changed, 117 insertions, 0 deletions
diff --git a/arch/powerpc/sysdev/fsl_rio.c b/arch/powerpc/sysdev/fsl_rio.c index c04b718307c8..08d60f183dad 100644 --- a/arch/powerpc/sysdev/fsl_rio.c +++ b/arch/powerpc/sysdev/fsl_rio.c | |||
| @@ -58,6 +58,19 @@ | |||
| 58 | #define RIO_ISR_AACR 0x10120 | 58 | #define RIO_ISR_AACR 0x10120 |
| 59 | #define RIO_ISR_AACR_AA 0x1 /* Accept All ID */ | 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 | #define __fsl_read_rio_config(x, addr, err, op) \ | 74 | #define __fsl_read_rio_config(x, addr, err, op) \ |
| 62 | __asm__ __volatile__( \ | 75 | __asm__ __volatile__( \ |
| 63 | "1: "op" %1,0(%2)\n" \ | 76 | "1: "op" %1,0(%2)\n" \ |
| @@ -266,6 +279,89 @@ fsl_rio_config_write(struct rio_mport *mport, int index, u16 destid, | |||
| 266 | return 0; | 279 | return 0; |
| 267 | } | 280 | } |
| 268 | 281 | ||
| 282 | static void fsl_rio_inbound_mem_init(struct rio_priv *priv) | ||
| 283 | { | ||
| 284 | int i; | ||
| 285 | |||
| 286 | /* close inbound windows */ | ||
| 287 | for (i = 0; i < RIO_INB_ATMU_COUNT; i++) | ||
| 288 | out_be32(&priv->inb_atmu_regs[i].riwar, 0); | ||
| 289 | } | ||
| 290 | |||
| 291 | int fsl_map_inb_mem(struct rio_mport *mport, dma_addr_t lstart, | ||
| 292 | u64 rstart, u32 size, u32 flags) | ||
| 293 | { | ||
| 294 | struct rio_priv *priv = mport->priv; | ||
| 295 | u32 base_size; | ||
| 296 | unsigned int base_size_log; | ||
| 297 | u64 win_start, win_end; | ||
| 298 | u32 riwar; | ||
| 299 | int i; | ||
| 300 | |||
| 301 | if ((size & (size - 1)) != 0) | ||
| 302 | return -EINVAL; | ||
| 303 | |||
| 304 | base_size_log = ilog2(size); | ||
| 305 | base_size = 1 << base_size_log; | ||
| 306 | |||
| 307 | /* check if addresses are aligned with the window size */ | ||
| 308 | if (lstart & (base_size - 1)) | ||
| 309 | return -EINVAL; | ||
| 310 | if (rstart & (base_size - 1)) | ||
| 311 | return -EINVAL; | ||
| 312 | |||
| 313 | /* check for conflicting ranges */ | ||
| 314 | for (i = 0; i < RIO_INB_ATMU_COUNT; i++) { | ||
| 315 | riwar = in_be32(&priv->inb_atmu_regs[i].riwar); | ||
| 316 | if ((riwar & RIWAR_ENABLE) == 0) | ||
| 317 | continue; | ||
| 318 | win_start = ((u64)(in_be32(&priv->inb_atmu_regs[i].riwbar) & RIWBAR_BADD_MASK)) | ||
| 319 | << RIWBAR_BADD_VAL_SHIFT; | ||
| 320 | win_end = win_start + ((1 << ((riwar & RIWAR_SIZE_MASK) + 1)) - 1); | ||
| 321 | if (rstart < win_end && (rstart + size) > win_start) | ||
| 322 | return -EINVAL; | ||
| 323 | } | ||
| 324 | |||
| 325 | /* find unused atmu */ | ||
| 326 | for (i = 0; i < RIO_INB_ATMU_COUNT; i++) { | ||
| 327 | riwar = in_be32(&priv->inb_atmu_regs[i].riwar); | ||
| 328 | if ((riwar & RIWAR_ENABLE) == 0) | ||
| 329 | break; | ||
| 330 | } | ||
| 331 | if (i >= RIO_INB_ATMU_COUNT) | ||
| 332 | return -ENOMEM; | ||
| 333 | |||
| 334 | out_be32(&priv->inb_atmu_regs[i].riwtar, lstart >> RIWTAR_TRAD_VAL_SHIFT); | ||
| 335 | out_be32(&priv->inb_atmu_regs[i].riwbar, rstart >> RIWBAR_BADD_VAL_SHIFT); | ||
| 336 | out_be32(&priv->inb_atmu_regs[i].riwar, RIWAR_ENABLE | RIWAR_TGINT_LOCAL | | ||
| 337 | RIWAR_RDTYP_SNOOP | RIWAR_WRTYP_SNOOP | (base_size_log - 1)); | ||
| 338 | |||
| 339 | return 0; | ||
| 340 | } | ||
| 341 | |||
| 342 | void fsl_unmap_inb_mem(struct rio_mport *mport, dma_addr_t lstart) | ||
| 343 | { | ||
| 344 | u32 win_start_shift, base_start_shift; | ||
| 345 | struct rio_priv *priv = mport->priv; | ||
| 346 | u32 riwar, riwtar; | ||
| 347 | int i; | ||
| 348 | |||
| 349 | /* skip default window */ | ||
| 350 | base_start_shift = lstart >> RIWTAR_TRAD_VAL_SHIFT; | ||
| 351 | for (i = 0; i < RIO_INB_ATMU_COUNT; i++) { | ||
| 352 | riwar = in_be32(&priv->inb_atmu_regs[i].riwar); | ||
| 353 | if ((riwar & RIWAR_ENABLE) == 0) | ||
| 354 | continue; | ||
| 355 | |||
| 356 | riwtar = in_be32(&priv->inb_atmu_regs[i].riwtar); | ||
| 357 | win_start_shift = riwtar & RIWTAR_TRAD_MASK; | ||
| 358 | if (win_start_shift == base_start_shift) { | ||
| 359 | out_be32(&priv->inb_atmu_regs[i].riwar, riwar & ~RIWAR_ENABLE); | ||
| 360 | return; | ||
| 361 | } | ||
| 362 | } | ||
| 363 | } | ||
| 364 | |||
| 269 | void fsl_rio_port_error_handler(int offset) | 365 | void fsl_rio_port_error_handler(int offset) |
| 270 | { | 366 | { |
| 271 | /*XXX: Error recovery is not implemented, we just clear errors */ | 367 | /*XXX: Error recovery is not implemented, we just clear errors */ |
| @@ -389,6 +485,8 @@ int fsl_rio_setup(struct platform_device *dev) | |||
| 389 | ops->add_outb_message = fsl_add_outb_message; | 485 | ops->add_outb_message = fsl_add_outb_message; |
| 390 | ops->add_inb_buffer = fsl_add_inb_buffer; | 486 | ops->add_inb_buffer = fsl_add_inb_buffer; |
| 391 | ops->get_inb_message = fsl_get_inb_message; | 487 | ops->get_inb_message = fsl_get_inb_message; |
| 488 | ops->map_inb = fsl_map_inb_mem; | ||
| 489 | ops->unmap_inb = fsl_unmap_inb_mem; | ||
| 392 | 490 | ||
| 393 | rmu_node = of_parse_phandle(dev->dev.of_node, "fsl,srio-rmu-handle", 0); | 491 | rmu_node = of_parse_phandle(dev->dev.of_node, "fsl,srio-rmu-handle", 0); |
| 394 | if (!rmu_node) { | 492 | if (!rmu_node) { |
| @@ -602,6 +700,11 @@ int fsl_rio_setup(struct platform_device *dev) | |||
| 602 | RIO_ATMU_REGS_PORT2_OFFSET)); | 700 | RIO_ATMU_REGS_PORT2_OFFSET)); |
| 603 | 701 | ||
| 604 | priv->maint_atmu_regs = priv->atmu_regs + 1; | 702 | priv->maint_atmu_regs = priv->atmu_regs + 1; |
| 703 | priv->inb_atmu_regs = (struct rio_inb_atmu_regs __iomem *) | ||
| 704 | (priv->regs_win + | ||
| 705 | ((i == 0) ? RIO_INB_ATMU_REGS_PORT1_OFFSET : | ||
| 706 | RIO_INB_ATMU_REGS_PORT2_OFFSET)); | ||
| 707 | |||
| 605 | 708 | ||
| 606 | /* Set to receive any dist ID for serial RapidIO controller. */ | 709 | /* Set to receive any dist ID for serial RapidIO controller. */ |
| 607 | if (port->phy_type == RIO_PHY_SERIAL) | 710 | if (port->phy_type == RIO_PHY_SERIAL) |
| @@ -620,6 +723,7 @@ int fsl_rio_setup(struct platform_device *dev) | |||
| 620 | rio_law_start = range_start; | 723 | rio_law_start = range_start; |
| 621 | 724 | ||
| 622 | fsl_rio_setup_rmu(port, rmu_np[i]); | 725 | fsl_rio_setup_rmu(port, rmu_np[i]); |
| 726 | fsl_rio_inbound_mem_init(priv); | ||
| 623 | 727 | ||
| 624 | dbell->mport[i] = port; | 728 | dbell->mport[i] = port; |
| 625 | 729 | ||
diff --git a/arch/powerpc/sysdev/fsl_rio.h b/arch/powerpc/sysdev/fsl_rio.h index ae8e27405a0d..d53407a34f32 100644 --- a/arch/powerpc/sysdev/fsl_rio.h +++ b/arch/powerpc/sysdev/fsl_rio.h | |||
| @@ -50,9 +50,12 @@ | |||
| 50 | #define RIO_S_DBELL_REGS_OFFSET 0x13400 | 50 | #define RIO_S_DBELL_REGS_OFFSET 0x13400 |
| 51 | #define RIO_S_PW_REGS_OFFSET 0x134e0 | 51 | #define RIO_S_PW_REGS_OFFSET 0x134e0 |
| 52 | #define RIO_ATMU_REGS_DBELL_OFFSET 0x10C40 | 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 | #define MAX_MSG_UNIT_NUM 2 | 56 | #define MAX_MSG_UNIT_NUM 2 |
| 55 | #define MAX_PORT_NUM 4 | 57 | #define MAX_PORT_NUM 4 |
| 58 | #define RIO_INB_ATMU_COUNT 4 | ||
| 56 | 59 | ||
| 57 | struct rio_atmu_regs { | 60 | struct rio_atmu_regs { |
| 58 | u32 rowtar; | 61 | u32 rowtar; |
| @@ -63,6 +66,15 @@ struct rio_atmu_regs { | |||
| 63 | u32 pad2[3]; | 66 | u32 pad2[3]; |
| 64 | }; | 67 | }; |
| 65 | 68 | ||
| 69 | struct rio_inb_atmu_regs { | ||
| 70 | u32 riwtar; | ||
| 71 | u32 pad1; | ||
| 72 | u32 riwbar; | ||
| 73 | u32 pad2; | ||
| 74 | u32 riwar; | ||
| 75 | u32 pad3[3]; | ||
| 76 | }; | ||
| 77 | |||
| 66 | struct rio_dbell_ring { | 78 | struct rio_dbell_ring { |
| 67 | void *virt; | 79 | void *virt; |
| 68 | dma_addr_t phys; | 80 | dma_addr_t phys; |
| @@ -99,6 +111,7 @@ struct rio_priv { | |||
| 99 | void __iomem *regs_win; | 111 | void __iomem *regs_win; |
| 100 | struct rio_atmu_regs __iomem *atmu_regs; | 112 | struct rio_atmu_regs __iomem *atmu_regs; |
| 101 | struct rio_atmu_regs __iomem *maint_atmu_regs; | 113 | struct rio_atmu_regs __iomem *maint_atmu_regs; |
| 114 | struct rio_inb_atmu_regs __iomem *inb_atmu_regs; | ||
| 102 | void __iomem *maint_win; | 115 | void __iomem *maint_win; |
| 103 | void *rmm_handle; /* RapidIO message manager(unit) Handle */ | 116 | void *rmm_handle; /* RapidIO message manager(unit) Handle */ |
| 104 | }; | 117 | }; |
