Merge "msm: mdss: Wait for vsync before iommu attach during cont splash"
diff --git a/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt b/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
index 3144045..c4b4707 100644
--- a/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
+++ b/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
@@ -290,6 +290,9 @@
- qcom,mdss-tear-check-frame-rate: Specify the value to be a real frame rate(fps) x 100 factor to tune the
timing of TE simulation with more precision.
The default value is 6000 with 60 fps.
+- qcom,panel-roi-alignment: Specifies the panel ROI alignment restrictions on its
+ left, top, width, height alignments and minimum width and
+ height values
Note, if a given optional qcom,* binding is not present, then the driver will configure
the default values specified.
@@ -395,5 +398,6 @@
qcom,mdss-tear-check-start-pos = <1280>;
qcom,mdss-tear-check-rd-ptr-trigger-intr = <1281>;
qcom,mdss-tear-check-frame-rate = <6000>;
+ qcom,panel-roi-alignment = <4 4 2 2 20 20>;
};
};
diff --git a/Documentation/devicetree/bindings/platform/msm/avtimer.txt b/Documentation/devicetree/bindings/platform/msm/avtimer.txt
new file mode 100644
index 0000000..86c9b67
--- /dev/null
+++ b/Documentation/devicetree/bindings/platform/msm/avtimer.txt
@@ -0,0 +1,21 @@
+* avtimer
+
+Avtimer provides an interface for clients to enable avtimer block
+on qdsp6. 64 bit AVtimer exposed by qdsp6 is used for audio and video
+stream synchronization during capture and playback usecases.
+
+Required properties:
+- reg : physical address and length of avtimer register
+- reg-names : AVtimer register name
+ Required register resource entries are:
+ "avtimer_lsb_addr" : AVtimer lsb physical address
+ "avtimer_msb_addr" : AVtimer msb physical address
+- compatible : Must be "qcom,avtimer"
+
+Example:
+ qcom,avtimer {
+ compatible = "qcom,avtimer";
+ reg = <0xfe053008 0x4>,
+ <0xfe05300c 0x4>;
+ reg-names = "avtimer_lsb_addr", "avtimer_msb_addr";
+ };
diff --git a/Documentation/devicetree/bindings/tty/serial/msm_serial_hs.txt b/Documentation/devicetree/bindings/tty/serial/msm_serial_hs.txt
index 762d40f..031be45 100644
--- a/Documentation/devicetree/bindings/tty/serial/msm_serial_hs.txt
+++ b/Documentation/devicetree/bindings/tty/serial/msm_serial_hs.txt
@@ -64,6 +64,9 @@
receiving interrupt with UART RX GPIO IRQ line (i.e. above wakeup_irq property),
HSUART driver injects provided character with property rx_to_inject.
- qcom, rx-char-to-inject : The character to be inserted on wakeup.
+- qcom, no-suspend-delay : This decides system to go to suspend immediately
+or not
+
- Refer to "Documentation/devicetree/bindings/arm/msm/msm_bus.txt" for
below optional properties:
- qcom,msm_bus,name
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index 4eb26a2..99dbec8 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 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
@@ -2523,6 +2523,13 @@
qcom,smdtty-dev-name = "LOOPBACK_TTY";
};
};
+
+ qcom,avtimer {
+ compatible = "qcom,avtimer";
+ reg = <0xfe053008 0x4>,
+ <0xfe05300c 0x4>;
+ reg-names = "avtimer_lsb_addr", "avtimer_msb_addr";
+ };
};
&gdsc_venus {
diff --git a/arch/arm/boot/dts/msm8974pro-pma8084-regulator.dtsi b/arch/arm/boot/dts/msm8974pro-pma8084-regulator.dtsi
index 49bf4ea..433d466 100644
--- a/arch/arm/boot/dts/msm8974pro-pma8084-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8974pro-pma8084-regulator.dtsi
@@ -483,6 +483,7 @@
qcom,use-phase-scaling-factor;
qcom,phase-scaling-factor-bits-pos = <16>;
qcom,valid-scaling-factor-versions = <0 1 1 0>;
+ qcom,force-auto-mode;
krait0_vreg: regulator@f9088000 {
compatible = "qcom,krait-regulator";
diff --git a/arch/arm/boot/dts/msm8974pro.dtsi b/arch/arm/boot/dts/msm8974pro.dtsi
index bb4c619..3e00a46 100644
--- a/arch/arm/boot/dts/msm8974pro.dtsi
+++ b/arch/arm/boot/dts/msm8974pro.dtsi
@@ -1723,7 +1723,11 @@
<3240000 1600000>,
<4048000 1600000>,
<4264000 1600000>;
- qcom,max-hw-load = <1216800>; /* 3840 X 2160 @ 30 fps + 1920 X 1088 @ 30 fps */
+ /*
+ * Performance is guaranteed only upto POR specification. Anything
+ * above that specification is best effort and might even be rejected.
+ */
+ qcom,max-hw-load = <1281600>; /* max(4k X 2304 @ 24, 4k X 2160 @ 30) + 1080p @ 30 */
qcom,buffer-type-tz-usage-table = <0x241 0x1>,
<0x106 0x2>,
<0x480 0x3>;
diff --git a/arch/arm/configs/msm8974-perf_defconfig b/arch/arm/configs/msm8974-perf_defconfig
index b9f0f8b..414a4df 100755
--- a/arch/arm/configs/msm8974-perf_defconfig
+++ b/arch/arm/configs/msm8974-perf_defconfig
@@ -509,3 +509,4 @@
CONFIG_MSM_RDBG=m
CONFIG_DEVMEM=n
CONFIG_DEVKMEM=n
+CONFIG_MSM_AVTIMER=y
diff --git a/arch/arm/configs/msm8974_defconfig b/arch/arm/configs/msm8974_defconfig
index e843739..3b2f2b5 100755
--- a/arch/arm/configs/msm8974_defconfig
+++ b/arch/arm/configs/msm8974_defconfig
@@ -565,3 +565,4 @@
CONFIG_SND_SOC_MSM_HDMI_CODEC_RX=y
CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE=y
CONFIG_MSM_RDBG=m
+CONFIG_MSM_AVTIMER=y
diff --git a/arch/arm/mach-msm/include/mach/msm_serial_hs.h b/arch/arm/mach-msm/include/mach/msm_serial_hs.h
index e6b677e..edc85ba 100644
--- a/arch/arm/mach-msm/include/mach/msm_serial_hs.h
+++ b/arch/arm/mach-msm/include/mach/msm_serial_hs.h
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2008 Google, Inc.
- * Copyright (C) 2010-2013, The Linux Foundation. All rights reserved.
+ * Copyright (C) 2010-2014, The Linux Foundation. All rights reserved.
* Author: Nick Pelly <npelly@google.com>
*
* This software is licensed under the terms of the GNU General Public
@@ -32,6 +32,8 @@
* @uart_rfr_gpio: GPIO number for UART RFR Line.
* @bam_tx_ep_pipe_index : BAM TX Endpoint Pipe Index for HSUART
* @bam_tx_ep_pipe_index : BAM RX Endpoint Pipe Index for HSUART
+ * @no_suspend_delay : Flag used to make system go to suspend
+ * immediately or not
*/
struct msm_serial_hs_platform_data {
int wakeup_irq; /* wakeup irq */
@@ -46,6 +48,7 @@
int uart_rfr_gpio;
unsigned bam_tx_ep_pipe_index;
unsigned bam_rx_ep_pipe_index;
+ bool no_suspend_delay;
};
unsigned int msm_hs_tx_empty(struct uart_port *uport);
diff --git a/drivers/crypto/msm/qce50.c b/drivers/crypto/msm/qce50.c
index ad7dd31..b93a82f 100644
--- a/drivers/crypto/msm/qce50.c
+++ b/drivers/crypto/msm/qce50.c
@@ -4820,9 +4820,9 @@
if (_qce_sps_add_sg_data(pce_dev, areq->src, areq->nbytes,
&pce_dev->ce_sps.in_transfer))
goto bad;
- _qce_set_flag(&pce_dev->ce_sps.in_transfer,
- SPS_IOVEC_FLAG_EOT|SPS_IOVEC_FLAG_NWD);
-
+ if (areq->nbytes)
+ _qce_set_flag(&pce_dev->ce_sps.in_transfer,
+ SPS_IOVEC_FLAG_EOT|SPS_IOVEC_FLAG_NWD);
if (_qce_sps_add_data(GET_PHYS_ADDR(pce_dev->ce_sps.result_dump),
CRYPTO_RESULT_DUMP_SIZE,
&pce_dev->ce_sps.out_transfer))
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index 1a11541..7c20d1e 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -917,6 +917,7 @@
}
spin_unlock_irqrestore(
&qseecom.registered_app_list_lock, flags);
+ ret = 0;
} else {
pr_warn("App (%s) does'nt exist, loading apps for first time\n",
(char *)(load_img_req.img_name));
diff --git a/drivers/misc/tspp.c b/drivers/misc/tspp.c
index 1ef9886..405c626 100644
--- a/drivers/misc/tspp.c
+++ b/drivers/misc/tspp.c
@@ -459,6 +459,7 @@
struct tspp_global_performance_regs *tspp_global_performance;
struct tspp_pipe_context_regs *tspp_pipe_context;
struct tspp_pipe_performance_regs *tspp_pipe_performance;
+ bool req_irqs;
struct dentry *dent;
struct dentry *debugfs_regs[ARRAY_SIZE(debugfs_tspp_regs)];
@@ -1064,12 +1065,6 @@
writel_relaxed(TSPP_RST_RESET, pdev->base + TSPP_RST);
wmb();
- /* BAM */
- if (sps_device_reset(pdev->bam_handle) != 0) {
- pr_err("tspp: error resetting bam");
- return -EBUSY;
- }
-
/* TSPP tables */
for (i = 0; i < TSPP_FILTER_TABLES; i++)
memset(pdev->filters[i],
@@ -1367,7 +1362,7 @@
goto failed;
}
}
-
+ device->req_irqs = true;
return 0;
failed:
@@ -1389,6 +1384,7 @@
if (device->tspp_irq)
free_irq(device->tspp_irq, device);
+ device->req_irqs = false;
}
/*** TSPP API functions ***/
@@ -1408,9 +1404,9 @@
{
u32 val;
int rc;
- bool req_irq = false;
struct tspp_device *pdev;
struct tspp_channel *channel;
+ bool req_irqs = false;
TSPP_DEBUG("tspp_open_stream %i %i %i %i",
dev, channel_id, source->source, source->mode);
@@ -1438,15 +1434,14 @@
source->enable_inverse);
/* Request IRQ resources on first open */
- if ((source->source == TSPP_SOURCE_TSIF0 ||
- source->source == TSPP_SOURCE_TSIF1) &&
- (pdev->tsif[0].ref_count + pdev->tsif[1].ref_count) == 0) {
+ if (!pdev->req_irqs && (source->source == TSPP_SOURCE_TSIF0 ||
+ source->source == TSPP_SOURCE_TSIF1)) {
rc = msm_tspp_req_irqs(pdev);
if (rc) {
pr_err("tspp: error requesting irqs\n");
return rc;
}
- req_irq = true;
+ req_irqs = true;
}
switch (source->source) {
@@ -1499,7 +1494,8 @@
return 0;
free_irq:
- if (req_irq)
+ /* Free irqs only if were requested during opening of this stream */
+ if (req_irqs)
msm_tspp_free_irqs(pdev);
return rc;
}
@@ -1576,6 +1572,26 @@
}
EXPORT_SYMBOL(tspp_close_stream);
+static int tspp_init_sps_device(struct tspp_device *dev)
+{
+ int ret;
+
+ ret = sps_register_bam_device(&dev->bam_props, &dev->bam_handle);
+ if (ret) {
+ pr_err("tspp: failed to register bam device, err-%d\n", ret);
+ return ret;
+ }
+
+ ret = sps_device_reset(dev->bam_handle);
+ if (ret) {
+ sps_deregister_bam_device(dev->bam_handle);
+ pr_err("tspp: error resetting bam device, err=%d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
/**
* tspp_open_channel - open a TSPP channel.
*
@@ -1618,6 +1634,16 @@
if (rc)
return rc;
+ if (pdev->bam_handle == SPS_DEV_HANDLE_INVALID) {
+ rc = tspp_init_sps_device(pdev);
+ if (rc) {
+ pr_err("tspp: failed to init sps device, err=%d\n",
+ rc);
+ tspp_clock_stop(pdev);
+ return rc;
+ }
+ }
+
wake_lock(&pdev->wake_lock);
}
@@ -1698,6 +1724,7 @@
err_desc_alloc:
sps_free_endpoint(channel->pipe);
err_sps_alloc:
+ channel->used = 0;
return rc;
}
EXPORT_SYMBOL(tspp_open_channel);
@@ -1805,6 +1832,9 @@
channel->locked = NULL;
if (tspp_channels_in_use(pdev) == 0) {
+ sps_deregister_bam_device(pdev->bam_handle);
+ pdev->bam_handle = SPS_DEV_HANDLE_INVALID;
+
wake_unlock(&pdev->wake_lock);
tspp_clock_stop(pdev);
}
@@ -3121,6 +3151,7 @@
if (msm_tspp_map_irqs(pdev, device))
goto err_irq;
+ device->req_irqs = false;
/* power management */
pm_runtime_set_active(&pdev->dev);
@@ -3155,11 +3186,7 @@
goto err_clock;
}
- if (sps_register_bam_device(&device->bam_props,
- &device->bam_handle) != 0) {
- pr_err("tspp: failed to register bam");
- goto err_bam;
- }
+ device->bam_handle = SPS_DEV_HANDLE_INVALID;
spin_lock_init(&device->spinlock);
tasklet_init(&device->tlet, tspp_sps_complete_tlet,
@@ -3202,7 +3229,6 @@
sps_deregister_bam_device(device->bam_handle);
err_clock:
-err_bam:
tspp_debugfs_exit(device);
for (i = 0; i < TSPP_TSIF_INSTANCES; i++)
tsif_debugfs_exit(&device->tsif[i]);
@@ -3240,7 +3266,6 @@
{
struct tspp_channel *channel;
u32 i;
- int rc;
struct tspp_device *device = platform_get_drvdata(pdev);
@@ -3252,24 +3277,15 @@
cdev_del(&channel->cdev);
}
- /* de-registering BAM device requires clocks */
- rc = tspp_clock_start(device);
- if (rc == 0) {
- sps_deregister_bam_device(device->bam_handle);
- tspp_clock_stop(device);
- }
-
- for (i = 0; i < TSPP_TSIF_INSTANCES; i++) {
+ for (i = 0; i < TSPP_TSIF_INSTANCES; i++)
tsif_debugfs_exit(&device->tsif[i]);
- if (device->tsif[i].tsif_irq)
- free_irq(device->tsif[i].tsif_irq, &device->tsif[i]);
- }
if (device->tsif_bus_client)
msm_bus_scale_unregister_client(device->tsif_bus_client);
wake_lock_destroy(&device->wake_lock);
- free_irq(device->tspp_irq, device);
+ if (device->req_irqs)
+ msm_tspp_free_irqs(device);
iounmap(device->bam_props.virt_addr);
iounmap(device->base);
diff --git a/drivers/net/ethernet/msm/msm_rmnet_bam.c b/drivers/net/ethernet/msm/msm_rmnet_bam.c
index 7ec317a..ff6a79c 100644
--- a/drivers/net/ethernet/msm/msm_rmnet_bam.c
+++ b/drivers/net/ethernet/msm/msm_rmnet_bam.c
@@ -118,7 +118,8 @@
struct device_attribute *attr,
char *buf)
{
- return sprintf(buf, "%lu\n", (unsigned long) timeout_suspend_us);
+ return snprintf(buf, PAGE_SIZE, "%lu\n",
+ (unsigned long) timeout_suspend_us);
}
static DEVICE_ATTR(timeout_suspend, 0664, timeout_suspend_show,
@@ -177,7 +178,7 @@
char *buf)
{
struct rmnet_private *p = netdev_priv(to_net_dev(d));
- return sprintf(buf, "%lu\n", p->wakeups_xmit);
+ return snprintf(buf, PAGE_SIZE, "%lu\n", p->wakeups_xmit);
}
DEVICE_ATTR(wakeups_xmit, 0444, wakeups_xmit_show, NULL);
@@ -186,7 +187,7 @@
char *buf)
{
struct rmnet_private *p = netdev_priv(to_net_dev(d));
- return sprintf(buf, "%lu\n", p->wakeups_rcv);
+ return snprintf(buf, PAGE_SIZE, "%lu\n", p->wakeups_rcv);
}
DEVICE_ATTR(wakeups_rcv, 0444, wakeups_rcv_show, NULL);
@@ -210,7 +211,7 @@
{
struct rmnet_private *p = netdev_priv(to_net_dev(d));
p = netdev_priv(to_net_dev(d));
- return sprintf(buf, "%lu\n", timeout_us);
+ return snprintf(buf, PAGE_SIZE, "%lu\n", timeout_us);
}
DEVICE_ATTR(timeout, 0664, timeout_show, timeout_store);
diff --git a/drivers/platform/msm/Kconfig b/drivers/platform/msm/Kconfig
index 11b064a..7c40677 100644
--- a/drivers/platform/msm/Kconfig
+++ b/drivers/platform/msm/Kconfig
@@ -115,7 +115,7 @@
to configure IPA core.
config MSM_AVTIMER
tristate "Avtimer Driver"
- depends on ARCH_MSM8960
+ depends on MSM_QDSP6_APRV2
help
This driver gets the Q6 out of power collapsed state and
exposes ioctl control to read avtimer tick.
diff --git a/drivers/platform/msm/avtimer.c b/drivers/platform/msm/avtimer.c
index f513ceb..d5fa885 100644
--- a/drivers/platform/msm/avtimer.c
+++ b/drivers/platform/msm/avtimer.c
@@ -1,5 +1,4 @@
-
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 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
@@ -21,71 +20,102 @@
#include <linux/io.h>
#include <linux/platform_device.h>
#include <linux/avtimer.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/wait.h>
+#include <linux/sched.h>
#include <mach/qdsp6v2/apr.h>
#define DEVICE_NAME "avtimer"
+#define TIMEOUT_MS 1000
+#define CORE_CLIENT 1
+#define TEMP_PORT ((CORE_CLIENT << 8) | 0x0001)
+#define AVCS_CMD_REMOTE_AVTIMER_VOTE_REQUEST 0x00012914
+#define AVCS_CMD_RSP_REMOTE_AVTIMER_VOTE_REQUEST 0x00012915
+#define AVCS_CMD_REMOTE_AVTIMER_RELEASE_REQUEST 0x00012916
+#define AVTIMER_REG_CNT 2
-#define ADSP_CMD_SET_POWER_COLLAPSE_STATE 0x0001115C
+struct adsp_avt_timer {
+ struct apr_hdr hdr;
+ union {
+ char client_name[8];
+ u32 avtimer_handle;
+ };
+} __packed;
-static int major; /* Major number assigned to our device driver */
+static int major;
+
struct avtimer_t {
+ struct apr_svc *core_handle_q;
struct cdev myc;
struct class *avtimer_class;
struct mutex avtimer_lock;
int avtimer_open_cnt;
- struct dev_avtimer_data *avtimer_pdata;
+ struct dev_avtimer_data avtimer_pdata;
+ wait_queue_head_t adsp_resp_wait;
+ int enable_timer_resp_recieved;
+ int timer_handle;
+ void __iomem *p_avtimer_msw;
+ void __iomem *p_avtimer_lsw;
};
+
static struct avtimer_t avtimer;
-static struct apr_svc *core_handle;
-
-struct adsp_power_collapse {
- struct apr_hdr hdr;
- uint32_t power_collapse;
-};
-
-static int32_t avcs_core_callback(struct apr_client_data *data, void *priv)
+static int32_t aprv2_core_fn_q(struct apr_client_data *data, void *priv)
{
- uint32_t *payload;
+ uint32_t *payload1;
- pr_debug("core msg: payload len = %u, apr resp opcode = 0x%X\n",
- data->payload_size, data->opcode);
+ pr_debug("%s: core msg: payload len = %u, apr resp opcode = 0x%X\n",
+ __func__, data->payload_size, data->opcode);
+
+ if (!data) {
+ pr_err("%s: Invalid params\n", __func__);
+ return -EINVAL;
+ }
switch (data->opcode) {
case APR_BASIC_RSP_RESULT:{
- if (data->payload_size == 0) {
+ if (!data->payload_size) {
pr_err("%s: APR_BASIC_RSP_RESULT No Payload ",
__func__);
return 0;
}
- payload = data->payload;
-
- switch (payload[0]) {
-
- case ADSP_CMD_SET_POWER_COLLAPSE_STATE:
- pr_debug("CMD_SET_POWER_COLLAPSE_STATE status[0x%x]\n",
- payload[1]);
+ payload1 = data->payload;
+ switch (payload1[0]) {
+ case AVCS_CMD_REMOTE_AVTIMER_RELEASE_REQUEST:
+ pr_debug("%s: Cmd = TIMER RELEASE status[0x%x]\n",
+ __func__, payload1[1]);
break;
default:
pr_err("Invalid cmd rsp[0x%x][0x%x]\n",
- payload[0], payload[1]);
+ payload1[0], payload1[1]);
break;
}
break;
}
+
case RESET_EVENTS:{
- pr_debug("Reset event received in Core service");
- apr_reset(core_handle);
- core_handle = NULL;
+ pr_debug("%s: Reset event received in AV timer\n", __func__);
+ apr_reset(avtimer.core_handle_q);
+ avtimer.core_handle_q = NULL;
break;
}
+ case AVCS_CMD_RSP_REMOTE_AVTIMER_VOTE_REQUEST:
+ payload1 = data->payload;
+ pr_debug("%s: RSP_REMOTE_AVTIMER_VOTE_REQUEST handle %x\n",
+ __func__, payload1[0]);
+ avtimer.timer_handle = payload1[0];
+ avtimer.enable_timer_resp_recieved = 1;
+ wake_up(&avtimer.adsp_resp_wait);
+ break;
default:
- pr_err("Message id from adsp core svc: %d\n", data->opcode);
+ pr_err("%s: Message adspcore svc: %d\n",
+ __func__, data->opcode);
break;
}
@@ -94,104 +124,147 @@
int avcs_core_open(void)
{
- if (core_handle == NULL)
- core_handle = apr_register("ADSP", "CORE",
- avcs_core_callback, 0xFFFFFFFF, NULL);
-
- pr_debug("Open_q %p\n", core_handle);
- if (core_handle == NULL) {
+ if (!avtimer.core_handle_q)
+ avtimer.core_handle_q = apr_register("ADSP", "CORE",
+ aprv2_core_fn_q, TEMP_PORT, NULL);
+ pr_debug("%s: Open_q %p\n", __func__, avtimer.core_handle_q);
+ if (!avtimer.core_handle_q) {
pr_err("%s: Unable to register CORE\n", __func__);
- return -ENODEV;
+ return -EINVAL;
}
return 0;
}
+EXPORT_SYMBOL(avcs_core_open);
-int avcs_core_disable_power_collapse(int disable)
+static int avcs_core_disable_avtimer(int timerhandle)
{
- struct adsp_power_collapse pc;
- int rc = 0;
+ int rc = -EINVAL;
+ struct adsp_avt_timer payload;
- if (core_handle) {
- pc.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_EVENT,
- APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
- pc.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
- sizeof(uint32_t));
- pc.hdr.src_port = 0;
- pc.hdr.dest_port = 0;
- pc.hdr.token = 0;
- pc.hdr.opcode = ADSP_CMD_SET_POWER_COLLAPSE_STATE;
- /*
- * When power_collapse set to 1 -- If the aDSP is in the power
- * collapsed state when this command is received, it is awakened
- * from this state. The aDSP does not power collapse again until
- * the client revokes this command
- * When power_collapse set to 0 -- This indicates to the aDSP
- * that the remote client does not need it to be out of power
- * collapse any longer. This may not always put the aDSP into
- * power collapse; the aDSP must honor an internal client's
- * power requirements as well.
- */
- pc.power_collapse = disable;
- rc = apr_send_pkt(core_handle, (uint32_t *)&pc);
- if (rc < 0) {
- pr_debug("disable power collapse = %d failed\n",
- disable);
- return rc;
- }
- pr_debug("disable power collapse = %d\n", disable);
+ if (!timerhandle) {
+ pr_err("%s: Invalid timer handle\n", __func__);
+ return -EINVAL;
}
- return 0;
+ memset(&payload, 0, sizeof(payload));
+ rc = avcs_core_open();
+ if (!rc && avtimer.core_handle_q) {
+ payload.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+ APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
+ payload.hdr.pkt_size =
+ sizeof(struct adsp_avt_timer);
+ payload.hdr.src_svc = avtimer.core_handle_q->id;
+ payload.hdr.src_domain = APR_DOMAIN_APPS;
+ payload.hdr.dest_domain = APR_DOMAIN_ADSP;
+ payload.hdr.dest_svc = APR_SVC_ADSP_CORE;
+ payload.hdr.src_port = TEMP_PORT;
+ payload.hdr.dest_port = TEMP_PORT;
+ payload.hdr.token = CORE_CLIENT;
+ payload.hdr.opcode = AVCS_CMD_REMOTE_AVTIMER_RELEASE_REQUEST;
+ payload.avtimer_handle = timerhandle;
+ pr_debug("%s: disable avtimer opcode %x handle %x\n",
+ __func__, payload.hdr.opcode, payload.avtimer_handle);
+ rc = apr_send_pkt(avtimer.core_handle_q,
+ (uint32_t *)&payload);
+ if (rc < 0)
+ pr_err("%s: Enable AVtimer failed op[0x%x]rc[%d]\n",
+ __func__, payload.hdr.opcode, rc);
+ else
+ rc = 0;
+ }
+ return rc;
}
+static int avcs_core_enable_avtimer(char *client_name)
+{
+ int rc = -EINVAL, ret = -EINVAL;
+ struct adsp_avt_timer payload;
+
+ if (!client_name) {
+ pr_err("%s: Invalid params\n", __func__);
+ return -EINVAL;
+ }
+ memset(&payload, 0, sizeof(payload));
+ rc = avcs_core_open();
+ if (!rc && avtimer.core_handle_q) {
+ avtimer.enable_timer_resp_recieved = 0;
+ payload.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_EVENT,
+ APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
+ payload.hdr.pkt_size =
+ sizeof(struct adsp_avt_timer);
+ payload.hdr.src_svc = avtimer.core_handle_q->id;
+ payload.hdr.src_domain = APR_DOMAIN_APPS;
+ payload.hdr.dest_domain = APR_DOMAIN_ADSP;
+ payload.hdr.dest_svc = APR_SVC_ADSP_CORE;
+ payload.hdr.src_port = TEMP_PORT;
+ payload.hdr.dest_port = TEMP_PORT;
+ payload.hdr.token = CORE_CLIENT;
+ payload.hdr.opcode = AVCS_CMD_REMOTE_AVTIMER_VOTE_REQUEST;
+ strlcpy(payload.client_name, client_name,
+ sizeof(payload.client_name));
+ pr_debug("%s: enable avtimer opcode %x client name %s\n",
+ __func__, payload.hdr.opcode, payload.client_name);
+ rc = apr_send_pkt(avtimer.core_handle_q,
+ (uint32_t *)&payload);
+ if (rc < 0) {
+ pr_err("%s: Enable AVtimer failed op[0x%x]rc[%d]\n",
+ __func__, payload.hdr.opcode, rc);
+ goto bail;
+ } else
+ rc = 0;
+ ret = wait_event_timeout(avtimer.adsp_resp_wait,
+ (avtimer.enable_timer_resp_recieved == 1),
+ msecs_to_jiffies(TIMEOUT_MS));
+ if (!ret) {
+ pr_err("%s: wait_event timeout for Enable timer\n",
+ __func__);
+ rc = -ETIMEDOUT;
+ }
+ if (rc)
+ avtimer.timer_handle = 0;
+ }
+bail:
+ return rc;
+}
+
+int avcs_core_disable_power_collapse(int enable)
+{
+ int rc = 0;
+ mutex_lock(&avtimer.avtimer_lock);
+ if (enable) {
+ if (avtimer.avtimer_open_cnt) {
+ avtimer.avtimer_open_cnt++;
+ pr_debug("%s: opened avtimer open count=%d\n",
+ __func__, avtimer.avtimer_open_cnt);
+ rc = 0;
+ goto done;
+ }
+ rc = avcs_core_enable_avtimer("timer");
+ if (!rc)
+ avtimer.avtimer_open_cnt++;
+ } else {
+ if (avtimer.avtimer_open_cnt > 0) {
+ avtimer.avtimer_open_cnt--;
+ if (!avtimer.avtimer_open_cnt) {
+ rc = avcs_core_disable_avtimer(
+ avtimer.timer_handle);
+ avtimer.timer_handle = 0;
+ }
+ }
+ }
+done:
+ mutex_unlock(&avtimer.avtimer_lock);
+ return rc;
+}
+EXPORT_SYMBOL(avcs_core_disable_power_collapse);
+
static int avtimer_open(struct inode *inode, struct file *file)
{
- int rc = 0;
- struct avtimer_t *pavtimer = &avtimer;
-
- pr_debug("avtimer_open\n");
- mutex_lock(&pavtimer->avtimer_lock);
-
- if (pavtimer->avtimer_open_cnt != 0) {
- pavtimer->avtimer_open_cnt++;
- pr_debug("%s: opened avtimer open count=%d\n",
- __func__, pavtimer->avtimer_open_cnt);
- mutex_unlock(&pavtimer->avtimer_lock);
- return 0;
- }
- try_module_get(THIS_MODULE);
-
- rc = avcs_core_open();
- if (core_handle)
- rc = avcs_core_disable_power_collapse(1);
-
- pavtimer->avtimer_open_cnt++;
- pr_debug("%s: opened avtimer open count=%d\n",
- __func__, pavtimer->avtimer_open_cnt);
- mutex_unlock(&pavtimer->avtimer_lock);
- pr_debug("avtimer_open leave rc=%d\n", rc);
-
- return rc;
+ return avcs_core_disable_power_collapse(1);
}
static int avtimer_release(struct inode *inode, struct file *file)
{
- int rc = 0;
- struct avtimer_t *pavtimer = &avtimer;
-
- mutex_lock(&pavtimer->avtimer_lock);
- pavtimer->avtimer_open_cnt--;
-
- if (core_handle && pavtimer->avtimer_open_cnt == 0)
- rc = avcs_core_disable_power_collapse(0);
-
- pr_debug("device_release(%p,%p) open count=%d\n",
- inode, file, pavtimer->avtimer_open_cnt);
-
- module_put(THIS_MODULE);
-
- mutex_unlock(&pavtimer->avtimer_lock);
-
- return rc;
+ return avcs_core_disable_power_collapse(0);
}
/*
@@ -200,56 +273,35 @@
static long avtimer_ioctl(struct file *file, unsigned int ioctl_num,
unsigned long ioctl_param)
{
- struct avtimer_t *pavtimer = &avtimer;
- pr_debug("avtimer_ioctl: ioctlnum=%d,param=%lx\n",
- ioctl_num, ioctl_param);
-
switch (ioctl_num) {
case IOCTL_GET_AVTIMER_TICK:
{
- void __iomem *p_avtimer_msw = NULL, *p_avtimer_lsw = NULL;
uint32_t avtimer_msw_1st = 0, avtimer_lsw = 0;
uint32_t avtimer_msw_2nd = 0;
uint64_t avtimer_tick;
-
- if (pavtimer->avtimer_pdata) {
- p_avtimer_lsw = ioremap(
- pavtimer->avtimer_pdata->avtimer_lsw_phy_addr, 4);
- p_avtimer_msw = ioremap(
- pavtimer->avtimer_pdata->avtimer_msw_phy_addr, 4);
- }
- if (!p_avtimer_lsw || !p_avtimer_msw) {
- pr_err("ioremap failed\n");
- return -EIO;
- }
do {
- avtimer_msw_1st = ioread32(p_avtimer_msw);
- avtimer_lsw = ioread32(p_avtimer_lsw);
- avtimer_msw_2nd = ioread32(p_avtimer_msw);
+ avtimer_msw_1st = ioread32(avtimer.p_avtimer_msw);
+ avtimer_lsw = ioread32(avtimer.p_avtimer_lsw);
+ avtimer_msw_2nd = ioread32(avtimer.p_avtimer_msw);
} while (avtimer_msw_1st != avtimer_msw_2nd);
avtimer_tick =
((uint64_t) avtimer_msw_1st << 32) | avtimer_lsw;
- pr_debug("AV Timer tick: msw: %d, lsw: %d\n", avtimer_msw_1st,
- avtimer_lsw);
+ pr_debug("%s: AV Timer tick: msw: %x, lsw: %x time %llx\n",
+ __func__, avtimer_msw_1st, avtimer_lsw, avtimer_tick);
if (copy_to_user((void *) ioctl_param, &avtimer_tick,
sizeof(avtimer_tick))) {
pr_err("copy_to_user failed\n");
- iounmap(p_avtimer_lsw);
- iounmap(p_avtimer_msw);
return -EFAULT;
}
- iounmap(p_avtimer_lsw);
- iounmap(p_avtimer_msw);
}
break;
default:
- pr_err("invalid cmd\n");
- break;
+ pr_err("%s: invalid cmd\n", __func__);
+ return -EINVAL;
}
-
return 0;
}
@@ -261,11 +313,44 @@
static int dev_avtimer_probe(struct platform_device *pdev)
{
- int result;
+ int result = 0;
dev_t dev = MKDEV(major, 0);
struct device *device_handle;
- struct avtimer_t *pavtimer = &avtimer;
+ struct resource *reg_lsb = NULL, *reg_msb = NULL;
+ if (!pdev) {
+ pr_err("%s: Invalid params\n", __func__);
+ return -EINVAL;
+ }
+ reg_lsb = platform_get_resource_byname(pdev,
+ IORESOURCE_MEM, "avtimer_lsb_addr");
+ if (!reg_lsb) {
+ dev_err(&pdev->dev, "%s: Looking up %s property",
+ "avtimer_lsb_addr", __func__);
+ return -EINVAL;
+ }
+ reg_msb = platform_get_resource_byname(pdev,
+ IORESOURCE_MEM, "avtimer_msb_addr");
+ if (!reg_msb) {
+ dev_err(&pdev->dev, "%s: Looking up %s property",
+ "avtimer_msb_addr", __func__);
+ return -EINVAL;
+ }
+ avtimer.p_avtimer_lsw = devm_ioremap_nocache(&pdev->dev,
+ reg_lsb->start, resource_size(reg_lsb));
+ if (!avtimer.p_avtimer_lsw) {
+ dev_err(&pdev->dev, "%s: ioremap failed for lsb avtimer register",
+ __func__);
+ return -ENOMEM;
+ }
+
+ avtimer.p_avtimer_msw = devm_ioremap_nocache(&pdev->dev,
+ reg_msb->start, resource_size(reg_msb));
+ if (!avtimer.p_avtimer_msw) {
+ dev_err(&pdev->dev, "%s: ioremap failed for msb avtimer register",
+ __func__);
+ goto unmap;
+ }
/* get the device number */
if (major)
result = register_chrdev_region(dev, 1, DEVICE_NAME);
@@ -275,68 +360,84 @@
}
if (result < 0) {
- pr_err("Registering avtimer device failed\n");
- return result;
+ pr_err("%s: Registering avtimer device failed\n", __func__);
+ goto unmap;
}
- pavtimer->avtimer_class = class_create(THIS_MODULE, "avtimer");
- if (IS_ERR(pavtimer->avtimer_class)) {
- result = PTR_ERR(pavtimer->avtimer_class);
- pr_err("Error creating avtimer class: %d\n", result);
+ avtimer.avtimer_class = class_create(THIS_MODULE, "avtimer");
+ if (IS_ERR(avtimer.avtimer_class)) {
+ result = PTR_ERR(avtimer.avtimer_class);
+ pr_err("%s: Error creating avtimer class: %d\n",
+ __func__, result);
goto unregister_chrdev_region;
}
- pavtimer->avtimer_pdata = pdev->dev.platform_data;
- cdev_init(&pavtimer->myc, &avtimer_fops);
- result = cdev_add(&pavtimer->myc, dev, 1);
+ cdev_init(&avtimer.myc, &avtimer_fops);
+ result = cdev_add(&avtimer.myc, dev, 1);
if (result < 0) {
- pr_err("Registering file operations failed\n");
+ pr_err("%s: Registering file operations failed\n", __func__);
goto class_destroy;
}
- device_handle = device_create(pavtimer->avtimer_class,
- NULL, pavtimer->myc.dev, NULL, "avtimer");
+ device_handle = device_create(avtimer.avtimer_class,
+ NULL, avtimer.myc.dev, NULL, "avtimer");
if (IS_ERR(device_handle)) {
result = PTR_ERR(device_handle);
- pr_err("device_create failed: %d\n", result);
+ pr_err("%s: device_create failed: %d\n", __func__, result);
goto class_destroy;
}
+ init_waitqueue_head(&avtimer.adsp_resp_wait);
+ mutex_init(&avtimer.avtimer_lock);
+ avtimer.avtimer_open_cnt = 0;
- mutex_init(&pavtimer->avtimer_lock);
- core_handle = NULL;
- pavtimer->avtimer_open_cnt = 0;
-
- pr_debug("Device create done for avtimer major=%d\n", major);
+ pr_debug("%s: Device create done for avtimer major=%d\n",
+ __func__, major);
return 0;
class_destroy:
- class_destroy(pavtimer->avtimer_class);
+ class_destroy(avtimer.avtimer_class);
unregister_chrdev_region:
unregister_chrdev_region(MKDEV(major, 0), 1);
+unmap:
+ if (avtimer.p_avtimer_lsw)
+ devm_iounmap(&pdev->dev, avtimer.p_avtimer_lsw);
+ if (avtimer.p_avtimer_msw)
+ devm_iounmap(&pdev->dev, avtimer.p_avtimer_msw);
+ avtimer.p_avtimer_lsw = NULL;
+ avtimer.p_avtimer_msw = NULL;
return result;
}
static int __devexit dev_avtimer_remove(struct platform_device *pdev)
{
- struct avtimer_t *pavtimer = &avtimer;
+ pr_debug("%s: dev_avtimer_remove\n", __func__);
- pr_debug("dev_avtimer_remove\n");
-
- device_destroy(pavtimer->avtimer_class, pavtimer->myc.dev);
- cdev_del(&pavtimer->myc);
- class_destroy(pavtimer->avtimer_class);
+ if (avtimer.p_avtimer_lsw)
+ devm_iounmap(&pdev->dev, avtimer.p_avtimer_lsw);
+ if (avtimer.p_avtimer_msw)
+ devm_iounmap(&pdev->dev, avtimer.p_avtimer_msw);
+ device_destroy(avtimer.avtimer_class, avtimer.myc.dev);
+ cdev_del(&avtimer.myc);
+ class_destroy(avtimer.avtimer_class);
unregister_chrdev_region(MKDEV(major, 0), 1);
return 0;
}
+static const struct of_device_id avtimer_machine_of_match[] = {
+ { .compatible = "qcom,avtimer", },
+ {},
+};
static struct platform_driver dev_avtimer_driver = {
.probe = dev_avtimer_probe,
- .remove = __exit_p(dev_avtimer_remove),
- .driver = {.name = "dev_avtimer"}
+ .remove = dev_avtimer_remove,
+ .driver = {
+ .name = "dev_avtimer",
+ .of_match_table = avtimer_machine_of_match,
+ },
};
static int __init avtimer_init(void)
@@ -344,21 +445,21 @@
s32 rc;
rc = platform_driver_register(&dev_avtimer_driver);
if (IS_ERR_VALUE(rc)) {
- pr_err("platform_driver_register failed.\n");
+ pr_err("%s: platform_driver_register failed\n", __func__);
goto error_platform_driver;
}
- pr_debug("dev_avtimer_init : done\n");
+ pr_debug("%s: dev_avtimer_init : done\n", __func__);
return 0;
error_platform_driver:
- pr_err("encounterd error\n");
- return -ENODEV;
+ pr_err("%s: encounterd error\n", __func__);
+ return rc;
}
static void __exit avtimer_exit(void)
{
- pr_debug("avtimer_exit\n");
+ pr_debug("%s: avtimer_exit\n", __func__);
platform_driver_unregister(&dev_avtimer_driver);
}
diff --git a/drivers/spi/spi_qsd.c b/drivers/spi/spi_qsd.c
index d8dc6f9..5686107 100644
--- a/drivers/spi/spi_qsd.c
+++ b/drivers/spi/spi_qsd.c
@@ -854,19 +854,6 @@
dd->bam.curr_rx_bytes_recvd += data_xfr_size;
*bytes_to_send -= data_xfr_size;
dd->bam.bam_rx_len -= data_xfr_size;
-
- if (!(dd->cur_rx_transfer->len - dd->bam.curr_rx_bytes_recvd)) {
- struct spi_transfer *t = dd->cur_rx_transfer;
- struct spi_transfer *next;
- if (t->transfer_list.next != &dd->cur_msg->transfers) {
- next = list_entry(t->transfer_list.next,
- struct spi_transfer,
- transfer_list);
- dd->read_buf = next->rx_buf;
- dd->cur_rx_transfer = next;
- dd->bam.curr_rx_bytes_recvd = 0;
- }
- }
return data_xfr_size;
}
@@ -904,19 +891,6 @@
dd->bam.curr_tx_bytes_sent += data_xfr_size;
*bytes_to_send -= data_xfr_size;
dd->bam.bam_tx_len -= data_xfr_size;
-
- if (!(dd->cur_tx_transfer->len - dd->bam.curr_tx_bytes_sent)) {
- struct spi_transfer *t = dd->cur_tx_transfer;
- struct spi_transfer *next;
- if (t->transfer_list.next != &dd->cur_msg->transfers) {
- next = list_entry(t->transfer_list.next,
- struct spi_transfer,
- transfer_list);
- dd->write_buf = next->tx_buf;
- dd->cur_tx_transfer = next;
- dd->bam.curr_tx_bytes_sent = 0;
- }
- }
return data_xfr_size;
}
@@ -939,7 +913,6 @@
u32 cons_desc_cnt = SPI_BAM_MAX_DESC_NUM - 1;
u32 byte_count = 0;
-
rx_bytes_to_recv = min_t(u32, dd->bam.bam_rx_len,
SPI_MAX_TRFR_BTWN_RESETS);
tx_bytes_to_send = min_t(u32, dd->bam.bam_tx_len,
@@ -958,11 +931,17 @@
while ((rx_bytes_to_recv + tx_bytes_to_send) &&
((cons_desc_cnt + prod_desc_cnt) > 0)) {
+ struct spi_transfer *t = NULL, *next;
+
if (dd->read_buf && (prod_desc_cnt > 0)) {
ret = msm_spi_bam_process_rx(dd, &rx_bytes_to_recv,
prod_desc_cnt);
if (ret < 0)
goto xfr_err;
+
+ if (!(dd->cur_rx_transfer->len
+ - dd->bam.curr_rx_bytes_recvd))
+ t = dd->cur_rx_transfer;
prod_desc_cnt--;
}
@@ -971,8 +950,25 @@
cons_desc_cnt);
if (ret < 0)
goto xfr_err;
+
+ if (!(dd->cur_tx_transfer->len
+ - dd->bam.curr_tx_bytes_sent))
+ t = dd->cur_tx_transfer;
cons_desc_cnt--;
}
+
+ if (t && (t->transfer_list.next != &dd->cur_msg->transfers)) {
+ next = list_entry(t->transfer_list.next,
+ struct spi_transfer,
+ transfer_list);
+ dd->read_buf = next->rx_buf;
+ dd->write_buf = next->tx_buf;
+ dd->cur_rx_transfer = next;
+ dd->cur_tx_transfer = next;
+ dd->bam.curr_rx_bytes_recvd = 0;
+ dd->bam.curr_tx_bytes_sent = 0;
+ }
+
byte_count += ret;
}
@@ -1918,9 +1914,12 @@
goto transfer_end;
msm_spi_start_write(dd, read_count);
} else if (dd->mode == SPI_BAM_MODE) {
- if ((msm_spi_bam_begin_transfer(dd)) < 0)
+ if ((msm_spi_bam_begin_transfer(dd)) < 0) {
dev_err(dd->dev, "%s: BAM transfer setup failed\n",
__func__);
+ dd->cur_msg->status = -EIO;
+ goto transfer_end;
+ }
}
/*
@@ -1960,6 +1959,8 @@
msm_spi_udelay(dd->xfrs_delay_usec);
transfer_end:
+ if (dd->mode == SPI_BAM_MODE)
+ msm_spi_bam_flush(dd);
msm_spi_dma_unmap_buffers(dd);
dd->mode = SPI_MODE_NONE;
diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c
index 159121f..e0b066a 100644
--- a/drivers/staging/android/binder.c
+++ b/drivers/staging/android/binder.c
@@ -1404,6 +1404,7 @@
struct binder_transaction *t;
struct binder_work *tcomplete;
size_t *offp, *off_end;
+ size_t off_min;
struct binder_proc *target_proc;
struct binder_thread *target_thread = NULL;
struct binder_node *target_node = NULL;
@@ -1604,18 +1605,23 @@
goto err_bad_offset;
}
off_end = (void *)offp + tr->offsets_size;
+ off_min = 0;
for (; offp < off_end; offp++) {
struct flat_binder_object *fp;
if (*offp > t->buffer->data_size - sizeof(*fp) ||
+ *offp < off_min ||
t->buffer->data_size < sizeof(*fp) ||
- !IS_ALIGNED(*offp, sizeof(void *))) {
- binder_user_error("binder: %d:%d got transaction with "
- "invalid offset, %zd\n",
- proc->pid, thread->pid, *offp);
+ !IS_ALIGNED(*offp, sizeof(u32))) {
+ binder_user_error("%d:%d got transaction with invalid offset, %lld (min %lld, max %lld)\n",
+ proc->pid, thread->pid, (u64)*offp,
+ (u64)off_min,
+ (u64)(t->buffer->data_size -
+ sizeof(*fp)));
return_error = BR_FAILED_REPLY;
goto err_bad_offset;
}
fp = (struct flat_binder_object *)(t->buffer->data + *offp);
+ off_min = *offp + sizeof(struct flat_binder_object);
switch (fp->type) {
case BINDER_TYPE_BINDER:
case BINDER_TYPE_WEAK_BINDER: {
diff --git a/drivers/tty/serial/msm_serial_hs.c b/drivers/tty/serial/msm_serial_hs.c
index a6c60ce..6be6599 100644
--- a/drivers/tty/serial/msm_serial_hs.c
+++ b/drivers/tty/serial/msm_serial_hs.c
@@ -62,8 +62,6 @@
#include <asm/atomic.h>
#include <asm/irq.h>
-#include <mach/hardware.h>
-#include <mach/dma.h>
#include <mach/sps.h>
#include <mach/msm_serial_hs.h>
#include <mach/msm_bus.h>
@@ -176,11 +174,6 @@
unsigned int dma_in_flight; /* tx dma in progress */
enum flush_reason flush;
wait_queue_head_t wait;
- struct msm_dmov_cmd xfer;
- dmov_box *command_ptr;
- u32 *command_ptr_ptr;
- dma_addr_t mapped_cmd_ptr;
- dma_addr_t mapped_cmd_ptr_ptr;
int tx_count;
dma_addr_t dma_base;
struct tasklet_struct tlet;
@@ -189,11 +182,6 @@
struct msm_hs_rx {
enum flush_reason flush;
- struct msm_dmov_cmd xfer;
- dma_addr_t cmdptr_dmaaddr;
- dmov_box *command_ptr;
- u32 *command_ptr_ptr;
- dma_addr_t mapped_cmd_ptr;
wait_queue_head_t wait;
dma_addr_t rbuffer;
unsigned char *buffer;
@@ -230,14 +218,6 @@
struct clk *pclk;
struct msm_hs_tx tx;
struct msm_hs_rx rx;
- /* gsbi uarts have to do additional writes to gsbi memory */
- /* block and top control status block. The following pointers */
- /* keep a handle to these blocks. */
- unsigned char __iomem *mapped_gsbi;
- int dma_tx_channel;
- int dma_rx_channel;
- int dma_tx_crci;
- int dma_rx_crci;
struct hrtimer clk_off_timer; /* to poll TXEMT before clock off */
ktime_t clk_off_delay;
enum msm_hs_clk_states_e clk_state;
@@ -266,70 +246,15 @@
u32 bus_perf_client;
/* BLSP UART required BUS Scaling data */
struct msm_bus_scale_pdata *bus_scale_table;
- bool rx_discard_flush_issued;
int rx_count_callback;
bool rx_bam_inprogress;
- unsigned int *reg_ptr;
wait_queue_head_t bam_disconnect_wait;
};
-unsigned int regmap_nonblsp[UART_DM_LAST] = {
- [UART_DM_MR1] = UARTDM_MR1_ADDR,
- [UART_DM_MR2] = UARTDM_MR2_ADDR,
- [UART_DM_IMR] = UARTDM_IMR_ADDR,
- [UART_DM_SR] = UARTDM_SR_ADDR,
- [UART_DM_CR] = UARTDM_CR_ADDR,
- [UART_DM_CSR] = UARTDM_CSR_ADDR,
- [UART_DM_IPR] = UARTDM_IPR_ADDR,
- [UART_DM_ISR] = UARTDM_ISR_ADDR,
- [UART_DM_RX_TOTAL_SNAP] = UARTDM_RX_TOTAL_SNAP_ADDR,
- [UART_DM_TFWR] = UARTDM_TFWR_ADDR,
- [UART_DM_RFWR] = UARTDM_RFWR_ADDR,
- [UART_DM_RF] = UARTDM_RF_ADDR,
- [UART_DM_TF] = UARTDM_TF_ADDR,
- [UART_DM_MISR] = UARTDM_MISR_ADDR,
- [UART_DM_DMRX] = UARTDM_DMRX_ADDR,
- [UART_DM_NCF_TX] = UARTDM_NCF_TX_ADDR,
- [UART_DM_DMEN] = UARTDM_DMEN_ADDR,
- [UART_DM_TXFS] = UARTDM_TXFS_ADDR,
- [UART_DM_RXFS] = UARTDM_RXFS_ADDR,
- [UART_DM_RX_TRANS_CTRL] = UARTDM_RX_TRANS_CTRL_ADDR,
-};
-
-unsigned int regmap_blsp[UART_DM_LAST] = {
- [UART_DM_MR1] = 0x0,
- [UART_DM_MR2] = 0x4,
- [UART_DM_IMR] = 0xb0,
- [UART_DM_SR] = 0xa4,
- [UART_DM_CR] = 0xa8,
- [UART_DM_CSR] = 0xa0,
- [UART_DM_IPR] = 0x18,
- [UART_DM_ISR] = 0xb4,
- [UART_DM_RX_TOTAL_SNAP] = 0xbc,
- [UART_DM_TFWR] = 0x1c,
- [UART_DM_RFWR] = 0x20,
- [UART_DM_RF] = 0x140,
- [UART_DM_TF] = 0x100,
- [UART_DM_MISR] = 0xac,
- [UART_DM_DMRX] = 0x34,
- [UART_DM_NCF_TX] = 0x40,
- [UART_DM_DMEN] = 0x3c,
- [UART_DM_TXFS] = 0x4c,
- [UART_DM_RXFS] = 0x50,
- [UART_DM_RX_TRANS_CTRL] = 0xcc,
- [UART_DM_BCR] = 0xc8,
-};
-
static struct of_device_id msm_hs_match_table[] = {
{ .compatible = "qcom,msm-hsuart-v14",
- .data = regmap_blsp
},
- {
- .compatible = "qcom,msm-hsuart-v13",
- .data = regmap_nonblsp
- },
- {}
};
@@ -404,30 +329,34 @@
{
int rc = 0;
+ mutex_lock(&msm_uport->clk_mutex);
if (1 == atomic_inc_return(&msm_uport->clk_count)) {
msm_hs_bus_voting(msm_uport, BUS_SCALING);
/* Turn on core clk and iface clk */
+ if (msm_uport->pclk) {
+ rc = clk_prepare_enable(msm_uport->pclk);
+ if (rc) {
+ dev_err(msm_uport->uport.dev,
+ "%s: Could not turn on pclk [%d]\n",
+ __func__, rc);
+ mutex_unlock(&msm_uport->clk_mutex);
+ return rc;
+ }
+ }
+
rc = clk_prepare_enable(msm_uport->clk);
if (rc) {
dev_err(msm_uport->uport.dev,
"%s: Could not turn on core clk [%d]\n",
__func__, rc);
+ clk_disable_unprepare(msm_uport->pclk);
+ mutex_unlock(&msm_uport->clk_mutex);
return rc;
}
-
- if (msm_uport->pclk) {
- rc = clk_prepare_enable(msm_uport->pclk);
- if (rc) {
- clk_disable_unprepare(msm_uport->clk);
- dev_err(msm_uport->uport.dev,
- "%s: Could not turn on pclk [%d]\n",
- __func__, rc);
- return rc;
- }
- }
msm_uport->clk_state = MSM_HS_CLK_ON;
MSM_HS_DBG("%s: Clock ON successful\n", __func__);
}
+ mutex_unlock(&msm_uport->clk_mutex);
return rc;
@@ -444,6 +373,7 @@
return;
}
+ mutex_lock(&msm_uport->clk_mutex);
rc = atomic_dec_return(&msm_uport->clk_count);
if (0 == rc) {
/* Turn off the core clk and iface clk*/
@@ -455,6 +385,7 @@
msm_uport->clk_state = MSM_HS_CLK_OFF;
MSM_HS_DBG("%s: Clock OFF successful\n", __func__);
}
+ mutex_unlock(&msm_uport->clk_mutex);
}
/* Check if the uport line number matches with user id stored in pdata.
@@ -536,21 +467,11 @@
return (msm_uport->wakeup.irq > 0);
}
-static inline int is_gsbi_uart(struct msm_hs_port *msm_uport)
-{
- /* assume gsbi uart if gsbi resource found in pdata */
- return ((msm_uport->mapped_gsbi != NULL));
-}
-static unsigned int is_blsp_uart(struct msm_hs_port *msm_uport)
-{
- return (msm_uport->uart_type == BLSP_HSUART);
-}
-
static void msm_hs_bus_voting(struct msm_hs_port *msm_uport, unsigned int vote)
{
int ret;
- if (is_blsp_uart(msm_uport) && msm_uport->bus_perf_client) {
+ if (msm_uport->bus_perf_client) {
MSM_HS_DBG("Bus voting:%d\n", vote);
ret = msm_bus_scale_client_update_request(
msm_uport->bus_perf_client, vote);
@@ -563,22 +484,13 @@
static inline unsigned int msm_hs_read(struct uart_port *uport,
unsigned int index)
{
- struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
- unsigned int offset;
-
- offset = *(msm_uport->reg_ptr + index);
-
- return readl_relaxed(uport->membase + offset);
+ return readl_relaxed(uport->membase + index);
}
static inline void msm_hs_write(struct uart_port *uport, unsigned int index,
unsigned int value)
{
- struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
- unsigned int offset;
-
- offset = *(msm_uport->reg_ptr + index);
- writel_relaxed(value, uport->membase + offset);
+ writel_relaxed(value, uport->membase + index);
}
static int sps_rx_disconnect(struct sps_pipe *sps_pipe_handler)
@@ -642,55 +554,6 @@
MSM_HS_DBG("clk_state:%d", msm_uport->clk_state);
}
-static void msm_hs_release_port(struct uart_port *port)
-{
- struct msm_hs_port *msm_uport = UARTDM_TO_MSM(port);
- struct platform_device *pdev = to_platform_device(port->dev);
- struct resource *gsbi_resource;
- resource_size_t size;
-
- if (is_gsbi_uart(msm_uport)) {
- iowrite32(GSBI_PROTOCOL_IDLE, msm_uport->mapped_gsbi +
- GSBI_CONTROL_ADDR);
- gsbi_resource = platform_get_resource_byname(pdev,
- IORESOURCE_MEM,
- "gsbi_resource");
- if (unlikely(!gsbi_resource))
- return;
-
- size = resource_size(gsbi_resource);
- release_mem_region(gsbi_resource->start, size);
- iounmap(msm_uport->mapped_gsbi);
- msm_uport->mapped_gsbi = NULL;
- }
-}
-
-static int msm_hs_request_port(struct uart_port *port)
-{
- struct msm_hs_port *msm_uport = UARTDM_TO_MSM(port);
- struct platform_device *pdev = to_platform_device(port->dev);
- struct resource *gsbi_resource;
- resource_size_t size;
-
- gsbi_resource = platform_get_resource_byname(pdev,
- IORESOURCE_MEM,
- "gsbi_resource");
- if (gsbi_resource) {
- size = resource_size(gsbi_resource);
- if (unlikely(!request_mem_region(gsbi_resource->start, size,
- "msm_serial_hs")))
- return -EBUSY;
- msm_uport->mapped_gsbi = ioremap(gsbi_resource->start,
- size);
- if (!msm_uport->mapped_gsbi) {
- release_mem_region(gsbi_resource->start, size);
- return -EBUSY;
- }
- }
- /* no gsbi uart */
- return 0;
-}
-
static int msm_serial_loopback_enable_set(void *data, u64 val)
{
struct msm_hs_port *msm_uport = data;
@@ -703,21 +566,15 @@
if (val) {
spin_lock_irqsave(&uport->lock, flags);
ret = msm_hs_read(uport, UART_DM_MR2);
- if (is_blsp_uart(msm_uport))
- ret |= (UARTDM_MR2_LOOP_MODE_BMSK |
- UARTDM_MR2_RFR_CTS_LOOP_MODE_BMSK);
- else
- ret |= UARTDM_MR2_LOOP_MODE_BMSK;
+ ret |= (UARTDM_MR2_LOOP_MODE_BMSK |
+ UARTDM_MR2_RFR_CTS_LOOP_MODE_BMSK);
msm_hs_write(uport, UART_DM_MR2, ret);
spin_unlock_irqrestore(&uport->lock, flags);
} else {
spin_lock_irqsave(&uport->lock, flags);
ret = msm_hs_read(uport, UART_DM_MR2);
- if (is_blsp_uart(msm_uport))
- ret &= ~(UARTDM_MR2_LOOP_MODE_BMSK |
- UARTDM_MR2_RFR_CTS_LOOP_MODE_BMSK);
- else
- ret &= ~UARTDM_MR2_LOOP_MODE_BMSK;
+ ret &= ~(UARTDM_MR2_LOOP_MODE_BMSK |
+ UARTDM_MR2_RFR_CTS_LOOP_MODE_BMSK);
msm_hs_write(uport, UART_DM_MR2, ret);
spin_unlock_irqrestore(&uport->lock, flags);
}
@@ -791,19 +648,10 @@
sysfs_remove_file(&pdev->dev.kobj, &dev_attr_clock.attr);
debugfs_remove(msm_uport->loopback_dir);
- dma_unmap_single(dev, msm_uport->rx.mapped_cmd_ptr, sizeof(dmov_box),
- DMA_TO_DEVICE);
dma_pool_free(msm_uport->rx.pool, msm_uport->rx.buffer,
msm_uport->rx.rbuffer);
dma_pool_destroy(msm_uport->rx.pool);
- dma_unmap_single(dev, msm_uport->rx.cmdptr_dmaaddr, sizeof(u32),
- DMA_TO_DEVICE);
- dma_unmap_single(dev, msm_uport->tx.mapped_cmd_ptr_ptr, sizeof(u32),
- DMA_TO_DEVICE);
- dma_unmap_single(dev, msm_uport->tx.mapped_cmd_ptr, sizeof(dmov_box),
- DMA_TO_DEVICE);
-
wake_lock_destroy(&msm_uport->rx.wake_lock);
wake_lock_destroy(&msm_uport->dma_wake_lock);
destroy_workqueue(msm_uport->hsuart_wq);
@@ -814,14 +662,6 @@
if (msm_uport->pclk)
clk_put(msm_uport->pclk);
- /* Free the tx resources */
- kfree(msm_uport->tx.command_ptr);
- kfree(msm_uport->tx.command_ptr_ptr);
-
- /* Free the rx resources */
- kfree(msm_uport->rx.command_ptr);
- kfree(msm_uport->rx.command_ptr_ptr);
-
iounmap(msm_uport->uport.membase);
return 0;
@@ -873,14 +713,14 @@
ret = sps_connect(sps_pipe_handle, sps_config);
if (ret) {
MSM_HS_ERR("msm_serial_hs: sps_connect() failed for tx!!\n"
- "pipe_handle=0x%x ret=%d", (u32)sps_pipe_handle, ret);
+ "pipe_handle=0x%p ret=%d", sps_pipe_handle, ret);
return ret;
}
/* Register callback event for EOT (End of transfer) event. */
ret = sps_register_event(sps_pipe_handle, sps_event);
if (ret) {
MSM_HS_ERR("msm_serial_hs: sps_connect() failed for tx!!\n"
- "pipe_handle=0x%x ret=%d", (u32)sps_pipe_handle, ret);
+ "pipe_handle=0x%p ret=%d", sps_pipe_handle, ret);
goto reg_event_err;
}
return 0;
@@ -914,14 +754,14 @@
ret = sps_connect(sps_pipe_handle, sps_config);
if (ret) {
MSM_HS_ERR("msm_serial_hs: sps_connect() failed for rx!!\n"
- "pipe_handle=0x%x ret=%d", (u32)sps_pipe_handle, ret);
+ "pipe_handle=0x%p ret=%d", sps_pipe_handle, ret);
return ret;
}
/* Register callback event for DESC_DONE event. */
ret = sps_register_event(sps_pipe_handle, sps_event);
if (ret) {
MSM_HS_ERR("msm_serial_hs: sps_connect() failed for rx!!\n"
- "pipe_handle=0x%x ret=%d", (u32)sps_pipe_handle, ret);
+ "pipe_handle=0x%p ret=%d", sps_pipe_handle, ret);
goto reg_event_err;
}
return 0;
@@ -1037,17 +877,15 @@
mb();
if (bps > 460800) {
uport->uartclk = bps * 16;
- if (is_blsp_uart(msm_uport)) {
- /* BLSP based UART supports maximum clock frequency
- * of 63.16 Mhz. With this (63.16 Mhz) clock frequency
- * UART can support baud rate of 3.94 Mbps which is
- * equivalent to 4 Mbps.
- * UART hardware is robust enough to handle this
- * deviation to achieve baud rate ~4 Mbps.
- */
- if (bps == 4000000)
- uport->uartclk = BLSP_UART_CLK_FMAX;
- }
+ /* BLSP based UART supports maximum clock frequency
+ * of 63.16 Mhz. With this (63.16 Mhz) clock frequency
+ * UART can support baud rate of 3.94 Mbps which is
+ * equivalent to 4 Mbps.
+ * UART hardware is robust enough to handle this
+ * deviation to achieve baud rate ~4 Mbps.
+ */
+ if (bps == 4000000)
+ uport->uartclk = BLSP_UART_CLK_FMAX;
} else {
uport->uartclk = 7372800;
}
@@ -1139,10 +977,12 @@
struct msm_hs_rx *rx = &msm_uport->rx;
struct sps_pipe *sps_pipe_handle = rx->prod.pipe_handle;
- if (msm_uport->clk_state != MSM_HS_CLK_ON) {
- MSM_HS_WARN("%s: Failed.Clocks are OFF\n", __func__);
- return;
- }
+ /**
+ * set_termios can be invoked from the framework when
+ * the clocks are off and the client has not had a chance
+ * to turn them on. Make sure that they are on
+ */
+ msm_hs_clock_vote(msm_uport);
mutex_lock(&msm_uport->clk_mutex);
msm_hs_write(uport, UART_DM_IMR, 0);
@@ -1169,12 +1009,8 @@
* suggested to do disable/reset or reset/disable at the same time.
*/
data = msm_hs_read(uport, UART_DM_DMEN);
- if (is_blsp_uart(msm_uport)) {
- /* Disable UARTDM RX BAM Interface */
- data &= ~UARTDM_RX_BAM_ENABLE_BMSK;
- } else {
- data &= ~UARTDM_RX_DM_EN_BMSK;
- }
+ /* Disable UARTDM RX BAM Interface */
+ data &= ~UARTDM_RX_BAM_ENABLE_BMSK;
msm_hs_write(uport, UART_DM_DMEN, data);
@@ -1250,37 +1086,18 @@
if (msm_uport->rx.flush == FLUSH_NONE) {
wake_lock(&msm_uport->rx.wake_lock);
msm_uport->rx.flush = FLUSH_DATA_INVALID;
- /*
- * Before using dmov APIs make sure that
- * previous writel are completed. Hence
- * dsb requires here.
- */
mb();
- if (is_blsp_uart(msm_uport)) {
- if (msm_uport->rx_bam_inprogress)
- ret = wait_event_timeout(msm_uport->rx.wait,
- msm_uport->rx_bam_inprogress == false,
- RX_FLUSH_COMPLETE_TIMEOUT);
- ret = sps_rx_disconnect(sps_pipe_handle);
- if (ret)
- MSM_HS_ERR("%s(): sps_disconnect failed\n",
- __func__);
- msm_hs_spsconnect_rx(uport);
- msm_uport->rx.flush = FLUSH_IGNORE;
- msm_serial_hs_rx_tlet((unsigned long) &rx->tlet);
- } else {
- msm_uport->rx_discard_flush_issued = true;
- /* do discard flush */
- msm_dmov_flush(msm_uport->dma_rx_channel, 0);
- MSM_HS_DBG("%s(): wainting for flush completion.\n",
- __func__);
+ if (msm_uport->rx_bam_inprogress)
ret = wait_event_timeout(msm_uport->rx.wait,
- msm_uport->rx_discard_flush_issued == false,
+ msm_uport->rx_bam_inprogress == false,
RX_FLUSH_COMPLETE_TIMEOUT);
- if (!ret)
- MSM_HS_ERR("%s(): Discard flush pending.\n",
- __func__);
- }
+ ret = sps_rx_disconnect(sps_pipe_handle);
+ if (ret)
+ MSM_HS_ERR("%s(): sps_disconnect failed\n",
+ __func__);
+ msm_hs_spsconnect_rx(uport);
+ msm_uport->rx.flush = FLUSH_IGNORE;
+ msm_serial_hs_rx_tlet((unsigned long) &rx->tlet);
}
/* Configure HW flow control
@@ -1302,6 +1119,7 @@
mutex_unlock(&msm_uport->clk_mutex);
MSM_HS_DBG("Exit %s\n", __func__);
dump_uart_hs_registers(msm_uport);
+ msm_hs_clock_unvote(msm_uport);
}
/*
@@ -1343,15 +1161,25 @@
{
struct msm_hs_port *msm_uport = container_of(w, struct msm_hs_port,
disconnect_rx_endpoint);
+ struct uart_port *uport = &msm_uport->uport;
struct msm_hs_rx *rx = &msm_uport->rx;
struct sps_pipe *sps_pipe_handle = rx->prod.pipe_handle;
+ struct platform_device *pdev = to_platform_device(uport->dev);
+ const struct msm_serial_hs_platform_data *pdata =
+ pdev->dev.platform_data;
int ret = 0;
+ msm_hs_clock_vote(msm_uport);
ret = sps_rx_disconnect(sps_pipe_handle);
+ msm_hs_clock_unvote(msm_uport);
+
if (ret)
MSM_HS_ERR("%s(): sps_disconnect failed\n", __func__);
-
- wake_lock_timeout(&msm_uport->rx.wake_lock, HZ / 2);
+ if (pdata->no_suspend_delay)
+ wake_unlock(&msm_uport->rx.wake_lock);
+ else
+ wake_lock_timeout(&msm_uport->rx.wake_lock,
+ HZ / 2);
msm_uport->rx.flush = FLUSH_SHUTDOWN;
MSM_HS_DBG("%s: Calling Completion\n", __func__);
wake_up(&msm_uport->bam_disconnect_wait);
@@ -1376,10 +1204,7 @@
if (msm_uport->clk_state != MSM_HS_CLK_OFF) {
/* disable dlink */
data = msm_hs_read(uport, UART_DM_DMEN);
- if (is_blsp_uart(msm_uport))
- data &= ~UARTDM_RX_BAM_ENABLE_BMSK;
- else
- data &= ~UARTDM_RX_DM_EN_BMSK;
+ data &= ~UARTDM_RX_BAM_ENABLE_BMSK;
msm_hs_write(uport, UART_DM_DMEN, data);
/* calling DMOV or CLOCK API. Hence mb() */
@@ -1388,19 +1213,11 @@
/* Disable the receiver */
if (msm_uport->rx.flush == FLUSH_NONE) {
wake_lock(&msm_uport->rx.wake_lock);
- if (is_blsp_uart(msm_uport)) {
- msm_uport->rx.flush = FLUSH_STOP;
- /* workqueue for BAM rx endpoint disconnect */
- queue_work(msm_uport->hsuart_wq,
- &msm_uport->disconnect_rx_endpoint);
- } else {
- /* do discard flush */
- msm_dmov_flush(msm_uport->dma_rx_channel, 0);
- }
- }
- if (!is_blsp_uart(msm_uport) && msm_uport->rx.flush != FLUSH_SHUTDOWN)
msm_uport->rx.flush = FLUSH_STOP;
-
+ /* workqueue for BAM rx endpoint disconnect */
+ queue_work(msm_uport->hsuart_wq,
+ &msm_uport->disconnect_rx_endpoint);
+ }
}
/* Transmit the next chunk of data */
@@ -1424,6 +1241,7 @@
__func__);
queue_work(msm_uport->hsuart_wq,
&msm_uport->clock_off_w);
+ wake_up(&msm_uport->tx.wait);
}
return;
}
@@ -1450,43 +1268,15 @@
dma_sync_single_for_device(uport->dev, aligned_src_addr,
aligned_tx_count, DMA_TO_DEVICE);
- if (is_blsp_uart(msm_uport))
- tx->tx_count = tx_count;
- else {
- tx->command_ptr->num_rows =
- (((tx_count + 15) >> 4) << 16) |
- ((tx_count + 15) >> 4);
- tx->command_ptr->src_row_addr = src_addr;
-
- dma_sync_single_for_device(uport->dev, tx->mapped_cmd_ptr,
- sizeof(dmov_box), DMA_TO_DEVICE);
-
- *tx->command_ptr_ptr = CMD_PTR_LP |
- DMOV_CMD_ADDR(tx->mapped_cmd_ptr);
- /* Save tx_count to use in Callback */
- tx->tx_count = tx_count;
- msm_hs_write(uport, UART_DM_NCF_TX, tx_count);
- msm_uport->imr_reg &= ~UARTDM_ISR_TX_READY_BMSK;
- msm_hs_write(uport, UART_DM_IMR, msm_uport->imr_reg);
- /* Calling next DMOV API. Hence mb() here. */
- mb();
-
- }
+ tx->tx_count = tx_count;
msm_uport->tx.flush = FLUSH_NONE;
- if (is_blsp_uart(msm_uport)) {
- sps_pipe_handle = tx->cons.pipe_handle;
- /* Queue transfer request to SPS */
- sps_transfer_one(sps_pipe_handle, src_addr, tx_count,
- msm_uport, flags);
- } else {
- dma_sync_single_for_device(uport->dev, tx->mapped_cmd_ptr_ptr,
- sizeof(u32), DMA_TO_DEVICE);
+ sps_pipe_handle = tx->cons.pipe_handle;
+ /* Queue transfer request to SPS */
+ sps_transfer_one(sps_pipe_handle, src_addr, tx_count,
+ msm_uport, flags);
- msm_dmov_enqueue_cmd(msm_uport->dma_tx_channel, &tx->xfer);
-
- }
MSM_HS_DBG("%s:Enqueue Tx Cmd\n", __func__);
dump_uart_hs_registers(msm_uport);
}
@@ -1524,43 +1314,34 @@
* disable in set_termios before configuring baud rate.
*/
data = msm_hs_read(uport, UART_DM_DMEN);
- if (is_blsp_uart(msm_uport)) {
- /* Enable UARTDM Rx BAM Interface */
- data |= UARTDM_RX_BAM_ENABLE_BMSK;
- } else {
- data |= UARTDM_RX_DM_EN_BMSK;
- }
+ /* Enable UARTDM Rx BAM Interface */
+ data |= UARTDM_RX_BAM_ENABLE_BMSK;
msm_hs_write(uport, UART_DM_DMEN, data);
msm_hs_write(uport, UART_DM_IMR, msm_uport->imr_reg);
/* Calling next DMOV API. Hence mb() here. */
mb();
- if (is_blsp_uart(msm_uport)) {
- /*
- * RX-transfer will be automatically re-activated
- * after last data of previous transfer was read.
- */
- data = (RX_STALE_AUTO_RE_EN | RX_TRANS_AUTO_RE_ACTIVATE |
- RX_DMRX_CYCLIC_EN);
- msm_hs_write(uport, UART_DM_RX_TRANS_CTRL, data);
- /* Issue RX BAM Start IFC command */
- msm_hs_write(uport, UART_DM_CR, START_RX_BAM_IFC);
- mb();
- }
+ /*
+ * RX-transfer will be automatically re-activated
+ * after last data of previous transfer was read.
+ */
+ data = (RX_STALE_AUTO_RE_EN | RX_TRANS_AUTO_RE_ACTIVATE |
+ RX_DMRX_CYCLIC_EN);
+ msm_hs_write(uport, UART_DM_RX_TRANS_CTRL, data);
+ /* Issue RX BAM Start IFC command */
+ msm_hs_write(uport, UART_DM_CR, START_RX_BAM_IFC);
+ mb();
msm_uport->rx.flush = FLUSH_NONE;
-
- if (is_blsp_uart(msm_uport)) {
- msm_uport->rx_bam_inprogress = true;
- sps_pipe_handle = rx->prod.pipe_handle;
- /* Queue transfer request to SPS */
- sps_transfer_one(sps_pipe_handle, rx->rbuffer,
- UARTDM_RX_BUF_SIZE, msm_uport, flags);
- msm_uport->rx_bam_inprogress = false;
- msm_uport->rx.rx_cmd_queued = true;
- wake_up(&msm_uport->rx.wait);
- }
+ msm_uport->rx_bam_inprogress = true;
+ sps_pipe_handle = rx->prod.pipe_handle;
+ /* Queue transfer request to SPS */
+ sps_transfer_one(sps_pipe_handle, rx->rbuffer,
+ UARTDM_RX_BUF_SIZE, msm_uport, flags);
+ msm_uport->rx_bam_inprogress = false;
+ msm_uport->rx.rx_cmd_queued = true;
+ wake_up(&msm_uport->rx.wait);
MSM_HS_DBG("%s:Enqueue Rx Cmd\n", __func__);
dump_uart_hs_registers(msm_uport);
}
@@ -1631,6 +1412,8 @@
struct msm_hs_rx *rx;
struct sps_pipe *sps_pipe_handle;
u32 sps_flags = SPS_IOVEC_FLAG_INT;
+ struct platform_device *pdev;
+ const struct msm_serial_hs_platform_data *pdata;
msm_uport = container_of((struct tasklet_struct *)tlet_ptr,
struct msm_hs_port, rx.tlet);
@@ -1638,6 +1421,8 @@
tty = uport->state->port.tty;
notify = &msm_uport->notify;
rx = &msm_uport->rx;
+ pdev = to_platform_device(uport->dev);
+ pdata = pdev->dev.platform_data;
msm_uport->rx.rx_cmd_queued = false;
msm_uport->rx.rx_cmd_exec = false;
@@ -1646,9 +1431,6 @@
spin_lock_irqsave(&uport->lock, flags);
- if (!is_blsp_uart(msm_uport))
- msm_hs_write(uport, UART_DM_CR, STALE_EVENT_DISABLE);
-
MSM_HS_DBG("In %s\n", __func__);
dump_uart_hs_registers(msm_uport);
@@ -1705,16 +1487,7 @@
if (flush >= FLUSH_DATA_INVALID)
goto out;
- if (is_blsp_uart(msm_uport)) {
- rx_count = msm_uport->rx_count_callback;
- } else {
- if (msm_uport->clk_state == MSM_HS_CLK_ON) {
- rx_count = msm_hs_read(uport, UART_DM_RX_TOTAL_SNAP);
- /* order the read of rx.buffer */
- rmb();
- } else
- MSM_HS_WARN("%s: Failed.Clocks are OFF\n", __func__);
- }
+ rx_count = msm_uport->rx_count_callback;
MSM_HS_DBG("%s():[UART_RX]<%d>\n", __func__, rx_count);
hex_dump_ipc("HSUART Read: ", msm_uport->rx.buffer, rx_count);
@@ -1729,20 +1502,16 @@
}
}
if (!msm_uport->rx.buffer_pending && !msm_uport->rx.rx_cmd_queued) {
- if (is_blsp_uart(msm_uport)) {
- msm_uport->rx.flush = FLUSH_NONE;
- msm_uport->rx_bam_inprogress = true;
- sps_pipe_handle = rx->prod.pipe_handle;
- MSM_HS_DBG("Queing bam descriptor\n");
- /* Queue transfer request to SPS */
- sps_transfer_one(sps_pipe_handle, rx->rbuffer,
- UARTDM_RX_BUF_SIZE, msm_uport, sps_flags);
- msm_uport->rx_bam_inprogress = false;
- msm_uport->rx.rx_cmd_queued = true;
- wake_up(&msm_uport->rx.wait);
-
- } else
- msm_hs_start_rx_locked(uport);
+ msm_uport->rx.flush = FLUSH_NONE;
+ msm_uport->rx_bam_inprogress = true;
+ sps_pipe_handle = rx->prod.pipe_handle;
+ MSM_HS_DBG("Queing bam descriptor\n");
+ /* Queue transfer request to SPS */
+ sps_transfer_one(sps_pipe_handle, rx->rbuffer,
+ UARTDM_RX_BUF_SIZE, msm_uport, sps_flags);
+ msm_uport->rx_bam_inprogress = false;
+ msm_uport->rx.rx_cmd_queued = true;
+ wake_up(&msm_uport->rx.wait);
}
out:
if (msm_uport->rx.buffer_pending) {
@@ -1751,8 +1520,12 @@
, msecs_to_jiffies(RETRY_TIMEOUT));
}
/* release wakelock in 500ms, not immediately, because higher layers
- * don't always take wakelocks when they should */
- wake_lock_timeout(&msm_uport->rx.wake_lock, HZ / 2);
+ * don't always take wakelocks when they should
+ */
+ if (pdata->no_suspend_delay)
+ wake_unlock(&msm_uport->rx.wake_lock);
+ else
+ wake_lock_timeout(&msm_uport->rx.wake_lock, HZ / 2);
/* tty_flip_buffer_push() might call msm_hs_start(), so unlock */
spin_unlock_irqrestore(&uport->lock, flags);
if (flush < FLUSH_DATA_INVALID)
@@ -1767,12 +1540,9 @@
if (msm_uport->clk_state != MSM_HS_CLK_ON) {
MSM_HS_WARN("%s: Failed.Clocks are OFF\n", __func__);
}
- if (msm_uport->tx.tx_ready_int_en == 0) {
- if (!is_blsp_uart(msm_uport))
- msm_uport->tx.tx_ready_int_en = 1;
- if (msm_uport->tx.dma_in_flight == 0)
+ if ((msm_uport->tx.tx_ready_int_en == 0) &&
+ (msm_uport->tx.dma_in_flight == 0))
msm_hs_submit_tx_locked(uport);
- }
}
/**
@@ -1792,7 +1562,7 @@
msm_uport->notify = *notify;
MSM_HS_DBG("%s: ev_id=%d, addr=0x%x, size=0x%x, flags=0x%x, line=%d\n",
- __func__, notify->event_id,
+ __func__, notify->event_id,
notify->data.transfer.iovec.addr,
notify->data.transfer.iovec.size,
notify->data.transfer.iovec.flags,
@@ -1801,30 +1571,6 @@
tasklet_schedule(&msm_uport->tx.tlet);
}
-/*
- * This routine is called when we are done with a DMA transfer
- *
- * This routine is registered with Data mover when we set
- * up a Data Mover transfer. It is called from Data mover ISR
- * when the DMA transfer is done.
- */
-static void msm_hs_dmov_tx_callback(struct msm_dmov_cmd *cmd_ptr,
- unsigned int result,
- struct msm_dmov_errdata *err)
-{
- struct msm_hs_port *msm_uport;
-
- msm_uport = container_of(cmd_ptr, struct msm_hs_port, tx.xfer);
- if (msm_uport->tx.flush == FLUSH_STOP)
- /* DMA FLUSH unsuccesfful */
- WARN_ON(!(result & DMOV_RSLT_FLUSH));
- else
- /* DMA did not finish properly */
- WARN_ON(!(result & DMOV_RSLT_DONE));
-
- tasklet_schedule(&msm_uport->tx.tlet);
-}
-
static void msm_serial_hs_tx_tlet(unsigned long tlet_ptr)
{
unsigned long flags;
@@ -1868,15 +1614,6 @@
return;
}
- /* TX_READY_BMSK only if non BAM mode */
- if (!is_blsp_uart(msm_uport)) {
- msm_uport->imr_reg |= UARTDM_ISR_TX_READY_BMSK;
- msm_hs_write(&(msm_uport->uport), UART_DM_IMR,
- msm_uport->imr_reg);
- /* Calling clk API. Hence mb() requires. */
- mb();
- }
-
spin_unlock_irqrestore(&(msm_uport->uport.lock), flags);
MSM_HS_DBG("In %s()\n", __func__);
dump_uart_hs_registers(msm_uport);
@@ -1918,39 +1655,6 @@
}
/*
- * This routine is called when we are done with a DMA transfer or the
- * a flush has been sent to the data mover driver.
- *
- * This routine is registered with Data mover when we set up a Data Mover
- * transfer. It is called from Data mover ISR when the DMA transfer is done.
- */
-static void msm_hs_dmov_rx_callback(struct msm_dmov_cmd *cmd_ptr,
- unsigned int result,
- struct msm_dmov_errdata *err)
-{
- struct msm_hs_port *msm_uport;
- struct uart_port *uport;
- unsigned long flags;
-
- msm_uport = container_of(cmd_ptr, struct msm_hs_port, rx.xfer);
- uport = &(msm_uport->uport);
-
- MSM_HS_DBG("%s(): called result:%x\n", __func__, result);
- if (!(result & DMOV_RSLT_ERROR)) {
- if (result & DMOV_RSLT_FLUSH) {
- if (msm_uport->rx_discard_flush_issued) {
- spin_lock_irqsave(&uport->lock, flags);
- msm_uport->rx_discard_flush_issued = false;
- spin_unlock_irqrestore(&uport->lock, flags);
- wake_up(&msm_uport->rx.wait);
- }
- }
- }
-
- tasklet_schedule(&msm_uport->rx.tlet);
-}
-
-/*
* Standard API, Current states of modem control inputs
*
* Since CTS can be handled entirely by HARDWARE we always
@@ -2060,24 +1764,9 @@
static void msm_hs_config_port(struct uart_port *uport, int cfg_flags)
{
- unsigned long flags;
- struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
-
- if (cfg_flags & UART_CONFIG_TYPE) {
+ if (cfg_flags & UART_CONFIG_TYPE)
uport->type = PORT_MSM;
- msm_hs_request_port(uport);
- }
- if (is_gsbi_uart(msm_uport)) {
- if (msm_uport->pclk)
- clk_prepare_enable(msm_uport->pclk);
- spin_lock_irqsave(&uport->lock, flags);
- iowrite32(GSBI_PROTOCOL_UART, msm_uport->mapped_gsbi +
- GSBI_CONTROL_ADDR);
- spin_unlock_irqrestore(&uport->lock, flags);
- if (msm_uport->pclk)
- clk_disable_unprepare(msm_uport->pclk);
- }
}
/* Handle CTS changes (Called from interrupt handler) */
@@ -2115,6 +1804,11 @@
mutex_lock(&msm_uport->clk_mutex);
spin_lock_irqsave(&uport->lock, flags);
+ if (msm_uport->clk_state == MSM_HS_CLK_OFF) {
+ spin_unlock_irqrestore(&uport->lock, flags);
+ mutex_unlock(&msm_uport->clk_mutex);
+ return 1;
+ }
MSM_HS_DBG("In %s:\n", __func__);
/* Cancel if tx tty buffer is not empty, dma is in flight,
* or tx fifo is not empty
@@ -2122,8 +1816,6 @@
if (msm_uport->clk_state != MSM_HS_CLK_REQUEST_OFF ||
!uart_circ_empty(tx_buf) || msm_uport->tx.dma_in_flight ||
msm_uport->imr_reg & UARTDM_ISR_TXLEV_BMSK) {
- spin_unlock_irqrestore(&uport->lock, flags);
- mutex_unlock(&msm_uport->clk_mutex);
if (msm_uport->clk_state == MSM_HS_CLK_REQUEST_OFF) {
msm_uport->clk_state = MSM_HS_CLK_ON;
/* Pulling RFR line high */
@@ -2134,6 +1826,8 @@
msm_hs_write(uport, UART_DM_MR1, data);
mb();
}
+ spin_unlock_irqrestore(&uport->lock, flags);
+ mutex_unlock(&msm_uport->clk_mutex);
MSM_HS_DBG("%s(): clkstate %d", __func__, msm_uport->clk_state);
return -1;
}
@@ -2150,11 +1844,8 @@
}
if (msm_uport->rx.flush != FLUSH_SHUTDOWN) {
- if (msm_uport->rx.flush == FLUSH_NONE) {
+ if (msm_uport->rx.flush == FLUSH_NONE)
msm_hs_stop_rx_locked(uport);
- if (!is_blsp_uart(msm_uport))
- msm_uport->rx_discard_flush_issued = true;
- }
MSM_HS_DBG("%s: rx.flush %d clk_state %d\n", __func__,
msm_uport->rx.flush, msm_uport->clk_state);
@@ -2174,7 +1865,9 @@
mb();
/* we really want to clock off */
+ mutex_unlock(&msm_uport->clk_mutex);
msm_hs_clock_unvote(msm_uport);
+ mutex_lock(&msm_uport->clk_mutex);
spin_lock_irqsave(&uport->lock, flags);
if (use_low_power_wakeup(msm_uport)) {
@@ -2247,11 +1940,6 @@
*/
mb();
MSM_HS_DBG("%s:Stal Interrupt\n", __func__);
-
- if (!is_blsp_uart(msm_uport) && (rx->flush == FLUSH_NONE)) {
- rx->flush = FLUSH_DATA_READY;
- msm_dmov_flush(msm_uport->dma_rx_channel, 1);
- }
}
/* tx ready interrupt */
if (isr_status & UARTDM_ISR_TX_READY_BMSK) {
@@ -2390,7 +2078,9 @@
disable_irq_nosync(msm_uport->wakeup.irq);
spin_unlock_irqrestore(&uport->lock, flags);
+ mutex_unlock(&msm_uport->clk_mutex);
ret = msm_hs_clock_vote(msm_uport);
+ mutex_lock(&msm_uport->clk_mutex);
if (ret) {
MSM_HS_INFO("Clock ON Failure"
"For UART CLK Stalling HSUART\n");
@@ -2405,8 +2095,10 @@
spin_unlock_irqrestore(&uport->lock, flags);
MSM_HS_DBG("%s:Calling wait forxcompletion\n",
__func__);
+ mutex_unlock(&msm_uport->clk_mutex);
ret = wait_event_timeout(msm_uport->bam_disconnect_wait,
msm_uport->rx.flush == FLUSH_SHUTDOWN, 300);
+ mutex_lock(&msm_uport->clk_mutex);
if (!ret)
MSM_HS_ERR("BAM Disconnect not happened\n");
spin_lock_irqsave(&uport->lock, flags);
@@ -2420,10 +2112,7 @@
msm_uport->rx.flush == FLUSH_SHUTDOWN) {
msm_hs_write(uport, UART_DM_CR, RESET_RX);
data = msm_hs_read(uport, UART_DM_DMEN);
- if (is_blsp_uart(msm_uport))
- data |= UARTDM_RX_BAM_ENABLE_BMSK;
- else
- data |= UARTDM_RX_DM_EN_BMSK;
+ data |= UARTDM_RX_BAM_ENABLE_BMSK;
msm_hs_write(uport, UART_DM_DMEN, data);
/* Complete above device write. Hence mb() here. */
mb();
@@ -2431,11 +2120,9 @@
MSM_HS_DBG("%s: rx.flush %d\n", __func__, msm_uport->rx.flush);
if (msm_uport->rx.flush == FLUSH_SHUTDOWN) {
- if (is_blsp_uart(msm_uport)) {
- spin_unlock_irqrestore(&uport->lock, flags);
- msm_hs_spsconnect_rx(uport);
- spin_lock_irqsave(&uport->lock, flags);
- }
+ spin_unlock_irqrestore(&uport->lock, flags);
+ msm_hs_spsconnect_rx(uport);
+ spin_lock_irqsave(&uport->lock, flags);
msm_hs_start_rx_locked(uport);
}
if (msm_uport->rx.flush == FLUSH_STOP)
@@ -2601,9 +2288,6 @@
unsigned long flags;
unsigned int data;
struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
- struct platform_device *pdev = to_platform_device(uport->dev);
- const struct msm_serial_hs_platform_data *pdata =
- pdev->dev.platform_data;
struct circ_buf *tx_buf = &uport->state->xmit;
struct msm_hs_tx *tx = &msm_uport->tx;
struct msm_hs_rx *rx = &msm_uport->rx;
@@ -2626,33 +2310,25 @@
return ret;
}
- if (is_blsp_uart(msm_uport)) {
- ret = msm_hs_config_uart_gpios(uport);
- if (ret) {
- MSM_HS_ERR("Uart GPIO request failed\n");
- goto deinit_uart_clk;
- }
- } else {
- if (pdata && pdata->gpio_config)
- if (unlikely(pdata->gpio_config(1)))
- dev_err(uport->dev, "Cannot configure gpios\n");
+ ret = msm_hs_config_uart_gpios(uport);
+ if (ret) {
+ MSM_HS_ERR("Uart GPIO request failed\n");
+ goto deinit_uart_clk;
}
/* SPS Connect for BAM endpoints */
- if (is_blsp_uart(msm_uport)) {
- /* SPS connect for TX */
- ret = msm_hs_spsconnect_tx(uport);
- if (ret) {
- MSM_HS_ERR("msm_serial_hs: SPS connect failed for TX");
- goto unconfig_uart_gpios;
- }
+ /* SPS connect for TX */
+ ret = msm_hs_spsconnect_tx(uport);
+ if (ret) {
+ MSM_HS_ERR("msm_serial_hs: SPS connect failed for TX");
+ goto unconfig_uart_gpios;
+ }
- /* SPS connect for RX */
- ret = msm_hs_spsconnect_rx(uport);
- if (ret) {
- MSM_HS_ERR("msm_serial_hs: SPS connect failed for RX");
- goto sps_disconnect_tx;
- }
+ /* SPS connect for RX */
+ ret = msm_hs_spsconnect_rx(uport);
+ if (ret) {
+ MSM_HS_ERR("msm_serial_hs: SPS connect failed for RX");
+ goto sps_disconnect_tx;
}
data = (UARTDM_BCR_TX_BREAK_DISABLE | UARTDM_BCR_STALE_IRQ_EMPTY |
@@ -2675,13 +2351,8 @@
msm_hs_write(uport, UART_DM_IPR, data);
}
- if (is_blsp_uart(msm_uport)) {
- /* Enable BAM mode */
- data = UARTDM_TX_BAM_ENABLE_BMSK | UARTDM_RX_BAM_ENABLE_BMSK;
- } else {
- /* Enable Data Mover Mode */
- data = UARTDM_TX_DM_EN_BMSK | UARTDM_RX_DM_EN_BMSK;
- }
+ /* Enable BAM mode */
+ data = UARTDM_TX_BAM_ENABLE_BMSK | UARTDM_RX_BAM_ENABLE_BMSK;
msm_hs_write(uport, UART_DM_DMEN, data);
/* Reset TX */
@@ -2703,23 +2374,6 @@
tx->dma_in_flight = 0;
rx->rx_cmd_exec = false;
- if (!is_blsp_uart(msm_uport)) {
- tx->xfer.complete_func = msm_hs_dmov_tx_callback;
-
- tx->command_ptr->cmd = CMD_LC |
- CMD_DST_CRCI(msm_uport->dma_tx_crci) | CMD_MODE_BOX;
-
- tx->command_ptr->src_dst_len = (MSM_UARTDM_BURST_SIZE << 16)
- | (MSM_UARTDM_BURST_SIZE);
-
- tx->command_ptr->row_offset = (MSM_UARTDM_BURST_SIZE << 16);
-
- tx->command_ptr->dst_row_addr =
- msm_uport->uport.mapbase + UARTDM_TF_ADDR;
-
- msm_uport->imr_reg |= UARTDM_ISR_RXSTALE_BMSK;
- }
-
/* Enable reading the current CTS, no harm even if CTS is ignored */
msm_uport->imr_reg |= UARTDM_ISR_CURRENT_CTS_BMSK;
@@ -2774,14 +2428,11 @@
if (use_low_power_wakeup(msm_uport))
irq_set_irq_wake(msm_uport->wakeup.irq, 0);
sps_disconnect_rx:
- if (is_blsp_uart(msm_uport))
- sps_disconnect(sps_pipe_handle_rx);
+ sps_disconnect(sps_pipe_handle_rx);
sps_disconnect_tx:
- if (is_blsp_uart(msm_uport))
- sps_disconnect(sps_pipe_handle_tx);
+ sps_disconnect(sps_pipe_handle_tx);
unconfig_uart_gpios:
- if (is_blsp_uart(msm_uport))
- msm_hs_unconfig_uart_gpios(uport);
+ msm_hs_unconfig_uart_gpios(uport);
deinit_uart_clk:
msm_hs_clock_unvote(msm_uport);
wake_unlock(&msm_uport->dma_wake_lock);
@@ -2814,7 +2465,7 @@
if (!rx->pool) {
MSM_HS_ERR("%s(): cannot allocate rx_buffer_pool", __func__);
ret = -ENOMEM;
- goto exit_tasket_init;
+ goto exit_tasklet_init;
}
rx->buffer = dma_pool_alloc(rx->pool, GFP_KERNEL, &rx->rbuffer);
@@ -2825,99 +2476,15 @@
}
/* Set up Uart Receive */
- if (is_blsp_uart(msm_uport))
- msm_hs_write(uport, UART_DM_RFWR, 32);
- else
- msm_hs_write(uport, UART_DM_RFWR, 0);
+ msm_hs_write(uport, UART_DM_RFWR, 32);
INIT_DELAYED_WORK(&rx->flip_insert_work, flip_insert_work);
- if (is_blsp_uart(msm_uport))
- return ret;
-
- /* Allocate the command pointer. Needs to be 64 bit aligned */
- tx->command_ptr = kmalloc(sizeof(dmov_box), GFP_KERNEL | __GFP_DMA);
- if (!tx->command_ptr) {
- return -ENOMEM;
- goto free_rx_buffer;
- }
-
- tx->command_ptr_ptr = kmalloc(sizeof(u32), GFP_KERNEL | __GFP_DMA);
- if (!tx->command_ptr_ptr) {
- ret = -ENOMEM;
- goto free_tx_command_ptr;
- }
-
- tx->mapped_cmd_ptr = dma_map_single(uport->dev, tx->command_ptr,
- sizeof(dmov_box), DMA_TO_DEVICE);
- tx->mapped_cmd_ptr_ptr = dma_map_single(uport->dev,
- tx->command_ptr_ptr,
- sizeof(u32), DMA_TO_DEVICE);
- tx->xfer.cmdptr = DMOV_CMD_ADDR(tx->mapped_cmd_ptr_ptr);
-
- /* Allocate the command pointer. Needs to be 64 bit aligned */
- rx->command_ptr = kmalloc(sizeof(dmov_box), GFP_KERNEL | __GFP_DMA);
- if (!rx->command_ptr) {
- MSM_HS_ERR("%s(): cannot allocate rx->command_ptr", __func__);
- ret = -ENOMEM;
- goto free_tx_command_ptr_ptr;
- }
-
- rx->command_ptr_ptr = kmalloc(sizeof(u32), GFP_KERNEL | __GFP_DMA);
- if (!rx->command_ptr_ptr) {
- MSM_HS_ERR("%s(): cannot allocate rx->command_ptr_ptr",
- __func__);
- ret = -ENOMEM;
- goto free_rx_command_ptr;
- }
-
- rx->command_ptr->num_rows = ((UARTDM_RX_BUF_SIZE >> 4) << 16) |
- (UARTDM_RX_BUF_SIZE >> 4);
-
- rx->command_ptr->dst_row_addr = rx->rbuffer;
-
- rx->xfer.complete_func = msm_hs_dmov_rx_callback;
-
- rx->command_ptr->cmd = CMD_LC |
- CMD_SRC_CRCI(msm_uport->dma_rx_crci) | CMD_MODE_BOX;
-
- rx->command_ptr->src_dst_len = (MSM_UARTDM_BURST_SIZE << 16)
- | (MSM_UARTDM_BURST_SIZE);
- rx->command_ptr->row_offset = MSM_UARTDM_BURST_SIZE;
- rx->command_ptr->src_row_addr = uport->mapbase + UARTDM_RF_ADDR;
-
- rx->mapped_cmd_ptr = dma_map_single(uport->dev, rx->command_ptr,
- sizeof(dmov_box), DMA_TO_DEVICE);
-
- *rx->command_ptr_ptr = CMD_PTR_LP | DMOV_CMD_ADDR(rx->mapped_cmd_ptr);
-
- rx->cmdptr_dmaaddr = dma_map_single(uport->dev, rx->command_ptr_ptr,
- sizeof(u32), DMA_TO_DEVICE);
- rx->xfer.cmdptr = DMOV_CMD_ADDR(rx->cmdptr_dmaaddr);
-
return ret;
-
-free_rx_command_ptr:
- kfree(rx->command_ptr);
-
-free_tx_command_ptr_ptr:
- kfree(msm_uport->tx.command_ptr_ptr);
- dma_unmap_single(uport->dev, msm_uport->tx.mapped_cmd_ptr_ptr,
- sizeof(u32), DMA_TO_DEVICE);
- dma_unmap_single(uport->dev, msm_uport->tx.mapped_cmd_ptr,
- sizeof(dmov_box), DMA_TO_DEVICE);
-
-free_tx_command_ptr:
- kfree(msm_uport->tx.command_ptr);
-
-free_rx_buffer:
- dma_pool_free(msm_uport->rx.pool, msm_uport->rx.buffer,
- msm_uport->rx.rbuffer);
-
free_pool:
dma_pool_destroy(msm_uport->rx.pool);
-exit_tasket_init:
+exit_tasklet_init:
wake_lock_destroy(&msm_uport->rx.wake_lock);
wake_lock_destroy(&msm_uport->dma_wake_lock);
tasklet_kill(&msm_uport->tx.tlet);
@@ -2963,6 +2530,9 @@
if (pdata->uart_rfr_gpio < 0)
MSM_HS_DBG("uart_rfr_gpio is not available\n");
+ pdata->no_suspend_delay = of_property_read_bool(node,
+ "qcom,no-suspend-delay");
+
pdata->inject_rx_on_wakeup = of_property_read_bool(node,
"qcom,inject-rx-on-wakeup");
@@ -3058,8 +2628,8 @@
/* Allocate endpoint context */
sps_pipe_handle = sps_alloc_endpoint();
if (!sps_pipe_handle) {
- MSM_HS_ERR("msm_serial_hs: sps_alloc_endpoint() failed!!\n"
- "is_producer=%d", is_producer);
+ MSM_HS_ERR("%s(): sps_alloc_endpoint() failed!!\n"
+ "is_producer=%d", __func__, is_producer);
rc = -ENOMEM;
goto out;
}
@@ -3067,8 +2637,8 @@
/* Get default connection configuration for an endpoint */
rc = sps_get_config(sps_pipe_handle, sps_config);
if (rc) {
- MSM_HS_ERR("msm_serial_hs: sps_get_config() failed!!\n"
- "pipe_handle=0x%x rc=%d", (u32)sps_pipe_handle, rc);
+ MSM_HS_ERR("%s(): failed! pipe_handle=0x%p rc=%d",
+ __func__, sps_pipe_handle, rc);
goto get_config_err;
}
@@ -3120,10 +2690,10 @@
/* Now save the sps pipe handle */
ep->pipe_handle = sps_pipe_handle;
- MSM_HS_DBG("msm_serial_hs: success !! %s: pipe_handle=0x%x\n"
- "desc_fifo.phys_base=0x%llx\n",
+ MSM_HS_DBG("msm_serial_hs: success !! %s: pipe_handle=0x%p\n"
+ "desc_fifo.phys_base=0x%pa\n",
is_producer ? "READ" : "WRITE",
- (u32) sps_pipe_handle, (u64) sps_config->desc.phys_base);
+ sps_pipe_handle, &sps_config->desc.phys_base);
return 0;
get_config_err:
@@ -3164,10 +2734,10 @@
bam.irq = (u32)msm_uport->bam_irq;
bam.manage = SPS_BAM_MGR_DEVICE_REMOTE;
- MSM_HS_DBG("msm_serial_hs: bam physical base=0x%x\n",
- (u32)bam.phys_addr);
- MSM_HS_DBG("msm_serial_hs: bam virtual base=0x%x\n",
- (u32)bam.virt_addr);
+ MSM_HS_DBG("msm_serial_hs: bam physical base=0x%pa\n",
+ &bam.phys_addr);
+ MSM_HS_DBG("msm_serial_hs: bam virtual base=0x%p\n",
+ bam.virt_addr);
/* Register UART Peripheral BAM device to SPS driver */
rc = sps_register_bam_device(&bam, &bam_handle);
@@ -3247,10 +2817,8 @@
struct msm_hs_port *msm_uport;
struct resource *core_resource;
struct resource *bam_resource;
- struct resource *resource;
int core_irqres, bam_irqres, wakeup_irqres;
struct msm_serial_hs_platform_data *pdata = pdev->dev.platform_data;
- const struct of_device_id *match;
unsigned long data;
if (pdev->dev.of_node) {
@@ -3288,96 +2856,71 @@
uport = &msm_uport->uport;
uport->dev = &pdev->dev;
- match = of_match_device(msm_hs_match_table, &pdev->dev);
- if (match)
- msm_uport->reg_ptr = (unsigned int *)match->data;
- else if (is_gsbi_uart(msm_uport))
- msm_uport->reg_ptr = regmap_nonblsp;
-
if (pdev->dev.of_node)
msm_uport->uart_type = BLSP_HSUART;
/* Get required resources for BAM HSUART */
- if (is_blsp_uart(msm_uport)) {
- core_resource = platform_get_resource_byname(pdev,
- IORESOURCE_MEM, "core_mem");
- if (!core_resource) {
- MSM_HS_ERR("Invalid core HSUART Resources.\n");
- return -ENXIO;
- }
- bam_resource = platform_get_resource_byname(pdev,
- IORESOURCE_MEM, "bam_mem");
- if (!bam_resource) {
- MSM_HS_ERR("Invalid BAM HSUART Resources.\n");
- return -ENXIO;
- }
- core_irqres = platform_get_irq_byname(pdev, "core_irq");
- if (core_irqres < 0) {
- MSM_HS_ERR("Invalid core irqres Resources.\n");
- return -ENXIO;
- }
- bam_irqres = platform_get_irq_byname(pdev, "bam_irq");
- if (bam_irqres < 0) {
- MSM_HS_ERR("Invalid bam irqres Resources.\n");
- return -ENXIO;
- }
- wakeup_irqres = platform_get_irq_byname(pdev, "wakeup_irq");
- if (wakeup_irqres < 0) {
- wakeup_irqres = -1;
- MSM_HS_DBG("Wakeup irq not specified.\n");
- }
+ core_resource = platform_get_resource_byname(pdev,
+ IORESOURCE_MEM, "core_mem");
+ if (!core_resource) {
+ MSM_HS_ERR("Invalid core HSUART Resources.\n");
+ return -ENXIO;
+ }
+ bam_resource = platform_get_resource_byname(pdev,
+ IORESOURCE_MEM, "bam_mem");
+ if (!bam_resource) {
+ MSM_HS_ERR("Invalid BAM HSUART Resources.\n");
+ return -ENXIO;
+ }
+ core_irqres = platform_get_irq_byname(pdev, "core_irq");
+ if (core_irqres < 0) {
+ MSM_HS_ERR("Invalid core irqres Resources.\n");
+ return -ENXIO;
+ }
+ bam_irqres = platform_get_irq_byname(pdev, "bam_irq");
+ if (bam_irqres < 0) {
+ MSM_HS_ERR("Invalid bam irqres Resources.\n");
+ return -ENXIO;
+ }
+ wakeup_irqres = platform_get_irq_byname(pdev, "wakeup_irq");
+ if (wakeup_irqres < 0) {
+ wakeup_irqres = -1;
+ MSM_HS_DBG("Wakeup irq not specified.\n");
+ }
- uport->mapbase = core_resource->start;
+ uport->mapbase = core_resource->start;
- uport->membase = ioremap(uport->mapbase,
- resource_size(core_resource));
- if (unlikely(!uport->membase)) {
- MSM_HS_ERR("UART Resource ioremap Failed.\n");
- return -ENOMEM;
- }
- msm_uport->bam_mem = bam_resource->start;
- msm_uport->bam_base = ioremap(msm_uport->bam_mem,
- resource_size(bam_resource));
- if (unlikely(!msm_uport->bam_base)) {
- MSM_HS_ERR("UART BAM Resource ioremap Failed.\n");
- iounmap(uport->membase);
- return -ENOMEM;
- }
+ uport->membase = ioremap(uport->mapbase,
+ resource_size(core_resource));
+ if (unlikely(!uport->membase)) {
+ MSM_HS_ERR("UART Resource ioremap Failed.\n");
+ return -ENOMEM;
+ }
+ msm_uport->bam_mem = bam_resource->start;
+ msm_uport->bam_base = ioremap(msm_uport->bam_mem,
+ resource_size(bam_resource));
+ if (unlikely(!msm_uport->bam_base)) {
+ MSM_HS_ERR("UART BAM Resource ioremap Failed.\n");
+ iounmap(uport->membase);
+ return -ENOMEM;
+ }
- uport->irq = core_irqres;
- msm_uport->bam_irq = bam_irqres;
- pdata->wakeup_irq = wakeup_irqres;
+ uport->irq = core_irqres;
+ msm_uport->bam_irq = bam_irqres;
+ pdata->wakeup_irq = wakeup_irqres;
- msm_uport->bus_scale_table = msm_bus_cl_get_pdata(pdev);
- if (!msm_uport->bus_scale_table) {
- MSM_HS_ERR("BLSP UART: Bus scaling is disabled.\n");
- } else {
- msm_uport->bus_perf_client =
- msm_bus_scale_register_client
- (msm_uport->bus_scale_table);
- if (IS_ERR(&msm_uport->bus_perf_client)) {
- MSM_HS_ERR("%s(): Bus client register failed.\n",
- __func__);
- ret = -EINVAL;
- goto unmap_memory;
- }
- }
+ msm_uport->bus_scale_table = msm_bus_cl_get_pdata(pdev);
+ if (!msm_uport->bus_scale_table) {
+ MSM_HS_ERR("BLSP UART: Bus scaling is disabled.\n");
} else {
-
- resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (unlikely(!resource))
- return -ENXIO;
- uport->mapbase = resource->start;
- uport->membase = ioremap(uport->mapbase,
- resource_size(resource));
- if (unlikely(!uport->membase))
- return -ENOMEM;
-
- uport->irq = platform_get_irq(pdev, 0);
- if (unlikely((int)uport->irq < 0)) {
- MSM_HS_ERR("UART IRQ Failed.\n");
- iounmap(uport->membase);
- return -ENXIO;
+ msm_uport->bus_perf_client =
+ msm_bus_scale_register_client
+ (msm_uport->bus_scale_table);
+ if (IS_ERR(&msm_uport->bus_perf_client)) {
+ MSM_HS_ERR("%s():Bus client register failed\n",
+ __func__);
+ ret = -EINVAL;
+ goto unmap_memory;
}
}
@@ -3389,35 +2932,10 @@
msm_uport->wakeup.inject_rx = pdata->inject_rx_on_wakeup;
msm_uport->wakeup.rx_to_inject = pdata->rx_to_inject;
- if (is_blsp_uart(msm_uport)) {
- msm_uport->bam_tx_ep_pipe_index =
- pdata->bam_tx_ep_pipe_index;
- msm_uport->bam_rx_ep_pipe_index =
- pdata->bam_rx_ep_pipe_index;
- }
- }
-
- if (!is_blsp_uart(msm_uport)) {
-
- resource = platform_get_resource_byname(pdev,
- IORESOURCE_DMA, "uartdm_channels");
- if (unlikely(!resource)) {
- ret = -ENXIO;
- goto deregister_bus_client;
- }
-
- msm_uport->dma_tx_channel = resource->start;
- msm_uport->dma_rx_channel = resource->end;
-
- resource = platform_get_resource_byname(pdev,
- IORESOURCE_DMA, "uartdm_crci");
- if (unlikely(!resource)) {
- ret = -ENXIO;
- goto deregister_bus_client;
- }
-
- msm_uport->dma_tx_crci = resource->start;
- msm_uport->dma_rx_crci = resource->end;
+ msm_uport->bam_tx_ep_pipe_index =
+ pdata->bam_tx_ep_pipe_index;
+ msm_uport->bam_rx_ep_pipe_index =
+ pdata->bam_rx_ep_pipe_index;
}
uport->iotype = UPIO_MEM;
@@ -3466,12 +2984,10 @@
/* Initialize SPS HW connected with UART core */
- if (is_blsp_uart(msm_uport)) {
- ret = msm_hs_sps_init(msm_uport);
- if (unlikely(ret)) {
- MSM_HS_ERR("SPS Initialization failed ! err=%d", ret);
- goto destroy_mutex;
- }
+ ret = msm_hs_sps_init(msm_uport);
+ if (unlikely(ret)) {
+ MSM_HS_ERR("SPS Initialization failed ! err=%d", ret);
+ goto destroy_mutex;
}
msm_hs_clock_vote(msm_uport);
@@ -3538,12 +3054,10 @@
clk_put(msm_uport->clk);
deregister_bus_client:
- if (is_blsp_uart(msm_uport))
- msm_bus_scale_unregister_client(msm_uport->bus_perf_client);
+ msm_bus_scale_unregister_client(msm_uport->bus_perf_client);
unmap_memory:
iounmap(uport->membase);
- if (is_blsp_uart(msm_uport))
- iounmap(msm_uport->bam_base);
+ iounmap(msm_uport->bam_base);
return ret;
}
@@ -3586,54 +3100,51 @@
static void msm_hs_shutdown(struct uart_port *uport)
{
int ret;
- unsigned int data;
- unsigned long flags;
struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
- struct platform_device *pdev = to_platform_device(uport->dev);
- const struct msm_serial_hs_platform_data *pdata =
- pdev->dev.platform_data;
+ struct circ_buf *tx_buf = &uport->state->xmit;
struct msm_hs_tx *tx = &msm_uport->tx;
struct sps_pipe *sps_pipe_handle = tx->cons.pipe_handle;
- msm_hs_clock_vote(msm_uport);
- if (msm_uport->tx.dma_in_flight) {
- if (!is_blsp_uart(msm_uport)) {
- spin_lock_irqsave(&uport->lock, flags);
- /* disable UART TX interface to DM */
- data = msm_hs_read(uport, UART_DM_DMEN);
- data &= ~UARTDM_TX_DM_EN_BMSK;
- msm_hs_write(uport, UART_DM_DMEN, data);
- /* turn OFF UART Transmitter */
- msm_hs_write(uport, UART_DM_CR,
- UARTDM_CR_TX_DISABLE_BMSK);
- /* reset UART TX */
- msm_hs_write(uport, UART_DM_CR, RESET_TX);
- /* reset UART TX Error */
- msm_hs_write(uport, UART_DM_CR, RESET_TX_ERROR);
- msm_uport->tx.flush = FLUSH_STOP;
- spin_unlock_irqrestore(&uport->lock, flags);
- /* discard flush */
- msm_dmov_flush(msm_uport->dma_tx_channel, 0);
- ret = wait_event_timeout(msm_uport->tx.wait,
- msm_uport->tx.flush == FLUSH_SHUTDOWN, 100);
- if (!ret)
- MSM_HS_ERR("%s():HSUART TX Stalls.\n", __func__);
- } else {
- /* BAM Disconnect for TX */
- ret = sps_disconnect(sps_pipe_handle);
- if (ret)
- MSM_HS_ERR("%s(): sps_disconnect failed\n",
- __func__);
- }
+ /*
+ * cancel the hrtimer first so that
+ * clk_state can not change in flight
+ */
+ hrtimer_cancel(&msm_uport->clk_off_timer);
+ flush_work(&msm_uport->clock_off_w);
+
+ if (use_low_power_wakeup(msm_uport))
+ irq_set_irq_wake(msm_uport->wakeup.irq, 0);
+
+ /* wake irq or uart irq is active depending on clk_state */
+ if (msm_uport->clk_state == MSM_HS_CLK_OFF) {
+ if (use_low_power_wakeup(msm_uport))
+ disable_irq(msm_uport->wakeup.irq);
+ } else {
+ disable_irq(uport->irq);
+ wake_unlock(&msm_uport->dma_wake_lock);
}
+
+ /* make sure tx tasklet finishes */
tasklet_kill(&msm_uport->tx.tlet);
- BUG_ON(msm_uport->rx.flush < FLUSH_STOP);
- wait_event(msm_uport->rx.wait, msm_uport->rx.flush == FLUSH_SHUTDOWN);
+ ret = wait_event_timeout(msm_uport->tx.wait,
+ uart_circ_empty(tx_buf), 500);
+ if (!ret)
+ MSM_HS_WARN("Shutdown called when tx buff not empty");
+
+ /* make sure rx tasklet finishes */
tasklet_kill(&msm_uport->rx.tlet);
+ wait_event(msm_uport->rx.wait, msm_uport->rx.flush == FLUSH_SHUTDOWN);
cancel_delayed_work_sync(&msm_uport->rx.flip_insert_work);
flush_workqueue(msm_uport->hsuart_wq);
- pm_runtime_disable(uport->dev);
+ msm_hs_clock_vote(msm_uport);
+ mutex_lock(&msm_uport->clk_mutex);
+ /* BAM Disconnect for TX */
+ ret = sps_disconnect(sps_pipe_handle);
+ if (ret)
+ MSM_HS_ERR("%s(): sps_disconnect failed\n",
+ __func__);
+ WARN_ON(msm_uport->rx.flush < FLUSH_STOP);
/* Disable the transmitter */
msm_hs_write(uport, UART_DM_CR, UARTDM_CR_TX_DISABLE_BMSK);
/* Disable the receiver */
@@ -3646,33 +3157,27 @@
* Hence mb() requires here.
*/
mb();
+ mutex_unlock(&msm_uport->clk_mutex);
+ msm_uport->rx.buffer_pending = NONE_PENDING;
+ MSM_HS_DBG("%s(): tx, rx events complete", __func__);
msm_hs_clock_unvote(msm_uport);
if (msm_uport->clk_state != MSM_HS_CLK_OFF) {
/* to balance clk_state */
msm_hs_clock_unvote(msm_uport);
- wake_unlock(&msm_uport->dma_wake_lock);
}
+ pm_runtime_disable(uport->dev);
msm_uport->clk_state = MSM_HS_CLK_PORT_OFF;
dma_unmap_single(uport->dev, msm_uport->tx.dma_base,
UART_XMIT_SIZE, DMA_TO_DEVICE);
- if (use_low_power_wakeup(msm_uport))
- irq_set_irq_wake(msm_uport->wakeup.irq, 0);
-
/* Free the interrupt */
free_irq(uport->irq, msm_uport);
if (use_low_power_wakeup(msm_uport))
free_irq(msm_uport->wakeup.irq, msm_uport);
- if (is_blsp_uart(msm_uport)) {
- msm_hs_unconfig_uart_gpios(uport);
- } else {
- if (pdata && pdata->gpio_config)
- if (pdata->gpio_config(0))
- dev_err(uport->dev, "GPIO config error\n");
- }
+ msm_hs_unconfig_uart_gpios(uport);
}
static void __exit msm_serial_hs_exit(void)
@@ -3758,8 +3263,6 @@
.set_termios = msm_hs_set_termios,
.type = msm_hs_type,
.config_port = msm_hs_config_port,
- .release_port = msm_hs_release_port,
- .request_port = msm_hs_request_port,
.flush_buffer = NULL,
.ioctl = msm_hs_ioctl,
};
diff --git a/drivers/tty/serial/msm_serial_hs_hwreg.h b/drivers/tty/serial/msm_serial_hs_hwreg.h
index 064bbda..47f9dca 100644
--- a/drivers/tty/serial/msm_serial_hs_hwreg.h
+++ b/drivers/tty/serial/msm_serial_hs_hwreg.h
@@ -1,6 +1,6 @@
/* drivers/serial/msm_serial_hs_hwreg.h
*
- * Copyright (c) 2007-2009, 2012-2013,The Linux Foundation. All rights reserved.
+ * Copyright (c) 2007-2009, 2012-2014,The Linux Foundation. All rights reserved.
*
* All source code in this file is licensed under the following license
* except where indicated.
@@ -61,28 +61,27 @@
};
enum msm_hs_regs {
- UART_DM_MR1,
- UART_DM_MR2,
- UART_DM_IMR,
- UART_DM_SR,
- UART_DM_CR,
- UART_DM_CSR,
- UART_DM_IPR,
- UART_DM_ISR,
- UART_DM_RX_TOTAL_SNAP,
- UART_DM_RFWR,
- UART_DM_TFWR,
- UART_DM_RF,
- UART_DM_TF,
- UART_DM_MISR,
- UART_DM_DMRX,
- UART_DM_NCF_TX,
- UART_DM_DMEN,
- UART_DM_TXFS,
- UART_DM_RXFS,
- UART_DM_RX_TRANS_CTRL,
- UART_DM_BCR,
- UART_DM_LAST,
+ UART_DM_MR1 = 0x0,
+ UART_DM_MR2 = 0x4,
+ UART_DM_IMR = 0xb0,
+ UART_DM_SR = 0xa4,
+ UART_DM_CR = 0xa8,
+ UART_DM_CSR = 0xa0,
+ UART_DM_IPR = 0x18,
+ UART_DM_ISR = 0xb4,
+ UART_DM_RX_TOTAL_SNAP = 0xbc,
+ UART_DM_TFWR = 0x1c,
+ UART_DM_RFWR = 0x20,
+ UART_DM_RF = 0x140,
+ UART_DM_TF = 0x100,
+ UART_DM_MISR = 0xac,
+ UART_DM_DMRX = 0x34,
+ UART_DM_NCF_TX = 0x40,
+ UART_DM_DMEN = 0x3c,
+ UART_DM_TXFS = 0x4c,
+ UART_DM_RXFS = 0x50,
+ UART_DM_RX_TRANS_CTRL = 0xcc,
+ UART_DM_BCR = 0xc8,
};
#define UARTDM_MR1_ADDR 0x0
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index ea724d6..f5a9ad3 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -25,6 +25,7 @@
#include <linux/debugfs.h>
#include <linux/seq_file.h>
#include <linux/pm_runtime.h>
+#include <linux/suspend.h>
#include <linux/of.h>
#include <linux/dma-mapping.h>
@@ -3394,10 +3395,12 @@
return;
}
- if (atomic_read(&motg->pm_suspended))
+ if (atomic_read(&motg->pm_suspended)) {
motg->sm_work_pending = true;
- else
+ } else if (!motg->sm_work_pending) {
+ /* process event only if previous one is not pending */
queue_work(system_nrt_wq, &motg->sm_work);
+ }
}
static void msm_pmic_id_status_w(struct work_struct *w)
@@ -3406,6 +3409,8 @@
pmic_id_status_work.work);
int work = 0;
+ dev_dbg(motg->phy.dev, "ID status_w\n");
+
if (msm_otg_read_pmic_id_state(motg)) {
if (!test_and_set_bit(ID, &motg->inputs)) {
pr_debug("PMIC: ID set\n");
@@ -3420,10 +3425,12 @@
}
if (work && (motg->phy.state != OTG_STATE_UNDEFINED)) {
- if (atomic_read(&motg->pm_suspended))
+ if (atomic_read(&motg->pm_suspended)) {
motg->sm_work_pending = true;
- else
+ } else if (!motg->sm_work_pending) {
+ /* process event only if previous one is not pending */
queue_work(system_nrt_wq, &motg->sm_work);
+ }
}
}
@@ -3447,6 +3454,34 @@
return IRQ_HANDLED;
}
+int msm_otg_pm_notify(struct notifier_block *notify_block,
+ unsigned long mode, void *unused)
+{
+ struct msm_otg *motg = container_of(
+ notify_block, struct msm_otg, pm_notify);
+
+ dev_dbg(motg->phy.dev, "OTG PM notify:%lx, sm_pending:%u\n", mode,
+ motg->sm_work_pending);
+
+ switch (mode) {
+ case PM_POST_SUSPEND:
+ /* OTG sm_work can be armed now */
+ atomic_set(&motg->pm_suspended, 0);
+
+ /* Handle any deferred wakeup events from USB during suspend */
+ if (motg->sm_work_pending) {
+ motg->sm_work_pending = false;
+ queue_work(system_nrt_wq, &motg->sm_work);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return NOTIFY_OK;
+}
+
static int msm_otg_mode_show(struct seq_file *s, void *unused)
{
struct msm_otg *motg = s->private;
@@ -4745,6 +4780,9 @@
if (ret)
dev_dbg(&pdev->dev, "fail to setup cdev\n");
+ motg->pm_notify.notifier_call = msm_otg_pm_notify;
+ register_pm_notifier(&motg->pm_notify);
+
return 0;
remove_phy:
@@ -4807,6 +4845,8 @@
if (phy->otg->host || phy->otg->gadget)
return -EBUSY;
+ unregister_pm_notifier(&motg->pm_notify);
+
if (!motg->ext_chg_device) {
device_destroy(motg->ext_chg_class, motg->ext_chg_dev);
cdev_del(&motg->ext_chg_cdev);
@@ -4975,7 +5015,8 @@
dev_dbg(dev, "OTG PM resume\n");
motg->pm_done = 0;
- atomic_set(&motg->pm_suspended, 0);
+ if (!motg->host_bus_suspend)
+ atomic_set(&motg->pm_suspended, 0);
if (motg->async_int || motg->sm_work_pending) {
pm_runtime_get_noresume(dev);
ret = msm_otg_resume(motg);
@@ -4985,7 +5026,12 @@
pm_runtime_set_active(dev);
pm_runtime_enable(dev);
- if (motg->sm_work_pending) {
+ /*
+ * Defer any host mode disconnect events until
+ * all devices are RESUMED
+ *
+ */
+ if (motg->sm_work_pending && !motg->host_bus_suspend) {
motg->sm_work_pending = false;
queue_work(system_nrt_wq, &motg->sm_work);
}
diff --git a/drivers/video/msm/mdss/mdss.h b/drivers/video/msm/mdss/mdss.h
index b1c0343..e8c938b 100644
--- a/drivers/video/msm/mdss/mdss.h
+++ b/drivers/video/msm/mdss/mdss.h
@@ -94,6 +94,15 @@
u32 fbc_lines;
};
+enum mdss_hw_index {
+ MDSS_HW_MDP,
+ MDSS_HW_DSI0,
+ MDSS_HW_DSI1,
+ MDSS_HW_HDMI,
+ MDSS_HW_EDP,
+ MDSS_MAX_HW_BLK
+};
+
struct mdss_data_type {
u32 mdp_rev;
struct clk *mdp_clk[MDSS_MAX_CLK];
@@ -199,18 +208,12 @@
struct mdss_prefill_data prefill_data;
bool ulps;
int iommu_ref_cnt;
+
+ u64 ab[MDSS_MAX_HW_BLK];
+ u64 ib[MDSS_MAX_HW_BLK];
};
extern struct mdss_data_type *mdss_res;
-enum mdss_hw_index {
- MDSS_HW_MDP,
- MDSS_HW_DSI0,
- MDSS_HW_DSI1,
- MDSS_HW_HDMI,
- MDSS_HW_EDP,
- MDSS_MAX_HW_BLK
-};
-
struct mdss_hw {
u32 hw_ndx;
void *ptr;
@@ -223,6 +226,7 @@
void mdss_disable_irq_nosync(struct mdss_hw *hw);
void mdss_bus_bandwidth_ctrl(int enable);
int mdss_iommu_ctrl(int enable);
+int mdss_bus_scale_set_quota(int client, u64 ab_quota, u64 ib_quota);
static inline struct ion_client *mdss_get_ionclient(void)
{
diff --git a/drivers/video/msm/mdss/mdss_dsi_host.c b/drivers/video/msm/mdss/mdss_dsi_host.c
index 267a687..d8cd22e 100644
--- a/drivers/video/msm/mdss/mdss_dsi_host.c
+++ b/drivers/video/msm/mdss/mdss_dsi_host.c
@@ -1263,7 +1263,8 @@
* also, axi bus bandwidth need since dsi controller will
* fetch dcs commands from axi bus
*/
- mdss_bus_bandwidth_ctrl(1);
+ mdss_bus_scale_set_quota(MDSS_HW_DSI0, SZ_1M, SZ_1M);
+
pr_debug("%s: from_mdp=%d pid=%d\n", __func__, from_mdp, current->pid);
mdss_dsi_clk_ctrl(ctrl, DSI_ALL_CLKS, 1);
@@ -1279,8 +1280,7 @@
ret = mdss_dsi_cmdlist_tx(ctrl, req);
mdss_iommu_ctrl(0);
mdss_dsi_clk_ctrl(ctrl, DSI_ALL_CLKS, 0);
- mdss_bus_bandwidth_ctrl(0);
-
+ mdss_bus_scale_set_quota(MDSS_HW_DSI0, 0, 0);
need_lock:
if (from_mdp) /* from pipe_commit */
diff --git a/drivers/video/msm/mdss/mdss_dsi_panel.c b/drivers/video/msm/mdss/mdss_dsi_panel.c
index 7575fe3..0e1cd66 100644
--- a/drivers/video/msm/mdss/mdss_dsi_panel.c
+++ b/drivers/video/msm/mdss/mdss_dsi_panel.c
@@ -728,6 +728,39 @@
return 0;
}
+static void mdss_dsi_parse_roi_alignment(struct device_node *np,
+ struct mdss_panel_info *pinfo)
+{
+ int len = 0;
+ u32 value[6];
+ struct property *data;
+ data = of_find_property(np, "qcom,panel-roi-alignment", &len);
+ len /= sizeof(u32);
+ if (!data || (len != 6)) {
+ pr_debug("%s: Panel roi alignment not found", __func__);
+ } else {
+ int rc = of_property_read_u32_array(np,
+ "qcom,panel-roi-alignment", value, len);
+ if (rc)
+ pr_debug("%s: Error reading panel roi alignment values",
+ __func__);
+ else {
+ pinfo->xstart_pix_align = value[0];
+ pinfo->width_pix_align = value[1];
+ pinfo->ystart_pix_align = value[2];
+ pinfo->height_pix_align = value[3];
+ pinfo->min_width = value[4];
+ pinfo->min_height = value[5];
+ }
+
+ pr_debug("%s: ROI alignment: [%d, %d, %d, %d, %d, %d]",
+ __func__, pinfo->xstart_pix_align,
+ pinfo->width_pix_align, pinfo->ystart_pix_align,
+ pinfo->height_pix_align, pinfo->min_width,
+ pinfo->min_height);
+ }
+}
+
static int mdss_dsi_parse_panel_features(struct device_node *np,
struct mdss_dsi_ctrl_pdata *ctrl)
{
@@ -1020,6 +1053,7 @@
pinfo->mipi.init_delay = (!rc ? tmp : 0);
mdss_dsi_parse_fbc_params(np, pinfo);
+ mdss_dsi_parse_roi_alignment(np, pinfo);
mdss_dsi_parse_trigger(np, &(pinfo->mipi.mdp_trigger),
"qcom,mdss-dsi-mdp-trigger");
diff --git a/drivers/video/msm/mdss/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c
index da2ae5f..a66f4b6 100644
--- a/drivers/video/msm/mdss/mdss_fb.c
+++ b/drivers/video/msm/mdss/mdss_fb.c
@@ -374,12 +374,32 @@
return ret;
}
+static ssize_t mdss_fb_get_panel_info(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct fb_info *fbi = dev_get_drvdata(dev);
+ struct msm_fb_data_type *mfd = fbi->par;
+ struct mdss_panel_info *pinfo = mfd->panel_info;
+ int ret;
+
+ ret = scnprintf(buf, PAGE_SIZE,
+ "pu_en=%d\nxstart=%d\nwalign=%d\nystart=%d\nhalign=%d\n"
+ "min_w=%d\nmin_h=%d",
+ pinfo->partial_update_enabled, pinfo->xstart_pix_align,
+ pinfo->width_pix_align, pinfo->ystart_pix_align,
+ pinfo->height_pix_align, pinfo->min_width,
+ pinfo->min_height);
+
+ return ret;
+}
+
static DEVICE_ATTR(msm_fb_type, S_IRUGO, mdss_fb_get_type, NULL);
static DEVICE_ATTR(msm_fb_split, S_IRUGO, mdss_fb_get_split, NULL);
static DEVICE_ATTR(show_blank_event, S_IRUGO, mdss_mdp_show_blank_event, NULL);
static DEVICE_ATTR(idle_time, S_IRUGO | S_IWUSR | S_IWGRP,
mdss_fb_get_idle_time, mdss_fb_set_idle_time);
static DEVICE_ATTR(idle_notify, S_IRUGO, mdss_fb_get_idle_notify, NULL);
+static DEVICE_ATTR(msm_fb_panel_info, S_IRUGO, mdss_fb_get_panel_info, NULL);
static struct attribute *mdss_fb_attrs[] = {
&dev_attr_msm_fb_type.attr,
@@ -387,6 +407,7 @@
&dev_attr_show_blank_event.attr,
&dev_attr_idle_time.attr,
&dev_attr_idle_notify.attr,
+ &dev_attr_msm_fb_panel_info.attr,
NULL,
};
diff --git a/drivers/video/msm/mdss/mdss_mdp.c b/drivers/video/msm/mdss/mdss_mdp.c
index 097d568..250b163 100644
--- a/drivers/video/msm/mdss/mdss_mdp.c
+++ b/drivers/video/msm/mdss/mdss_mdp.c
@@ -329,7 +329,7 @@
pr_debug("register bus_hdl=%x\n", mdata->bus_hdl);
}
- return mdss_mdp_bus_scale_set_quota(AB_QUOTA, IB_QUOTA);
+ return mdss_bus_scale_set_quota(MDSS_HW_MDP, AB_QUOTA, IB_QUOTA);
}
static void mdss_mdp_bus_scale_unregister(struct mdss_data_type *mdata)
@@ -396,6 +396,29 @@
new_uc_idx);
}
+int mdss_bus_scale_set_quota(int client, u64 ab_quota, u64 ib_quota)
+{
+ int rc = 0;
+ int i;
+ u64 total_ab = 0;
+ u64 total_ib = 0;
+
+ mutex_lock(&bus_bw_lock);
+
+ mdss_res->ab[client] = ab_quota;
+ mdss_res->ib[client] = ib_quota;
+ for (i = 0; i < MDSS_MAX_HW_BLK; i++) {
+ total_ab += mdss_res->ab[i];
+ total_ib = max(total_ib, mdss_res->ib[i]);
+ }
+
+ rc = mdss_mdp_bus_scale_set_quota(total_ab, total_ib);
+
+ mutex_unlock(&bus_bw_lock);
+
+ return rc;
+}
+
static inline u32 mdss_mdp_irq_mask(u32 intr_type, u32 intf_num)
{
if (intr_type == MDSS_MDP_IRQ_INTF_UNDER_RUN ||
diff --git a/drivers/video/msm/mdss/mdss_mdp_ctl.c b/drivers/video/msm/mdss/mdss_mdp_ctl.c
index 4b7f89d..8a0c9b1 100644
--- a/drivers/video/msm/mdss/mdss_mdp_ctl.c
+++ b/drivers/video/msm/mdss/mdss_mdp_ctl.c
@@ -847,7 +847,7 @@
&mdss_res->ab_factor);
trace_mdp_perf_update_bus(bus_ab_quota, bus_ib_quota);
ATRACE_INT("bus_quota", bus_ib_quota);
- mdss_mdp_bus_scale_set_quota(bus_ab_quota, bus_ib_quota);
+ mdss_bus_scale_set_quota(MDSS_HW_MDP, bus_ab_quota, bus_ib_quota);
pr_debug("ab=%llu ib=%llu\n", bus_ab_quota, bus_ib_quota);
ATRACE_END(__func__);
}
diff --git a/drivers/video/msm/mdss/mdss_mdp_pipe.c b/drivers/video/msm/mdss/mdss_mdp_pipe.c
index 32b8cbf..70544c0 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pipe.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pipe.c
@@ -924,8 +924,17 @@
dst = pipe->dst;
src = pipe->src;
- if (pipe->mixer->type == MDSS_MDP_MIXER_TYPE_INTF)
+ if (pipe->mixer->type == MDSS_MDP_MIXER_TYPE_INTF) {
mdss_mdp_crop_rect(&src, &dst, &sci);
+ if (pipe->flags & MDP_FLIP_LR) {
+ src.x = pipe->src.x + (pipe->src.x + pipe->src.w)
+ - (src.x + src.w);
+ }
+ if (pipe->flags & MDP_FLIP_UD) {
+ src.y = pipe->src.y + (pipe->src.y + pipe->src.h)
+ - (src.y + src.h);
+ }
+ }
src_size = (src.h << 16) | src.w;
src_xy = (src.y << 16) | src.x;
diff --git a/drivers/video/msm/mdss/mdss_panel.h b/drivers/video/msm/mdss/mdss_panel.h
index 8393bed..c43cdd3 100644
--- a/drivers/video/msm/mdss/mdss_panel.h
+++ b/drivers/video/msm/mdss/mdss_panel.h
@@ -324,6 +324,13 @@
int new_fps;
int panel_max_fps;
int panel_max_vtotal;
+ u32 xstart_pix_align;
+ u32 width_pix_align;
+ u32 ystart_pix_align;
+ u32 height_pix_align;
+ u32 min_width;
+ u32 min_height;
+
u32 cont_splash_enabled;
u32 partial_update_enabled;
struct ion_handle *splash_ihdl;
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index 44fe134..b93f693 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -338,6 +338,10 @@
* @regs: ioremapped register base address.
* @inputs: OTG state machine inputs(Id, SessValid etc).
* @sm_work: OTG state machine work.
+ * @pm_suspended: OTG device is system(PM) suspended.
+ * @pm_notify: Notifier to receive system wide PM transition events.
+ It is used to defer wakeup events processing until
+ system is RESUMED.
* @in_lpm: indicates low power mode (LPM) state.
* @async_int: IRQ line on which ASYNC interrupt arrived in LPM.
* @cur_power: The amount of mA available from downstream port.
@@ -401,6 +405,7 @@
struct work_struct sm_work;
bool sm_work_pending;
atomic_t pm_suspended;
+ struct notifier_block pm_notify;
atomic_t in_lpm;
int async_int;
unsigned cur_power;
diff --git a/include/net/netlink.h b/include/net/netlink.h
index f394fe5..c0f13ad 100644
--- a/include/net/netlink.h
+++ b/include/net/netlink.h
@@ -98,6 +98,10 @@
* nla_put_u16(skb, type, value) add u16 attribute to skb
* nla_put_u32(skb, type, value) add u32 attribute to skb
* nla_put_u64(skb, type, value) add u64 attribute to skb
+ * nla_put_s8(skb, type, value) add s8 attribute to skb
+ * nla_put_s16(skb, type, value) add s16 attribute to skb
+ * nla_put_s32(skb, type, value) add s32 attribute to skb
+ * nla_put_s64(skb, type, value) add s64 attribute to skb
* nla_put_string(skb, type, str) add string attribute to skb
* nla_put_flag(skb, type) add flag attribute to skb
* nla_put_msecs(skb, type, jiffies) add msecs attribute to skb
@@ -135,6 +139,10 @@
* nla_get_u16(nla) get payload for a u16 attribute
* nla_get_u32(nla) get payload for a u32 attribute
* nla_get_u64(nla) get payload for a u64 attribute
+ * nla_get_s8(nla) get payload for a s8 attribute
+ * nla_get_s16(nla) get payload for a s16 attribute
+ * nla_get_s32(nla) get payload for a s32 attribute
+ * nla_get_s64(nla) get payload for a s64 attribute
* nla_get_flag(nla) return 1 if flag is true
* nla_get_msecs(nla) get payload for a msecs attribute
*
@@ -174,6 +182,10 @@
NLA_NESTED_COMPAT,
NLA_NUL_STRING,
NLA_BINARY,
+ NLA_S8,
+ NLA_S16,
+ NLA_S32,
+ NLA_S64,
__NLA_TYPE_MAX,
};
@@ -200,6 +212,8 @@
* NLA_MSECS Leaving the length field zero will verify the
* given type fits, using it verifies minimum length
* just like "All other"
+ * NLA_S8, NLA_S16,
+ * NLA_S32, NLA_S64,
* All other Minimum length of attribute payload
*
* Example:
@@ -794,6 +808,50 @@
}
/**
+ * nla_put_s8 - Add a s8 netlink attribute to a socket buffer
+ * @skb: socket buffer to add attribute to
+ * @attrtype: attribute type
+ * @value: numeric value
+ */
+static inline int nla_put_s8(struct sk_buff *skb, int attrtype, s8 value)
+{
+ return nla_put(skb, attrtype, sizeof(s8), &value);
+}
+
+/**
+ * nla_put_s16 - Add a s16 netlink attribute to a socket buffer
+ * @skb: socket buffer to add attribute to
+ * @attrtype: attribute type
+ * @value: numeric value
+ */
+static inline int nla_put_s16(struct sk_buff *skb, int attrtype, s16 value)
+{
+ return nla_put(skb, attrtype, sizeof(s16), &value);
+}
+
+/**
+ * nla_put_s32 - Add a s32 netlink attribute to a socket buffer
+ * @skb: socket buffer to add attribute to
+ * @attrtype: attribute type
+ * @value: numeric value
+ */
+static inline int nla_put_s32(struct sk_buff *skb, int attrtype, s32 value)
+{
+ return nla_put(skb, attrtype, sizeof(s32), &value);
+}
+
+/**
+ * nla_put_s64 - Add a s64 netlink attribute to a socket buffer
+ * @skb: socket buffer to add attribute to
+ * @attrtype: attribute type
+ * @value: numeric value
+ */
+static inline int nla_put_s64(struct sk_buff *skb, int attrtype, s64 value)
+{
+ return nla_put(skb, attrtype, sizeof(s64), &value);
+}
+
+/**
* nla_put_string - Add a string netlink attribute to a socket buffer
* @skb: socket buffer to add attribute to
* @attrtype: attribute type
@@ -963,6 +1021,46 @@
}
/**
+ * nla_get_s32 - return payload of s32 attribute
+ * @nla: s32 netlink attribute
+ */
+static inline s32 nla_get_s32(const struct nlattr *nla)
+{
+ return *(s32 *) nla_data(nla);
+}
+
+/**
+ * nla_get_s16 - return payload of s16 attribute
+ * @nla: s16 netlink attribute
+ */
+static inline s16 nla_get_s16(const struct nlattr *nla)
+{
+ return *(s16 *) nla_data(nla);
+}
+
+/**
+ * nla_get_s8 - return payload of s8 attribute
+ * @nla: s8 netlink attribute
+ */
+static inline s8 nla_get_s8(const struct nlattr *nla)
+{
+ return *(s8 *) nla_data(nla);
+}
+
+/**
+ * nla_get_s64 - return payload of s64 attribute
+ * @nla: s64 netlink attribute
+ */
+static inline s64 nla_get_s64(const struct nlattr *nla)
+{
+ s64 tmp;
+
+ nla_memcpy(&tmp, nla, sizeof(tmp));
+
+ return tmp;
+}
+
+/**
* nla_get_flag - return payload of flag attribute
* @nla: flag netlink attribute
*/
diff --git a/sound/soc/codecs/wcd9320.c b/sound/soc/codecs/wcd9320.c
index 5602dd1..e17925f 100644
--- a/sound/soc/codecs/wcd9320.c
+++ b/sound/soc/codecs/wcd9320.c
@@ -35,6 +35,9 @@
#include <linux/pm_runtime.h>
#include <linux/kernel.h>
#include <linux/gpio.h>
+#include <linux/pm_qos.h>
+#include <linux/pm.h>
+#include <mach/cpuidle.h>
#include "wcd9320.h"
#include "wcd9xxx-resmgr.h"
#include "wcd9xxx-common.h"
@@ -449,6 +452,7 @@
* end of impedance measurement
*/
struct list_head reg_save_restore;
+ struct pm_qos_request pm_qos_req;
};
static const u32 comp_shift[] = {
@@ -2675,8 +2679,15 @@
const struct firmware *fw;
struct mad_audio_cal *mad_cal;
const char *filename = TAIKO_MAD_AUDIO_FIRMWARE_PATH;
+ struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
pr_debug("%s: enter\n", __func__);
+ /* wakeup for codec calibration access */
+ pm_qos_add_request(&taiko->pm_qos_req,
+ PM_QOS_CPU_DMA_LATENCY,
+ PM_QOS_DEFAULT_VALUE);
+ pm_qos_update_request(&taiko->pm_qos_req,
+ msm_cpuidle_get_deep_idle_latency());
ret = request_firmware(&fw, filename, codec->dev);
if (ret != 0) {
pr_err("Failed to acquire MAD firwmare data %s: %d\n", filename,
@@ -2746,7 +2757,9 @@
release_firmware(fw);
pr_debug("%s: leave ret %d\n", __func__, ret);
-
+ pm_qos_update_request(&taiko->pm_qos_req,
+ PM_QOS_DEFAULT_VALUE);
+ pm_qos_remove_request(&taiko->pm_qos_req);
return ret;
}
diff --git a/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c
index f6702c5..3bc6abe 100644
--- a/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c
@@ -599,6 +599,16 @@
prtd->session_id,
SNDRV_PCM_STREAM_PLAYBACK);
+ /*
+ * Setting the master volume gain to 0 while
+ * configuring ASM session. This is to address
+ * DSP pop noise issue where. This change is
+ * there from begining may be DSP limitation
+ */
+ ret = msm_compr_set_volume(cstream, 0, 0);
+ if (ret < 0)
+ pr_err("%s : Set Volume failed : %d", __func__, ret);
+
ret = q6asm_set_softvolume(ac, &softvol);
if (ret < 0)
pr_err("%s: Send SoftVolume Param failed ret=%d\n",