OSDN Git Service

mhi: core: Enable parsing of dev window from dt
authorTony Truong <truong@codeaurora.org>
Fri, 31 Jul 2015 19:42:44 +0000 (12:42 -0700)
committerDavid Keitel <dkeitel@codeaurora.org>
Thu, 24 Mar 2016 04:24:42 +0000 (21:24 -0700)
Enable parsing of device window size from device tree
and calculating the appropriate addressing limitations.

Change-Id: I252a593a74f0cc00e6295a45d4d13db6c79cdfca
Signed-off-by: Andrei Danaila <adanaila@codeaurora.org>
Signed-off-by: Tony Truong <truong@codeaurora.org>
12 files changed:
Documentation/devicetree/bindings/mhi/msm_mhi.txt
arch/arm/boot/dts/qcom/apq8096-v3-pmi8994-mdm9x55-i2s-cdp.dts
arch/arm/boot/dts/qcom/apq8096-v3-pmi8994-mdm9x55-i2s-mtp.dts
arch/arm/boot/dts/qcom/apq8096-v3-pmi8994-mdm9x55-slimbus-mtp.dts
arch/arm/boot/dts/qcom/apq8096-v3-pmi8994-pm8004-mdm9x55-i2s-cdp.dts
arch/arm/boot/dts/qcom/apq8096-v3-pmi8994-pm8004-pmk8001-mdm9x55-i2s-cdp.dts
arch/arm/boot/dts/qcom/apq8096-v3-pmi8994-pmk8001-mdm9x55-i2s-cdp.dts
arch/arm/boot/dts/qcom/apq8096-v3-pmi8996-mdm9x55-i2s-cdp.dts
arch/arm/boot/dts/qcom/apq8096-v3-pmi8996-mdm9x55-i2s-mtp.dts
arch/arm/boot/dts/qcom/apq8096-v3-pmi8996-mdm9x55-slimbus-mtp.dts
drivers/platform/msm/mhi/mhi.h
drivers/platform/msm/mhi/mhi_init.c

index 36d8866..da8b021 100644 (file)
@@ -20,6 +20,7 @@ Required properties:
   - mhi-chan-cfg-#: mhi channel configuration parameters for platform
   - mhi-event-cfg-#: mhi event ring configuration parameters for platform
   - mhi-event-rings: number of event rings supported by platform
+  - mhi-dev-address-win-size: size of the MHI device addressing window
 
 Example:
 
@@ -36,4 +37,5 @@ Example:
                mhi-event-rings = <6>;
                mhi-chan-cfg-102 = <0x66 0x80 0x5 0x62>;
                mhi-event-cfg-0 = <0x80 0x0 0x0 0x11>;
+               mhi-dev-address-win-size= <0x10 0x00000000>;
        };
index bc77462..b434140 100644 (file)
@@ -95,6 +95,7 @@
        mhi-event-cfg-2 = <0x80 0x2 0x5 0x11>;
        mhi-event-cfg-3 = <0x100 0x3 0x1 0x9>;
        mhi-event-cfg-4 = <0x100 0x4 0x1 0x8>;
+       mhi-dev-address-win-size = <0x10 0x00000000>;
 };
 
 &pm8994_mpps {
index d52dc46..d017949 100644 (file)
@@ -94,6 +94,7 @@
        mhi-event-cfg-2 = <0x80 0x2 0x5 0x11>;
        mhi-event-cfg-3 = <0x100 0x3 0x1 0x9>;
        mhi-event-cfg-4 = <0x100 0x4 0x1 0x8>;
+       mhi-dev-address-win-size = <0x10 0x00000000>;
 };
 
 &pm8994_mpps {
index c60608e..2fbb98c 100644 (file)
@@ -95,6 +95,7 @@
        mhi-event-cfg-2 = <0x80 0x2 0x5 0x11>;
        mhi-event-cfg-3 = <0x100 0x3 0x1 0x9>;
        mhi-event-cfg-4 = <0x100 0x4 0x1 0x8>;
+       mhi-dev-address-win-size = <0x10 0x00000000>;
 };
 
 &pm8994_mpps {
index 1b5e9c0..eae754d 100644 (file)
@@ -95,6 +95,7 @@
        mhi-event-cfg-2 = <0x80 0x2 0x5 0x11>;
        mhi-event-cfg-3 = <0x100 0x3 0x1 0x9>;
        mhi-event-cfg-4 = <0x100 0x4 0x1 0x8>;
+       mhi-dev-address-win-size = <0x10 0x00000000>;
 };
 
 &pm8994_mpps {
index db20cdf..b3ebfc1 100644 (file)
@@ -95,6 +95,7 @@
        mhi-event-cfg-2 = <0x80 0x2 0x5 0x11>;
        mhi-event-cfg-3 = <0x100 0x3 0x1 0x9>;
        mhi-event-cfg-4 = <0x100 0x4 0x1 0x8>;
+       mhi-dev-address-win-size = <0x10 0x00000000>;
 };
 
 &pm8994_mpps {
index 5ed9044..17d7717 100644 (file)
@@ -95,6 +95,7 @@
        mhi-event-cfg-2 = <0x80 0x2 0x5 0x11>;
        mhi-event-cfg-3 = <0x100 0x3 0x1 0x9>;
        mhi-event-cfg-4 = <0x100 0x4 0x1 0x8>;
+       mhi-dev-address-win-size = <0x10 0x00000000>;
 };
 
 &pm8994_mpps {
index 92bba34..ab51e67 100644 (file)
@@ -96,6 +96,7 @@
        mhi-event-cfg-2 = <0x80 0x2 0x5 0x11>;
        mhi-event-cfg-3 = <0x100 0x3 0x1 0x9>;
        mhi-event-cfg-4 = <0x100 0x4 0x1 0x8>;
+       mhi-dev-address-win-size = <0x10 0x00000000>;
 };
 
 &pm8994_mpps {
index c6e9cab..3e4d111 100644 (file)
@@ -96,6 +96,7 @@
        mhi-event-cfg-2 = <0x80 0x2 0x5 0x11>;
        mhi-event-cfg-3 = <0x100 0x3 0x1 0x9>;
        mhi-event-cfg-4 = <0x100 0x4 0x1 0x8>;
+       mhi-dev-address-win-size = <0x10 0x00000000>;
 };
 
 &pm8994_mpps {
index f6be248..c5c1fe0 100644 (file)
@@ -96,6 +96,7 @@
        mhi-event-cfg-2 = <0x80 0x2 0x5 0x11>;
        mhi-event-cfg-3 = <0x100 0x3 0x1 0x9>;
        mhi-event-cfg-4 = <0x100 0x4 0x1 0x8>;
+       mhi-dev-address-win-size = <0x10 0x00000000>;
 };
 
 &pm8994_mpps {
index 7d55b67..588f91a 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -441,8 +441,8 @@ struct mhi_dev_space {
        dma_addr_t dma_dev_mem_start;
        size_t dev_mem_len;
        struct mhi_ring_ctxt ring_ctxt;
-       dma_addr_t start_win_addr;
-       dma_addr_t end_win_addr;
+       u64 start_win_addr;
+       u64 end_win_addr;
 };
 
 struct mhi_device_ctxt {
index 15ef91f..e6a90be 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -19,6 +19,7 @@
 #include <linux/cpu.h>
 #include <linux/kthread.h>
 #include <linux/slab.h>
+#include <linux/of.h>
 #include <linux/completion.h>
 #include <linux/platform_device.h>
 
@@ -214,15 +215,54 @@ static int enable_bb_ctxt(struct mhi_ring *bb_ctxt, int nr_el)
        return 0;
 }
 
-static void calculate_mhi_addressing_window(
-                       struct mhi_device_ctxt *mhi_dev_ctxt)
+/*
+ * The device can have severe addressing limitations, and in this case
+ * the MHI driver may be restricted on where memory can be allocated.
+ *
+ * The allocation of the MHI control data structures takes place as one
+ * big, physically contiguous allocation.
+ * The device's addressing window, must be placed around that control segment
+ * allocation.
+ * Here we attempt to do this by building an addressing window around the
+ * initial allocated control segment.
+ *
+ * The window size is specified by the device and must be contiguous,
+ * but depending on where the control segment was allocated, it may be
+ * necessary to leave more room, before the ctrl segment start or after
+ * the ctrl segment end.
+ * The following assumptions are made:
+ * Assumption: 1. size of allocated ctrl seg << (device allocation window / 2)
+ *            2. allocated ctrl seg is physically contiguous
+ */
+static int calculate_mhi_addressing_window(struct mhi_device_ctxt *mhi_dev_ctxt)
 {
-       dma_addr_t dma_dev_mem_start;
-       dma_addr_t dma_seg_size = 0x1FF00000UL;
-       dma_addr_t dma_max_addr = (dma_addr_t)(-1);
+       u64 dma_dev_mem_start = 0;
+       u64 dma_seg_size = 0;
+       u64 dma_max_addr = (dma_addr_t)(-1);
+       u64 dev_address_limit = 0;
+       int r = 0;
+       const struct device_node *np =
+               mhi_dev_ctxt->dev_info->plat_dev->dev.of_node;
 
        dma_dev_mem_start = mhi_dev_ctxt->dev_space.dma_dev_mem_start;
-
+       r = of_property_read_u64(np, "mhi-dev-address-win-size",
+                                &dev_address_limit);
+       if (r) {
+               mhi_log(MHI_MSG_ERROR,
+                       "Failed to get device addressing limit ret %d",
+                       r);
+               return r;
+       }
+       /* Mask off the last 3 bits for address calculation */
+       dev_address_limit &= ~0x7;
+       mhi_log(MHI_MSG_INFO, "Device Addressing limit 0x%llx\n",
+                               dev_address_limit);
+       dma_seg_size = dev_address_limit / 2;
+
+       /*
+        * The region of the allocated control segment is within the
+        * first half of the device's addressing limit
+        */
        if (dma_dev_mem_start < dma_seg_size) {
                mhi_dev_ctxt->dev_space.start_win_addr = 0;
                mhi_dev_ctxt->dev_space.end_win_addr =
@@ -230,15 +270,26 @@ static void calculate_mhi_addressing_window(
                                       (dma_seg_size - dma_dev_mem_start);
        } else if (dma_dev_mem_start >= dma_seg_size &&
                        dma_dev_mem_start <= (dma_max_addr - dma_seg_size)) {
+               /*
+                * The start of the control segment is located past
+                * halfway point of the device's addressing limit
+                * Place the control segment in the middle of the device's
+                * addressing range
+                */
                mhi_dev_ctxt->dev_space.start_win_addr =
                                         dma_dev_mem_start - dma_seg_size;
                mhi_dev_ctxt->dev_space.end_win_addr =
                                         dma_dev_mem_start + dma_seg_size;
        } else if (dma_dev_mem_start > (dma_max_addr - dma_seg_size)) {
-               mhi_dev_ctxt->dev_space.start_win_addr =
-                               dma_dev_mem_start - (dma_seg_size +
-                                               (dma_seg_size - (dma_max_addr -
-                                                       dma_dev_mem_start)));
+               /*
+                * The start of the control segment is located at the tail end
+                * of the host addressing space. Leave extra addressing space
+                * at window start
+                */
+               mhi_dev_ctxt->dev_space.start_win_addr = dma_dev_mem_start;
+               mhi_dev_ctxt->dev_space.start_win_addr -=
+                       dma_seg_size + (dma_seg_size -
+                                       (dma_max_addr - dma_dev_mem_start));
                mhi_dev_ctxt->dev_space.end_win_addr = dma_max_addr;
        }
        mhi_log(MHI_MSG_INFO,
@@ -246,7 +297,7 @@ static void calculate_mhi_addressing_window(
                (u64)dma_dev_mem_start,
                (u64)mhi_dev_ctxt->dev_space.start_win_addr,
                (u64)mhi_dev_ctxt->dev_space.end_win_addr);
-
+       return 0;
 }
 
 int init_mhi_dev_mem(struct mhi_device_ctxt *mhi_dev_ctxt)
@@ -274,7 +325,12 @@ int init_mhi_dev_mem(struct mhi_device_ctxt *mhi_dev_ctxt)
        dma_dev_mem_start = mhi_dev_ctxt->dev_space.dma_dev_mem_start;
        memset(dev_mem_start, 0, mhi_dev_ctxt->dev_space.dev_mem_len);
 
-       calculate_mhi_addressing_window(mhi_dev_ctxt);
+       r = calculate_mhi_addressing_window(mhi_dev_ctxt);
+       if (r) {
+               mhi_log(MHI_MSG_ERROR,
+               "Failed to calculate addressing window ret %d", r);
+               return r;
+       }
 
        mhi_log(MHI_MSG_INFO, "Starting Seg address: virt 0x%p, dma 0x%llx\n",
                                        dev_mem_start, (u64)dma_dev_mem_start);
@@ -441,7 +497,7 @@ error_state_change_event_handle:
        kfree(mhi_dev_ctxt->mhi_ev_wq.state_change_event);
 error_event_handle_alloc:
        kfree(mhi_dev_ctxt->mhi_ev_wq.mhi_event_wq);
-       return MHI_STATUS_ERROR;
+       return -ENOMEM;
 }
 
 static int mhi_init_state_change_thread_work_queue(