rapidio/tsi721: add inbound memory mapping callbacks
authorAlexandre Bounine <alexandre.bounine@idt.com>
Fri, 5 Oct 2012 00:16:00 +0000 (17:16 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 5 Oct 2012 18:05:21 +0000 (03:05 +0900)
Add Tsi721 routines to support RapidIO subsystem's inbound memory mapping
interface (RapidIO to system's local memory).

Signed-off-by: Alexandre Bounine <alexandre.bounine@idt.com>
Cc: Matt Porter <mporter@kernel.crashing.org>
Cc: Li Yang <leoli@freescale.com>
Cc: Kumar Gala <galak@kernel.crashing.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
drivers/rapidio/devices/tsi721.c
drivers/rapidio/devices/tsi721.h

index 78dff6f407367a21eed9495b523ee4ca7e03cfc3..38ecd8f4d60e28a3eade51815f0b5eb22cb1361d 100644 (file)
@@ -861,6 +861,90 @@ static void tsi721_init_pc2sr_mapping(struct tsi721_device *priv)
                iowrite32(0, priv->regs + TSI721_OBWINLB(i));
 }
 
+/**
+ * tsi721_rio_map_inb_mem -- Mapping inbound memory region.
+ * @mport: RapidIO master port
+ * @lstart: Local memory space start address.
+ * @rstart: RapidIO space start address.
+ * @size: The mapping region size.
+ * @flags: Flags for mapping. 0 for using default flags.
+ *
+ * Return: 0 -- Success.
+ *
+ * This function will create the inbound mapping
+ * from rstart to lstart.
+ */
+static int tsi721_rio_map_inb_mem(struct rio_mport *mport, dma_addr_t lstart,
+               u64 rstart, u32 size, u32 flags)
+{
+       struct tsi721_device *priv = mport->priv;
+       int i;
+       u32 regval;
+
+       if (!is_power_of_2(size) || size < 0x1000 ||
+           ((u64)lstart & (size - 1)) || (rstart & (size - 1)))
+               return -EINVAL;
+
+       /* Search for free inbound translation window */
+       for (i = 0; i < TSI721_IBWIN_NUM; i++) {
+               regval = ioread32(priv->regs + TSI721_IBWIN_LB(i));
+               if (!(regval & TSI721_IBWIN_LB_WEN))
+                       break;
+       }
+
+       if (i >= TSI721_IBWIN_NUM) {
+               dev_err(&priv->pdev->dev,
+                       "Unable to find free inbound window\n");
+               return -EBUSY;
+       }
+
+       iowrite32(TSI721_IBWIN_SIZE(size) << 8,
+                       priv->regs + TSI721_IBWIN_SZ(i));
+
+       iowrite32(((u64)lstart >> 32), priv->regs + TSI721_IBWIN_TUA(i));
+       iowrite32(((u64)lstart & TSI721_IBWIN_TLA_ADD),
+                 priv->regs + TSI721_IBWIN_TLA(i));
+
+       iowrite32(rstart >> 32, priv->regs + TSI721_IBWIN_UB(i));
+       iowrite32((rstart & TSI721_IBWIN_LB_BA) | TSI721_IBWIN_LB_WEN,
+               priv->regs + TSI721_IBWIN_LB(i));
+       dev_dbg(&priv->pdev->dev,
+               "Configured IBWIN%d mapping (RIO_0x%llx -> PCIe_0x%llx)\n",
+               i, rstart, (unsigned long long)lstart);
+
+       return 0;
+}
+
+/**
+ * fsl_rio_unmap_inb_mem -- Unmapping inbound memory region.
+ * @mport: RapidIO master port
+ * @lstart: Local memory space start address.
+ */
+static void tsi721_rio_unmap_inb_mem(struct rio_mport *mport,
+                               dma_addr_t lstart)
+{
+       struct tsi721_device *priv = mport->priv;
+       int i;
+       u64 addr;
+       u32 regval;
+
+       /* Search for matching active inbound translation window */
+       for (i = 0; i < TSI721_IBWIN_NUM; i++) {
+               regval = ioread32(priv->regs + TSI721_IBWIN_LB(i));
+               if (regval & TSI721_IBWIN_LB_WEN) {
+                       regval = ioread32(priv->regs + TSI721_IBWIN_TUA(i));
+                       addr = (u64)regval << 32;
+                       regval = ioread32(priv->regs + TSI721_IBWIN_TLA(i));
+                       addr |= regval & TSI721_IBWIN_TLA_ADD;
+
+                       if (addr == (u64)lstart) {
+                               iowrite32(0, priv->regs + TSI721_IBWIN_LB(i));
+                               break;
+                       }
+               }
+       }
+}
+
 /**
  * tsi721_init_sr2pc_mapping - initializes inbound (SRIO->PCIe)
  * translation regions.
@@ -874,7 +958,7 @@ static void tsi721_init_sr2pc_mapping(struct tsi721_device *priv)
 
        /* Disable all SR2PC inbound windows */
        for (i = 0; i < TSI721_IBWIN_NUM; i++)
-               iowrite32(0, priv->regs + TSI721_IBWINLB(i));
+               iowrite32(0, priv->regs + TSI721_IBWIN_LB(i));
 }
 
 /**
@@ -2144,6 +2228,8 @@ static int __devinit tsi721_setup_mport(struct tsi721_device *priv)
        ops->add_outb_message = tsi721_add_outb_message;
        ops->add_inb_buffer = tsi721_add_inb_buffer;
        ops->get_inb_message = tsi721_get_inb_message;
+       ops->map_inb = tsi721_rio_map_inb_mem;
+       ops->unmap_inb = tsi721_rio_unmap_inb_mem;
 
        mport = kzalloc(sizeof(struct rio_mport), GFP_KERNEL);
        if (!mport) {
index 59de9d7be3460a08250bcd197dc858bed0af6dee..7d5b13ba8d4f49fa3a2d7f364940214f3a5ce6bb 100644 (file)
 
 #define TSI721_IBWIN_NUM       8
 
-#define TSI721_IBWINLB(x)      (0x29000 + (x) * 0x20)
-#define TSI721_IBWINLB_BA      0xfffff000
-#define TSI721_IBWINLB_WEN     0x00000001
+#define TSI721_IBWIN_LB(x)     (0x29000 + (x) * 0x20)
+#define TSI721_IBWIN_LB_BA     0xfffff000
+#define TSI721_IBWIN_LB_WEN    0x00000001
+
+#define TSI721_IBWIN_UB(x)     (0x29004 + (x) * 0x20)
+#define TSI721_IBWIN_SZ(x)     (0x29008 + (x) * 0x20)
+#define TSI721_IBWIN_SZ_SIZE   0x00001f00
+#define TSI721_IBWIN_SIZE(size)        (__fls(size) - 12)
+
+#define TSI721_IBWIN_TLA(x)    (0x2900c + (x) * 0x20)
+#define TSI721_IBWIN_TLA_ADD   0xfffff000
+#define TSI721_IBWIN_TUA(x)    (0x29010 + (x) * 0x20)
 
 #define TSI721_SR2PC_GEN_INTE  0x29800
 #define TSI721_SR2PC_PWE       0x29804