aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/sysdev/fsl_rio.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/sysdev/fsl_rio.c')
-rw-r--r--arch/powerpc/sysdev/fsl_rio.c104
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
282static 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
291int 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
342void 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
269void fsl_rio_port_error_handler(int offset) 365void 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