diff options
Diffstat (limited to 'arch/powerpc/sysdev/fsl_rio.c')
-rw-r--r-- | arch/powerpc/sysdev/fsl_rio.c | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/arch/powerpc/sysdev/fsl_rio.c b/arch/powerpc/sysdev/fsl_rio.c index 39d32480f0eb..c1cd3698f534 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 | ||