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 | }; |