blob: 4b6ba6783abe9aeee9f51ccabe02952253609f71 [file] [log] [blame]
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001/* drivers/serial/msm_serial_hs.c
Mayank Rana55046232011-03-07 10:28:42 +05302 *
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003 * MSM 7k High speed uart driver
4 *
Mayank Rana55046232011-03-07 10:28:42 +05305 * Copyright (c) 2008 Google Inc.
Mayank Ranaadc41562013-01-04 12:44:01 +05306 * Copyright (c) 2007-2013, The Linux Foundation. All rights reserved.
Mayank Rana55046232011-03-07 10:28:42 +05307 * Modified: Nick Pelly <npelly@google.com>
8 *
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07009 * All source code in this file is licensed under the following license
10 * except where indicated.
11 *
Mayank Rana55046232011-03-07 10:28:42 +053012 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * version 2 as published by the Free Software Foundation.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 * See the GNU General Public License for more details.
20 *
21 * Has optional support for uart power management independent of linux
22 * suspend/resume:
23 *
24 * RX wakeup.
25 * UART wakeup can be triggered by RX activity (using a wakeup GPIO on the
26 * UART RX pin). This should only be used if there is not a wakeup
27 * GPIO on the UART CTS, and the first RX byte is known (for example, with the
28 * Bluetooth Texas Instruments HCILL protocol), since the first RX byte will
29 * always be lost. RTS will be asserted even while the UART is off in this mode
30 * of operation. See msm_serial_hs_platform_data.rx_wakeup_irq.
31 */
32
33#include <linux/module.h>
34
35#include <linux/serial.h>
36#include <linux/serial_core.h>
37#include <linux/slab.h>
38#include <linux/init.h>
39#include <linux/interrupt.h>
40#include <linux/irq.h>
41#include <linux/io.h>
42#include <linux/ioport.h>
Saket Saurabh10e88b32013-02-04 15:26:34 +053043#include <linux/atomic.h>
Mayank Rana55046232011-03-07 10:28:42 +053044#include <linux/kernel.h>
45#include <linux/timer.h>
46#include <linux/clk.h>
47#include <linux/platform_device.h>
48#include <linux/pm_runtime.h>
49#include <linux/dma-mapping.h>
50#include <linux/dmapool.h>
Steve Mucklef132c6c2012-06-06 18:30:57 -070051#include <linux/tty_flip.h>
Mayank Rana55046232011-03-07 10:28:42 +053052#include <linux/wait.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070053#include <linux/sysfs.h>
54#include <linux/stat.h>
55#include <linux/device.h>
56#include <linux/wakelock.h>
57#include <linux/debugfs.h>
Mayank Ranaff398d02012-12-18 10:22:50 +053058#include <linux/of.h>
59#include <linux/of_device.h>
60#include <linux/of_gpio.h>
Saket Saurabhfe3b93b2013-02-04 18:44:12 +053061#include <linux/gpio.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070062#include <asm/atomic.h>
Mayank Rana55046232011-03-07 10:28:42 +053063#include <asm/irq.h>
Mayank Rana55046232011-03-07 10:28:42 +053064
65#include <mach/hardware.h>
66#include <mach/dma.h>
Saket Saurabhcbf6c522013-01-07 16:30:37 +053067#include <mach/sps.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070068#include <mach/msm_serial_hs.h>
Mayank Rana88d49142013-01-16 17:28:53 +053069#include <mach/msm_bus.h>
Mayank Rana55046232011-03-07 10:28:42 +053070
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070071#include "msm_serial_hs_hwreg.h"
Saket Saurabhcbf6c522013-01-07 16:30:37 +053072#define UART_SPS_CONS_PERIPHERAL 0
73#define UART_SPS_PROD_PERIPHERAL 1
Mayank Rana55046232011-03-07 10:28:42 +053074
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070075static int hs_serial_debug_mask = 1;
76module_param_named(debug_mask, hs_serial_debug_mask,
77 int, S_IRUGO | S_IWUSR | S_IWGRP);
Mayank Ranaff398d02012-12-18 10:22:50 +053078/*
79 * There are 3 different kind of UART Core available on MSM.
80 * High Speed UART (i.e. Legacy HSUART), GSBI based HSUART
81 * and BSLP based HSUART.
82 */
83enum uart_core_type {
84 LEGACY_HSUART,
85 GSBI_HSUART,
86 BLSP_HSUART,
87};
Mayank Rana55046232011-03-07 10:28:42 +053088
Mayank Rana55046232011-03-07 10:28:42 +053089enum flush_reason {
90 FLUSH_NONE,
91 FLUSH_DATA_READY,
92 FLUSH_DATA_INVALID, /* values after this indicate invalid data */
93 FLUSH_IGNORE = FLUSH_DATA_INVALID,
94 FLUSH_STOP,
95 FLUSH_SHUTDOWN,
96};
97
Mayank Rana55046232011-03-07 10:28:42 +053098enum msm_hs_clk_states_e {
99 MSM_HS_CLK_PORT_OFF, /* port not in use */
100 MSM_HS_CLK_OFF, /* clock disabled */
101 MSM_HS_CLK_REQUEST_OFF, /* disable after TX and RX flushed */
102 MSM_HS_CLK_ON, /* clock enabled */
103};
104
105/* Track the forced RXSTALE flush during clock off sequence.
106 * These states are only valid during MSM_HS_CLK_REQUEST_OFF */
107enum msm_hs_clk_req_off_state_e {
108 CLK_REQ_OFF_START,
109 CLK_REQ_OFF_RXSTALE_ISSUED,
110 CLK_REQ_OFF_FLUSH_ISSUED,
111 CLK_REQ_OFF_RXSTALE_FLUSHED,
112};
113
Saket Saurabhcbf6c522013-01-07 16:30:37 +0530114/* SPS data structures to support HSUART with BAM
115 * @sps_pipe - This struct defines BAM pipe descriptor
116 * @sps_connect - This struct defines a connection's end point
117 * @sps_register - This struct defines a event registration parameters
118 */
119struct msm_hs_sps_ep_conn_data {
120 struct sps_pipe *pipe_handle;
121 struct sps_connect config;
122 struct sps_register_event event;
123};
124
Mayank Rana55046232011-03-07 10:28:42 +0530125struct msm_hs_tx {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700126 unsigned int tx_ready_int_en; /* ok to dma more tx */
127 unsigned int dma_in_flight; /* tx dma in progress */
Mayank Ranaaf2f0082012-05-22 10:16:02 +0530128 enum flush_reason flush;
129 wait_queue_head_t wait;
Mayank Rana55046232011-03-07 10:28:42 +0530130 struct msm_dmov_cmd xfer;
131 dmov_box *command_ptr;
132 u32 *command_ptr_ptr;
133 dma_addr_t mapped_cmd_ptr;
134 dma_addr_t mapped_cmd_ptr_ptr;
135 int tx_count;
136 dma_addr_t dma_base;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700137 struct tasklet_struct tlet;
Saket Saurabhcbf6c522013-01-07 16:30:37 +0530138 struct msm_hs_sps_ep_conn_data cons;
Mayank Rana55046232011-03-07 10:28:42 +0530139};
140
Mayank Rana55046232011-03-07 10:28:42 +0530141struct msm_hs_rx {
142 enum flush_reason flush;
143 struct msm_dmov_cmd xfer;
144 dma_addr_t cmdptr_dmaaddr;
145 dmov_box *command_ptr;
146 u32 *command_ptr_ptr;
147 dma_addr_t mapped_cmd_ptr;
148 wait_queue_head_t wait;
149 dma_addr_t rbuffer;
150 unsigned char *buffer;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700151 unsigned int buffer_pending;
Mayank Rana55046232011-03-07 10:28:42 +0530152 struct dma_pool *pool;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700153 struct wake_lock wake_lock;
154 struct delayed_work flip_insert_work;
155 struct tasklet_struct tlet;
Saket Saurabhcbf6c522013-01-07 16:30:37 +0530156 struct msm_hs_sps_ep_conn_data prod;
Mayank Rana55046232011-03-07 10:28:42 +0530157};
158
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700159enum buffer_states {
160 NONE_PENDING = 0x0,
161 FIFO_OVERRUN = 0x1,
162 PARITY_ERROR = 0x2,
163 CHARS_NORMAL = 0x4,
164};
165
166/* optional low power wakeup, typically on a GPIO RX irq */
167struct msm_hs_wakeup {
Mayank Rana55046232011-03-07 10:28:42 +0530168 int irq; /* < 0 indicates low power wakeup disabled */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700169 unsigned char ignore; /* bool */
170
171 /* bool: inject char into rx tty on wakeup */
Mayank Rana55046232011-03-07 10:28:42 +0530172 unsigned char inject_rx;
173 char rx_to_inject;
174};
175
Mayank Rana55046232011-03-07 10:28:42 +0530176struct msm_hs_port {
177 struct uart_port uport;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700178 unsigned long imr_reg; /* shadow value of UARTDM_IMR */
Mayank Rana55046232011-03-07 10:28:42 +0530179 struct clk *clk;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700180 struct clk *pclk;
Mayank Rana55046232011-03-07 10:28:42 +0530181 struct msm_hs_tx tx;
182 struct msm_hs_rx rx;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700183 /* gsbi uarts have to do additional writes to gsbi memory */
184 /* block and top control status block. The following pointers */
185 /* keep a handle to these blocks. */
186 unsigned char __iomem *mapped_gsbi;
Mayank Rana55046232011-03-07 10:28:42 +0530187 int dma_tx_channel;
188 int dma_rx_channel;
189 int dma_tx_crci;
190 int dma_rx_crci;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700191 struct hrtimer clk_off_timer; /* to poll TXEMT before clock off */
Mayank Rana55046232011-03-07 10:28:42 +0530192 ktime_t clk_off_delay;
193 enum msm_hs_clk_states_e clk_state;
194 enum msm_hs_clk_req_off_state_e clk_req_off_state;
195
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700196 struct msm_hs_wakeup wakeup;
197 struct wake_lock dma_wake_lock; /* held while any DMA active */
Mayank Rana17e0e1a2012-04-07 02:10:33 +0530198
199 struct dentry *loopback_dir;
Mayank Ranacb589d82012-03-01 11:50:03 +0530200 struct work_struct clock_off_w; /* work for actual clock off */
201 struct workqueue_struct *hsuart_wq; /* hsuart workqueue */
202 struct mutex clk_mutex; /* mutex to guard against clock off/clock on */
Saket Saurabhcbf6c522013-01-07 16:30:37 +0530203 struct work_struct reset_bam_rx; /* work for reset bam rx endpoint */
204 struct work_struct disconnect_rx_endpoint; /* disconnect rx_endpoint */
Saket Saurabhce394102012-10-29 19:51:28 +0530205 bool tty_flush_receive;
Mayank Ranaff398d02012-12-18 10:22:50 +0530206 enum uart_core_type uart_type;
207 u32 bam_handle;
208 resource_size_t bam_mem;
209 int bam_irq;
210 unsigned char __iomem *bam_base;
211 unsigned int bam_tx_ep_pipe_index;
212 unsigned int bam_rx_ep_pipe_index;
Saket Saurabhcbf6c522013-01-07 16:30:37 +0530213 /* struct sps_event_notify is an argument passed when triggering a
214 * callback event object registered for an SPS connection end point.
215 */
216 struct sps_event_notify notify;
Mayank Rana88d49142013-01-16 17:28:53 +0530217 /* bus client handler */
218 u32 bus_perf_client;
219 /* BLSP UART required BUS Scaling data */
220 struct msm_bus_scale_pdata *bus_scale_table;
Mayank Rana55046232011-03-07 10:28:42 +0530221};
222
223#define MSM_UARTDM_BURST_SIZE 16 /* DM burst size (in bytes) */
224#define UARTDM_TX_BUF_SIZE UART_XMIT_SIZE
225#define UARTDM_RX_BUF_SIZE 512
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700226#define RETRY_TIMEOUT 5
Saket Saurabh51690e52012-08-17 14:17:46 +0530227#define UARTDM_NR 256
Mayank Ranaff398d02012-12-18 10:22:50 +0530228#define BAM_PIPE_MIN 0
229#define BAM_PIPE_MAX 11
Mayank Ranae4bc7de2013-01-22 12:51:16 +0530230#define BUS_SCALING 1
231#define BUS_RESET 0
Mayank Rana55046232011-03-07 10:28:42 +0530232
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700233static struct dentry *debug_base;
Mayank Rana55046232011-03-07 10:28:42 +0530234static struct msm_hs_port q_uart_port[UARTDM_NR];
235static struct platform_driver msm_serial_hs_platform_driver;
236static struct uart_driver msm_hs_driver;
237static struct uart_ops msm_hs_ops;
Saket Saurabhcbf6c522013-01-07 16:30:37 +0530238static void msm_hs_start_rx_locked(struct uart_port *uport);
239static void msm_serial_hs_rx_tlet(unsigned long tlet_ptr);
240static void flip_insert_work(struct work_struct *work);
Mayank Rana55046232011-03-07 10:28:42 +0530241
242#define UARTDM_TO_MSM(uart_port) \
243 container_of((uart_port), struct msm_hs_port, uport)
244
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700245static ssize_t show_clock(struct device *dev, struct device_attribute *attr,
246 char *buf)
Mayank Rana55046232011-03-07 10:28:42 +0530247{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700248 int state = 1;
249 enum msm_hs_clk_states_e clk_state;
250 unsigned long flags;
251
252 struct platform_device *pdev = container_of(dev, struct
253 platform_device, dev);
254 struct msm_hs_port *msm_uport = &q_uart_port[pdev->id];
255
256 spin_lock_irqsave(&msm_uport->uport.lock, flags);
257 clk_state = msm_uport->clk_state;
258 spin_unlock_irqrestore(&msm_uport->uport.lock, flags);
259
260 if (clk_state <= MSM_HS_CLK_OFF)
261 state = 0;
262
Mayank Rana18958b02011-09-28 12:33:36 +0530263 return snprintf(buf, PAGE_SIZE, "%d\n", state);
Mayank Rana55046232011-03-07 10:28:42 +0530264}
265
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700266static ssize_t set_clock(struct device *dev, struct device_attribute *attr,
267 const char *buf, size_t count)
268{
269 int state;
270 struct platform_device *pdev = container_of(dev, struct
271 platform_device, dev);
272 struct msm_hs_port *msm_uport = &q_uart_port[pdev->id];
273
274 state = buf[0] - '0';
275 switch (state) {
276 case 0: {
277 msm_hs_request_clock_off(&msm_uport->uport);
278 break;
279 }
280 case 1: {
281 msm_hs_request_clock_on(&msm_uport->uport);
282 break;
283 }
284 default: {
285 return -EINVAL;
286 }
287 }
288 return count;
289}
290
291static DEVICE_ATTR(clock, S_IWUSR | S_IRUGO, show_clock, set_clock);
292
293static inline unsigned int use_low_power_wakeup(struct msm_hs_port *msm_uport)
294{
295 return (msm_uport->wakeup.irq > 0);
296}
297
298static inline int is_gsbi_uart(struct msm_hs_port *msm_uport)
299{
300 /* assume gsbi uart if gsbi resource found in pdata */
301 return ((msm_uport->mapped_gsbi != NULL));
302}
Mayank Ranaff398d02012-12-18 10:22:50 +0530303static unsigned int is_blsp_uart(struct msm_hs_port *msm_uport)
304{
305 return (msm_uport->uart_type == BLSP_HSUART);
306}
Mayank Ranae4bc7de2013-01-22 12:51:16 +0530307
308static void msm_hs_bus_voting(struct msm_hs_port *msm_uport, unsigned int vote)
309{
310 int ret;
311
312 if (is_blsp_uart(msm_uport) && msm_uport->bus_perf_client) {
313 pr_debug("Bus voting:%d\n", vote);
314 ret = msm_bus_scale_client_update_request(
315 msm_uport->bus_perf_client, vote);
316 if (ret)
317 pr_err("%s(): Failed for Bus voting: %d\n",
318 __func__, vote);
319 }
320}
321
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700322static inline unsigned int msm_hs_read(struct uart_port *uport,
Mayank Rana55046232011-03-07 10:28:42 +0530323 unsigned int offset)
324{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700325 return readl_relaxed(uport->membase + offset);
Mayank Rana55046232011-03-07 10:28:42 +0530326}
327
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700328static inline void msm_hs_write(struct uart_port *uport, unsigned int offset,
Mayank Rana55046232011-03-07 10:28:42 +0530329 unsigned int value)
330{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700331 writel_relaxed(value, uport->membase + offset);
Mayank Rana55046232011-03-07 10:28:42 +0530332}
333
334static void msm_hs_release_port(struct uart_port *port)
335{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700336 struct msm_hs_port *msm_uport = UARTDM_TO_MSM(port);
337 struct platform_device *pdev = to_platform_device(port->dev);
338 struct resource *gsbi_resource;
339 resource_size_t size;
340
341 if (is_gsbi_uart(msm_uport)) {
342 iowrite32(GSBI_PROTOCOL_IDLE, msm_uport->mapped_gsbi +
343 GSBI_CONTROL_ADDR);
344 gsbi_resource = platform_get_resource_byname(pdev,
345 IORESOURCE_MEM,
346 "gsbi_resource");
Mayank Rana53a2c772011-11-01 14:29:14 +0530347 if (unlikely(!gsbi_resource))
348 return;
349
350 size = resource_size(gsbi_resource);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700351 release_mem_region(gsbi_resource->start, size);
352 iounmap(msm_uport->mapped_gsbi);
353 msm_uport->mapped_gsbi = NULL;
354 }
Mayank Rana55046232011-03-07 10:28:42 +0530355}
356
357static int msm_hs_request_port(struct uart_port *port)
358{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700359 struct msm_hs_port *msm_uport = UARTDM_TO_MSM(port);
360 struct platform_device *pdev = to_platform_device(port->dev);
361 struct resource *gsbi_resource;
362 resource_size_t size;
Mayank Rana55046232011-03-07 10:28:42 +0530363
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700364 gsbi_resource = platform_get_resource_byname(pdev,
365 IORESOURCE_MEM,
366 "gsbi_resource");
367 if (gsbi_resource) {
Mayank Rana53a2c772011-11-01 14:29:14 +0530368 size = resource_size(gsbi_resource);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700369 if (unlikely(!request_mem_region(gsbi_resource->start, size,
370 "msm_serial_hs")))
371 return -EBUSY;
372 msm_uport->mapped_gsbi = ioremap(gsbi_resource->start,
373 size);
374 if (!msm_uport->mapped_gsbi) {
375 release_mem_region(gsbi_resource->start, size);
376 return -EBUSY;
377 }
378 }
379 /* no gsbi uart */
Mayank Rana55046232011-03-07 10:28:42 +0530380 return 0;
381}
382
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700383static int msm_serial_loopback_enable_set(void *data, u64 val)
384{
385 struct msm_hs_port *msm_uport = data;
386 struct uart_port *uport = &(msm_uport->uport);
387 unsigned long flags;
388 int ret = 0;
389
Mayank Ranae4bc7de2013-01-22 12:51:16 +0530390 msm_hs_bus_voting(msm_uport, BUS_SCALING);
391
Mayank Ranacb589d82012-03-01 11:50:03 +0530392 clk_prepare_enable(msm_uport->clk);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700393 if (msm_uport->pclk)
Mayank Ranacb589d82012-03-01 11:50:03 +0530394 clk_prepare_enable(msm_uport->pclk);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700395
396 if (val) {
397 spin_lock_irqsave(&uport->lock, flags);
398 ret = msm_hs_read(uport, UARTDM_MR2_ADDR);
Saket Saurabhcbf6c522013-01-07 16:30:37 +0530399 if (is_blsp_uart(msm_uport))
400 ret |= (UARTDM_MR2_LOOP_MODE_BMSK |
401 UARTDM_MR2_RFR_CTS_LOOP_MODE_BMSK);
402 else
403 ret |= UARTDM_MR2_LOOP_MODE_BMSK;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700404 msm_hs_write(uport, UARTDM_MR2_ADDR, ret);
405 spin_unlock_irqrestore(&uport->lock, flags);
406 } else {
407 spin_lock_irqsave(&uport->lock, flags);
408 ret = msm_hs_read(uport, UARTDM_MR2_ADDR);
Saket Saurabhcbf6c522013-01-07 16:30:37 +0530409 if (is_blsp_uart(msm_uport))
410 ret &= ~(UARTDM_MR2_LOOP_MODE_BMSK |
411 UARTDM_MR2_RFR_CTS_LOOP_MODE_BMSK);
412 else
413 ret &= ~UARTDM_MR2_LOOP_MODE_BMSK;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700414 msm_hs_write(uport, UARTDM_MR2_ADDR, ret);
415 spin_unlock_irqrestore(&uport->lock, flags);
416 }
417 /* Calling CLOCK API. Hence mb() requires here. */
418 mb();
Mayank Ranacb589d82012-03-01 11:50:03 +0530419 clk_disable_unprepare(msm_uport->clk);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700420 if (msm_uport->pclk)
Mayank Ranacb589d82012-03-01 11:50:03 +0530421 clk_disable_unprepare(msm_uport->pclk);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700422
Mayank Ranae4bc7de2013-01-22 12:51:16 +0530423 msm_hs_bus_voting(msm_uport, BUS_RESET);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700424 return 0;
425}
426
427static int msm_serial_loopback_enable_get(void *data, u64 *val)
428{
429 struct msm_hs_port *msm_uport = data;
430 struct uart_port *uport = &(msm_uport->uport);
431 unsigned long flags;
432 int ret = 0;
433
Mayank Ranae4bc7de2013-01-22 12:51:16 +0530434 msm_hs_bus_voting(msm_uport, BUS_SCALING);
435
Mayank Ranacb589d82012-03-01 11:50:03 +0530436 clk_prepare_enable(msm_uport->clk);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700437 if (msm_uport->pclk)
Mayank Ranacb589d82012-03-01 11:50:03 +0530438 clk_prepare_enable(msm_uport->pclk);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700439
440 spin_lock_irqsave(&uport->lock, flags);
441 ret = msm_hs_read(&msm_uport->uport, UARTDM_MR2_ADDR);
442 spin_unlock_irqrestore(&uport->lock, flags);
443
Mayank Ranacb589d82012-03-01 11:50:03 +0530444 clk_disable_unprepare(msm_uport->clk);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700445 if (msm_uport->pclk)
Mayank Ranacb589d82012-03-01 11:50:03 +0530446 clk_disable_unprepare(msm_uport->pclk);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700447
448 *val = (ret & UARTDM_MR2_LOOP_MODE_BMSK) ? 1 : 0;
Mayank Ranae4bc7de2013-01-22 12:51:16 +0530449
450 msm_hs_bus_voting(msm_uport, BUS_RESET);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700451 return 0;
452}
453DEFINE_SIMPLE_ATTRIBUTE(loopback_enable_fops, msm_serial_loopback_enable_get,
454 msm_serial_loopback_enable_set, "%llu\n");
455
456/*
457 * msm_serial_hs debugfs node: <debugfs_root>/msm_serial_hs/loopback.<id>
458 * writing 1 turns on internal loopback mode in HW. Useful for automation
459 * test scripts.
460 * writing 0 disables the internal loopback mode. Default is disabled.
461 */
Stephen Boyd7bce0972012-04-25 11:54:27 -0700462static void __devinit msm_serial_debugfs_init(struct msm_hs_port *msm_uport,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700463 int id)
464{
465 char node_name[15];
466 snprintf(node_name, sizeof(node_name), "loopback.%d", id);
Mayank Rana17e0e1a2012-04-07 02:10:33 +0530467 msm_uport->loopback_dir = debugfs_create_file(node_name,
468 S_IRUGO | S_IWUSR,
469 debug_base,
470 msm_uport,
471 &loopback_enable_fops);
472
473 if (IS_ERR_OR_NULL(msm_uport->loopback_dir))
474 pr_err("%s(): Cannot create loopback.%d debug entry",
475 __func__, id);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700476}
477
Mayank Rana55046232011-03-07 10:28:42 +0530478static int __devexit msm_hs_remove(struct platform_device *pdev)
479{
480
481 struct msm_hs_port *msm_uport;
482 struct device *dev;
483
484 if (pdev->id < 0 || pdev->id >= UARTDM_NR) {
485 printk(KERN_ERR "Invalid plaform device ID = %d\n", pdev->id);
486 return -EINVAL;
487 }
488
489 msm_uport = &q_uart_port[pdev->id];
490 dev = msm_uport->uport.dev;
491
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700492 sysfs_remove_file(&pdev->dev.kobj, &dev_attr_clock.attr);
Mayank Rana17e0e1a2012-04-07 02:10:33 +0530493 debugfs_remove(msm_uport->loopback_dir);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700494
Mayank Rana55046232011-03-07 10:28:42 +0530495 dma_unmap_single(dev, msm_uport->rx.mapped_cmd_ptr, sizeof(dmov_box),
496 DMA_TO_DEVICE);
497 dma_pool_free(msm_uport->rx.pool, msm_uport->rx.buffer,
498 msm_uport->rx.rbuffer);
499 dma_pool_destroy(msm_uport->rx.pool);
500
Mayank Rana8431de82011-12-08 09:06:08 +0530501 dma_unmap_single(dev, msm_uport->rx.cmdptr_dmaaddr, sizeof(u32),
Mayank Rana55046232011-03-07 10:28:42 +0530502 DMA_TO_DEVICE);
Mayank Rana8431de82011-12-08 09:06:08 +0530503 dma_unmap_single(dev, msm_uport->tx.mapped_cmd_ptr_ptr, sizeof(u32),
Mayank Rana55046232011-03-07 10:28:42 +0530504 DMA_TO_DEVICE);
505 dma_unmap_single(dev, msm_uport->tx.mapped_cmd_ptr, sizeof(dmov_box),
506 DMA_TO_DEVICE);
507
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700508 wake_lock_destroy(&msm_uport->rx.wake_lock);
509 wake_lock_destroy(&msm_uport->dma_wake_lock);
Mayank Ranacb589d82012-03-01 11:50:03 +0530510 destroy_workqueue(msm_uport->hsuart_wq);
511 mutex_destroy(&msm_uport->clk_mutex);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700512
Mayank Rana55046232011-03-07 10:28:42 +0530513 uart_remove_one_port(&msm_hs_driver, &msm_uport->uport);
514 clk_put(msm_uport->clk);
Mayank Ranacb589d82012-03-01 11:50:03 +0530515 if (msm_uport->pclk)
516 clk_put(msm_uport->pclk);
Mayank Rana55046232011-03-07 10:28:42 +0530517
518 /* Free the tx resources */
519 kfree(msm_uport->tx.command_ptr);
520 kfree(msm_uport->tx.command_ptr_ptr);
521
522 /* Free the rx resources */
523 kfree(msm_uport->rx.command_ptr);
524 kfree(msm_uport->rx.command_ptr_ptr);
525
526 iounmap(msm_uport->uport.membase);
527
528 return 0;
529}
530
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700531static int msm_hs_init_clk(struct uart_port *uport)
Mayank Rana55046232011-03-07 10:28:42 +0530532{
533 int ret;
534 struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
535
Mayank Rana55046232011-03-07 10:28:42 +0530536 /* Set up the MREG/NREG/DREG/MNDREG */
537 ret = clk_set_rate(msm_uport->clk, uport->uartclk);
538 if (ret) {
539 printk(KERN_WARNING "Error setting clock rate on UART\n");
Mayank Rana55046232011-03-07 10:28:42 +0530540 return ret;
541 }
542
Mayank Ranacb589d82012-03-01 11:50:03 +0530543 ret = clk_prepare_enable(msm_uport->clk);
Mayank Rana55046232011-03-07 10:28:42 +0530544 if (ret) {
545 printk(KERN_ERR "Error could not turn on UART clk\n");
546 return ret;
547 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700548 if (msm_uport->pclk) {
Mayank Ranacb589d82012-03-01 11:50:03 +0530549 ret = clk_prepare_enable(msm_uport->pclk);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700550 if (ret) {
Mayank Ranacb589d82012-03-01 11:50:03 +0530551 clk_disable_unprepare(msm_uport->clk);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700552 dev_err(uport->dev,
553 "Error could not turn on UART pclk\n");
554 return ret;
555 }
Mayank Rana55046232011-03-07 10:28:42 +0530556 }
557
558 msm_uport->clk_state = MSM_HS_CLK_ON;
559 return 0;
560}
561
Saket Saurabhcbf6c522013-01-07 16:30:37 +0530562
563/* Connect a UART peripheral's SPS endpoint(consumer endpoint)
564 *
565 * Also registers a SPS callback function for the consumer
566 * process with the SPS driver
567 *
568 * @uport - Pointer to uart uport structure
569 *
570 * @return - 0 if successful else negative value.
571 *
572 */
573
574static int msm_hs_spsconnect_tx(struct uart_port *uport)
575{
576 int ret;
577 struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
578 struct msm_hs_tx *tx = &msm_uport->tx;
579 struct sps_pipe *sps_pipe_handle = tx->cons.pipe_handle;
580 struct sps_connect *sps_config = &tx->cons.config;
581 struct sps_register_event *sps_event = &tx->cons.event;
582
583 /* Establish connection between peripheral and memory endpoint */
584 ret = sps_connect(sps_pipe_handle, sps_config);
585 if (ret) {
586 pr_err("msm_serial_hs: sps_connect() failed for tx!!\n"
587 "pipe_handle=0x%x ret=%d", (u32)sps_pipe_handle, ret);
588 return ret;
589 }
590 /* Register callback event for EOT (End of transfer) event. */
591 ret = sps_register_event(sps_pipe_handle, sps_event);
592 if (ret) {
593 pr_err("msm_serial_hs: sps_connect() failed for tx!!\n"
594 "pipe_handle=0x%x ret=%d", (u32)sps_pipe_handle, ret);
595 goto reg_event_err;
596 }
597 return 0;
598
599reg_event_err:
600 sps_disconnect(sps_pipe_handle);
601 return ret;
602}
603
604/* Connect a UART peripheral's SPS endpoint(producer endpoint)
605 *
606 * Also registers a SPS callback function for the producer
607 * process with the SPS driver
608 *
609 * @uport - Pointer to uart uport structure
610 *
611 * @return - 0 if successful else negative value.
612 *
613 */
614
615static int msm_hs_spsconnect_rx(struct uart_port *uport)
616{
617 int ret;
618 struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
619 struct msm_hs_rx *rx = &msm_uport->rx;
620 struct sps_pipe *sps_pipe_handle = rx->prod.pipe_handle;
621 struct sps_connect *sps_config = &rx->prod.config;
622 struct sps_register_event *sps_event = &rx->prod.event;
623
624 /* Establish connection between peripheral and memory endpoint */
625 ret = sps_connect(sps_pipe_handle, sps_config);
626 if (ret) {
627 pr_err("msm_serial_hs: sps_connect() failed for rx!!\n"
628 "pipe_handle=0x%x ret=%d", (u32)sps_pipe_handle, ret);
629 return ret;
630 }
631 /* Register callback event for EOT (End of transfer) event. */
632 ret = sps_register_event(sps_pipe_handle, sps_event);
633 if (ret) {
634 pr_err("msm_serial_hs: sps_connect() failed for rx!!\n"
635 "pipe_handle=0x%x ret=%d", (u32)sps_pipe_handle, ret);
636 goto reg_event_err;
637 }
638 return 0;
639
640reg_event_err:
641 sps_disconnect(sps_pipe_handle);
642 return ret;
643}
644
Mayank Rana55046232011-03-07 10:28:42 +0530645/*
646 * programs the UARTDM_CSR register with correct bit rates
647 *
648 * Interrupts should be disabled before we are called, as
649 * we modify Set Baud rate
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700650 * Set receive stale interrupt level, dependant on Bit Rate
Mayank Rana55046232011-03-07 10:28:42 +0530651 * Goal is to have around 8 ms before indicate stale.
652 * roundup (((Bit Rate * .008) / 10) + 1
653 */
Saket Saurabhcbf6c522013-01-07 16:30:37 +0530654static void msm_hs_set_bps_locked(struct uart_port *uport,
655 unsigned int bps)
Mayank Rana55046232011-03-07 10:28:42 +0530656{
657 unsigned long rxstale;
658 unsigned long data;
659 struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
660
661 switch (bps) {
662 case 300:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700663 msm_hs_write(uport, UARTDM_CSR_ADDR, 0x00);
Mayank Rana55046232011-03-07 10:28:42 +0530664 rxstale = 1;
665 break;
666 case 600:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700667 msm_hs_write(uport, UARTDM_CSR_ADDR, 0x11);
Mayank Rana55046232011-03-07 10:28:42 +0530668 rxstale = 1;
669 break;
670 case 1200:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700671 msm_hs_write(uport, UARTDM_CSR_ADDR, 0x22);
Mayank Rana55046232011-03-07 10:28:42 +0530672 rxstale = 1;
673 break;
674 case 2400:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700675 msm_hs_write(uport, UARTDM_CSR_ADDR, 0x33);
Mayank Rana55046232011-03-07 10:28:42 +0530676 rxstale = 1;
677 break;
678 case 4800:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700679 msm_hs_write(uport, UARTDM_CSR_ADDR, 0x44);
Mayank Rana55046232011-03-07 10:28:42 +0530680 rxstale = 1;
681 break;
682 case 9600:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700683 msm_hs_write(uport, UARTDM_CSR_ADDR, 0x55);
Mayank Rana55046232011-03-07 10:28:42 +0530684 rxstale = 2;
685 break;
686 case 14400:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700687 msm_hs_write(uport, UARTDM_CSR_ADDR, 0x66);
Mayank Rana55046232011-03-07 10:28:42 +0530688 rxstale = 3;
689 break;
690 case 19200:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700691 msm_hs_write(uport, UARTDM_CSR_ADDR, 0x77);
Mayank Rana55046232011-03-07 10:28:42 +0530692 rxstale = 4;
693 break;
694 case 28800:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700695 msm_hs_write(uport, UARTDM_CSR_ADDR, 0x88);
Mayank Rana55046232011-03-07 10:28:42 +0530696 rxstale = 6;
697 break;
698 case 38400:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700699 msm_hs_write(uport, UARTDM_CSR_ADDR, 0x99);
Mayank Rana55046232011-03-07 10:28:42 +0530700 rxstale = 8;
701 break;
702 case 57600:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700703 msm_hs_write(uport, UARTDM_CSR_ADDR, 0xaa);
Mayank Rana55046232011-03-07 10:28:42 +0530704 rxstale = 16;
705 break;
706 case 76800:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700707 msm_hs_write(uport, UARTDM_CSR_ADDR, 0xbb);
Mayank Rana55046232011-03-07 10:28:42 +0530708 rxstale = 16;
709 break;
710 case 115200:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700711 msm_hs_write(uport, UARTDM_CSR_ADDR, 0xcc);
Mayank Rana55046232011-03-07 10:28:42 +0530712 rxstale = 31;
713 break;
714 case 230400:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700715 msm_hs_write(uport, UARTDM_CSR_ADDR, 0xee);
Mayank Rana55046232011-03-07 10:28:42 +0530716 rxstale = 31;
717 break;
718 case 460800:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700719 msm_hs_write(uport, UARTDM_CSR_ADDR, 0xff);
Mayank Rana55046232011-03-07 10:28:42 +0530720 rxstale = 31;
721 break;
722 case 4000000:
723 case 3686400:
724 case 3200000:
725 case 3500000:
726 case 3000000:
727 case 2500000:
728 case 1500000:
729 case 1152000:
730 case 1000000:
731 case 921600:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700732 msm_hs_write(uport, UARTDM_CSR_ADDR, 0xff);
Mayank Rana55046232011-03-07 10:28:42 +0530733 rxstale = 31;
734 break;
735 default:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700736 msm_hs_write(uport, UARTDM_CSR_ADDR, 0xff);
Mayank Rana55046232011-03-07 10:28:42 +0530737 /* default to 9600 */
738 bps = 9600;
739 rxstale = 2;
740 break;
741 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700742 /*
743 * uart baud rate depends on CSR and MND Values
744 * we are updating CSR before and then calling
745 * clk_set_rate which updates MND Values. Hence
746 * dsb requires here.
747 */
748 mb();
749 if (bps > 460800) {
Mayank Rana55046232011-03-07 10:28:42 +0530750 uport->uartclk = bps * 16;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700751 } else {
752 uport->uartclk = 7372800;
753 }
Mayank Ranae6725162012-08-22 17:44:25 +0530754
Mayank Rana55046232011-03-07 10:28:42 +0530755 if (clk_set_rate(msm_uport->clk, uport->uartclk)) {
756 printk(KERN_WARNING "Error setting clock rate on UART\n");
Mayank Ranae6725162012-08-22 17:44:25 +0530757 WARN_ON(1);
Mayank Rana55046232011-03-07 10:28:42 +0530758 }
759
760 data = rxstale & UARTDM_IPR_STALE_LSB_BMSK;
761 data |= UARTDM_IPR_STALE_TIMEOUT_MSB_BMSK & (rxstale << 2);
762
763 msm_hs_write(uport, UARTDM_IPR_ADDR, data);
Mayank Rana2d4d2f62011-07-21 17:31:31 +0530764 /*
765 * It is suggested to do reset of transmitter and receiver after
766 * changing any protocol configuration. Here Baud rate and stale
767 * timeout are getting updated. Hence reset transmitter and receiver.
768 */
769 msm_hs_write(uport, UARTDM_CR_ADDR, RESET_TX);
770 msm_hs_write(uport, UARTDM_CR_ADDR, RESET_RX);
Mayank Rana55046232011-03-07 10:28:42 +0530771}
772
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700773
774static void msm_hs_set_std_bps_locked(struct uart_port *uport,
775 unsigned int bps)
776{
777 unsigned long rxstale;
778 unsigned long data;
779
780 switch (bps) {
781 case 9600:
782 msm_hs_write(uport, UARTDM_CSR_ADDR, 0x99);
783 rxstale = 2;
784 break;
785 case 14400:
786 msm_hs_write(uport, UARTDM_CSR_ADDR, 0xaa);
787 rxstale = 3;
788 break;
789 case 19200:
790 msm_hs_write(uport, UARTDM_CSR_ADDR, 0xbb);
791 rxstale = 4;
792 break;
793 case 28800:
794 msm_hs_write(uport, UARTDM_CSR_ADDR, 0xcc);
795 rxstale = 6;
796 break;
797 case 38400:
798 msm_hs_write(uport, UARTDM_CSR_ADDR, 0xdd);
799 rxstale = 8;
800 break;
801 case 57600:
802 msm_hs_write(uport, UARTDM_CSR_ADDR, 0xee);
803 rxstale = 16;
804 break;
805 case 115200:
806 msm_hs_write(uport, UARTDM_CSR_ADDR, 0xff);
807 rxstale = 31;
808 break;
809 default:
810 msm_hs_write(uport, UARTDM_CSR_ADDR, 0x99);
811 /* default to 9600 */
812 bps = 9600;
813 rxstale = 2;
814 break;
815 }
816
817 data = rxstale & UARTDM_IPR_STALE_LSB_BMSK;
818 data |= UARTDM_IPR_STALE_TIMEOUT_MSB_BMSK & (rxstale << 2);
819
820 msm_hs_write(uport, UARTDM_IPR_ADDR, data);
Mayank Rana55046232011-03-07 10:28:42 +0530821}
822
Saket Saurabhcbf6c522013-01-07 16:30:37 +0530823
824/* Reset BAM RX Endpoint Pipe Index from workqueue context*/
825
826static void hsuart_reset_bam_rx_work(struct work_struct *w)
827{
828 struct msm_hs_port *msm_uport = container_of(w, struct msm_hs_port,
829 reset_bam_rx);
830 struct uart_port *uport = &msm_uport->uport;
831 struct msm_hs_rx *rx = &msm_uport->rx;
832 struct sps_pipe *sps_pipe_handle = rx->prod.pipe_handle;
833
834 sps_disconnect(sps_pipe_handle);
835 msm_hs_spsconnect_rx(uport);
836
837 msm_serial_hs_rx_tlet((unsigned long) &rx->tlet);
838}
839
Mayank Rana55046232011-03-07 10:28:42 +0530840/*
841 * termios : new ktermios
842 * oldtermios: old ktermios previous setting
843 *
844 * Configure the serial port
845 */
846static void msm_hs_set_termios(struct uart_port *uport,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700847 struct ktermios *termios,
848 struct ktermios *oldtermios)
Mayank Rana55046232011-03-07 10:28:42 +0530849{
850 unsigned int bps;
851 unsigned long data;
Mayank Rana55046232011-03-07 10:28:42 +0530852 unsigned int c_cflag = termios->c_cflag;
853 struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
Saket Saurabhcbf6c522013-01-07 16:30:37 +0530854 struct msm_hs_rx *rx = &msm_uport->rx;
855 struct sps_pipe *sps_pipe_handle = rx->prod.pipe_handle;
Mayank Rana55046232011-03-07 10:28:42 +0530856
Mayank Ranae6725162012-08-22 17:44:25 +0530857 mutex_lock(&msm_uport->clk_mutex);
Saket Saurabha8bd52e2013-02-15 12:50:27 +0530858 msm_hs_write(uport, UARTDM_IMR_ADDR, 0);
Mayank Rana55046232011-03-07 10:28:42 +0530859
Mayank Rana2d4d2f62011-07-21 17:31:31 +0530860 /*
861 * Disable Rx channel of UARTDM
862 * DMA Rx Stall happens if enqueue and flush of Rx command happens
863 * concurrently. Hence before changing the baud rate/protocol
864 * configuration and sending flush command to ADM, disable the Rx
865 * channel of UARTDM.
866 * Note: should not reset the receiver here immediately as it is not
867 * suggested to do disable/reset or reset/disable at the same time.
868 */
869 data = msm_hs_read(uport, UARTDM_DMEN_ADDR);
Saket Saurabhcbf6c522013-01-07 16:30:37 +0530870 if (is_blsp_uart(msm_uport)) {
871 /* Disable UARTDM RX BAM Interface */
872 data &= ~UARTDM_RX_BAM_ENABLE_BMSK;
873 } else {
874 data &= ~UARTDM_RX_DM_EN_BMSK;
875 }
876
Mayank Rana2d4d2f62011-07-21 17:31:31 +0530877 msm_hs_write(uport, UARTDM_DMEN_ADDR, data);
Mayank Rana55046232011-03-07 10:28:42 +0530878
879 /* 300 is the minimum baud support by the driver */
880 bps = uart_get_baud_rate(uport, termios, oldtermios, 200, 4000000);
881
882 /* Temporary remapping 200 BAUD to 3.2 mbps */
883 if (bps == 200)
884 bps = 3200000;
885
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700886 uport->uartclk = clk_get_rate(msm_uport->clk);
887 if (!uport->uartclk)
888 msm_hs_set_std_bps_locked(uport, bps);
889 else
Saket Saurabhcbf6c522013-01-07 16:30:37 +0530890 msm_hs_set_bps_locked(uport, bps);
Mayank Rana55046232011-03-07 10:28:42 +0530891
892 data = msm_hs_read(uport, UARTDM_MR2_ADDR);
893 data &= ~UARTDM_MR2_PARITY_MODE_BMSK;
894 /* set parity */
895 if (PARENB == (c_cflag & PARENB)) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700896 if (PARODD == (c_cflag & PARODD)) {
Mayank Rana55046232011-03-07 10:28:42 +0530897 data |= ODD_PARITY;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700898 } else if (CMSPAR == (c_cflag & CMSPAR)) {
Mayank Rana55046232011-03-07 10:28:42 +0530899 data |= SPACE_PARITY;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700900 } else {
Mayank Rana55046232011-03-07 10:28:42 +0530901 data |= EVEN_PARITY;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700902 }
Mayank Rana55046232011-03-07 10:28:42 +0530903 }
904
905 /* Set bits per char */
906 data &= ~UARTDM_MR2_BITS_PER_CHAR_BMSK;
907
908 switch (c_cflag & CSIZE) {
909 case CS5:
910 data |= FIVE_BPC;
911 break;
912 case CS6:
913 data |= SIX_BPC;
914 break;
915 case CS7:
916 data |= SEVEN_BPC;
917 break;
918 default:
919 data |= EIGHT_BPC;
920 break;
921 }
922 /* stop bits */
923 if (c_cflag & CSTOPB) {
924 data |= STOP_BIT_TWO;
925 } else {
926 /* otherwise 1 stop bit */
927 data |= STOP_BIT_ONE;
928 }
929 data |= UARTDM_MR2_ERROR_MODE_BMSK;
930 /* write parity/bits per char/stop bit configuration */
931 msm_hs_write(uport, UARTDM_MR2_ADDR, data);
932
933 /* Configure HW flow control */
934 data = msm_hs_read(uport, UARTDM_MR1_ADDR);
935
936 data &= ~(UARTDM_MR1_CTS_CTL_BMSK | UARTDM_MR1_RX_RDY_CTL_BMSK);
937
938 if (c_cflag & CRTSCTS) {
939 data |= UARTDM_MR1_CTS_CTL_BMSK;
940 data |= UARTDM_MR1_RX_RDY_CTL_BMSK;
941 }
942
943 msm_hs_write(uport, UARTDM_MR1_ADDR, data);
944
945 uport->ignore_status_mask = termios->c_iflag & INPCK;
946 uport->ignore_status_mask |= termios->c_iflag & IGNPAR;
Mayank Ranaadc41562013-01-04 12:44:01 +0530947 uport->ignore_status_mask |= termios->c_iflag & IGNBRK;
Mayank Rana85aeee12012-11-27 14:49:46 +0530948
Mayank Rana55046232011-03-07 10:28:42 +0530949 uport->read_status_mask = (termios->c_cflag & CREAD);
950
Mayank Rana55046232011-03-07 10:28:42 +0530951
952 /* Set Transmit software time out */
953 uart_update_timeout(uport, c_cflag, bps);
954
955 msm_hs_write(uport, UARTDM_CR_ADDR, RESET_RX);
956 msm_hs_write(uport, UARTDM_CR_ADDR, RESET_TX);
957
958 if (msm_uport->rx.flush == FLUSH_NONE) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700959 wake_lock(&msm_uport->rx.wake_lock);
Mayank Rana55046232011-03-07 10:28:42 +0530960 msm_uport->rx.flush = FLUSH_IGNORE;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700961 /*
962 * Before using dmov APIs make sure that
963 * previous writel are completed. Hence
964 * dsb requires here.
965 */
966 mb();
Saket Saurabhcbf6c522013-01-07 16:30:37 +0530967 if (is_blsp_uart(msm_uport)) {
968 sps_disconnect(sps_pipe_handle);
969 msm_hs_spsconnect_rx(uport);
970 msm_serial_hs_rx_tlet((unsigned long) &rx->tlet);
971 } else {
972 /* do discard flush */
973 msm_dmov_flush(msm_uport->dma_rx_channel, 0);
974 }
Mayank Rana55046232011-03-07 10:28:42 +0530975 }
976
977 msm_hs_write(uport, UARTDM_IMR_ADDR, msm_uport->imr_reg);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700978 mb();
Mayank Ranae6725162012-08-22 17:44:25 +0530979 mutex_unlock(&msm_uport->clk_mutex);
Mayank Rana55046232011-03-07 10:28:42 +0530980}
981
982/*
983 * Standard API, Transmitter
984 * Any character in the transmit shift register is sent
985 */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700986unsigned int msm_hs_tx_empty(struct uart_port *uport)
Mayank Rana55046232011-03-07 10:28:42 +0530987{
988 unsigned int data;
989 unsigned int ret = 0;
Mayank Rana55046232011-03-07 10:28:42 +0530990
991 data = msm_hs_read(uport, UARTDM_SR_ADDR);
992 if (data & UARTDM_SR_TXEMT_BMSK)
993 ret = TIOCSER_TEMT;
994
Mayank Rana55046232011-03-07 10:28:42 +0530995 return ret;
996}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700997EXPORT_SYMBOL(msm_hs_tx_empty);
Mayank Rana55046232011-03-07 10:28:42 +0530998
999/*
1000 * Standard API, Stop transmitter.
1001 * Any character in the transmit shift register is sent as
1002 * well as the current data mover transfer .
1003 */
1004static void msm_hs_stop_tx_locked(struct uart_port *uport)
1005{
1006 struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
1007
1008 msm_uport->tx.tx_ready_int_en = 0;
1009}
1010
Saket Saurabhcbf6c522013-01-07 16:30:37 +05301011/* Disconnect BAM RX Endpoint Pipe Index from workqueue context*/
1012static void hsuart_disconnect_rx_endpoint_work(struct work_struct *w)
1013{
1014 struct msm_hs_port *msm_uport = container_of(w, struct msm_hs_port,
1015 disconnect_rx_endpoint);
1016 struct msm_hs_rx *rx = &msm_uport->rx;
1017 struct sps_pipe *sps_pipe_handle = rx->prod.pipe_handle;
1018
1019 sps_disconnect(sps_pipe_handle);
1020 wake_lock_timeout(&msm_uport->rx.wake_lock, HZ / 2);
1021 msm_uport->rx.flush = FLUSH_SHUTDOWN;
1022 wake_up(&msm_uport->rx.wait);
1023}
1024
Mayank Rana55046232011-03-07 10:28:42 +05301025/*
1026 * Standard API, Stop receiver as soon as possible.
1027 *
1028 * Function immediately terminates the operation of the
1029 * channel receiver and any incoming characters are lost. None
1030 * of the receiver status bits are affected by this command and
1031 * characters that are already in the receive FIFO there.
1032 */
1033static void msm_hs_stop_rx_locked(struct uart_port *uport)
1034{
1035 struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
1036 unsigned int data;
1037
Mayank Rana55046232011-03-07 10:28:42 +05301038 /* disable dlink */
1039 data = msm_hs_read(uport, UARTDM_DMEN_ADDR);
Saket Saurabhcbf6c522013-01-07 16:30:37 +05301040 if (is_blsp_uart(msm_uport))
1041 data &= ~UARTDM_RX_BAM_ENABLE_BMSK;
1042 else
1043 data &= ~UARTDM_RX_DM_EN_BMSK;
Mayank Rana55046232011-03-07 10:28:42 +05301044 msm_hs_write(uport, UARTDM_DMEN_ADDR, data);
1045
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001046 /* calling DMOV or CLOCK API. Hence mb() */
1047 mb();
Mayank Rana55046232011-03-07 10:28:42 +05301048 /* Disable the receiver */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001049 if (msm_uport->rx.flush == FLUSH_NONE) {
1050 wake_lock(&msm_uport->rx.wake_lock);
Saket Saurabhcbf6c522013-01-07 16:30:37 +05301051 if (is_blsp_uart(msm_uport)) {
1052 msm_uport->rx.flush = FLUSH_STOP;
1053 /* workqueue for BAM rx endpoint disconnect */
1054 queue_work(msm_uport->hsuart_wq,
1055 &msm_uport->disconnect_rx_endpoint);
1056 } else {
1057 /* do discard flush */
1058 msm_dmov_flush(msm_uport->dma_rx_channel, 0);
1059 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001060 }
Saket Saurabhcbf6c522013-01-07 16:30:37 +05301061 if (!is_blsp_uart(msm_uport) && msm_uport->rx.flush != FLUSH_SHUTDOWN)
Mayank Rana55046232011-03-07 10:28:42 +05301062 msm_uport->rx.flush = FLUSH_STOP;
Mayank Rana55046232011-03-07 10:28:42 +05301063}
1064
1065/* Transmit the next chunk of data */
1066static void msm_hs_submit_tx_locked(struct uart_port *uport)
1067{
1068 int left;
1069 int tx_count;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001070 int aligned_tx_count;
Mayank Rana55046232011-03-07 10:28:42 +05301071 dma_addr_t src_addr;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001072 dma_addr_t aligned_src_addr;
Saket Saurabhcbf6c522013-01-07 16:30:37 +05301073 u32 flags = SPS_IOVEC_FLAG_EOT;
Mayank Rana55046232011-03-07 10:28:42 +05301074 struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
1075 struct msm_hs_tx *tx = &msm_uport->tx;
1076 struct circ_buf *tx_buf = &msm_uport->uport.state->xmit;
Saket Saurabhcbf6c522013-01-07 16:30:37 +05301077 struct sps_pipe *sps_pipe_handle;
Mayank Rana55046232011-03-07 10:28:42 +05301078
1079 if (uart_circ_empty(tx_buf) || uport->state->port.tty->stopped) {
1080 msm_hs_stop_tx_locked(uport);
1081 return;
1082 }
1083
1084 tx->dma_in_flight = 1;
1085
1086 tx_count = uart_circ_chars_pending(tx_buf);
1087
1088 if (UARTDM_TX_BUF_SIZE < tx_count)
1089 tx_count = UARTDM_TX_BUF_SIZE;
1090
1091 left = UART_XMIT_SIZE - tx_buf->tail;
1092
1093 if (tx_count > left)
1094 tx_count = left;
1095
1096 src_addr = tx->dma_base + tx_buf->tail;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001097 /* Mask the src_addr to align on a cache
1098 * and add those bytes to tx_count */
1099 aligned_src_addr = src_addr & ~(dma_get_cache_alignment() - 1);
1100 aligned_tx_count = tx_count + src_addr - aligned_src_addr;
1101
1102 dma_sync_single_for_device(uport->dev, aligned_src_addr,
1103 aligned_tx_count, DMA_TO_DEVICE);
Mayank Rana55046232011-03-07 10:28:42 +05301104
Saket Saurabhcbf6c522013-01-07 16:30:37 +05301105 if (is_blsp_uart(msm_uport)) {
1106 /* Issue TX BAM Start IFC command */
1107 msm_hs_write(uport, UARTDM_CR_ADDR, START_TX_BAM_IFC);
1108 } else {
1109 tx->command_ptr->num_rows =
1110 (((tx_count + 15) >> 4) << 16) |
1111 ((tx_count + 15) >> 4);
1112 tx->command_ptr->src_row_addr = src_addr;
Mayank Rana55046232011-03-07 10:28:42 +05301113
Saket Saurabhcbf6c522013-01-07 16:30:37 +05301114 dma_sync_single_for_device(uport->dev, tx->mapped_cmd_ptr,
1115 sizeof(dmov_box), DMA_TO_DEVICE);
Mayank Rana55046232011-03-07 10:28:42 +05301116
Saket Saurabhcbf6c522013-01-07 16:30:37 +05301117 *tx->command_ptr_ptr = CMD_PTR_LP |
1118 DMOV_CMD_ADDR(tx->mapped_cmd_ptr);
1119 }
Mayank Rana55046232011-03-07 10:28:42 +05301120
Mayank Rana55046232011-03-07 10:28:42 +05301121 /* Save tx_count to use in Callback */
1122 tx->tx_count = tx_count;
1123 msm_hs_write(uport, UARTDM_NCF_TX_ADDR, tx_count);
1124
1125 /* Disable the tx_ready interrupt */
1126 msm_uport->imr_reg &= ~UARTDM_ISR_TX_READY_BMSK;
1127 msm_hs_write(uport, UARTDM_IMR_ADDR, msm_uport->imr_reg);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001128 /* Calling next DMOV API. Hence mb() here. */
1129 mb();
1130
Mayank Ranaaf2f0082012-05-22 10:16:02 +05301131 msm_uport->tx.flush = FLUSH_NONE;
Saket Saurabhcbf6c522013-01-07 16:30:37 +05301132
1133 if (is_blsp_uart(msm_uport)) {
1134 sps_pipe_handle = tx->cons.pipe_handle;
1135 /* Queue transfer request to SPS */
1136 sps_transfer_one(sps_pipe_handle, src_addr, tx_count,
1137 msm_uport, flags);
1138 } else {
1139 dma_sync_single_for_device(uport->dev, tx->mapped_cmd_ptr_ptr,
1140 sizeof(u32), DMA_TO_DEVICE);
1141
1142 msm_dmov_enqueue_cmd(msm_uport->dma_tx_channel, &tx->xfer);
1143 }
Mayank Rana55046232011-03-07 10:28:42 +05301144}
1145
1146/* Start to receive the next chunk of data */
1147static void msm_hs_start_rx_locked(struct uart_port *uport)
1148{
1149 struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
Saket Saurabhcbf6c522013-01-07 16:30:37 +05301150 struct msm_hs_rx *rx = &msm_uport->rx;
1151 struct sps_pipe *sps_pipe_handle;
1152 u32 flags = SPS_IOVEC_FLAG_EOT;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001153 unsigned int buffer_pending = msm_uport->rx.buffer_pending;
Mayank Rana2d4d2f62011-07-21 17:31:31 +05301154 unsigned int data;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001155
1156 msm_uport->rx.buffer_pending = 0;
1157 if (buffer_pending && hs_serial_debug_mask)
1158 printk(KERN_ERR "Error: rx started in buffer state = %x",
1159 buffer_pending);
Mayank Rana55046232011-03-07 10:28:42 +05301160
Saket Saurabhcbf6c522013-01-07 16:30:37 +05301161 if (is_blsp_uart(msm_uport)) {
1162 /* Issue RX BAM Start IFC command */
1163 msm_hs_write(uport, UARTDM_CR_ADDR, START_RX_BAM_IFC);
1164 }
Mayank Rana55046232011-03-07 10:28:42 +05301165 msm_hs_write(uport, UARTDM_CR_ADDR, RESET_STALE_INT);
1166 msm_hs_write(uport, UARTDM_DMRX_ADDR, UARTDM_RX_BUF_SIZE);
1167 msm_hs_write(uport, UARTDM_CR_ADDR, STALE_EVENT_ENABLE);
1168 msm_uport->imr_reg |= UARTDM_ISR_RXLEV_BMSK;
Mayank Rana2d4d2f62011-07-21 17:31:31 +05301169
1170 /*
1171 * Enable UARTDM Rx Interface as previously it has been
1172 * disable in set_termios before configuring baud rate.
1173 */
1174 data = msm_hs_read(uport, UARTDM_DMEN_ADDR);
Saket Saurabhcbf6c522013-01-07 16:30:37 +05301175 if (is_blsp_uart(msm_uport)) {
1176 /* Enable UARTDM Rx BAM Interface */
1177 data |= UARTDM_RX_BAM_ENABLE_BMSK;
1178 } else {
1179 data |= UARTDM_RX_DM_EN_BMSK;
1180 }
1181
Mayank Rana2d4d2f62011-07-21 17:31:31 +05301182 msm_hs_write(uport, UARTDM_DMEN_ADDR, data);
Mayank Rana55046232011-03-07 10:28:42 +05301183 msm_hs_write(uport, UARTDM_IMR_ADDR, msm_uport->imr_reg);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001184 /* Calling next DMOV API. Hence mb() here. */
1185 mb();
Mayank Rana55046232011-03-07 10:28:42 +05301186
1187 msm_uport->rx.flush = FLUSH_NONE;
Mayank Rana55046232011-03-07 10:28:42 +05301188
Saket Saurabhcbf6c522013-01-07 16:30:37 +05301189 if (is_blsp_uart(msm_uport)) {
1190 sps_pipe_handle = rx->prod.pipe_handle;
1191 /* Queue transfer request to SPS */
1192 sps_transfer_one(sps_pipe_handle, rx->rbuffer,
1193 UARTDM_RX_BUF_SIZE, msm_uport, flags);
1194 } else {
1195 msm_dmov_enqueue_cmd(msm_uport->dma_rx_channel,
1196 &msm_uport->rx.xfer);
1197 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001198}
1199
1200static void flip_insert_work(struct work_struct *work)
1201{
1202 unsigned long flags;
1203 int retval;
1204 struct msm_hs_port *msm_uport =
1205 container_of(work, struct msm_hs_port,
1206 rx.flip_insert_work.work);
1207 struct tty_struct *tty = msm_uport->uport.state->port.tty;
1208
1209 spin_lock_irqsave(&msm_uport->uport.lock, flags);
1210 if (msm_uport->rx.buffer_pending == NONE_PENDING) {
1211 if (hs_serial_debug_mask)
1212 printk(KERN_ERR "Error: No buffer pending in %s",
1213 __func__);
1214 return;
1215 }
1216 if (msm_uport->rx.buffer_pending & FIFO_OVERRUN) {
1217 retval = tty_insert_flip_char(tty, 0, TTY_OVERRUN);
1218 if (retval)
1219 msm_uport->rx.buffer_pending &= ~FIFO_OVERRUN;
1220 }
1221 if (msm_uport->rx.buffer_pending & PARITY_ERROR) {
1222 retval = tty_insert_flip_char(tty, 0, TTY_PARITY);
1223 if (retval)
1224 msm_uport->rx.buffer_pending &= ~PARITY_ERROR;
1225 }
1226 if (msm_uport->rx.buffer_pending & CHARS_NORMAL) {
1227 int rx_count, rx_offset;
1228 rx_count = (msm_uport->rx.buffer_pending & 0xFFFF0000) >> 16;
1229 rx_offset = (msm_uport->rx.buffer_pending & 0xFFD0) >> 5;
1230 retval = tty_insert_flip_string(tty, msm_uport->rx.buffer +
1231 rx_offset, rx_count);
1232 msm_uport->rx.buffer_pending &= (FIFO_OVERRUN |
1233 PARITY_ERROR);
1234 if (retval != rx_count)
1235 msm_uport->rx.buffer_pending |= CHARS_NORMAL |
1236 retval << 8 | (rx_count - retval) << 16;
1237 }
1238 if (msm_uport->rx.buffer_pending)
1239 schedule_delayed_work(&msm_uport->rx.flip_insert_work,
1240 msecs_to_jiffies(RETRY_TIMEOUT));
1241 else
1242 if ((msm_uport->clk_state == MSM_HS_CLK_ON) &&
1243 (msm_uport->rx.flush <= FLUSH_IGNORE)) {
1244 if (hs_serial_debug_mask)
1245 printk(KERN_WARNING
1246 "msm_serial_hs: "
1247 "Pending buffers cleared. "
1248 "Restarting\n");
1249 msm_hs_start_rx_locked(&msm_uport->uport);
1250 }
1251 spin_unlock_irqrestore(&msm_uport->uport.lock, flags);
1252 tty_flip_buffer_push(tty);
1253}
1254
1255static void msm_serial_hs_rx_tlet(unsigned long tlet_ptr)
1256{
1257 int retval;
1258 int rx_count;
Saket Saurabhcbf6c522013-01-07 16:30:37 +05301259 static int remaining_rx_count, bytes_pending;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001260 unsigned long status;
1261 unsigned long flags;
1262 unsigned int error_f = 0;
1263 struct uart_port *uport;
1264 struct msm_hs_port *msm_uport;
1265 unsigned int flush;
1266 struct tty_struct *tty;
1267
1268 msm_uport = container_of((struct tasklet_struct *)tlet_ptr,
1269 struct msm_hs_port, rx.tlet);
1270 uport = &msm_uport->uport;
1271 tty = uport->state->port.tty;
1272
1273 status = msm_hs_read(uport, UARTDM_SR_ADDR);
1274
1275 spin_lock_irqsave(&uport->lock, flags);
1276
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001277 msm_hs_write(uport, UARTDM_CR_ADDR, STALE_EVENT_DISABLE);
1278
1279 /* overflow is not connect to data in a FIFO */
1280 if (unlikely((status & UARTDM_SR_OVERRUN_BMSK) &&
1281 (uport->read_status_mask & CREAD))) {
1282 retval = tty_insert_flip_char(tty, 0, TTY_OVERRUN);
1283 if (!retval)
1284 msm_uport->rx.buffer_pending |= TTY_OVERRUN;
1285 uport->icount.buf_overrun++;
1286 error_f = 1;
1287 }
1288
1289 if (!(uport->ignore_status_mask & INPCK))
1290 status = status & ~(UARTDM_SR_PAR_FRAME_BMSK);
1291
1292 if (unlikely(status & UARTDM_SR_PAR_FRAME_BMSK)) {
1293 /* Can not tell difference between parity & frame error */
Mayank Rana85aeee12012-11-27 14:49:46 +05301294 if (hs_serial_debug_mask)
1295 printk(KERN_WARNING "msm_serial_hs: parity error\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001296 uport->icount.parity++;
1297 error_f = 1;
Mayank Rana85aeee12012-11-27 14:49:46 +05301298 if (!(uport->ignore_status_mask & IGNPAR)) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001299 retval = tty_insert_flip_char(tty, 0, TTY_PARITY);
1300 if (!retval)
1301 msm_uport->rx.buffer_pending |= TTY_PARITY;
1302 }
1303 }
1304
Mayank Rana85aeee12012-11-27 14:49:46 +05301305 if (unlikely(status & UARTDM_SR_RX_BREAK_BMSK)) {
1306 if (hs_serial_debug_mask)
1307 printk(KERN_WARNING "msm_serial_hs: Rx break\n");
1308 uport->icount.brk++;
1309 error_f = 1;
1310 if (!(uport->ignore_status_mask & IGNBRK)) {
1311 retval = tty_insert_flip_char(tty, 0, TTY_BREAK);
1312 if (!retval)
1313 msm_uport->rx.buffer_pending |= TTY_BREAK;
1314 }
1315 }
1316
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001317 if (error_f)
1318 msm_hs_write(uport, UARTDM_CR_ADDR, RESET_ERROR_STATUS);
1319
1320 if (msm_uport->clk_req_off_state == CLK_REQ_OFF_FLUSH_ISSUED)
1321 msm_uport->clk_req_off_state = CLK_REQ_OFF_RXSTALE_FLUSHED;
1322 flush = msm_uport->rx.flush;
1323 if (flush == FLUSH_IGNORE)
1324 if (!msm_uport->rx.buffer_pending)
1325 msm_hs_start_rx_locked(uport);
1326
1327 if (flush == FLUSH_STOP) {
1328 msm_uport->rx.flush = FLUSH_SHUTDOWN;
1329 wake_up(&msm_uport->rx.wait);
1330 }
1331 if (flush >= FLUSH_DATA_INVALID)
1332 goto out;
1333
1334 rx_count = msm_hs_read(uport, UARTDM_RX_TOTAL_SNAP_ADDR);
1335
Saket Saurabhcbf6c522013-01-07 16:30:37 +05301336 if (is_blsp_uart(msm_uport)) {
1337 if (rx_count > UARTDM_RX_BUF_SIZE) {
1338 if (bytes_pending) {
1339 rx_count = remaining_rx_count;
1340 bytes_pending = 0;
1341 } else {
1342 remaining_rx_count = rx_count -
1343 UARTDM_RX_BUF_SIZE;
1344 if (remaining_rx_count)
1345 bytes_pending = 1;
1346 rx_count = UARTDM_RX_BUF_SIZE;
1347 }
1348 }
1349 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001350 /* order the read of rx.buffer */
1351 rmb();
1352
1353 if (0 != (uport->read_status_mask & CREAD)) {
1354 retval = tty_insert_flip_string(tty, msm_uport->rx.buffer,
1355 rx_count);
1356 if (retval != rx_count) {
1357 msm_uport->rx.buffer_pending |= CHARS_NORMAL |
1358 retval << 5 | (rx_count - retval) << 16;
1359 }
1360 }
1361
1362 /* order the read of rx.buffer and the start of next rx xfer */
1363 wmb();
1364
1365 if (!msm_uport->rx.buffer_pending)
1366 msm_hs_start_rx_locked(uport);
1367
1368out:
1369 if (msm_uport->rx.buffer_pending) {
1370 if (hs_serial_debug_mask)
1371 printk(KERN_WARNING
1372 "msm_serial_hs: "
1373 "tty buffer exhausted. "
1374 "Stalling\n");
1375 schedule_delayed_work(&msm_uport->rx.flip_insert_work
1376 , msecs_to_jiffies(RETRY_TIMEOUT));
1377 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001378 /* release wakelock in 500ms, not immediately, because higher layers
1379 * don't always take wakelocks when they should */
1380 wake_lock_timeout(&msm_uport->rx.wake_lock, HZ / 2);
1381 /* tty_flip_buffer_push() might call msm_hs_start(), so unlock */
1382 spin_unlock_irqrestore(&uport->lock, flags);
1383 if (flush < FLUSH_DATA_INVALID)
1384 tty_flip_buffer_push(tty);
Mayank Rana55046232011-03-07 10:28:42 +05301385}
1386
1387/* Enable the transmitter Interrupt */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001388static void msm_hs_start_tx_locked(struct uart_port *uport )
Mayank Rana55046232011-03-07 10:28:42 +05301389{
1390 struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
1391
Mayank Rana55046232011-03-07 10:28:42 +05301392 if (msm_uport->tx.tx_ready_int_en == 0) {
1393 msm_uport->tx.tx_ready_int_en = 1;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001394 if (msm_uport->tx.dma_in_flight == 0)
1395 msm_hs_submit_tx_locked(uport);
Mayank Rana55046232011-03-07 10:28:42 +05301396 }
Mayank Rana55046232011-03-07 10:28:42 +05301397}
1398
Saket Saurabhcbf6c522013-01-07 16:30:37 +05301399/**
1400 * Callback notification from SPS driver
1401 *
1402 * This callback function gets triggered called from
1403 * SPS driver when requested SPS data transfer is
1404 * completed.
1405 *
1406 */
1407
1408static void msm_hs_sps_tx_callback(struct sps_event_notify *notify)
1409{
1410 struct msm_hs_port *msm_uport =
1411 (struct msm_hs_port *)
1412 ((struct sps_event_notify *)notify)->user;
1413
1414 msm_uport->notify = *notify;
1415 pr_debug("%s: sps ev_id=%d, addr=0x%x, size=0x%x, flags=0x%x\n",
1416 __func__, notify->event_id,
1417 notify->data.transfer.iovec.addr,
1418 notify->data.transfer.iovec.size,
1419 notify->data.transfer.iovec.flags);
1420
1421 tasklet_schedule(&msm_uport->tx.tlet);
1422}
1423
Mayank Rana55046232011-03-07 10:28:42 +05301424/*
1425 * This routine is called when we are done with a DMA transfer
1426 *
1427 * This routine is registered with Data mover when we set
1428 * up a Data Mover transfer. It is called from Data mover ISR
1429 * when the DMA transfer is done.
1430 */
1431static void msm_hs_dmov_tx_callback(struct msm_dmov_cmd *cmd_ptr,
1432 unsigned int result,
1433 struct msm_dmov_errdata *err)
1434{
Mayank Rana55046232011-03-07 10:28:42 +05301435 struct msm_hs_port *msm_uport;
1436
Mayank Rana55046232011-03-07 10:28:42 +05301437 msm_uport = container_of(cmd_ptr, struct msm_hs_port, tx.xfer);
Mayank Ranaaf2f0082012-05-22 10:16:02 +05301438 if (msm_uport->tx.flush == FLUSH_STOP)
1439 /* DMA FLUSH unsuccesfful */
1440 WARN_ON(!(result & DMOV_RSLT_FLUSH));
1441 else
1442 /* DMA did not finish properly */
1443 WARN_ON(!(result & DMOV_RSLT_DONE));
Mayank Rana55046232011-03-07 10:28:42 +05301444
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001445 tasklet_schedule(&msm_uport->tx.tlet);
1446}
1447
1448static void msm_serial_hs_tx_tlet(unsigned long tlet_ptr)
1449{
1450 unsigned long flags;
1451 struct msm_hs_port *msm_uport = container_of((struct tasklet_struct *)
1452 tlet_ptr, struct msm_hs_port, tx.tlet);
1453
1454 spin_lock_irqsave(&(msm_uport->uport.lock), flags);
Mayank Ranaaf2f0082012-05-22 10:16:02 +05301455 if (msm_uport->tx.flush == FLUSH_STOP) {
1456 msm_uport->tx.flush = FLUSH_SHUTDOWN;
1457 wake_up(&msm_uport->tx.wait);
1458 spin_unlock_irqrestore(&(msm_uport->uport.lock), flags);
1459 return;
1460 }
Mayank Rana55046232011-03-07 10:28:42 +05301461
1462 msm_uport->imr_reg |= UARTDM_ISR_TX_READY_BMSK;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001463 msm_hs_write(&(msm_uport->uport), UARTDM_IMR_ADDR, msm_uport->imr_reg);
1464 /* Calling clk API. Hence mb() requires. */
1465 mb();
Mayank Rana55046232011-03-07 10:28:42 +05301466
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001467 spin_unlock_irqrestore(&(msm_uport->uport.lock), flags);
Mayank Rana55046232011-03-07 10:28:42 +05301468}
1469
Saket Saurabhcbf6c522013-01-07 16:30:37 +05301470/**
1471 * Callback notification from SPS driver
1472 *
1473 * This callback function gets triggered called from
1474 * SPS driver when requested SPS data transfer is
1475 * completed.
1476 *
1477 */
1478
1479static void msm_hs_sps_rx_callback(struct sps_event_notify *notify)
1480{
1481
1482 struct msm_hs_port *msm_uport =
1483 (struct msm_hs_port *)
1484 ((struct sps_event_notify *)notify)->user;
1485
1486 msm_uport->notify = *notify;
1487 pr_debug("%s: sps ev_id=%d, addr=0x%x, size=0x%x, flags=0x%x\n",
1488 __func__, notify->event_id,
1489 notify->data.transfer.iovec.addr,
1490 notify->data.transfer.iovec.size,
1491 notify->data.transfer.iovec.flags);
1492
1493 if (msm_uport->rx.flush == FLUSH_NONE)
1494 tasklet_schedule(&msm_uport->rx.tlet);
1495}
1496
Mayank Rana55046232011-03-07 10:28:42 +05301497/*
1498 * This routine is called when we are done with a DMA transfer or the
1499 * a flush has been sent to the data mover driver.
1500 *
1501 * This routine is registered with Data mover when we set up a Data Mover
1502 * transfer. It is called from Data mover ISR when the DMA transfer is done.
1503 */
1504static void msm_hs_dmov_rx_callback(struct msm_dmov_cmd *cmd_ptr,
1505 unsigned int result,
1506 struct msm_dmov_errdata *err)
1507{
Mayank Rana55046232011-03-07 10:28:42 +05301508 struct msm_hs_port *msm_uport;
1509
1510 msm_uport = container_of(cmd_ptr, struct msm_hs_port, rx.xfer);
Mayank Rana55046232011-03-07 10:28:42 +05301511
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001512 tasklet_schedule(&msm_uport->rx.tlet);
Mayank Rana55046232011-03-07 10:28:42 +05301513}
1514
1515/*
1516 * Standard API, Current states of modem control inputs
1517 *
1518 * Since CTS can be handled entirely by HARDWARE we always
1519 * indicate clear to send and count on the TX FIFO to block when
1520 * it fills up.
1521 *
1522 * - TIOCM_DCD
1523 * - TIOCM_CTS
1524 * - TIOCM_DSR
1525 * - TIOCM_RI
1526 * (Unsupported) DCD and DSR will return them high. RI will return low.
1527 */
1528static unsigned int msm_hs_get_mctrl_locked(struct uart_port *uport)
1529{
1530 return TIOCM_DSR | TIOCM_CAR | TIOCM_CTS;
1531}
1532
1533/*
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001534 * Standard API, Set or clear RFR_signal
1535 *
1536 * Set RFR high, (Indicate we are not ready for data), we disable auto
1537 * ready for receiving and then set RFR_N high. To set RFR to low we just turn
1538 * back auto ready for receiving and it should lower RFR signal
1539 * when hardware is ready
Mayank Rana55046232011-03-07 10:28:42 +05301540 */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001541void msm_hs_set_mctrl_locked(struct uart_port *uport,
Mayank Rana55046232011-03-07 10:28:42 +05301542 unsigned int mctrl)
1543{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001544 unsigned int set_rts;
1545 unsigned int data;
Mayank Rana55046232011-03-07 10:28:42 +05301546
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001547 /* RTS is active low */
1548 set_rts = TIOCM_RTS & mctrl ? 0 : 1;
Mayank Rana55046232011-03-07 10:28:42 +05301549
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001550 data = msm_hs_read(uport, UARTDM_MR1_ADDR);
1551 if (set_rts) {
1552 /*disable auto ready-for-receiving */
1553 data &= ~UARTDM_MR1_RX_RDY_CTL_BMSK;
1554 msm_hs_write(uport, UARTDM_MR1_ADDR, data);
1555 /* set RFR_N to high */
1556 msm_hs_write(uport, UARTDM_CR_ADDR, RFR_HIGH);
1557 } else {
1558 /* Enable auto ready-for-receiving */
1559 data |= UARTDM_MR1_RX_RDY_CTL_BMSK;
1560 msm_hs_write(uport, UARTDM_MR1_ADDR, data);
1561 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001562 mb();
Mayank Rana55046232011-03-07 10:28:42 +05301563}
1564
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001565void msm_hs_set_mctrl(struct uart_port *uport,
1566 unsigned int mctrl)
1567{
1568 unsigned long flags;
1569
1570 spin_lock_irqsave(&uport->lock, flags);
1571 msm_hs_set_mctrl_locked(uport, mctrl);
1572 spin_unlock_irqrestore(&uport->lock, flags);
1573}
1574EXPORT_SYMBOL(msm_hs_set_mctrl);
1575
Mayank Rana55046232011-03-07 10:28:42 +05301576/* Standard API, Enable modem status (CTS) interrupt */
1577static void msm_hs_enable_ms_locked(struct uart_port *uport)
1578{
1579 struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
1580
Mayank Rana55046232011-03-07 10:28:42 +05301581 /* Enable DELTA_CTS Interrupt */
1582 msm_uport->imr_reg |= UARTDM_ISR_DELTA_CTS_BMSK;
1583 msm_hs_write(uport, UARTDM_IMR_ADDR, msm_uport->imr_reg);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001584 mb();
Mayank Rana55046232011-03-07 10:28:42 +05301585
1586}
1587
Saket Saurabhce394102012-10-29 19:51:28 +05301588static void msm_hs_flush_buffer(struct uart_port *uport)
1589{
1590 struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
1591
Saket Saurabhcbf6c522013-01-07 16:30:37 +05301592 if (msm_uport->tx.dma_in_flight)
1593 msm_uport->tty_flush_receive = true;
Saket Saurabhce394102012-10-29 19:51:28 +05301594}
1595
Mayank Rana55046232011-03-07 10:28:42 +05301596/*
1597 * Standard API, Break Signal
1598 *
1599 * Control the transmission of a break signal. ctl eq 0 => break
1600 * signal terminate ctl ne 0 => start break signal
1601 */
1602static void msm_hs_break_ctl(struct uart_port *uport, int ctl)
1603{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001604 unsigned long flags;
Mayank Rana55046232011-03-07 10:28:42 +05301605
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001606 spin_lock_irqsave(&uport->lock, flags);
Mayank Rana55046232011-03-07 10:28:42 +05301607 msm_hs_write(uport, UARTDM_CR_ADDR, ctl ? START_BREAK : STOP_BREAK);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001608 mb();
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001609 spin_unlock_irqrestore(&uport->lock, flags);
Mayank Rana55046232011-03-07 10:28:42 +05301610}
1611
1612static void msm_hs_config_port(struct uart_port *uport, int cfg_flags)
1613{
1614 unsigned long flags;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001615 struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
Mayank Rana55046232011-03-07 10:28:42 +05301616
Mayank Rana55046232011-03-07 10:28:42 +05301617 if (cfg_flags & UART_CONFIG_TYPE) {
1618 uport->type = PORT_MSM;
1619 msm_hs_request_port(uport);
1620 }
Mayank Ranabbfd2692011-09-20 08:51:17 +05301621
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001622 if (is_gsbi_uart(msm_uport)) {
Mayank Rana00b6bff2011-08-17 08:33:42 +05301623 if (msm_uport->pclk)
Mayank Ranacb589d82012-03-01 11:50:03 +05301624 clk_prepare_enable(msm_uport->pclk);
1625 spin_lock_irqsave(&uport->lock, flags);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001626 iowrite32(GSBI_PROTOCOL_UART, msm_uport->mapped_gsbi +
1627 GSBI_CONTROL_ADDR);
Mayank Ranacb589d82012-03-01 11:50:03 +05301628 spin_unlock_irqrestore(&uport->lock, flags);
Mayank Rana00b6bff2011-08-17 08:33:42 +05301629 if (msm_uport->pclk)
Mayank Ranacb589d82012-03-01 11:50:03 +05301630 clk_disable_unprepare(msm_uport->pclk);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001631 }
Mayank Rana55046232011-03-07 10:28:42 +05301632}
1633
1634/* Handle CTS changes (Called from interrupt handler) */
Mayank Ranaee815f32011-12-08 09:06:09 +05301635static void msm_hs_handle_delta_cts_locked(struct uart_port *uport)
Mayank Rana55046232011-03-07 10:28:42 +05301636{
Mayank Rana55046232011-03-07 10:28:42 +05301637 /* clear interrupt */
1638 msm_hs_write(uport, UARTDM_CR_ADDR, RESET_CTS);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001639 /* Calling CLOCK API. Hence mb() requires here. */
1640 mb();
Mayank Rana55046232011-03-07 10:28:42 +05301641 uport->icount.cts++;
1642
Mayank Rana55046232011-03-07 10:28:42 +05301643 /* clear the IOCTL TIOCMIWAIT if called */
1644 wake_up_interruptible(&uport->state->port.delta_msr_wait);
1645}
1646
1647/* check if the TX path is flushed, and if so clock off
1648 * returns 0 did not clock off, need to retry (still sending final byte)
1649 * -1 did not clock off, do not retry
1650 * 1 if we clocked off
1651 */
Mayank Ranacb589d82012-03-01 11:50:03 +05301652static int msm_hs_check_clock_off(struct uart_port *uport)
Mayank Rana55046232011-03-07 10:28:42 +05301653{
1654 unsigned long sr_status;
Mayank Ranacb589d82012-03-01 11:50:03 +05301655 unsigned long flags;
Mayank Rana55046232011-03-07 10:28:42 +05301656 struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
1657 struct circ_buf *tx_buf = &uport->state->xmit;
1658
Mayank Ranacb589d82012-03-01 11:50:03 +05301659 mutex_lock(&msm_uport->clk_mutex);
1660 spin_lock_irqsave(&uport->lock, flags);
1661
Mayank Rana55046232011-03-07 10:28:42 +05301662 /* Cancel if tx tty buffer is not empty, dma is in flight,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001663 * or tx fifo is not empty */
Mayank Rana55046232011-03-07 10:28:42 +05301664 if (msm_uport->clk_state != MSM_HS_CLK_REQUEST_OFF ||
1665 !uart_circ_empty(tx_buf) || msm_uport->tx.dma_in_flight ||
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001666 msm_uport->imr_reg & UARTDM_ISR_TXLEV_BMSK) {
Mayank Ranacb589d82012-03-01 11:50:03 +05301667 spin_unlock_irqrestore(&uport->lock, flags);
1668 mutex_unlock(&msm_uport->clk_mutex);
Mayank Rana55046232011-03-07 10:28:42 +05301669 return -1;
1670 }
1671
1672 /* Make sure the uart is finished with the last byte */
1673 sr_status = msm_hs_read(uport, UARTDM_SR_ADDR);
Mayank Ranacb589d82012-03-01 11:50:03 +05301674 if (!(sr_status & UARTDM_SR_TXEMT_BMSK)) {
1675 spin_unlock_irqrestore(&uport->lock, flags);
1676 mutex_unlock(&msm_uport->clk_mutex);
Mayank Rana55046232011-03-07 10:28:42 +05301677 return 0; /* retry */
Mayank Ranacb589d82012-03-01 11:50:03 +05301678 }
Mayank Rana55046232011-03-07 10:28:42 +05301679
1680 /* Make sure forced RXSTALE flush complete */
1681 switch (msm_uport->clk_req_off_state) {
1682 case CLK_REQ_OFF_START:
1683 msm_uport->clk_req_off_state = CLK_REQ_OFF_RXSTALE_ISSUED;
Saket Saurabhcbf6c522013-01-07 16:30:37 +05301684 if (is_blsp_uart(msm_uport)) {
1685 /* Stale interrupt when RX-FIFO is empty
1686 * will fire if STALE_IRQ_EMPTY bit is set
1687 * for UART Core v1.4
1688 */
1689 msm_hs_write(uport, UARTDM_BCR_ADDR,
1690 UARTDM_BCR_STALE_IRQ_EMPTY);
1691 }
Mayank Rana55046232011-03-07 10:28:42 +05301692 msm_hs_write(uport, UARTDM_CR_ADDR, FORCE_STALE_EVENT);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001693 /*
1694 * Before returning make sure that device writel completed.
1695 * Hence mb() requires here.
1696 */
1697 mb();
Mayank Ranacb589d82012-03-01 11:50:03 +05301698 spin_unlock_irqrestore(&uport->lock, flags);
1699 mutex_unlock(&msm_uport->clk_mutex);
Mayank Rana55046232011-03-07 10:28:42 +05301700 return 0; /* RXSTALE flush not complete - retry */
1701 case CLK_REQ_OFF_RXSTALE_ISSUED:
1702 case CLK_REQ_OFF_FLUSH_ISSUED:
Mayank Ranacb589d82012-03-01 11:50:03 +05301703 spin_unlock_irqrestore(&uport->lock, flags);
1704 mutex_unlock(&msm_uport->clk_mutex);
Mayank Rana55046232011-03-07 10:28:42 +05301705 return 0; /* RXSTALE flush not complete - retry */
1706 case CLK_REQ_OFF_RXSTALE_FLUSHED:
1707 break; /* continue */
1708 }
1709
1710 if (msm_uport->rx.flush != FLUSH_SHUTDOWN) {
1711 if (msm_uport->rx.flush == FLUSH_NONE)
1712 msm_hs_stop_rx_locked(uport);
Mayank Ranacb589d82012-03-01 11:50:03 +05301713
1714 spin_unlock_irqrestore(&uport->lock, flags);
1715 mutex_unlock(&msm_uport->clk_mutex);
Mayank Rana55046232011-03-07 10:28:42 +05301716 return 0; /* come back later to really clock off */
1717 }
1718
Mayank Rana55046232011-03-07 10:28:42 +05301719 spin_unlock_irqrestore(&uport->lock, flags);
1720
Mayank Rana55046232011-03-07 10:28:42 +05301721 /* we really want to clock off */
Mayank Ranacb589d82012-03-01 11:50:03 +05301722 clk_disable_unprepare(msm_uport->clk);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001723 if (msm_uport->pclk)
Mayank Ranacb589d82012-03-01 11:50:03 +05301724 clk_disable_unprepare(msm_uport->pclk);
1725
Mayank Rana55046232011-03-07 10:28:42 +05301726 msm_uport->clk_state = MSM_HS_CLK_OFF;
Mayank Ranacb589d82012-03-01 11:50:03 +05301727
1728 spin_lock_irqsave(&uport->lock, flags);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001729 if (use_low_power_wakeup(msm_uport)) {
1730 msm_uport->wakeup.ignore = 1;
1731 enable_irq(msm_uport->wakeup.irq);
Mayank Rana55046232011-03-07 10:28:42 +05301732 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001733 wake_unlock(&msm_uport->dma_wake_lock);
Mayank Ranacb589d82012-03-01 11:50:03 +05301734
1735 spin_unlock_irqrestore(&uport->lock, flags);
Mayank Rana88d49142013-01-16 17:28:53 +05301736
1737 /* Reset PNOC Bus Scaling */
Mayank Ranae4bc7de2013-01-22 12:51:16 +05301738 msm_hs_bus_voting(msm_uport, BUS_RESET);
Mayank Ranacb589d82012-03-01 11:50:03 +05301739 mutex_unlock(&msm_uport->clk_mutex);
Mayank Ranae4bc7de2013-01-22 12:51:16 +05301740
Mayank Rana55046232011-03-07 10:28:42 +05301741 return 1;
1742}
1743
Mayank Ranacb589d82012-03-01 11:50:03 +05301744static void hsuart_clock_off_work(struct work_struct *w)
1745{
1746 struct msm_hs_port *msm_uport = container_of(w, struct msm_hs_port,
1747 clock_off_w);
Mayank Rana55046232011-03-07 10:28:42 +05301748 struct uart_port *uport = &msm_uport->uport;
1749
Mayank Ranacb589d82012-03-01 11:50:03 +05301750 if (!msm_hs_check_clock_off(uport)) {
1751 hrtimer_start(&msm_uport->clk_off_timer,
1752 msm_uport->clk_off_delay,
1753 HRTIMER_MODE_REL);
Mayank Rana55046232011-03-07 10:28:42 +05301754 }
Mayank Ranacb589d82012-03-01 11:50:03 +05301755}
Mayank Rana55046232011-03-07 10:28:42 +05301756
Mayank Ranacb589d82012-03-01 11:50:03 +05301757static enum hrtimer_restart msm_hs_clk_off_retry(struct hrtimer *timer)
1758{
1759 struct msm_hs_port *msm_uport = container_of(timer, struct msm_hs_port,
1760 clk_off_timer);
Mayank Rana55046232011-03-07 10:28:42 +05301761
Mayank Ranacb589d82012-03-01 11:50:03 +05301762 queue_work(msm_uport->hsuart_wq, &msm_uport->clock_off_w);
1763 return HRTIMER_NORESTART;
Mayank Rana55046232011-03-07 10:28:42 +05301764}
1765
1766static irqreturn_t msm_hs_isr(int irq, void *dev)
1767{
1768 unsigned long flags;
1769 unsigned long isr_status;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001770 struct msm_hs_port *msm_uport = (struct msm_hs_port *)dev;
Mayank Rana55046232011-03-07 10:28:42 +05301771 struct uart_port *uport = &msm_uport->uport;
1772 struct circ_buf *tx_buf = &uport->state->xmit;
1773 struct msm_hs_tx *tx = &msm_uport->tx;
1774 struct msm_hs_rx *rx = &msm_uport->rx;
1775
1776 spin_lock_irqsave(&uport->lock, flags);
1777
1778 isr_status = msm_hs_read(uport, UARTDM_MISR_ADDR);
1779
1780 /* Uart RX starting */
1781 if (isr_status & UARTDM_ISR_RXLEV_BMSK) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001782 wake_lock(&rx->wake_lock); /* hold wakelock while rx dma */
Mayank Rana55046232011-03-07 10:28:42 +05301783 msm_uport->imr_reg &= ~UARTDM_ISR_RXLEV_BMSK;
1784 msm_hs_write(uport, UARTDM_IMR_ADDR, msm_uport->imr_reg);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001785 /* Complete device write for IMR. Hence mb() requires. */
1786 mb();
Mayank Rana55046232011-03-07 10:28:42 +05301787 }
1788 /* Stale rx interrupt */
1789 if (isr_status & UARTDM_ISR_RXSTALE_BMSK) {
1790 msm_hs_write(uport, UARTDM_CR_ADDR, STALE_EVENT_DISABLE);
1791 msm_hs_write(uport, UARTDM_CR_ADDR, RESET_STALE_INT);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001792 /*
1793 * Complete device write before calling DMOV API. Hence
1794 * mb() requires here.
1795 */
1796 mb();
Mayank Rana55046232011-03-07 10:28:42 +05301797
Saket Saurabhcbf6c522013-01-07 16:30:37 +05301798 if (msm_uport->clk_req_off_state ==
1799 CLK_REQ_OFF_RXSTALE_ISSUED) {
Mayank Rana55046232011-03-07 10:28:42 +05301800 msm_uport->clk_req_off_state =
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001801 CLK_REQ_OFF_FLUSH_ISSUED;
1802
Saket Saurabhcbf6c522013-01-07 16:30:37 +05301803 if (is_blsp_uart(msm_uport)) {
1804 /* Reset BCR Register for UARTDM Core v14*/
1805 msm_hs_write(uport, UARTDM_BCR_ADDR, 0x0);
1806 }
1807 }
1808
Mayank Rana55046232011-03-07 10:28:42 +05301809 if (rx->flush == FLUSH_NONE) {
1810 rx->flush = FLUSH_DATA_READY;
Saket Saurabhcbf6c522013-01-07 16:30:37 +05301811 if (is_blsp_uart(msm_uport)) {
1812 queue_work(msm_uport->hsuart_wq,
1813 &msm_uport->reset_bam_rx);
1814 } else {
1815 msm_dmov_flush(msm_uport->dma_rx_channel, 1);
1816 }
Mayank Rana55046232011-03-07 10:28:42 +05301817 }
1818 }
1819 /* tx ready interrupt */
1820 if (isr_status & UARTDM_ISR_TX_READY_BMSK) {
1821 /* Clear TX Ready */
1822 msm_hs_write(uport, UARTDM_CR_ADDR, CLEAR_TX_READY);
1823
1824 if (msm_uport->clk_state == MSM_HS_CLK_REQUEST_OFF) {
1825 msm_uport->imr_reg |= UARTDM_ISR_TXLEV_BMSK;
1826 msm_hs_write(uport, UARTDM_IMR_ADDR,
1827 msm_uport->imr_reg);
1828 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001829 /*
1830 * Complete both writes before starting new TX.
1831 * Hence mb() requires here.
1832 */
1833 mb();
Mayank Rana55046232011-03-07 10:28:42 +05301834 /* Complete DMA TX transactions and submit new transactions */
Saket Saurabhce394102012-10-29 19:51:28 +05301835
1836 /* Do not update tx_buf.tail if uart_flush_buffer already
1837 called in serial core */
1838 if (!msm_uport->tty_flush_receive)
1839 tx_buf->tail = (tx_buf->tail +
1840 tx->tx_count) & ~UART_XMIT_SIZE;
1841 else
1842 msm_uport->tty_flush_receive = false;
Mayank Rana55046232011-03-07 10:28:42 +05301843
1844 tx->dma_in_flight = 0;
1845
1846 uport->icount.tx += tx->tx_count;
1847 if (tx->tx_ready_int_en)
1848 msm_hs_submit_tx_locked(uport);
1849
1850 if (uart_circ_chars_pending(tx_buf) < WAKEUP_CHARS)
1851 uart_write_wakeup(uport);
1852 }
1853 if (isr_status & UARTDM_ISR_TXLEV_BMSK) {
1854 /* TX FIFO is empty */
1855 msm_uport->imr_reg &= ~UARTDM_ISR_TXLEV_BMSK;
1856 msm_hs_write(uport, UARTDM_IMR_ADDR, msm_uport->imr_reg);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001857 /*
1858 * Complete device write before starting clock_off request.
1859 * Hence mb() requires here.
1860 */
1861 mb();
Mayank Ranacb589d82012-03-01 11:50:03 +05301862 queue_work(msm_uport->hsuart_wq, &msm_uport->clock_off_w);
Mayank Rana55046232011-03-07 10:28:42 +05301863 }
1864
1865 /* Change in CTS interrupt */
1866 if (isr_status & UARTDM_ISR_DELTA_CTS_BMSK)
Mayank Ranaee815f32011-12-08 09:06:09 +05301867 msm_hs_handle_delta_cts_locked(uport);
Mayank Rana55046232011-03-07 10:28:42 +05301868
1869 spin_unlock_irqrestore(&uport->lock, flags);
1870
1871 return IRQ_HANDLED;
1872}
1873
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001874/* request to turn off uart clock once pending TX is flushed */
1875void msm_hs_request_clock_off(struct uart_port *uport) {
1876 unsigned long flags;
Mayank Rana55046232011-03-07 10:28:42 +05301877 struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
1878
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001879 spin_lock_irqsave(&uport->lock, flags);
Mayank Rana55046232011-03-07 10:28:42 +05301880 if (msm_uport->clk_state == MSM_HS_CLK_ON) {
1881 msm_uport->clk_state = MSM_HS_CLK_REQUEST_OFF;
1882 msm_uport->clk_req_off_state = CLK_REQ_OFF_START;
Mayank Rana55046232011-03-07 10:28:42 +05301883 msm_uport->imr_reg |= UARTDM_ISR_TXLEV_BMSK;
1884 msm_hs_write(uport, UARTDM_IMR_ADDR, msm_uport->imr_reg);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001885 /*
1886 * Complete device write before retuning back.
1887 * Hence mb() requires here.
1888 */
1889 mb();
Mayank Rana55046232011-03-07 10:28:42 +05301890 }
Mayank Rana55046232011-03-07 10:28:42 +05301891 spin_unlock_irqrestore(&uport->lock, flags);
1892}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001893EXPORT_SYMBOL(msm_hs_request_clock_off);
Mayank Rana55046232011-03-07 10:28:42 +05301894
Mayank Ranacb589d82012-03-01 11:50:03 +05301895void msm_hs_request_clock_on(struct uart_port *uport)
Mayank Rana55046232011-03-07 10:28:42 +05301896{
1897 struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
Mayank Ranacb589d82012-03-01 11:50:03 +05301898 unsigned long flags;
Mayank Rana55046232011-03-07 10:28:42 +05301899 unsigned int data;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001900 int ret = 0;
Mayank Rana55046232011-03-07 10:28:42 +05301901
Mayank Ranacb589d82012-03-01 11:50:03 +05301902 mutex_lock(&msm_uport->clk_mutex);
1903 spin_lock_irqsave(&uport->lock, flags);
Mayank Rana55046232011-03-07 10:28:42 +05301904
1905 switch (msm_uport->clk_state) {
1906 case MSM_HS_CLK_OFF:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001907 wake_lock(&msm_uport->dma_wake_lock);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001908 disable_irq_nosync(msm_uport->wakeup.irq);
Mayank Ranacb589d82012-03-01 11:50:03 +05301909 spin_unlock_irqrestore(&uport->lock, flags);
Mayank Rana88d49142013-01-16 17:28:53 +05301910
1911 /* Vote for PNOC BUS Scaling */
Mayank Ranae4bc7de2013-01-22 12:51:16 +05301912 msm_hs_bus_voting(msm_uport, BUS_SCALING);
Mayank Rana88d49142013-01-16 17:28:53 +05301913
Mayank Ranacb589d82012-03-01 11:50:03 +05301914 ret = clk_prepare_enable(msm_uport->clk);
1915 if (ret) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001916 dev_err(uport->dev, "Clock ON Failure"
Mayank Ranacb589d82012-03-01 11:50:03 +05301917 "For UART CLK Stalling HSUART\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001918 break;
1919 }
Mayank Ranacb589d82012-03-01 11:50:03 +05301920
1921 if (msm_uport->pclk) {
1922 ret = clk_prepare_enable(msm_uport->pclk);
1923 if (unlikely(ret)) {
1924 clk_disable_unprepare(msm_uport->clk);
1925 dev_err(uport->dev, "Clock ON Failure"
1926 "For UART Pclk Stalling HSUART\n");
1927 break;
1928 }
1929 }
1930 spin_lock_irqsave(&uport->lock, flags);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001931 /* else fall-through */
Mayank Rana55046232011-03-07 10:28:42 +05301932 case MSM_HS_CLK_REQUEST_OFF:
1933 if (msm_uport->rx.flush == FLUSH_STOP ||
1934 msm_uport->rx.flush == FLUSH_SHUTDOWN) {
1935 msm_hs_write(uport, UARTDM_CR_ADDR, RESET_RX);
1936 data = msm_hs_read(uport, UARTDM_DMEN_ADDR);
Saket Saurabhcbf6c522013-01-07 16:30:37 +05301937 if (is_blsp_uart(msm_uport))
1938 data |= UARTDM_RX_BAM_ENABLE_BMSK;
1939 else
1940 data |= UARTDM_RX_DM_EN_BMSK;
Mayank Rana55046232011-03-07 10:28:42 +05301941 msm_hs_write(uport, UARTDM_DMEN_ADDR, data);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001942 /* Complete above device write. Hence mb() here. */
1943 mb();
Mayank Rana55046232011-03-07 10:28:42 +05301944 }
1945 hrtimer_try_to_cancel(&msm_uport->clk_off_timer);
1946 if (msm_uport->rx.flush == FLUSH_SHUTDOWN)
1947 msm_hs_start_rx_locked(uport);
Mayank Rana55046232011-03-07 10:28:42 +05301948 if (msm_uport->rx.flush == FLUSH_STOP)
1949 msm_uport->rx.flush = FLUSH_IGNORE;
1950 msm_uport->clk_state = MSM_HS_CLK_ON;
1951 break;
1952 case MSM_HS_CLK_ON:
1953 break;
1954 case MSM_HS_CLK_PORT_OFF:
1955 break;
1956 }
Mayank Rana55046232011-03-07 10:28:42 +05301957
Mayank Rana55046232011-03-07 10:28:42 +05301958 spin_unlock_irqrestore(&uport->lock, flags);
Mayank Ranacb589d82012-03-01 11:50:03 +05301959 mutex_unlock(&msm_uport->clk_mutex);
Mayank Rana55046232011-03-07 10:28:42 +05301960}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001961EXPORT_SYMBOL(msm_hs_request_clock_on);
Mayank Rana55046232011-03-07 10:28:42 +05301962
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001963static irqreturn_t msm_hs_wakeup_isr(int irq, void *dev)
Mayank Rana55046232011-03-07 10:28:42 +05301964{
1965 unsigned int wakeup = 0;
1966 unsigned long flags;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001967 struct msm_hs_port *msm_uport = (struct msm_hs_port *)dev;
Mayank Rana55046232011-03-07 10:28:42 +05301968 struct uart_port *uport = &msm_uport->uport;
1969 struct tty_struct *tty = NULL;
1970
1971 spin_lock_irqsave(&uport->lock, flags);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001972 if (msm_uport->clk_state == MSM_HS_CLK_OFF) {
1973 /* ignore the first irq - it is a pending irq that occured
Mayank Rana55046232011-03-07 10:28:42 +05301974 * before enable_irq() */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001975 if (msm_uport->wakeup.ignore)
1976 msm_uport->wakeup.ignore = 0;
Mayank Rana55046232011-03-07 10:28:42 +05301977 else
1978 wakeup = 1;
1979 }
1980
1981 if (wakeup) {
1982 /* the uart was clocked off during an rx, wake up and
1983 * optionally inject char into tty rx */
Mayank Ranacb589d82012-03-01 11:50:03 +05301984 spin_unlock_irqrestore(&uport->lock, flags);
1985 msm_hs_request_clock_on(uport);
1986 spin_lock_irqsave(&uport->lock, flags);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001987 if (msm_uport->wakeup.inject_rx) {
Mayank Rana55046232011-03-07 10:28:42 +05301988 tty = uport->state->port.tty;
1989 tty_insert_flip_char(tty,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001990 msm_uport->wakeup.rx_to_inject,
Mayank Rana55046232011-03-07 10:28:42 +05301991 TTY_NORMAL);
Mayank Rana55046232011-03-07 10:28:42 +05301992 }
1993 }
1994
1995 spin_unlock_irqrestore(&uport->lock, flags);
1996
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001997 if (wakeup && msm_uport->wakeup.inject_rx)
1998 tty_flip_buffer_push(tty);
Mayank Rana55046232011-03-07 10:28:42 +05301999 return IRQ_HANDLED;
2000}
2001
2002static const char *msm_hs_type(struct uart_port *port)
2003{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002004 return ("MSM HS UART");
Mayank Rana55046232011-03-07 10:28:42 +05302005}
2006
Saket Saurabhfe3b93b2013-02-04 18:44:12 +05302007/**
2008 * msm_hs_unconfig_uart_gpios: Unconfigures UART GPIOs
2009 * @uport: uart port
2010 */
2011static void msm_hs_unconfig_uart_gpios(struct uart_port *uport)
2012{
2013 struct platform_device *pdev = to_platform_device(uport->dev);
2014 const struct msm_serial_hs_platform_data *pdata =
2015 pdev->dev.platform_data;
2016
2017 if (pdata) {
2018 if (gpio_is_valid(pdata->uart_tx_gpio))
2019 gpio_free(pdata->uart_tx_gpio);
2020 if (gpio_is_valid(pdata->uart_rx_gpio))
2021 gpio_free(pdata->uart_rx_gpio);
2022 if (gpio_is_valid(pdata->uart_cts_gpio))
2023 gpio_free(pdata->uart_cts_gpio);
2024 if (gpio_is_valid(pdata->uart_rfr_gpio))
2025 gpio_free(pdata->uart_rfr_gpio);
2026 } else {
2027 pr_err("Error:Pdata is NULL.\n");
2028 }
2029}
2030
2031/**
2032 * msm_hs_config_uart_gpios - Configures UART GPIOs
2033 * @uport: uart port
2034 */
2035static int msm_hs_config_uart_gpios(struct uart_port *uport)
2036{
2037 struct platform_device *pdev = to_platform_device(uport->dev);
2038 const struct msm_serial_hs_platform_data *pdata =
2039 pdev->dev.platform_data;
2040 int ret = 0;
2041
2042 if (pdata) {
2043 if (gpio_is_valid(pdata->uart_tx_gpio)) {
2044 ret = gpio_request(pdata->uart_tx_gpio,
2045 "UART_TX_GPIO");
2046 if (unlikely(ret)) {
2047 pr_err("gpio request failed for:%d\n",
2048 pdata->uart_tx_gpio);
2049 goto exit_uart_config;
2050 }
2051 }
2052
2053 if (gpio_is_valid(pdata->uart_rx_gpio)) {
2054 ret = gpio_request(pdata->uart_rx_gpio,
2055 "UART_RX_GPIO");
2056 if (unlikely(ret)) {
2057 pr_err("gpio request failed for:%d\n",
2058 pdata->uart_rx_gpio);
2059 goto uart_tx_unconfig;
2060 }
2061 }
2062
2063 if (gpio_is_valid(pdata->uart_cts_gpio)) {
2064 ret = gpio_request(pdata->uart_cts_gpio,
2065 "UART_CTS_GPIO");
2066 if (unlikely(ret)) {
2067 pr_err("gpio request failed for:%d\n",
2068 pdata->uart_cts_gpio);
2069 goto uart_rx_unconfig;
2070 }
2071 }
2072
2073 if (gpio_is_valid(pdata->uart_rfr_gpio)) {
2074 ret = gpio_request(pdata->uart_rfr_gpio,
2075 "UART_RFR_GPIO");
2076 if (unlikely(ret)) {
2077 pr_err("gpio request failed for:%d\n",
2078 pdata->uart_rfr_gpio);
2079 goto uart_cts_unconfig;
2080 }
2081 }
2082 } else {
2083 pr_err("Pdata is NULL.\n");
2084 ret = -EINVAL;
2085 }
2086 return ret;
2087
2088uart_cts_unconfig:
2089 if (gpio_is_valid(pdata->uart_cts_gpio))
2090 gpio_free(pdata->uart_cts_gpio);
2091uart_rx_unconfig:
2092 if (gpio_is_valid(pdata->uart_rx_gpio))
2093 gpio_free(pdata->uart_rx_gpio);
2094uart_tx_unconfig:
2095 if (gpio_is_valid(pdata->uart_tx_gpio))
2096 gpio_free(pdata->uart_tx_gpio);
2097exit_uart_config:
2098 return ret;
2099}
2100
Mayank Rana55046232011-03-07 10:28:42 +05302101/* Called when port is opened */
2102static int msm_hs_startup(struct uart_port *uport)
2103{
2104 int ret;
2105 int rfr_level;
2106 unsigned long flags;
2107 unsigned int data;
2108 struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
Mayank Rana40836782012-11-16 14:45:47 +05302109 struct platform_device *pdev = to_platform_device(uport->dev);
2110 const struct msm_serial_hs_platform_data *pdata =
2111 pdev->dev.platform_data;
Mayank Rana55046232011-03-07 10:28:42 +05302112 struct circ_buf *tx_buf = &uport->state->xmit;
2113 struct msm_hs_tx *tx = &msm_uport->tx;
Saket Saurabhcbf6c522013-01-07 16:30:37 +05302114 struct msm_hs_rx *rx = &msm_uport->rx;
2115 struct sps_pipe *sps_pipe_handle_tx = tx->cons.pipe_handle;
2116 struct sps_pipe *sps_pipe_handle_rx = rx->prod.pipe_handle;
Mayank Rana55046232011-03-07 10:28:42 +05302117
2118 rfr_level = uport->fifosize;
2119 if (rfr_level > 16)
2120 rfr_level -= 16;
2121
2122 tx->dma_base = dma_map_single(uport->dev, tx_buf->buf, UART_XMIT_SIZE,
2123 DMA_TO_DEVICE);
2124
Mayank Rana679436e2012-03-31 05:41:14 +05302125 wake_lock(&msm_uport->dma_wake_lock);
Mayank Rana55046232011-03-07 10:28:42 +05302126 /* turn on uart clk */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002127 ret = msm_hs_init_clk(uport);
Mayank Rana55046232011-03-07 10:28:42 +05302128 if (unlikely(ret)) {
Mayank Rana679436e2012-03-31 05:41:14 +05302129 pr_err("Turning ON uartclk error\n");
2130 wake_unlock(&msm_uport->dma_wake_lock);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002131 return ret;
Mayank Rana55046232011-03-07 10:28:42 +05302132 }
2133
Saket Saurabhfe3b93b2013-02-04 18:44:12 +05302134 if (is_blsp_uart(msm_uport)) {
2135 ret = msm_hs_config_uart_gpios(uport);
2136 if (ret) {
2137 pr_err("Uart GPIO request failed\n");
2138 goto deinit_uart_clk;
2139 }
2140 } else {
2141 if (pdata && pdata->gpio_config)
2142 if (unlikely(pdata->gpio_config(1)))
2143 dev_err(uport->dev, "Cannot configure gpios\n");
2144 }
Saket Saurabhcbf6c522013-01-07 16:30:37 +05302145
2146 /* SPS Connect for BAM endpoints */
2147 if (is_blsp_uart(msm_uport)) {
2148 /* SPS connect for TX */
2149 ret = msm_hs_spsconnect_tx(uport);
2150 if (ret) {
2151 pr_err("msm_serial_hs: SPS connect failed for TX");
Saket Saurabhfe3b93b2013-02-04 18:44:12 +05302152 goto unconfig_uart_gpios;
Saket Saurabhcbf6c522013-01-07 16:30:37 +05302153 }
2154
2155 /* SPS connect for RX */
2156 ret = msm_hs_spsconnect_rx(uport);
2157 if (ret) {
2158 pr_err("msm_serial_hs: SPS connect failed for RX");
2159 goto sps_disconnect_tx;
2160 }
2161 }
2162
Mayank Rana55046232011-03-07 10:28:42 +05302163 /* Set auto RFR Level */
2164 data = msm_hs_read(uport, UARTDM_MR1_ADDR);
2165 data &= ~UARTDM_MR1_AUTO_RFR_LEVEL1_BMSK;
2166 data &= ~UARTDM_MR1_AUTO_RFR_LEVEL0_BMSK;
2167 data |= (UARTDM_MR1_AUTO_RFR_LEVEL1_BMSK & (rfr_level << 2));
2168 data |= (UARTDM_MR1_AUTO_RFR_LEVEL0_BMSK & rfr_level);
2169 msm_hs_write(uport, UARTDM_MR1_ADDR, data);
2170
2171 /* Make sure RXSTALE count is non-zero */
2172 data = msm_hs_read(uport, UARTDM_IPR_ADDR);
2173 if (!data) {
2174 data |= 0x1f & UARTDM_IPR_STALE_LSB_BMSK;
2175 msm_hs_write(uport, UARTDM_IPR_ADDR, data);
2176 }
2177
Saket Saurabhcbf6c522013-01-07 16:30:37 +05302178 if (is_blsp_uart(msm_uport)) {
2179 /* Enable BAM mode */
2180 data = UARTDM_TX_BAM_ENABLE_BMSK | UARTDM_RX_BAM_ENABLE_BMSK;
2181 } else {
2182 /* Enable Data Mover Mode */
2183 data = UARTDM_TX_DM_EN_BMSK | UARTDM_RX_DM_EN_BMSK;
2184 }
Mayank Rana55046232011-03-07 10:28:42 +05302185 msm_hs_write(uport, UARTDM_DMEN_ADDR, data);
2186
2187 /* Reset TX */
2188 msm_hs_write(uport, UARTDM_CR_ADDR, RESET_TX);
2189 msm_hs_write(uport, UARTDM_CR_ADDR, RESET_RX);
2190 msm_hs_write(uport, UARTDM_CR_ADDR, RESET_ERROR_STATUS);
2191 msm_hs_write(uport, UARTDM_CR_ADDR, RESET_BREAK_INT);
2192 msm_hs_write(uport, UARTDM_CR_ADDR, RESET_STALE_INT);
2193 msm_hs_write(uport, UARTDM_CR_ADDR, RESET_CTS);
2194 msm_hs_write(uport, UARTDM_CR_ADDR, RFR_LOW);
2195 /* Turn on Uart Receiver */
2196 msm_hs_write(uport, UARTDM_CR_ADDR, UARTDM_CR_RX_EN_BMSK);
2197
2198 /* Turn on Uart Transmitter */
2199 msm_hs_write(uport, UARTDM_CR_ADDR, UARTDM_CR_TX_EN_BMSK);
2200
2201 /* Initialize the tx */
2202 tx->tx_ready_int_en = 0;
2203 tx->dma_in_flight = 0;
2204
Saket Saurabhcbf6c522013-01-07 16:30:37 +05302205 if (!is_blsp_uart(msm_uport)) {
2206 tx->xfer.complete_func = msm_hs_dmov_tx_callback;
Mayank Rana55046232011-03-07 10:28:42 +05302207
Saket Saurabhcbf6c522013-01-07 16:30:37 +05302208 tx->command_ptr->cmd = CMD_LC |
2209 CMD_DST_CRCI(msm_uport->dma_tx_crci) | CMD_MODE_BOX;
Mayank Rana55046232011-03-07 10:28:42 +05302210
Saket Saurabhcbf6c522013-01-07 16:30:37 +05302211 tx->command_ptr->src_dst_len = (MSM_UARTDM_BURST_SIZE << 16)
Mayank Rana55046232011-03-07 10:28:42 +05302212 | (MSM_UARTDM_BURST_SIZE);
2213
Saket Saurabhcbf6c522013-01-07 16:30:37 +05302214 tx->command_ptr->row_offset = (MSM_UARTDM_BURST_SIZE << 16);
Mayank Rana55046232011-03-07 10:28:42 +05302215
Saket Saurabhcbf6c522013-01-07 16:30:37 +05302216 tx->command_ptr->dst_row_addr =
2217 msm_uport->uport.mapbase + UARTDM_TF_ADDR;
2218 }
Mayank Rana55046232011-03-07 10:28:42 +05302219
Mayank Rana55046232011-03-07 10:28:42 +05302220 msm_uport->imr_reg |= UARTDM_ISR_RXSTALE_BMSK;
2221 /* Enable reading the current CTS, no harm even if CTS is ignored */
2222 msm_uport->imr_reg |= UARTDM_ISR_CURRENT_CTS_BMSK;
2223
2224 msm_hs_write(uport, UARTDM_TFWR_ADDR, 0); /* TXLEV on empty TX fifo */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002225 /*
2226 * Complete all device write related configuration before
2227 * queuing RX request. Hence mb() requires here.
2228 */
2229 mb();
Mayank Rana55046232011-03-07 10:28:42 +05302230
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002231 if (use_low_power_wakeup(msm_uport)) {
2232 ret = irq_set_irq_wake(msm_uport->wakeup.irq, 1);
Mayank Rana679436e2012-03-31 05:41:14 +05302233 if (unlikely(ret)) {
2234 pr_err("%s():Err setting wakeup irq\n", __func__);
Saket Saurabhcbf6c522013-01-07 16:30:37 +05302235 goto sps_disconnect_rx;
Mayank Rana679436e2012-03-31 05:41:14 +05302236 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002237 }
Mayank Rana55046232011-03-07 10:28:42 +05302238
2239 ret = request_irq(uport->irq, msm_hs_isr, IRQF_TRIGGER_HIGH,
2240 "msm_hs_uart", msm_uport);
2241 if (unlikely(ret)) {
Mayank Rana679436e2012-03-31 05:41:14 +05302242 pr_err("%s():Error getting uart irq\n", __func__);
2243 goto free_wake_irq;
Mayank Rana55046232011-03-07 10:28:42 +05302244 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002245 if (use_low_power_wakeup(msm_uport)) {
Mayank Ranacb589d82012-03-01 11:50:03 +05302246
2247 ret = request_threaded_irq(msm_uport->wakeup.irq, NULL,
2248 msm_hs_wakeup_isr,
2249 IRQF_TRIGGER_FALLING,
2250 "msm_hs_wakeup", msm_uport);
2251
Mayank Rana55046232011-03-07 10:28:42 +05302252 if (unlikely(ret)) {
Mayank Rana679436e2012-03-31 05:41:14 +05302253 pr_err("%s():Err getting uart wakeup_irq\n", __func__);
2254 goto free_uart_irq;
Mayank Rana55046232011-03-07 10:28:42 +05302255 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002256 disable_irq(msm_uport->wakeup.irq);
Mayank Rana55046232011-03-07 10:28:42 +05302257 }
2258
Mayank Rana88d49142013-01-16 17:28:53 +05302259 /* Vote for PNOC BUS Scaling */
Mayank Ranae4bc7de2013-01-22 12:51:16 +05302260 msm_hs_bus_voting(msm_uport, BUS_SCALING);
Mayank Rana88d49142013-01-16 17:28:53 +05302261
Mayank Rana55046232011-03-07 10:28:42 +05302262 spin_lock_irqsave(&uport->lock, flags);
2263
Mayank Rana55046232011-03-07 10:28:42 +05302264 msm_hs_start_rx_locked(uport);
2265
2266 spin_unlock_irqrestore(&uport->lock, flags);
2267 ret = pm_runtime_set_active(uport->dev);
2268 if (ret)
2269 dev_err(uport->dev, "set active error:%d\n", ret);
2270 pm_runtime_enable(uport->dev);
2271
2272 return 0;
2273
Mayank Rana679436e2012-03-31 05:41:14 +05302274free_uart_irq:
2275 free_irq(uport->irq, msm_uport);
2276free_wake_irq:
2277 irq_set_irq_wake(msm_uport->wakeup.irq, 0);
Saket Saurabhcbf6c522013-01-07 16:30:37 +05302278sps_disconnect_rx:
2279 if (is_blsp_uart(msm_uport))
2280 sps_disconnect(sps_pipe_handle_rx);
2281sps_disconnect_tx:
2282 if (is_blsp_uart(msm_uport))
2283 sps_disconnect(sps_pipe_handle_tx);
Saket Saurabhfe3b93b2013-02-04 18:44:12 +05302284unconfig_uart_gpios:
2285 if (is_blsp_uart(msm_uport))
2286 msm_hs_unconfig_uart_gpios(uport);
Mayank Rana679436e2012-03-31 05:41:14 +05302287deinit_uart_clk:
Mayank Ranacb589d82012-03-01 11:50:03 +05302288 clk_disable_unprepare(msm_uport->clk);
Mayank Rana679436e2012-03-31 05:41:14 +05302289 if (msm_uport->pclk)
Mayank Ranacb589d82012-03-01 11:50:03 +05302290 clk_disable_unprepare(msm_uport->pclk);
Mayank Rana679436e2012-03-31 05:41:14 +05302291 wake_unlock(&msm_uport->dma_wake_lock);
2292
Mayank Rana55046232011-03-07 10:28:42 +05302293 return ret;
2294}
2295
2296/* Initialize tx and rx data structures */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002297static int uartdm_init_port(struct uart_port *uport)
Mayank Rana55046232011-03-07 10:28:42 +05302298{
2299 int ret = 0;
2300 struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
2301 struct msm_hs_tx *tx = &msm_uport->tx;
2302 struct msm_hs_rx *rx = &msm_uport->rx;
2303
Mayank Rana55046232011-03-07 10:28:42 +05302304 init_waitqueue_head(&rx->wait);
Mayank Ranaaf2f0082012-05-22 10:16:02 +05302305 init_waitqueue_head(&tx->wait);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002306 wake_lock_init(&rx->wake_lock, WAKE_LOCK_SUSPEND, "msm_serial_hs_rx");
2307 wake_lock_init(&msm_uport->dma_wake_lock, WAKE_LOCK_SUSPEND,
2308 "msm_serial_hs_dma");
2309
2310 tasklet_init(&rx->tlet, msm_serial_hs_rx_tlet,
2311 (unsigned long) &rx->tlet);
2312 tasklet_init(&tx->tlet, msm_serial_hs_tx_tlet,
2313 (unsigned long) &tx->tlet);
Mayank Rana55046232011-03-07 10:28:42 +05302314
2315 rx->pool = dma_pool_create("rx_buffer_pool", uport->dev,
2316 UARTDM_RX_BUF_SIZE, 16, 0);
2317 if (!rx->pool) {
2318 pr_err("%s(): cannot allocate rx_buffer_pool", __func__);
2319 ret = -ENOMEM;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002320 goto exit_tasket_init;
Mayank Rana55046232011-03-07 10:28:42 +05302321 }
2322
2323 rx->buffer = dma_pool_alloc(rx->pool, GFP_KERNEL, &rx->rbuffer);
2324 if (!rx->buffer) {
2325 pr_err("%s(): cannot allocate rx->buffer", __func__);
2326 ret = -ENOMEM;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002327 goto free_pool;
Mayank Rana55046232011-03-07 10:28:42 +05302328 }
2329
Mayank Ranaff398d02012-12-18 10:22:50 +05302330 /* Set up Uart Receive */
2331 msm_hs_write(uport, UARTDM_RFWR_ADDR, 0);
2332
2333 INIT_DELAYED_WORK(&rx->flip_insert_work, flip_insert_work);
2334
2335 if (is_blsp_uart(msm_uport))
2336 return ret;
2337
2338 /* Allocate the command pointer. Needs to be 64 bit aligned */
2339 tx->command_ptr = kmalloc(sizeof(dmov_box), GFP_KERNEL | __GFP_DMA);
2340 if (!tx->command_ptr) {
2341 return -ENOMEM;
2342 goto free_rx_buffer;
2343 }
2344
2345 tx->command_ptr_ptr = kmalloc(sizeof(u32), GFP_KERNEL | __GFP_DMA);
2346 if (!tx->command_ptr_ptr) {
2347 ret = -ENOMEM;
2348 goto free_tx_command_ptr;
2349 }
2350
2351 tx->mapped_cmd_ptr = dma_map_single(uport->dev, tx->command_ptr,
2352 sizeof(dmov_box), DMA_TO_DEVICE);
2353 tx->mapped_cmd_ptr_ptr = dma_map_single(uport->dev,
2354 tx->command_ptr_ptr,
2355 sizeof(u32), DMA_TO_DEVICE);
2356 tx->xfer.cmdptr = DMOV_CMD_ADDR(tx->mapped_cmd_ptr_ptr);
2357
Mayank Rana55046232011-03-07 10:28:42 +05302358 /* Allocate the command pointer. Needs to be 64 bit aligned */
2359 rx->command_ptr = kmalloc(sizeof(dmov_box), GFP_KERNEL | __GFP_DMA);
2360 if (!rx->command_ptr) {
2361 pr_err("%s(): cannot allocate rx->command_ptr", __func__);
2362 ret = -ENOMEM;
Mayank Ranaff398d02012-12-18 10:22:50 +05302363 goto free_tx_command_ptr_ptr;
Mayank Rana55046232011-03-07 10:28:42 +05302364 }
2365
Mayank Rana8431de82011-12-08 09:06:08 +05302366 rx->command_ptr_ptr = kmalloc(sizeof(u32), GFP_KERNEL | __GFP_DMA);
Mayank Rana55046232011-03-07 10:28:42 +05302367 if (!rx->command_ptr_ptr) {
2368 pr_err("%s(): cannot allocate rx->command_ptr_ptr", __func__);
2369 ret = -ENOMEM;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002370 goto free_rx_command_ptr;
Mayank Rana55046232011-03-07 10:28:42 +05302371 }
2372
2373 rx->command_ptr->num_rows = ((UARTDM_RX_BUF_SIZE >> 4) << 16) |
2374 (UARTDM_RX_BUF_SIZE >> 4);
2375
2376 rx->command_ptr->dst_row_addr = rx->rbuffer;
2377
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002378 rx->xfer.complete_func = msm_hs_dmov_rx_callback;
2379
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002380 rx->command_ptr->cmd = CMD_LC |
2381 CMD_SRC_CRCI(msm_uport->dma_rx_crci) | CMD_MODE_BOX;
2382
2383 rx->command_ptr->src_dst_len = (MSM_UARTDM_BURST_SIZE << 16)
2384 | (MSM_UARTDM_BURST_SIZE);
2385 rx->command_ptr->row_offset = MSM_UARTDM_BURST_SIZE;
2386 rx->command_ptr->src_row_addr = uport->mapbase + UARTDM_RF_ADDR;
2387
Mayank Rana55046232011-03-07 10:28:42 +05302388 rx->mapped_cmd_ptr = dma_map_single(uport->dev, rx->command_ptr,
2389 sizeof(dmov_box), DMA_TO_DEVICE);
2390
2391 *rx->command_ptr_ptr = CMD_PTR_LP | DMOV_CMD_ADDR(rx->mapped_cmd_ptr);
2392
2393 rx->cmdptr_dmaaddr = dma_map_single(uport->dev, rx->command_ptr_ptr,
Mayank Rana8431de82011-12-08 09:06:08 +05302394 sizeof(u32), DMA_TO_DEVICE);
Mayank Rana55046232011-03-07 10:28:42 +05302395 rx->xfer.cmdptr = DMOV_CMD_ADDR(rx->cmdptr_dmaaddr);
2396
Mayank Rana55046232011-03-07 10:28:42 +05302397 return ret;
2398
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002399free_rx_command_ptr:
Mayank Rana55046232011-03-07 10:28:42 +05302400 kfree(rx->command_ptr);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002401
Mayank Ranaff398d02012-12-18 10:22:50 +05302402free_tx_command_ptr_ptr:
2403 kfree(msm_uport->tx.command_ptr_ptr);
2404 dma_unmap_single(uport->dev, msm_uport->tx.mapped_cmd_ptr_ptr,
2405 sizeof(u32), DMA_TO_DEVICE);
2406 dma_unmap_single(uport->dev, msm_uport->tx.mapped_cmd_ptr,
2407 sizeof(dmov_box), DMA_TO_DEVICE);
2408
2409free_tx_command_ptr:
2410 kfree(msm_uport->tx.command_ptr);
2411
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002412free_rx_buffer:
Mayank Rana55046232011-03-07 10:28:42 +05302413 dma_pool_free(msm_uport->rx.pool, msm_uport->rx.buffer,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002414 msm_uport->rx.rbuffer);
2415
2416free_pool:
Mayank Rana55046232011-03-07 10:28:42 +05302417 dma_pool_destroy(msm_uport->rx.pool);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002418
2419exit_tasket_init:
2420 wake_lock_destroy(&msm_uport->rx.wake_lock);
2421 wake_lock_destroy(&msm_uport->dma_wake_lock);
2422 tasklet_kill(&msm_uport->tx.tlet);
2423 tasklet_kill(&msm_uport->rx.tlet);
Mayank Rana55046232011-03-07 10:28:42 +05302424 return ret;
2425}
2426
Mayank Ranaff398d02012-12-18 10:22:50 +05302427struct msm_serial_hs_platform_data
2428 *msm_hs_dt_to_pdata(struct platform_device *pdev)
2429{
2430 struct device_node *node = pdev->dev.of_node;
2431 struct msm_serial_hs_platform_data *pdata;
2432 int rx_to_inject, ret;
2433
2434 pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
2435 if (!pdata) {
2436 pr_err("unable to allocate memory for platform data\n");
2437 return ERR_PTR(-ENOMEM);
2438 }
2439
2440 /* UART TX GPIO */
2441 pdata->uart_tx_gpio = of_get_named_gpio(node,
2442 "qcom,tx-gpio", 0);
2443 if (pdata->uart_tx_gpio < 0)
2444 pr_debug("uart_tx_gpio is not available\n");
2445
2446 /* UART RX GPIO */
2447 pdata->uart_rx_gpio = of_get_named_gpio(node,
2448 "qcom,rx-gpio", 0);
2449 if (pdata->uart_rx_gpio < 0)
2450 pr_debug("uart_rx_gpio is not available\n");
2451
2452 /* UART CTS GPIO */
2453 pdata->uart_cts_gpio = of_get_named_gpio(node,
2454 "qcom,cts-gpio", 0);
2455 if (pdata->uart_cts_gpio < 0)
2456 pr_debug("uart_cts_gpio is not available\n");
2457
2458 /* UART RFR GPIO */
2459 pdata->uart_rfr_gpio = of_get_named_gpio(node,
2460 "qcom,rfr-gpio", 0);
2461 if (pdata->uart_rfr_gpio < 0)
2462 pr_debug("uart_rfr_gpio is not available\n");
2463
2464 pdata->inject_rx_on_wakeup = of_property_read_bool(node,
2465 "qcom,inject-rx-on-wakeup");
2466
2467 if (pdata->inject_rx_on_wakeup) {
2468 ret = of_property_read_u32(node, "qcom,rx-char-to-inject",
2469 &rx_to_inject);
2470 if (ret < 0) {
2471 pr_err("Error: Rx_char_to_inject not specified.\n");
2472 return ERR_PTR(ret);
2473 }
2474 pdata->rx_to_inject = (char)rx_to_inject;
2475 }
2476
2477 ret = of_property_read_u32(node, "qcom,bam-tx-ep-pipe-index",
2478 &pdata->bam_tx_ep_pipe_index);
2479 if (ret < 0) {
2480 pr_err("Error: Getting UART BAM TX EP Pipe Index.\n");
2481 return ERR_PTR(ret);
2482 }
2483
2484 if (!(pdata->bam_tx_ep_pipe_index >= BAM_PIPE_MIN &&
2485 pdata->bam_tx_ep_pipe_index <= BAM_PIPE_MAX)) {
2486 pr_err("Error: Invalid UART BAM TX EP Pipe Index.\n");
2487 return ERR_PTR(-EINVAL);
2488 }
2489
2490 ret = of_property_read_u32(node, "qcom,bam-rx-ep-pipe-index",
2491 &pdata->bam_rx_ep_pipe_index);
2492 if (ret < 0) {
2493 pr_err("Error: Getting UART BAM RX EP Pipe Index.\n");
2494 return ERR_PTR(ret);
2495 }
2496
2497 if (!(pdata->bam_rx_ep_pipe_index >= BAM_PIPE_MIN &&
2498 pdata->bam_rx_ep_pipe_index <= BAM_PIPE_MAX)) {
2499 pr_err("Error: Invalid UART BAM RX EP Pipe Index.\n");
2500 return ERR_PTR(-EINVAL);
2501 }
2502
2503 pr_debug("tx_ep_pipe_index:%d rx_ep_pipe_index:%d\n"
2504 "tx_gpio:%d rx_gpio:%d rfr_gpio:%d cts_gpio:%d",
2505 pdata->bam_tx_ep_pipe_index, pdata->bam_rx_ep_pipe_index,
2506 pdata->uart_tx_gpio, pdata->uart_rx_gpio, pdata->uart_cts_gpio,
2507 pdata->uart_rfr_gpio);
2508
2509 return pdata;
2510}
2511
Saket Saurabhcbf6c522013-01-07 16:30:37 +05302512
2513/**
2514 * Deallocate UART peripheral's SPS endpoint
2515 * @msm_uport - Pointer to msm_hs_port structure
2516 * @ep - Pointer to sps endpoint data structure
2517 */
2518
2519static void msm_hs_exit_ep_conn(struct msm_hs_port *msm_uport,
2520 struct msm_hs_sps_ep_conn_data *ep)
2521{
2522 struct sps_pipe *sps_pipe_handle = ep->pipe_handle;
2523 struct sps_connect *sps_config = &ep->config;
2524
2525 dma_free_coherent(msm_uport->uport.dev,
2526 sps_config->desc.size,
2527 &sps_config->desc.phys_base,
2528 GFP_KERNEL);
2529 sps_free_endpoint(sps_pipe_handle);
2530}
2531
2532
2533/**
2534 * Allocate UART peripheral's SPS endpoint
2535 *
2536 * This function allocates endpoint context
2537 * by calling appropriate SPS driver APIs.
2538 *
2539 * @msm_uport - Pointer to msm_hs_port structure
2540 * @ep - Pointer to sps endpoint data structure
2541 * @is_produce - 1 means Producer endpoint
2542 * - 0 means Consumer endpoint
2543 *
2544 * @return - 0 if successful else negative value
2545 */
2546
2547static int msm_hs_sps_init_ep_conn(struct msm_hs_port *msm_uport,
2548 struct msm_hs_sps_ep_conn_data *ep,
2549 bool is_producer)
2550{
2551 int rc = 0;
2552 struct sps_pipe *sps_pipe_handle;
2553 struct sps_connect *sps_config = &ep->config;
2554 struct sps_register_event *sps_event = &ep->event;
2555
2556 /* Allocate endpoint context */
2557 sps_pipe_handle = sps_alloc_endpoint();
2558 if (!sps_pipe_handle) {
2559 pr_err("msm_serial_hs: sps_alloc_endpoint() failed!!\n"
2560 "is_producer=%d", is_producer);
2561 rc = -ENOMEM;
2562 goto out;
2563 }
2564
2565 /* Get default connection configuration for an endpoint */
2566 rc = sps_get_config(sps_pipe_handle, sps_config);
2567 if (rc) {
2568 pr_err("msm_serial_hs: sps_get_config() failed!!\n"
2569 "pipe_handle=0x%x rc=%d", (u32)sps_pipe_handle, rc);
2570 goto get_config_err;
2571 }
2572
2573 /* Modify the default connection configuration */
2574 if (is_producer) {
2575 /* For UART producer transfer, source is UART peripheral
2576 where as destination is system memory */
2577 sps_config->source = msm_uport->bam_handle;
2578 sps_config->destination = SPS_DEV_HANDLE_MEM;
2579 sps_config->mode = SPS_MODE_SRC;
2580 sps_config->src_pipe_index = msm_uport->bam_rx_ep_pipe_index;
2581 sps_config->dest_pipe_index = 0;
2582 sps_config->options = SPS_O_EOT;
2583 } else {
2584 /* For UART consumer transfer, source is system memory
2585 where as destination is UART peripheral */
2586 sps_config->source = SPS_DEV_HANDLE_MEM;
2587 sps_config->destination = msm_uport->bam_handle;
2588 sps_config->mode = SPS_MODE_DEST;
2589 sps_config->src_pipe_index = 0;
2590 sps_config->dest_pipe_index = msm_uport->bam_tx_ep_pipe_index;
2591 sps_config->options = SPS_O_EOT;
2592 }
2593
2594 sps_config->event_thresh = 0x10;
2595
2596 /* Allocate maximum descriptor fifo size */
2597 sps_config->desc.size = 65532;
2598 sps_config->desc.base = dma_alloc_coherent(msm_uport->uport.dev,
2599 sps_config->desc.size,
2600 &sps_config->desc.phys_base,
2601 GFP_KERNEL);
2602 if (!sps_config->desc.base) {
2603 rc = -ENOMEM;
2604 pr_err("msm_serial_hs: dma_alloc_coherent() failed!!\n");
2605 goto get_config_err;
2606 }
2607 memset(sps_config->desc.base, 0x00, sps_config->desc.size);
2608
2609 sps_event->mode = SPS_TRIGGER_CALLBACK;
2610 sps_event->options = SPS_O_EOT;
2611 if (is_producer)
2612 sps_event->callback = msm_hs_sps_rx_callback;
2613 else
2614 sps_event->callback = msm_hs_sps_tx_callback;
2615
2616 sps_event->user = (void *)msm_uport;
2617
2618 /* Now save the sps pipe handle */
2619 ep->pipe_handle = sps_pipe_handle;
2620 pr_debug("msm_serial_hs: success !! %s: pipe_handle=0x%x\n"
2621 "desc_fifo.phys_base=0x%x\n",
2622 is_producer ? "READ" : "WRITE",
2623 (u32)sps_pipe_handle, sps_config->desc.phys_base);
2624 return 0;
2625
2626get_config_err:
2627 sps_free_endpoint(sps_pipe_handle);
2628out:
2629 return rc;
2630}
2631
2632/**
2633 * Initialize SPS HW connected with UART core
2634 *
2635 * This function register BAM HW resources with
2636 * SPS driver and then initialize 2 SPS endpoints
2637 *
2638 * msm_uport - Pointer to msm_hs_port structure
2639 *
2640 * @return - 0 if successful else negative value
2641 */
2642
2643static int msm_hs_sps_init(struct msm_hs_port *msm_uport)
2644{
2645 int rc = 0;
2646 struct sps_bam_props bam = {0};
2647 u32 bam_handle;
2648
2649 rc = sps_phy2h(msm_uport->bam_mem, &bam_handle);
2650 if (rc || !bam_handle) {
2651 bam.phys_addr = msm_uport->bam_mem;
2652 bam.virt_addr = msm_uport->bam_base;
2653 /*
2654 * This event thresold value is only significant for BAM-to-BAM
2655 * transfer. It's ignored for BAM-to-System mode transfer.
2656 */
2657 bam.event_threshold = 0x10; /* Pipe event threshold */
2658 bam.summing_threshold = 1; /* BAM event threshold */
2659
2660 /* SPS driver wll handle the UART BAM IRQ */
2661 bam.irq = (u32)msm_uport->bam_irq;
2662 bam.manage = SPS_BAM_MGR_LOCAL;
2663
2664 pr_debug("msm_serial_hs: bam physical base=0x%x\n",
2665 (u32)bam.phys_addr);
2666 pr_debug("msm_serial_hs: bam virtual base=0x%x\n",
2667 (u32)bam.virt_addr);
2668
2669 /* Register UART Peripheral BAM device to SPS driver */
2670 rc = sps_register_bam_device(&bam, &bam_handle);
2671 if (rc) {
2672 pr_err("msm_serial_hs: BAM device register failed\n");
2673 return rc;
2674 }
2675 pr_info("msm_serial_hs: BAM device registered. bam_handle=0x%x",
2676 msm_uport->bam_handle);
2677 }
2678 msm_uport->bam_handle = bam_handle;
2679
2680 rc = msm_hs_sps_init_ep_conn(msm_uport, &msm_uport->rx.prod,
2681 UART_SPS_PROD_PERIPHERAL);
2682 if (rc) {
2683 pr_err("%s: Failed to Init Producer BAM-pipe", __func__);
2684 goto deregister_bam;
2685 }
2686
2687 rc = msm_hs_sps_init_ep_conn(msm_uport, &msm_uport->tx.cons,
2688 UART_SPS_CONS_PERIPHERAL);
2689 if (rc) {
2690 pr_err("%s: Failed to Init Consumer BAM-pipe", __func__);
2691 goto deinit_ep_conn_prod;
2692 }
2693 return 0;
2694
2695deinit_ep_conn_prod:
2696 msm_hs_exit_ep_conn(msm_uport, &msm_uport->rx.prod);
2697deregister_bam:
2698 sps_deregister_bam_device(msm_uport->bam_handle);
2699 return rc;
2700}
2701
Saket Saurabh10e88b32013-02-04 15:26:34 +05302702#define BLSP_UART_NR 12
2703static int deviceid[BLSP_UART_NR] = {0};
2704static atomic_t msm_serial_hs_next_id = ATOMIC_INIT(0);
2705
Mayank Rana55046232011-03-07 10:28:42 +05302706static int __devinit msm_hs_probe(struct platform_device *pdev)
2707{
Saket Saurabh10e88b32013-02-04 15:26:34 +05302708 int ret = 0, alias_num = -1;
Mayank Rana55046232011-03-07 10:28:42 +05302709 struct uart_port *uport;
2710 struct msm_hs_port *msm_uport;
Mayank Ranaff398d02012-12-18 10:22:50 +05302711 struct resource *core_resource;
2712 struct resource *bam_resource;
Mayank Rana55046232011-03-07 10:28:42 +05302713 struct resource *resource;
Mayank Ranaff398d02012-12-18 10:22:50 +05302714 int core_irqres, bam_irqres;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002715 struct msm_serial_hs_platform_data *pdata = pdev->dev.platform_data;
Mayank Ranaff398d02012-12-18 10:22:50 +05302716
2717 if (pdev->dev.of_node) {
2718 dev_dbg(&pdev->dev, "device tree enabled\n");
2719 pdata = msm_hs_dt_to_pdata(pdev);
2720 if (IS_ERR(pdata))
2721 return PTR_ERR(pdata);
2722
Saket Saurabh10e88b32013-02-04 15:26:34 +05302723 if (pdev->id == -1) {
2724 pdev->id = atomic_inc_return(&msm_serial_hs_next_id)-1;
2725 deviceid[pdev->id] = 1;
2726 }
2727
2728 /* Use alias from device tree if present
2729 * Alias is used as an optional property
2730 */
2731 alias_num = of_alias_get_id(pdev->dev.of_node, "uart");
2732 if (alias_num >= 0) {
2733 /* If alias_num is between 0 and 11, check that it not
2734 * equal to previous incremented pdev-ids. If it is
2735 * equal to previous pdev.ids , fail deviceprobe.
2736 */
2737 if (alias_num < BLSP_UART_NR) {
2738 if (deviceid[alias_num] == 0) {
2739 pdev->id = alias_num;
2740 } else {
2741 pr_err("alias_num=%d already used\n",
2742 alias_num);
2743 return -EINVAL;
2744 }
2745 } else {
2746 pdev->id = alias_num;
2747 }
2748 }
Mayank Ranaff398d02012-12-18 10:22:50 +05302749
2750 pdev->dev.platform_data = pdata;
2751 }
Mayank Rana55046232011-03-07 10:28:42 +05302752
2753 if (pdev->id < 0 || pdev->id >= UARTDM_NR) {
Mayank Ranaff398d02012-12-18 10:22:50 +05302754 pr_err("Invalid plaform device ID = %d\n", pdev->id);
Mayank Rana55046232011-03-07 10:28:42 +05302755 return -EINVAL;
2756 }
2757
2758 msm_uport = &q_uart_port[pdev->id];
2759 uport = &msm_uport->uport;
Mayank Rana55046232011-03-07 10:28:42 +05302760 uport->dev = &pdev->dev;
2761
Mayank Ranaff398d02012-12-18 10:22:50 +05302762 if (pdev->dev.of_node)
2763 msm_uport->uart_type = BLSP_HSUART;
Mayank Rana55046232011-03-07 10:28:42 +05302764
Mayank Ranaff398d02012-12-18 10:22:50 +05302765 /* Get required resources for BAM HSUART */
2766 if (is_blsp_uart(msm_uport)) {
2767 core_resource = platform_get_resource_byname(pdev,
2768 IORESOURCE_MEM, "core_mem");
2769 bam_resource = platform_get_resource_byname(pdev,
2770 IORESOURCE_MEM, "bam_mem");
2771 core_irqres = platform_get_irq_byname(pdev, "core_irq");
2772 bam_irqres = platform_get_irq_byname(pdev, "bam_irq");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002773
Mayank Ranaff398d02012-12-18 10:22:50 +05302774 if (!core_resource) {
2775 pr_err("Invalid core HSUART Resources.\n");
2776 return -ENXIO;
2777 }
2778
2779 if (!bam_resource) {
2780 pr_err("Invalid BAM HSUART Resources.\n");
2781 return -ENXIO;
2782 }
2783
2784 if (!core_irqres) {
2785 pr_err("Invalid core irqres Resources.\n");
2786 return -ENXIO;
2787 }
2788 if (!bam_irqres) {
2789 pr_err("Invalid bam irqres Resources.\n");
2790 return -ENXIO;
2791 }
2792
2793 uport->mapbase = core_resource->start;
2794
2795 uport->membase = ioremap(uport->mapbase,
2796 resource_size(core_resource));
2797 if (unlikely(!uport->membase)) {
2798 pr_err("UART Resource ioremap Failed.\n");
2799 return -ENOMEM;
2800 }
2801 msm_uport->bam_mem = bam_resource->start;
2802 msm_uport->bam_base = ioremap(msm_uport->bam_mem,
2803 resource_size(bam_resource));
2804 if (unlikely(!msm_uport->bam_base)) {
2805 pr_err("UART BAM Resource ioremap Failed.\n");
2806 iounmap(uport->membase);
2807 return -ENOMEM;
2808 }
2809
2810 uport->irq = core_irqres;
2811 msm_uport->bam_irq = bam_irqres;
2812
Mayank Rana88d49142013-01-16 17:28:53 +05302813 msm_uport->bus_scale_table = msm_bus_cl_get_pdata(pdev);
2814 if (!msm_uport->bus_scale_table) {
Mayank Ranae4bc7de2013-01-22 12:51:16 +05302815 pr_err("BLSP UART: Bus scaling is disabled.\n");
Mayank Rana88d49142013-01-16 17:28:53 +05302816 } else {
2817 msm_uport->bus_perf_client =
2818 msm_bus_scale_register_client
2819 (msm_uport->bus_scale_table);
2820 if (IS_ERR(&msm_uport->bus_perf_client)) {
2821 pr_err("%s(): Bus client register failed.\n",
2822 __func__);
Mayank Ranae4bc7de2013-01-22 12:51:16 +05302823 ret = -EINVAL;
Mayank Rana88d49142013-01-16 17:28:53 +05302824 goto unmap_memory;
2825 }
2826 }
Mayank Ranaff398d02012-12-18 10:22:50 +05302827 } else {
2828
2829 resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
2830 if (unlikely(!resource))
2831 return -ENXIO;
2832 uport->mapbase = resource->start;
2833 uport->membase = ioremap(uport->mapbase,
2834 resource_size(resource));
2835 if (unlikely(!uport->membase))
2836 return -ENOMEM;
2837
2838 uport->irq = platform_get_irq(pdev, 0);
2839 if (unlikely((int)uport->irq < 0)) {
2840 pr_err("UART IRQ Failed.\n");
2841 iounmap(uport->membase);
2842 return -ENXIO;
2843 }
2844 }
Mayank Rana55046232011-03-07 10:28:42 +05302845
Mayank Rana55046232011-03-07 10:28:42 +05302846 if (pdata == NULL)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002847 msm_uport->wakeup.irq = -1;
2848 else {
2849 msm_uport->wakeup.irq = pdata->wakeup_irq;
2850 msm_uport->wakeup.ignore = 1;
2851 msm_uport->wakeup.inject_rx = pdata->inject_rx_on_wakeup;
2852 msm_uport->wakeup.rx_to_inject = pdata->rx_to_inject;
2853
Mayank Ranaff398d02012-12-18 10:22:50 +05302854 if (unlikely(msm_uport->wakeup.irq < 0)) {
2855 ret = -ENXIO;
2856 goto unmap_memory;
2857 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002858
Mayank Ranaff398d02012-12-18 10:22:50 +05302859 if (is_blsp_uart(msm_uport)) {
2860 msm_uport->bam_tx_ep_pipe_index =
2861 pdata->bam_tx_ep_pipe_index;
2862 msm_uport->bam_rx_ep_pipe_index =
2863 pdata->bam_rx_ep_pipe_index;
2864 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002865 }
Mayank Rana55046232011-03-07 10:28:42 +05302866
Mayank Ranaff398d02012-12-18 10:22:50 +05302867 if (!is_blsp_uart(msm_uport)) {
Mayank Rana55046232011-03-07 10:28:42 +05302868
Mayank Ranaff398d02012-12-18 10:22:50 +05302869 resource = platform_get_resource_byname(pdev,
2870 IORESOURCE_DMA, "uartdm_channels");
2871 if (unlikely(!resource)) {
2872 ret = -ENXIO;
2873 goto unmap_memory;
2874 }
2875
2876 msm_uport->dma_tx_channel = resource->start;
2877 msm_uport->dma_rx_channel = resource->end;
2878
2879 resource = platform_get_resource_byname(pdev,
2880 IORESOURCE_DMA, "uartdm_crci");
2881 if (unlikely(!resource)) {
2882 ret = -ENXIO;
2883 goto unmap_memory;
2884 }
2885
2886 msm_uport->dma_tx_crci = resource->start;
2887 msm_uport->dma_rx_crci = resource->end;
2888 }
Mayank Rana55046232011-03-07 10:28:42 +05302889
2890 uport->iotype = UPIO_MEM;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002891 uport->fifosize = 64;
Mayank Rana55046232011-03-07 10:28:42 +05302892 uport->ops = &msm_hs_ops;
2893 uport->flags = UPF_BOOT_AUTOCONF;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002894 uport->uartclk = 7372800;
Mayank Rana55046232011-03-07 10:28:42 +05302895 msm_uport->imr_reg = 0x0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002896
Matt Wagantalle2522372011-08-17 14:52:21 -07002897 msm_uport->clk = clk_get(&pdev->dev, "core_clk");
Mayank Ranaff398d02012-12-18 10:22:50 +05302898 if (IS_ERR(msm_uport->clk)) {
2899 ret = PTR_ERR(msm_uport->clk);
2900 goto unmap_memory;
2901 }
Mayank Rana55046232011-03-07 10:28:42 +05302902
Matt Wagantalle2522372011-08-17 14:52:21 -07002903 msm_uport->pclk = clk_get(&pdev->dev, "iface_clk");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002904 /*
2905 * Some configurations do not require explicit pclk control so
2906 * do not flag error on pclk get failure.
2907 */
2908 if (IS_ERR(msm_uport->pclk))
2909 msm_uport->pclk = NULL;
2910
2911 ret = clk_set_rate(msm_uport->clk, uport->uartclk);
2912 if (ret) {
2913 printk(KERN_WARNING "Error setting clock rate on UART\n");
Mayank Ranaff398d02012-12-18 10:22:50 +05302914 goto unmap_memory;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002915 }
2916
Mayank Ranacb589d82012-03-01 11:50:03 +05302917 msm_uport->hsuart_wq = alloc_workqueue("k_hsuart",
2918 WQ_UNBOUND | WQ_MEM_RECLAIM, 1);
2919 if (!msm_uport->hsuart_wq) {
2920 pr_err("%s(): Unable to create workqueue hsuart_wq\n",
2921 __func__);
Mayank Ranaff398d02012-12-18 10:22:50 +05302922 ret = -ENOMEM;
2923 goto unmap_memory;
Mayank Ranacb589d82012-03-01 11:50:03 +05302924 }
2925
2926 INIT_WORK(&msm_uport->clock_off_w, hsuart_clock_off_work);
Saket Saurabhcbf6c522013-01-07 16:30:37 +05302927
2928 /* Init work for Reset Rx bam endpoints */
2929 INIT_WORK(&msm_uport->reset_bam_rx, hsuart_reset_bam_rx_work);
2930
2931 /* Init work for sps_disconnect in stop_rx_locked */
2932 INIT_WORK(&msm_uport->disconnect_rx_endpoint,
2933 hsuart_disconnect_rx_endpoint_work);
Mayank Ranacb589d82012-03-01 11:50:03 +05302934 mutex_init(&msm_uport->clk_mutex);
2935
Saket Saurabhcbf6c522013-01-07 16:30:37 +05302936 /* Initialize SPS HW connected with UART core */
2937 if (is_blsp_uart(msm_uport)) {
2938 ret = msm_hs_sps_init(msm_uport);
2939 if (unlikely(ret)) {
2940 pr_err("SPS Initialization failed ! err=%d", ret);
Saket Saurabh2c3f0b92013-01-16 15:06:39 +05302941 goto workqueue_destroy;
Saket Saurabhcbf6c522013-01-07 16:30:37 +05302942 }
2943 }
2944
Mayank Ranae4bc7de2013-01-22 12:51:16 +05302945 msm_hs_bus_voting(msm_uport, BUS_SCALING);
2946
Matt Wagantall7f32d2a2012-05-17 15:48:04 -07002947 clk_prepare_enable(msm_uport->clk);
2948 if (msm_uport->pclk)
2949 clk_prepare_enable(msm_uport->pclk);
2950
Mayank Rana55046232011-03-07 10:28:42 +05302951 ret = uartdm_init_port(uport);
Matt Wagantall7f32d2a2012-05-17 15:48:04 -07002952 if (unlikely(ret)) {
Saket Saurabh2c3f0b92013-01-16 15:06:39 +05302953 goto err_clock;
Matt Wagantall7f32d2a2012-05-17 15:48:04 -07002954 }
Mayank Rana55046232011-03-07 10:28:42 +05302955
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002956 /* configure the CR Protection to Enable */
2957 msm_hs_write(uport, UARTDM_CR_ADDR, CR_PROTECTION_EN);
Matt Wagantall7f32d2a2012-05-17 15:48:04 -07002958
Matt Wagantall7f32d2a2012-05-17 15:48:04 -07002959
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002960 /*
2961 * Enable Command register protection before going ahead as this hw
2962 * configuration makes sure that issued cmd to CR register gets complete
2963 * before next issued cmd start. Hence mb() requires here.
2964 */
2965 mb();
Mayank Rana55046232011-03-07 10:28:42 +05302966
2967 msm_uport->clk_state = MSM_HS_CLK_PORT_OFF;
2968 hrtimer_init(&msm_uport->clk_off_timer, CLOCK_MONOTONIC,
2969 HRTIMER_MODE_REL);
2970 msm_uport->clk_off_timer.function = msm_hs_clk_off_retry;
2971 msm_uport->clk_off_delay = ktime_set(0, 1000000); /* 1ms */
2972
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002973 ret = sysfs_create_file(&pdev->dev.kobj, &dev_attr_clock.attr);
2974 if (unlikely(ret))
Saket Saurabh2c3f0b92013-01-16 15:06:39 +05302975 goto err_clock;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002976
2977 msm_serial_debugfs_init(msm_uport, pdev->id);
2978
Mayank Rana55046232011-03-07 10:28:42 +05302979 uport->line = pdev->id;
Saket Saurabh51690e52012-08-17 14:17:46 +05302980 if (pdata != NULL && pdata->userid && pdata->userid <= UARTDM_NR)
2981 uport->line = pdata->userid;
Mayank Ranaff398d02012-12-18 10:22:50 +05302982 ret = uart_add_one_port(&msm_hs_driver, uport);
Saket Saurabh2c3f0b92013-01-16 15:06:39 +05302983 if (!ret) {
Mayank Ranae4bc7de2013-01-22 12:51:16 +05302984
2985 msm_hs_bus_voting(msm_uport, BUS_RESET);
Saket Saurabh2c3f0b92013-01-16 15:06:39 +05302986 clk_disable_unprepare(msm_uport->clk);
2987 if (msm_uport->pclk)
2988 clk_disable_unprepare(msm_uport->pclk);
Mayank Ranaff398d02012-12-18 10:22:50 +05302989 return ret;
Saket Saurabh2c3f0b92013-01-16 15:06:39 +05302990 }
Mayank Ranaff398d02012-12-18 10:22:50 +05302991
Saket Saurabh2c3f0b92013-01-16 15:06:39 +05302992err_clock:
Mayank Ranae4bc7de2013-01-22 12:51:16 +05302993
2994 msm_hs_bus_voting(msm_uport, BUS_RESET);
Saket Saurabh2c3f0b92013-01-16 15:06:39 +05302995 clk_disable_unprepare(msm_uport->clk);
2996 if (msm_uport->pclk)
2997 clk_disable_unprepare(msm_uport->pclk);
2998workqueue_destroy:
2999 destroy_workqueue(msm_uport->hsuart_wq);
Mayank Ranaff398d02012-12-18 10:22:50 +05303000unmap_memory:
3001 iounmap(uport->membase);
3002 if (is_blsp_uart(msm_uport))
3003 iounmap(msm_uport->bam_base);
3004
3005 return ret;
Mayank Rana55046232011-03-07 10:28:42 +05303006}
3007
3008static int __init msm_serial_hs_init(void)
3009{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003010 int ret;
3011 int i;
Mayank Rana55046232011-03-07 10:28:42 +05303012
3013 /* Init all UARTS as non-configured */
3014 for (i = 0; i < UARTDM_NR; i++)
3015 q_uart_port[i].uport.type = PORT_UNKNOWN;
3016
Mayank Rana55046232011-03-07 10:28:42 +05303017 ret = uart_register_driver(&msm_hs_driver);
3018 if (unlikely(ret)) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003019 printk(KERN_ERR "%s failed to load\n", __FUNCTION__);
3020 return ret;
Mayank Rana55046232011-03-07 10:28:42 +05303021 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003022 debug_base = debugfs_create_dir("msm_serial_hs", NULL);
3023 if (IS_ERR_OR_NULL(debug_base))
3024 pr_info("msm_serial_hs: Cannot create debugfs dir\n");
Mayank Rana55046232011-03-07 10:28:42 +05303025
3026 ret = platform_driver_register(&msm_serial_hs_platform_driver);
3027 if (ret) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003028 printk(KERN_ERR "%s failed to load\n", __FUNCTION__);
3029 debugfs_remove_recursive(debug_base);
3030 uart_unregister_driver(&msm_hs_driver);
3031 return ret;
Mayank Rana55046232011-03-07 10:28:42 +05303032 }
3033
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003034 printk(KERN_INFO "msm_serial_hs module loaded\n");
Mayank Rana55046232011-03-07 10:28:42 +05303035 return ret;
3036}
Mayank Rana55046232011-03-07 10:28:42 +05303037
3038/*
3039 * Called by the upper layer when port is closed.
3040 * - Disables the port
3041 * - Unhook the ISR
3042 */
3043static void msm_hs_shutdown(struct uart_port *uport)
3044{
Mayank Ranaaf2f0082012-05-22 10:16:02 +05303045 int ret;
3046 unsigned int data;
3047 unsigned long flags;
Mayank Rana55046232011-03-07 10:28:42 +05303048 struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
Mayank Rana40836782012-11-16 14:45:47 +05303049 struct platform_device *pdev = to_platform_device(uport->dev);
3050 const struct msm_serial_hs_platform_data *pdata =
3051 pdev->dev.platform_data;
Saket Saurabhcbf6c522013-01-07 16:30:37 +05303052 struct msm_hs_tx *tx = &msm_uport->tx;
3053 struct sps_pipe *sps_pipe_handle = tx->cons.pipe_handle;
Mayank Rana55046232011-03-07 10:28:42 +05303054
Mayank Ranaaf2f0082012-05-22 10:16:02 +05303055 if (msm_uport->tx.dma_in_flight) {
Saket Saurabhcbf6c522013-01-07 16:30:37 +05303056 if (!is_blsp_uart(msm_uport)) {
3057 spin_lock_irqsave(&uport->lock, flags);
3058 /* disable UART TX interface to DM */
3059 data = msm_hs_read(uport, UARTDM_DMEN_ADDR);
3060 data &= ~UARTDM_TX_DM_EN_BMSK;
3061 msm_hs_write(uport, UARTDM_DMEN_ADDR, data);
3062 /* turn OFF UART Transmitter */
3063 msm_hs_write(uport, UARTDM_CR_ADDR,
3064 UARTDM_CR_TX_DISABLE_BMSK);
3065 /* reset UART TX */
3066 msm_hs_write(uport, UARTDM_CR_ADDR, RESET_TX);
3067 /* reset UART TX Error */
3068 msm_hs_write(uport, UARTDM_CR_ADDR, RESET_TX_ERROR);
3069 msm_uport->tx.flush = FLUSH_STOP;
3070 spin_unlock_irqrestore(&uport->lock, flags);
3071 /* discard flush */
3072 msm_dmov_flush(msm_uport->dma_tx_channel, 0);
3073 ret = wait_event_timeout(msm_uport->tx.wait,
3074 msm_uport->tx.flush == FLUSH_SHUTDOWN, 100);
3075 if (!ret)
3076 pr_err("%s():HSUART TX Stalls.\n", __func__);
3077 } else {
3078 /* BAM Disconnect for TX */
3079 sps_disconnect(sps_pipe_handle);
3080 }
Mayank Ranaaf2f0082012-05-22 10:16:02 +05303081 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003082 tasklet_kill(&msm_uport->tx.tlet);
Mayank Ranaaf2f0082012-05-22 10:16:02 +05303083 BUG_ON(msm_uport->rx.flush < FLUSH_STOP);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003084 wait_event(msm_uport->rx.wait, msm_uport->rx.flush == FLUSH_SHUTDOWN);
3085 tasklet_kill(&msm_uport->rx.tlet);
3086 cancel_delayed_work_sync(&msm_uport->rx.flip_insert_work);
Mayank Ranacb589d82012-03-01 11:50:03 +05303087 flush_workqueue(msm_uport->hsuart_wq);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003088 pm_runtime_disable(uport->dev);
3089 pm_runtime_set_suspended(uport->dev);
Mayank Rana55046232011-03-07 10:28:42 +05303090
3091 /* Disable the transmitter */
3092 msm_hs_write(uport, UARTDM_CR_ADDR, UARTDM_CR_TX_DISABLE_BMSK);
3093 /* Disable the receiver */
3094 msm_hs_write(uport, UARTDM_CR_ADDR, UARTDM_CR_RX_DISABLE_BMSK);
3095
Mayank Rana55046232011-03-07 10:28:42 +05303096 msm_uport->imr_reg = 0;
3097 msm_hs_write(uport, UARTDM_IMR_ADDR, msm_uport->imr_reg);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003098 /*
3099 * Complete all device write before actually disabling uartclk.
3100 * Hence mb() requires here.
3101 */
3102 mb();
Mayank Rana88d49142013-01-16 17:28:53 +05303103
3104 /* Reset PNOC Bus Scaling */
Mayank Ranae4bc7de2013-01-22 12:51:16 +05303105 msm_hs_bus_voting(msm_uport, BUS_RESET);
Mayank Rana88d49142013-01-16 17:28:53 +05303106
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003107 if (msm_uport->clk_state != MSM_HS_CLK_OFF) {
Mayank Ranacb589d82012-03-01 11:50:03 +05303108 /* to balance clk_state */
3109 clk_disable_unprepare(msm_uport->clk);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003110 if (msm_uport->pclk)
Mayank Ranacb589d82012-03-01 11:50:03 +05303111 clk_disable_unprepare(msm_uport->pclk);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003112 wake_unlock(&msm_uport->dma_wake_lock);
3113 }
Mayank Rana55046232011-03-07 10:28:42 +05303114
Mayank Ranaaf2f0082012-05-22 10:16:02 +05303115 msm_uport->clk_state = MSM_HS_CLK_PORT_OFF;
Mayank Rana55046232011-03-07 10:28:42 +05303116 dma_unmap_single(uport->dev, msm_uport->tx.dma_base,
3117 UART_XMIT_SIZE, DMA_TO_DEVICE);
3118
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003119 if (use_low_power_wakeup(msm_uport))
3120 irq_set_irq_wake(msm_uport->wakeup.irq, 0);
Mayank Rana55046232011-03-07 10:28:42 +05303121
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003122 /* Free the interrupt */
3123 free_irq(uport->irq, msm_uport);
3124 if (use_low_power_wakeup(msm_uport))
3125 free_irq(msm_uport->wakeup.irq, msm_uport);
Mayank Rana40836782012-11-16 14:45:47 +05303126
Saket Saurabhfe3b93b2013-02-04 18:44:12 +05303127 if (is_blsp_uart(msm_uport)) {
3128 msm_hs_unconfig_uart_gpios(uport);
3129 } else {
3130 if (pdata && pdata->gpio_config)
3131 if (pdata->gpio_config(0))
3132 dev_err(uport->dev, "GPIO config error\n");
3133 }
Mayank Rana55046232011-03-07 10:28:42 +05303134}
3135
3136static void __exit msm_serial_hs_exit(void)
3137{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003138 printk(KERN_INFO "msm_serial_hs module removed\n");
Mayank Rana17e0e1a2012-04-07 02:10:33 +05303139 debugfs_remove_recursive(debug_base);
Mayank Rana55046232011-03-07 10:28:42 +05303140 platform_driver_unregister(&msm_serial_hs_platform_driver);
3141 uart_unregister_driver(&msm_hs_driver);
3142}
Mayank Rana55046232011-03-07 10:28:42 +05303143
Mayank Rana55046232011-03-07 10:28:42 +05303144static int msm_hs_runtime_idle(struct device *dev)
3145{
3146 /*
3147 * returning success from idle results in runtime suspend to be
3148 * called
3149 */
3150 return 0;
3151}
3152
3153static int msm_hs_runtime_resume(struct device *dev)
3154{
3155 struct platform_device *pdev = container_of(dev, struct
3156 platform_device, dev);
3157 struct msm_hs_port *msm_uport = &q_uart_port[pdev->id];
Mayank Rana55046232011-03-07 10:28:42 +05303158 msm_hs_request_clock_on(&msm_uport->uport);
3159 return 0;
3160}
3161
3162static int msm_hs_runtime_suspend(struct device *dev)
3163{
3164 struct platform_device *pdev = container_of(dev, struct
3165 platform_device, dev);
3166 struct msm_hs_port *msm_uport = &q_uart_port[pdev->id];
Mayank Rana55046232011-03-07 10:28:42 +05303167 msm_hs_request_clock_off(&msm_uport->uport);
3168 return 0;
3169}
Mayank Rana55046232011-03-07 10:28:42 +05303170
3171static const struct dev_pm_ops msm_hs_dev_pm_ops = {
3172 .runtime_suspend = msm_hs_runtime_suspend,
3173 .runtime_resume = msm_hs_runtime_resume,
3174 .runtime_idle = msm_hs_runtime_idle,
3175};
3176
Mayank Ranaff398d02012-12-18 10:22:50 +05303177static struct of_device_id msm_hs_match_table[] = {
3178 { .compatible = "qcom,msm-hsuart-v14" },
3179 {}
3180};
3181
Mayank Rana55046232011-03-07 10:28:42 +05303182static struct platform_driver msm_serial_hs_platform_driver = {
Mayank Rana17e0e1a2012-04-07 02:10:33 +05303183 .probe = msm_hs_probe,
Mayank Rana55046232011-03-07 10:28:42 +05303184 .remove = __devexit_p(msm_hs_remove),
3185 .driver = {
3186 .name = "msm_serial_hs",
Mayank Rana55046232011-03-07 10:28:42 +05303187 .pm = &msm_hs_dev_pm_ops,
Mayank Ranaff398d02012-12-18 10:22:50 +05303188 .of_match_table = msm_hs_match_table,
Mayank Rana55046232011-03-07 10:28:42 +05303189 },
3190};
3191
3192static struct uart_driver msm_hs_driver = {
3193 .owner = THIS_MODULE,
3194 .driver_name = "msm_serial_hs",
3195 .dev_name = "ttyHS",
3196 .nr = UARTDM_NR,
3197 .cons = 0,
3198};
3199
3200static struct uart_ops msm_hs_ops = {
3201 .tx_empty = msm_hs_tx_empty,
3202 .set_mctrl = msm_hs_set_mctrl_locked,
3203 .get_mctrl = msm_hs_get_mctrl_locked,
3204 .stop_tx = msm_hs_stop_tx_locked,
3205 .start_tx = msm_hs_start_tx_locked,
3206 .stop_rx = msm_hs_stop_rx_locked,
3207 .enable_ms = msm_hs_enable_ms_locked,
3208 .break_ctl = msm_hs_break_ctl,
3209 .startup = msm_hs_startup,
3210 .shutdown = msm_hs_shutdown,
3211 .set_termios = msm_hs_set_termios,
Mayank Rana55046232011-03-07 10:28:42 +05303212 .type = msm_hs_type,
3213 .config_port = msm_hs_config_port,
3214 .release_port = msm_hs_release_port,
3215 .request_port = msm_hs_request_port,
Saket Saurabhce394102012-10-29 19:51:28 +05303216 .flush_buffer = msm_hs_flush_buffer,
Mayank Rana55046232011-03-07 10:28:42 +05303217};
3218
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003219module_init(msm_serial_hs_init);
3220module_exit(msm_serial_hs_exit);
Mayank Rana55046232011-03-07 10:28:42 +05303221MODULE_DESCRIPTION("High Speed UART Driver for the MSM chipset");
3222MODULE_VERSION("1.2");
3223MODULE_LICENSE("GPL v2");