mhi: core: Enable parsing of dev window from dt

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>
This commit is contained in:
Tony Truong 2015-07-31 12:42:44 -07:00 committed by David Keitel
parent f688e16bf5
commit 39e32e5185
12 changed files with 83 additions and 16 deletions

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

View 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 {

View 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 {

View 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 {

View 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 {

View 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 {

View 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 {

View 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 {

View 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 {

View 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 {

View 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 {

View 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(