blob: cbfc4d55eb5b4c47a8a100cc07e4465805746086 [file] [log] [blame]
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001/*
2 * drivers/serial/msm_serial.c - driver for msm7k serial device and console
3 *
4 * Copyright (C) 2007 Google, Inc.
Mayank Rana22e4b382012-01-11 21:35:00 +05305 * Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07006 *
7 * This software is licensed under the terms of the GNU General Public
8 * License version 2, as published by the Free Software Foundation, and
9 * may be copied, distributed, and modified under those terms.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
16
17/* Acknowledgements:
18 * This file is based on msm_serial.c, originally
19 * Written by Robert Love <rlove@google.com> */
20
Mayank Rana1295c082012-12-03 13:56:12 +053021#define pr_fmt(fmt) "%s: " fmt, __func__
22
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070023#if defined(CONFIG_SERIAL_MSM_HSL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
24#define SUPPORT_SYSRQ
25#endif
26
Sathish Ambley3d50c762011-10-25 15:26:00 -070027#include <linux/atomic.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070028#include <linux/hrtimer.h>
29#include <linux/module.h>
30#include <linux/io.h>
31#include <linux/ioport.h>
32#include <linux/irq.h>
33#include <linux/init.h>
34#include <linux/delay.h>
35#include <linux/console.h>
36#include <linux/tty.h>
37#include <linux/tty_flip.h>
38#include <linux/serial_core.h>
39#include <linux/serial.h>
40#include <linux/nmi.h>
41#include <linux/clk.h>
42#include <linux/platform_device.h>
43#include <linux/pm_runtime.h>
44#include <linux/gpio.h>
Mayank Rana8dddd752011-07-13 11:19:58 +053045#include <linux/debugfs.h>
Sathish Ambley3d50c762011-10-25 15:26:00 -070046#include <linux/of.h>
47#include <linux/of_device.h>
Mayank Rana9fc393d2012-12-04 19:10:36 +053048#include <linux/of_gpio.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070049#include <mach/board.h>
50#include <mach/msm_serial_hs_lite.h>
51#include <asm/mach-types.h>
52#include "msm_serial_hs_hwreg.h"
53
Mayank Rana9fc393d2012-12-04 19:10:36 +053054/*
55 * There are 3 different kind of UART Core available on MSM.
56 * High Speed UART (i.e. Legacy HSUART), GSBI based HSUART
57 * and BSLP based HSUART.
58 */
59enum uart_core_type {
60 LEGACY_HSUART,
61 GSBI_HSUART,
62 BLSP_HSUART,
63};
64
65/*
66 * UART can be used in 2-wire or 4-wire mode.
67 * Use uart_func_mode to set 2-wire or 4-wire mode.
68 */
69enum uart_func_mode {
70 UART_TWO_WIRE, /* can't support HW Flow control. */
71 UART_FOUR_WIRE,/* can support HW Flow control. */
72};
73
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070074struct msm_hsl_port {
75 struct uart_port uart;
76 char name[16];
77 struct clk *clk;
78 struct clk *pclk;
Mayank Rana8dddd752011-07-13 11:19:58 +053079 struct dentry *loopback_dir;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070080 unsigned int imr;
81 unsigned int *uart_csr_code;
82 unsigned int *gsbi_mapbase;
83 unsigned int *mapped_gsbi;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070084 unsigned int old_snap_state;
Sathish Ambley99e2a242011-10-25 15:49:53 -070085 unsigned int ver_id;
Stepan Moskovchenko1d4731e2012-02-21 20:18:23 -080086 int tx_timeout;
Mayank Rana44659372012-12-03 17:59:45 +053087 struct mutex clk_mutex;
Mayank Rana9fc393d2012-12-04 19:10:36 +053088 enum uart_core_type uart_type;
89 enum uart_func_mode func_mode;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070090};
91
Sathish Ambley99e2a242011-10-25 15:49:53 -070092#define UARTDM_VERSION_11_13 0
93#define UARTDM_VERSION_14 1
94
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070095#define UART_TO_MSM(uart_port) ((struct msm_hsl_port *) uart_port)
96#define is_console(port) ((port)->cons && \
97 (port)->cons->index == (port)->line)
Sathish Ambley99e2a242011-10-25 15:49:53 -070098
99static const unsigned int regmap[][UARTDM_LAST] = {
100 [UARTDM_VERSION_11_13] = {
101 [UARTDM_MR1] = UARTDM_MR1_ADDR,
102 [UARTDM_MR2] = UARTDM_MR2_ADDR,
103 [UARTDM_IMR] = UARTDM_IMR_ADDR,
104 [UARTDM_SR] = UARTDM_SR_ADDR,
105 [UARTDM_CR] = UARTDM_CR_ADDR,
106 [UARTDM_CSR] = UARTDM_CSR_ADDR,
107 [UARTDM_IPR] = UARTDM_IPR_ADDR,
108 [UARTDM_ISR] = UARTDM_ISR_ADDR,
109 [UARTDM_RX_TOTAL_SNAP] = UARTDM_RX_TOTAL_SNAP_ADDR,
110 [UARTDM_TFWR] = UARTDM_TFWR_ADDR,
111 [UARTDM_RFWR] = UARTDM_RFWR_ADDR,
112 [UARTDM_RF] = UARTDM_RF_ADDR,
113 [UARTDM_TF] = UARTDM_TF_ADDR,
114 [UARTDM_MISR] = UARTDM_MISR_ADDR,
115 [UARTDM_DMRX] = UARTDM_DMRX_ADDR,
116 [UARTDM_NCF_TX] = UARTDM_NCF_TX_ADDR,
117 [UARTDM_DMEN] = UARTDM_DMEN_ADDR,
Stepan Moskovchenko1d4731e2012-02-21 20:18:23 -0800118 [UARTDM_TXFS] = UARTDM_TXFS_ADDR,
119 [UARTDM_RXFS] = UARTDM_RXFS_ADDR,
Sathish Ambley99e2a242011-10-25 15:49:53 -0700120 },
121 [UARTDM_VERSION_14] = {
122 [UARTDM_MR1] = 0x0,
123 [UARTDM_MR2] = 0x4,
124 [UARTDM_IMR] = 0xb0,
125 [UARTDM_SR] = 0xa4,
126 [UARTDM_CR] = 0xa8,
127 [UARTDM_CSR] = 0xa0,
128 [UARTDM_IPR] = 0x18,
129 [UARTDM_ISR] = 0xb4,
130 [UARTDM_RX_TOTAL_SNAP] = 0xbc,
131 [UARTDM_TFWR] = 0x1c,
132 [UARTDM_RFWR] = 0x20,
133 [UARTDM_RF] = 0x140,
134 [UARTDM_TF] = 0x100,
135 [UARTDM_MISR] = 0xac,
136 [UARTDM_DMRX] = 0x34,
137 [UARTDM_NCF_TX] = 0x40,
138 [UARTDM_DMEN] = 0x3c,
Stepan Moskovchenko1d4731e2012-02-21 20:18:23 -0800139 [UARTDM_TXFS] = 0x4c,
140 [UARTDM_RXFS] = 0x50,
Sathish Ambley99e2a242011-10-25 15:49:53 -0700141 },
142};
143
Sathish Ambley3d50c762011-10-25 15:26:00 -0700144static struct of_device_id msm_hsl_match_table[] = {
Sathish Ambley99e2a242011-10-25 15:49:53 -0700145 { .compatible = "qcom,msm-lsuart-v14",
146 .data = (void *)UARTDM_VERSION_14
147 },
Sathish Ambley3d50c762011-10-25 15:26:00 -0700148 {}
149};
Stepan Moskovchenko51fc4e62012-06-19 17:04:21 -0700150
151#ifdef CONFIG_SERIAL_MSM_HSL_CONSOLE
152static int get_console_state(struct uart_port *port);
153#else
154static inline int get_console_state(struct uart_port *port) { return -ENODEV; };
155#endif
156
Mayank Rana8dddd752011-07-13 11:19:58 +0530157static struct dentry *debug_base;
Stepan Moskovchenko9ec24842012-05-15 13:58:58 -0700158static inline void wait_for_xmitr(struct uart_port *port);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700159static inline void msm_hsl_write(struct uart_port *port,
160 unsigned int val, unsigned int off)
161{
162 iowrite32(val, port->membase + off);
163}
164static inline unsigned int msm_hsl_read(struct uart_port *port,
165 unsigned int off)
166{
167 return ioread32(port->membase + off);
168}
169
170static unsigned int msm_serial_hsl_has_gsbi(struct uart_port *port)
171{
Mayank Rana9fc393d2012-12-04 19:10:36 +0530172 return (UART_TO_MSM(port)->uart_type == GSBI_HSUART);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700173}
174
Mayank Rana9fc393d2012-12-04 19:10:36 +0530175/**
176 * set_gsbi_uart_func_mode: Check the currently used GSBI UART mode
177 * and set the new required GSBI UART Mode if it is different.
178 * @port: uart port
179 */
180static void set_gsbi_uart_func_mode(struct uart_port *port)
181{
182 struct msm_hsl_port *msm_hsl_port = UART_TO_MSM(port);
183 unsigned int set_gsbi_uart_mode = GSBI_PROTOCOL_I2C_UART;
184 unsigned int cur_gsbi_uart_mode;
185
186 if (msm_hsl_port->func_mode == UART_FOUR_WIRE)
187 set_gsbi_uart_mode = GSBI_PROTOCOL_UART;
188
189 if (msm_hsl_port->pclk)
190 clk_prepare_enable(msm_hsl_port->pclk);
191
192 /* Read current used GSBI UART Mode and set only if it is different. */
193 cur_gsbi_uart_mode = ioread32(msm_hsl_port->mapped_gsbi +
194 GSBI_CONTROL_ADDR);
195 if ((cur_gsbi_uart_mode & set_gsbi_uart_mode) != set_gsbi_uart_mode)
196 /*
197 * Programmed GSBI based UART protocol mode i.e. I2C/UART
198 * Shared Mode or UART Mode.
199 */
200 iowrite32(set_gsbi_uart_mode,
201 msm_hsl_port->mapped_gsbi + GSBI_CONTROL_ADDR);
202
203 if (msm_hsl_port->pclk)
204 clk_disable_unprepare(msm_hsl_port->pclk);
205}
206
207/**
208 * msm_hsl_config_uart_tx_rx_gpios - Configures UART Tx and RX GPIOs
209 * @port: uart port
210 */
211static int msm_hsl_config_uart_tx_rx_gpios(struct uart_port *port)
212{
213 struct platform_device *pdev = to_platform_device(port->dev);
214 const struct msm_serial_hslite_platform_data *pdata =
215 pdev->dev.platform_data;
216 int ret;
217
218 if (pdata) {
219 ret = gpio_request(pdata->uart_tx_gpio,
220 "UART_TX_GPIO");
221 if (unlikely(ret)) {
222 pr_err("gpio request failed for:%d\n",
223 pdata->uart_tx_gpio);
224 goto exit_uart_config;
225 }
226
227 ret = gpio_request(pdata->uart_rx_gpio, "UART_RX_GPIO");
228 if (unlikely(ret)) {
229 pr_err("gpio request failed for:%d\n",
230 pdata->uart_rx_gpio);
231 gpio_free(pdata->uart_tx_gpio);
232 goto exit_uart_config;
233 }
234 } else {
235 pr_err("Pdata is NULL.\n");
236 ret = -EINVAL;
237 }
238
239exit_uart_config:
240 return ret;
241}
242
243/**
244 * msm_hsl_unconfig_uart_tx_rx_gpios: Unconfigures UART Tx and RX GPIOs
245 * @port: uart port
246 */
247static void msm_hsl_unconfig_uart_tx_rx_gpios(struct uart_port *port)
248{
249 struct platform_device *pdev = to_platform_device(port->dev);
250 const struct msm_serial_hslite_platform_data *pdata =
251 pdev->dev.platform_data;
252
253 if (pdata) {
254 gpio_free(pdata->uart_tx_gpio);
255 gpio_free(pdata->uart_rx_gpio);
256 } else {
257 pr_err("Error:Pdata is NULL.\n");
258 }
259}
260
261/**
262 * msm_hsl_config_uart_hwflow_gpios: Configures UART HWFlow GPIOs
263 * @port: uart port
264 */
265static int msm_hsl_config_uart_hwflow_gpios(struct uart_port *port)
266{
267 struct platform_device *pdev = to_platform_device(port->dev);
268 const struct msm_serial_hslite_platform_data *pdata =
269 pdev->dev.platform_data;
270 int ret = -EINVAL;
271
272 if (pdata) {
273 ret = gpio_request(pdata->uart_cts_gpio,
274 "UART_CTS_GPIO");
275 if (unlikely(ret)) {
276 pr_err("gpio request failed for:%d\n",
277 pdata->uart_cts_gpio);
278 goto exit_config_uart;
279 }
280
281 ret = gpio_request(pdata->uart_rfr_gpio,
282 "UART_RFR_GPIO");
283 if (unlikely(ret)) {
284 pr_err("gpio request failed for:%d\n",
285 pdata->uart_rfr_gpio);
286 gpio_free(pdata->uart_cts_gpio);
287 goto exit_config_uart;
288 }
289 } else {
290 pr_err("Error: Pdata is NULL.\n");
291 }
292
293exit_config_uart:
294 return ret;
295}
296
297/**
298 * msm_hsl_unconfig_uart_hwflow_gpios: Unonfigures UART HWFlow GPIOs
299 * @port: uart port
300 */
301static void msm_hsl_unconfig_uart_hwflow_gpios(struct uart_port *port)
302{
303 struct platform_device *pdev = to_platform_device(port->dev);
304 const struct msm_serial_hslite_platform_data *pdata =
305 pdev->dev.platform_data;
306
307 if (pdata) {
308 gpio_free(pdata->uart_cts_gpio);
309 gpio_free(pdata->uart_rfr_gpio);
310 } else {
311 pr_err("Error: Pdata is NULL.\n");
312 }
313
314}
315
316/**
317 * msm_hsl_config_uart_gpios: Configures UART GPIOs and returns success or
318 * Failure
319 * @port: uart port
320 */
321static int msm_hsl_config_uart_gpios(struct uart_port *port)
322{
323 struct msm_hsl_port *msm_hsl_port = UART_TO_MSM(port);
324 int ret;
325
326 /* Configure UART Tx and Rx GPIOs */
327 ret = msm_hsl_config_uart_tx_rx_gpios(port);
328 if (!ret) {
329 if (msm_hsl_port->func_mode == UART_FOUR_WIRE) {
330 /*if 4-wire uart, configure CTS and RFR GPIOs */
331 ret = msm_hsl_config_uart_hwflow_gpios(port);
332 if (ret)
333 msm_hsl_unconfig_uart_tx_rx_gpios(port);
334 }
335 } else {
336 msm_hsl_unconfig_uart_tx_rx_gpios(port);
337 }
338
339 return ret;
340}
341
342/**
343 * msm_hsl_unconfig_uart_gpios: Unconfigures UART GPIOs
344 * @port: uart port
345 */
346static void msm_hsl_unconfig_uart_gpios(struct uart_port *port)
347{
348 struct msm_hsl_port *msm_hsl_port = UART_TO_MSM(port);
349
350 msm_hsl_unconfig_uart_tx_rx_gpios(port);
351 if (msm_hsl_port->func_mode == UART_FOUR_WIRE)
352 msm_hsl_unconfig_uart_hwflow_gpios(port);
353}
Stepan Moskovchenko798fe552012-03-29 19:47:19 -0700354static int get_line(struct platform_device *pdev)
355{
Stepan Moskovchenko5e023432012-10-25 18:44:17 -0700356 struct msm_hsl_port *msm_hsl_port = platform_get_drvdata(pdev);
Stepan Moskovchenko5e023432012-10-25 18:44:17 -0700357 return msm_hsl_port->uart.line;
Stepan Moskovchenko798fe552012-03-29 19:47:19 -0700358}
359
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700360static int clk_en(struct uart_port *port, int enable)
361{
362 struct msm_hsl_port *msm_hsl_port = UART_TO_MSM(port);
363 int ret = 0;
364
365 if (enable) {
366
Mayank Rana5d0252a2012-01-24 13:58:43 +0530367 ret = clk_prepare_enable(msm_hsl_port->clk);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700368 if (ret)
369 goto err;
370 if (msm_hsl_port->pclk) {
Mayank Rana5d0252a2012-01-24 13:58:43 +0530371 ret = clk_prepare_enable(msm_hsl_port->pclk);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700372 if (ret) {
Mayank Rana5d0252a2012-01-24 13:58:43 +0530373 clk_disable_unprepare(msm_hsl_port->clk);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700374 goto err;
375 }
376 }
377 } else {
Mayank Rana5d0252a2012-01-24 13:58:43 +0530378
379 clk_disable_unprepare(msm_hsl_port->clk);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700380 if (msm_hsl_port->pclk)
Mayank Rana5d0252a2012-01-24 13:58:43 +0530381 clk_disable_unprepare(msm_hsl_port->pclk);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700382 }
383err:
384 return ret;
385}
Mayank Rana8dddd752011-07-13 11:19:58 +0530386static int msm_hsl_loopback_enable_set(void *data, u64 val)
387{
388 struct msm_hsl_port *msm_hsl_port = data;
389 struct uart_port *port = &(msm_hsl_port->uart);
Sathish Ambley99e2a242011-10-25 15:49:53 -0700390 unsigned int vid;
Mayank Rana8dddd752011-07-13 11:19:58 +0530391 unsigned long flags;
392 int ret = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700393
Mayank Rana1295c082012-12-03 13:56:12 +0530394 ret = clk_set_rate(msm_hsl_port->clk, port->uartclk);
395 if (!ret) {
Mayank Rana8dddd752011-07-13 11:19:58 +0530396 clk_en(port, 1);
Mayank Rana1295c082012-12-03 13:56:12 +0530397 } else {
398 pr_err("Error: setting uartclk rate as %u\n",
399 port->uartclk);
Mayank Rana8dddd752011-07-13 11:19:58 +0530400 return -EINVAL;
401 }
402
Sathish Ambley99e2a242011-10-25 15:49:53 -0700403 vid = msm_hsl_port->ver_id;
Mayank Rana8dddd752011-07-13 11:19:58 +0530404 if (val) {
405 spin_lock_irqsave(&port->lock, flags);
Sathish Ambley99e2a242011-10-25 15:49:53 -0700406 ret = msm_hsl_read(port, regmap[vid][UARTDM_MR2]);
Mayank Rana8dddd752011-07-13 11:19:58 +0530407 ret |= UARTDM_MR2_LOOP_MODE_BMSK;
Sathish Ambley99e2a242011-10-25 15:49:53 -0700408 msm_hsl_write(port, ret, regmap[vid][UARTDM_MR2]);
Mayank Rana8dddd752011-07-13 11:19:58 +0530409 spin_unlock_irqrestore(&port->lock, flags);
410 } else {
411 spin_lock_irqsave(&port->lock, flags);
Sathish Ambley99e2a242011-10-25 15:49:53 -0700412 ret = msm_hsl_read(port, regmap[vid][UARTDM_MR2]);
Mayank Rana8dddd752011-07-13 11:19:58 +0530413 ret &= ~UARTDM_MR2_LOOP_MODE_BMSK;
Sathish Ambley99e2a242011-10-25 15:49:53 -0700414 msm_hsl_write(port, ret, regmap[vid][UARTDM_MR2]);
Mayank Rana8dddd752011-07-13 11:19:58 +0530415 spin_unlock_irqrestore(&port->lock, flags);
416 }
417
418 clk_en(port, 0);
419 return 0;
420}
421static int msm_hsl_loopback_enable_get(void *data, u64 *val)
422{
423 struct msm_hsl_port *msm_hsl_port = data;
424 struct uart_port *port = &(msm_hsl_port->uart);
425 unsigned long flags;
426 int ret = 0;
427
Mayank Rana1295c082012-12-03 13:56:12 +0530428 ret = clk_set_rate(msm_hsl_port->clk, port->uartclk);
429 if (!ret) {
Mayank Rana8dddd752011-07-13 11:19:58 +0530430 clk_en(port, 1);
Mayank Rana1295c082012-12-03 13:56:12 +0530431 } else {
432 pr_err("Error setting uartclk rate as %u\n",
433 port->uartclk);
Mayank Rana8dddd752011-07-13 11:19:58 +0530434 return -EINVAL;
435 }
436
437 spin_lock_irqsave(&port->lock, flags);
Sathish Ambley99e2a242011-10-25 15:49:53 -0700438 ret = msm_hsl_read(port, regmap[msm_hsl_port->ver_id][UARTDM_MR2]);
Mayank Rana8dddd752011-07-13 11:19:58 +0530439 spin_unlock_irqrestore(&port->lock, flags);
440 clk_en(port, 0);
441
442 *val = (ret & UARTDM_MR2_LOOP_MODE_BMSK) ? 1 : 0;
443 return 0;
444}
445DEFINE_SIMPLE_ATTRIBUTE(loopback_enable_fops, msm_hsl_loopback_enable_get,
446 msm_hsl_loopback_enable_set, "%llu\n");
447/*
448 * msm_serial_hsl debugfs node: <debugfs_root>/msm_serial_hsl/loopback.<id>
449 * writing 1 turns on internal loopback mode in HW. Useful for automation
450 * test scripts.
451 * writing 0 disables the internal loopback mode. Default is disabled.
452 */
453static void msm_hsl_debugfs_init(struct msm_hsl_port *msm_uport,
454 int id)
455{
456 char node_name[15];
457
458 snprintf(node_name, sizeof(node_name), "loopback.%d", id);
459 msm_uport->loopback_dir = debugfs_create_file(node_name,
460 S_IRUGO | S_IWUSR,
461 debug_base,
462 msm_uport,
463 &loopback_enable_fops);
464
465 if (IS_ERR_OR_NULL(msm_uport->loopback_dir))
Mayank Rana1295c082012-12-03 13:56:12 +0530466 pr_err("Cannot create loopback.%d debug entry", id);
Mayank Rana8dddd752011-07-13 11:19:58 +0530467}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700468static void msm_hsl_stop_tx(struct uart_port *port)
469{
470 struct msm_hsl_port *msm_hsl_port = UART_TO_MSM(port);
471
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700472 msm_hsl_port->imr &= ~UARTDM_ISR_TXLEV_BMSK;
Sathish Ambley99e2a242011-10-25 15:49:53 -0700473 msm_hsl_write(port, msm_hsl_port->imr,
474 regmap[msm_hsl_port->ver_id][UARTDM_IMR]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700475}
476
477static void msm_hsl_start_tx(struct uart_port *port)
478{
479 struct msm_hsl_port *msm_hsl_port = UART_TO_MSM(port);
480
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700481 msm_hsl_port->imr |= UARTDM_ISR_TXLEV_BMSK;
Sathish Ambley99e2a242011-10-25 15:49:53 -0700482 msm_hsl_write(port, msm_hsl_port->imr,
483 regmap[msm_hsl_port->ver_id][UARTDM_IMR]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700484}
485
486static void msm_hsl_stop_rx(struct uart_port *port)
487{
488 struct msm_hsl_port *msm_hsl_port = UART_TO_MSM(port);
489
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700490 msm_hsl_port->imr &= ~(UARTDM_ISR_RXLEV_BMSK |
491 UARTDM_ISR_RXSTALE_BMSK);
Sathish Ambley99e2a242011-10-25 15:49:53 -0700492 msm_hsl_write(port, msm_hsl_port->imr,
493 regmap[msm_hsl_port->ver_id][UARTDM_IMR]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700494}
495
496static void msm_hsl_enable_ms(struct uart_port *port)
497{
498 struct msm_hsl_port *msm_hsl_port = UART_TO_MSM(port);
499
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700500 msm_hsl_port->imr |= UARTDM_ISR_DELTA_CTS_BMSK;
Sathish Ambley99e2a242011-10-25 15:49:53 -0700501 msm_hsl_write(port, msm_hsl_port->imr,
502 regmap[msm_hsl_port->ver_id][UARTDM_IMR]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700503}
504
505static void handle_rx(struct uart_port *port, unsigned int misr)
506{
507 struct tty_struct *tty = port->state->port.tty;
Sathish Ambley99e2a242011-10-25 15:49:53 -0700508 unsigned int vid;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700509 unsigned int sr;
510 int count = 0;
511 struct msm_hsl_port *msm_hsl_port = UART_TO_MSM(port);
512
Sathish Ambley99e2a242011-10-25 15:49:53 -0700513 vid = msm_hsl_port->ver_id;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700514 /*
515 * Handle overrun. My understanding of the hardware is that overrun
516 * is not tied to the RX buffer, so we handle the case out of band.
517 */
Sathish Ambley99e2a242011-10-25 15:49:53 -0700518 if ((msm_hsl_read(port, regmap[vid][UARTDM_SR]) &
519 UARTDM_SR_OVERRUN_BMSK)) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700520 port->icount.overrun++;
521 tty_insert_flip_char(tty, 0, TTY_OVERRUN);
Sathish Ambley99e2a242011-10-25 15:49:53 -0700522 msm_hsl_write(port, RESET_ERROR_STATUS,
523 regmap[vid][UARTDM_CR]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700524 }
525
526 if (misr & UARTDM_ISR_RXSTALE_BMSK) {
Sathish Ambley99e2a242011-10-25 15:49:53 -0700527 count = msm_hsl_read(port,
528 regmap[vid][UARTDM_RX_TOTAL_SNAP]) -
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700529 msm_hsl_port->old_snap_state;
530 msm_hsl_port->old_snap_state = 0;
531 } else {
Sathish Ambley99e2a242011-10-25 15:49:53 -0700532 count = 4 * (msm_hsl_read(port, regmap[vid][UARTDM_RFWR]));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700533 msm_hsl_port->old_snap_state += count;
534 }
535
536 /* and now the main RX loop */
537 while (count > 0) {
538 unsigned int c;
539 char flag = TTY_NORMAL;
540
Sathish Ambley99e2a242011-10-25 15:49:53 -0700541 sr = msm_hsl_read(port, regmap[vid][UARTDM_SR]);
542 if ((sr & UARTDM_SR_RXRDY_BMSK) == 0) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700543 msm_hsl_port->old_snap_state -= count;
544 break;
545 }
Sathish Ambley99e2a242011-10-25 15:49:53 -0700546 c = msm_hsl_read(port, regmap[vid][UARTDM_RF]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700547 if (sr & UARTDM_SR_RX_BREAK_BMSK) {
548 port->icount.brk++;
549 if (uart_handle_break(port))
550 continue;
551 } else if (sr & UARTDM_SR_PAR_FRAME_BMSK) {
552 port->icount.frame++;
553 } else {
554 port->icount.rx++;
555 }
556
557 /* Mask conditions we're ignorning. */
558 sr &= port->read_status_mask;
559 if (sr & UARTDM_SR_RX_BREAK_BMSK)
560 flag = TTY_BREAK;
561 else if (sr & UARTDM_SR_PAR_FRAME_BMSK)
562 flag = TTY_FRAME;
563
564 /* TODO: handle sysrq */
565 /* if (!uart_handle_sysrq_char(port, c)) */
566 tty_insert_flip_string(tty, (char *) &c,
567 (count > 4) ? 4 : count);
568 count -= 4;
569 }
570
571 tty_flip_buffer_push(tty);
572}
573
574static void handle_tx(struct uart_port *port)
575{
576 struct circ_buf *xmit = &port->state->xmit;
577 int sent_tx;
578 int tx_count;
579 int x;
580 unsigned int tf_pointer = 0;
Sathish Ambley99e2a242011-10-25 15:49:53 -0700581 unsigned int vid;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700582
Sathish Ambley99e2a242011-10-25 15:49:53 -0700583 vid = UART_TO_MSM(port)->ver_id;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700584 tx_count = uart_circ_chars_pending(xmit);
585
586 if (tx_count > (UART_XMIT_SIZE - xmit->tail))
587 tx_count = UART_XMIT_SIZE - xmit->tail;
588 if (tx_count >= port->fifosize)
589 tx_count = port->fifosize;
590
591 /* Handle x_char */
592 if (port->x_char) {
Stepan Moskovchenko9ec24842012-05-15 13:58:58 -0700593 wait_for_xmitr(port);
Stepan Moskovchenko4f1025f2012-05-15 13:00:05 -0700594 msm_hsl_write(port, tx_count + 1, regmap[vid][UARTDM_NCF_TX]);
595 msm_hsl_read(port, regmap[vid][UARTDM_NCF_TX]);
Sathish Ambley99e2a242011-10-25 15:49:53 -0700596 msm_hsl_write(port, port->x_char, regmap[vid][UARTDM_TF]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700597 port->icount.tx++;
598 port->x_char = 0;
599 } else if (tx_count) {
Stepan Moskovchenko9ec24842012-05-15 13:58:58 -0700600 wait_for_xmitr(port);
Sathish Ambley99e2a242011-10-25 15:49:53 -0700601 msm_hsl_write(port, tx_count, regmap[vid][UARTDM_NCF_TX]);
Stepan Moskovchenko4f1025f2012-05-15 13:00:05 -0700602 msm_hsl_read(port, regmap[vid][UARTDM_NCF_TX]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700603 }
604 if (!tx_count) {
605 msm_hsl_stop_tx(port);
606 return;
607 }
608
609 while (tf_pointer < tx_count) {
Sathish Ambley99e2a242011-10-25 15:49:53 -0700610 if (unlikely(!(msm_hsl_read(port, regmap[vid][UARTDM_SR]) &
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700611 UARTDM_SR_TXRDY_BMSK)))
612 continue;
613 switch (tx_count - tf_pointer) {
614 case 1: {
615 x = xmit->buf[xmit->tail];
616 port->icount.tx++;
617 break;
618 }
619 case 2: {
620 x = xmit->buf[xmit->tail]
621 | xmit->buf[xmit->tail+1] << 8;
622 port->icount.tx += 2;
623 break;
624 }
625 case 3: {
626 x = xmit->buf[xmit->tail]
627 | xmit->buf[xmit->tail+1] << 8
628 | xmit->buf[xmit->tail + 2] << 16;
629 port->icount.tx += 3;
630 break;
631 }
632 default: {
633 x = *((int *)&(xmit->buf[xmit->tail]));
634 port->icount.tx += 4;
635 break;
636 }
637 }
Sathish Ambley99e2a242011-10-25 15:49:53 -0700638 msm_hsl_write(port, x, regmap[vid][UARTDM_TF]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700639 xmit->tail = ((tx_count - tf_pointer < 4) ?
640 (tx_count - tf_pointer + xmit->tail) :
641 (xmit->tail + 4)) & (UART_XMIT_SIZE - 1);
642 tf_pointer += 4;
643 sent_tx = 1;
644 }
645
646 if (uart_circ_empty(xmit))
647 msm_hsl_stop_tx(port);
648
649 if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
650 uart_write_wakeup(port);
651
652}
653
654static void handle_delta_cts(struct uart_port *port)
655{
Sathish Ambley99e2a242011-10-25 15:49:53 -0700656 unsigned int vid = UART_TO_MSM(port)->ver_id;
657
658 msm_hsl_write(port, RESET_CTS, regmap[vid][UARTDM_CR]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700659 port->icount.cts++;
660 wake_up_interruptible(&port->state->port.delta_msr_wait);
661}
662
663static irqreturn_t msm_hsl_irq(int irq, void *dev_id)
664{
665 struct uart_port *port = dev_id;
666 struct msm_hsl_port *msm_hsl_port = UART_TO_MSM(port);
Sathish Ambley99e2a242011-10-25 15:49:53 -0700667 unsigned int vid;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700668 unsigned int misr;
669 unsigned long flags;
670
671 spin_lock_irqsave(&port->lock, flags);
Sathish Ambley99e2a242011-10-25 15:49:53 -0700672 vid = msm_hsl_port->ver_id;
673 misr = msm_hsl_read(port, regmap[vid][UARTDM_MISR]);
674 /* disable interrupt */
675 msm_hsl_write(port, 0, regmap[vid][UARTDM_IMR]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700676
677 if (misr & (UARTDM_ISR_RXSTALE_BMSK | UARTDM_ISR_RXLEV_BMSK)) {
678 handle_rx(port, misr);
679 if (misr & (UARTDM_ISR_RXSTALE_BMSK))
Sathish Ambley99e2a242011-10-25 15:49:53 -0700680 msm_hsl_write(port, RESET_STALE_INT,
681 regmap[vid][UARTDM_CR]);
682 msm_hsl_write(port, 6500, regmap[vid][UARTDM_DMRX]);
683 msm_hsl_write(port, STALE_EVENT_ENABLE, regmap[vid][UARTDM_CR]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700684 }
685 if (misr & UARTDM_ISR_TXLEV_BMSK)
686 handle_tx(port);
687
688 if (misr & UARTDM_ISR_DELTA_CTS_BMSK)
689 handle_delta_cts(port);
690
691 /* restore interrupt */
Sathish Ambley99e2a242011-10-25 15:49:53 -0700692 msm_hsl_write(port, msm_hsl_port->imr, regmap[vid][UARTDM_IMR]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700693 spin_unlock_irqrestore(&port->lock, flags);
694
695 return IRQ_HANDLED;
696}
697
698static unsigned int msm_hsl_tx_empty(struct uart_port *port)
699{
700 unsigned int ret;
Mayank Ranaa4ad7b32012-01-24 10:23:48 +0530701 unsigned int vid = UART_TO_MSM(port)->ver_id;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700702
Sathish Ambley99e2a242011-10-25 15:49:53 -0700703 ret = (msm_hsl_read(port, regmap[vid][UARTDM_SR]) &
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700704 UARTDM_SR_TXEMT_BMSK) ? TIOCSER_TEMT : 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700705 return ret;
706}
707
708static void msm_hsl_reset(struct uart_port *port)
709{
Sathish Ambley99e2a242011-10-25 15:49:53 -0700710 unsigned int vid = UART_TO_MSM(port)->ver_id;
711
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700712 /* reset everything */
Sathish Ambley99e2a242011-10-25 15:49:53 -0700713 msm_hsl_write(port, RESET_RX, regmap[vid][UARTDM_CR]);
714 msm_hsl_write(port, RESET_TX, regmap[vid][UARTDM_CR]);
715 msm_hsl_write(port, RESET_ERROR_STATUS, regmap[vid][UARTDM_CR]);
716 msm_hsl_write(port, RESET_BREAK_INT, regmap[vid][UARTDM_CR]);
717 msm_hsl_write(port, RESET_CTS, regmap[vid][UARTDM_CR]);
718 msm_hsl_write(port, RFR_LOW, regmap[vid][UARTDM_CR]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700719}
720
721static unsigned int msm_hsl_get_mctrl(struct uart_port *port)
722{
723 return TIOCM_CAR | TIOCM_CTS | TIOCM_DSR | TIOCM_RTS;
724}
725
726static void msm_hsl_set_mctrl(struct uart_port *port, unsigned int mctrl)
727{
Sathish Ambley99e2a242011-10-25 15:49:53 -0700728 unsigned int vid = UART_TO_MSM(port)->ver_id;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700729 unsigned int mr;
730 unsigned int loop_mode;
731
Sathish Ambley99e2a242011-10-25 15:49:53 -0700732 mr = msm_hsl_read(port, regmap[vid][UARTDM_MR1]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700733
734 if (!(mctrl & TIOCM_RTS)) {
735 mr &= ~UARTDM_MR1_RX_RDY_CTL_BMSK;
Sathish Ambley99e2a242011-10-25 15:49:53 -0700736 msm_hsl_write(port, mr, regmap[vid][UARTDM_MR1]);
737 msm_hsl_write(port, RFR_HIGH, regmap[vid][UARTDM_CR]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700738 } else {
739 mr |= UARTDM_MR1_RX_RDY_CTL_BMSK;
Sathish Ambley99e2a242011-10-25 15:49:53 -0700740 msm_hsl_write(port, mr, regmap[vid][UARTDM_MR1]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700741 }
742
743 loop_mode = TIOCM_LOOP & mctrl;
744 if (loop_mode) {
Sathish Ambley99e2a242011-10-25 15:49:53 -0700745 mr = msm_hsl_read(port, regmap[vid][UARTDM_MR2]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700746 mr |= UARTDM_MR2_LOOP_MODE_BMSK;
Sathish Ambley99e2a242011-10-25 15:49:53 -0700747 msm_hsl_write(port, mr, regmap[vid][UARTDM_MR2]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700748
749 /* Reset TX */
750 msm_hsl_reset(port);
751
752 /* Turn on Uart Receiver & Transmitter*/
753 msm_hsl_write(port, UARTDM_CR_RX_EN_BMSK
Sathish Ambley99e2a242011-10-25 15:49:53 -0700754 | UARTDM_CR_TX_EN_BMSK, regmap[vid][UARTDM_CR]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700755 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700756}
757
758static void msm_hsl_break_ctl(struct uart_port *port, int break_ctl)
759{
Sathish Ambley99e2a242011-10-25 15:49:53 -0700760 unsigned int vid = UART_TO_MSM(port)->ver_id;
761
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700762 if (break_ctl)
Sathish Ambley99e2a242011-10-25 15:49:53 -0700763 msm_hsl_write(port, START_BREAK, regmap[vid][UARTDM_CR]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700764 else
Sathish Ambley99e2a242011-10-25 15:49:53 -0700765 msm_hsl_write(port, STOP_BREAK, regmap[vid][UARTDM_CR]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700766}
767
Mayank Rana44659372012-12-03 17:59:45 +0530768/**
769 * msm_hsl_set_baud_rate: set requested baud rate
770 * @port: uart port
771 * @baud: baud rate to set (in bps)
772 */
773static void msm_hsl_set_baud_rate(struct uart_port *port,
774 unsigned int baud)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700775{
776 unsigned int baud_code, rxstale, watermark;
Mayank Ranae9a54342011-06-29 20:27:08 +0530777 unsigned int data;
Sathish Ambley99e2a242011-10-25 15:49:53 -0700778 unsigned int vid;
Mayank Ranae9a54342011-06-29 20:27:08 +0530779 struct msm_hsl_port *msm_hsl_port = UART_TO_MSM(port);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700780
781 switch (baud) {
782 case 300:
Mayank Rana9825dc62011-07-26 10:47:46 +0530783 baud_code = UARTDM_CSR_75;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700784 rxstale = 1;
785 break;
786 case 600:
Mayank Rana9825dc62011-07-26 10:47:46 +0530787 baud_code = UARTDM_CSR_150;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700788 rxstale = 1;
789 break;
790 case 1200:
Mayank Rana9825dc62011-07-26 10:47:46 +0530791 baud_code = UARTDM_CSR_300;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700792 rxstale = 1;
793 break;
794 case 2400:
Mayank Rana9825dc62011-07-26 10:47:46 +0530795 baud_code = UARTDM_CSR_600;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700796 rxstale = 1;
797 break;
798 case 4800:
Mayank Rana9825dc62011-07-26 10:47:46 +0530799 baud_code = UARTDM_CSR_1200;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700800 rxstale = 1;
801 break;
802 case 9600:
Mayank Rana9825dc62011-07-26 10:47:46 +0530803 baud_code = UARTDM_CSR_2400;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700804 rxstale = 2;
805 break;
806 case 14400:
Mayank Rana9825dc62011-07-26 10:47:46 +0530807 baud_code = UARTDM_CSR_3600;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700808 rxstale = 3;
809 break;
810 case 19200:
Mayank Rana9825dc62011-07-26 10:47:46 +0530811 baud_code = UARTDM_CSR_4800;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700812 rxstale = 4;
813 break;
814 case 28800:
Mayank Rana9825dc62011-07-26 10:47:46 +0530815 baud_code = UARTDM_CSR_7200;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700816 rxstale = 6;
817 break;
818 case 38400:
Mayank Rana9825dc62011-07-26 10:47:46 +0530819 baud_code = UARTDM_CSR_9600;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700820 rxstale = 8;
821 break;
822 case 57600:
Mayank Rana9825dc62011-07-26 10:47:46 +0530823 baud_code = UARTDM_CSR_14400;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700824 rxstale = 16;
825 break;
826 case 115200:
Mayank Rana9825dc62011-07-26 10:47:46 +0530827 baud_code = UARTDM_CSR_28800;
828 rxstale = 31;
829 break;
830 case 230400:
831 baud_code = UARTDM_CSR_57600;
832 rxstale = 31;
833 break;
834 case 460800:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700835 baud_code = UARTDM_CSR_115200;
836 rxstale = 31;
837 break;
Mayank Rana44659372012-12-03 17:59:45 +0530838 case 4000000:
839 case 3686400:
840 case 3200000:
841 case 3500000:
842 case 3000000:
843 case 2500000:
844 case 1500000:
845 case 1152000:
846 case 1000000:
847 case 921600:
848 baud_code = 0xff;
849 rxstale = 31;
850 break;
851 default: /*115200 baud rate */
Mayank Rana9825dc62011-07-26 10:47:46 +0530852 baud_code = UARTDM_CSR_28800;
853 rxstale = 31;
854 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700855 }
856
Sathish Ambley99e2a242011-10-25 15:49:53 -0700857 vid = msm_hsl_port->ver_id;
858 msm_hsl_write(port, baud_code, regmap[vid][UARTDM_CSR]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700859
Mayank Rana44659372012-12-03 17:59:45 +0530860 /*
861 * uart baud rate depends on CSR and MND Values
862 * we are updating CSR before and then calling
863 * clk_set_rate which updates MND Values. Hence
864 * dsb requires here.
865 */
866 mb();
867
868 /*
869 * Check requested baud rate and for higher baud rate than 460800,
870 * calculate required uart clock frequency and set the same.
871 */
Mayank Ranaaf409702012-12-12 18:37:24 +0530872 if (baud > 460800)
Mayank Rana44659372012-12-03 17:59:45 +0530873 port->uartclk = baud * 16;
Mayank Ranaaf409702012-12-12 18:37:24 +0530874 else
875 port->uartclk = 7372800;
876
877 if (clk_set_rate(msm_hsl_port->clk, port->uartclk)) {
878 pr_err("Error: setting uartclk rate %u\n", port->uartclk);
879 WARN_ON(1);
880 return;
Mayank Rana44659372012-12-03 17:59:45 +0530881 }
882
883 /* Set timeout to be ~600x the character transmit time */
884 msm_hsl_port->tx_timeout = (1000000000 / baud) * 6;
885
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700886 /* RX stale watermark */
887 watermark = UARTDM_IPR_STALE_LSB_BMSK & rxstale;
888 watermark |= UARTDM_IPR_STALE_TIMEOUT_MSB_BMSK & (rxstale << 2);
Sathish Ambley99e2a242011-10-25 15:49:53 -0700889 msm_hsl_write(port, watermark, regmap[vid][UARTDM_IPR]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700890
Mayank Ranaad56d5f2011-08-16 09:07:04 +0530891 /* Set RX watermark
892 * Configure Rx Watermark as 3/4 size of Rx FIFO.
893 * RFWR register takes value in Words for UARTDM Core
894 * whereas it is consider to be in Bytes for UART Core.
Mayank Ranaf9f90302012-12-06 17:04:28 +0530895 * Hence configuring Rx Watermark as 48 Words.
Mayank Ranaad56d5f2011-08-16 09:07:04 +0530896 */
Mayank Ranaf9f90302012-12-06 17:04:28 +0530897 watermark = (port->fifosize * 3) / 4;
Sathish Ambley99e2a242011-10-25 15:49:53 -0700898 msm_hsl_write(port, watermark, regmap[vid][UARTDM_RFWR]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700899
900 /* set TX watermark */
Sathish Ambley99e2a242011-10-25 15:49:53 -0700901 msm_hsl_write(port, 0, regmap[vid][UARTDM_TFWR]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700902
Sathish Ambley99e2a242011-10-25 15:49:53 -0700903 msm_hsl_write(port, CR_PROTECTION_EN, regmap[vid][UARTDM_CR]);
Mayank Ranae9a54342011-06-29 20:27:08 +0530904 msm_hsl_reset(port);
905
906 data = UARTDM_CR_TX_EN_BMSK;
907 data |= UARTDM_CR_RX_EN_BMSK;
908 /* enable TX & RX */
Sathish Ambley99e2a242011-10-25 15:49:53 -0700909 msm_hsl_write(port, data, regmap[vid][UARTDM_CR]);
Mayank Ranae9a54342011-06-29 20:27:08 +0530910
Mayank Rana9717aba2012-02-27 18:20:38 +0530911 msm_hsl_write(port, RESET_STALE_INT, regmap[vid][UARTDM_CR]);
Mayank Ranae9a54342011-06-29 20:27:08 +0530912 /* turn on RX and CTS interrupts */
913 msm_hsl_port->imr = UARTDM_ISR_RXSTALE_BMSK
914 | UARTDM_ISR_DELTA_CTS_BMSK | UARTDM_ISR_RXLEV_BMSK;
Sathish Ambley99e2a242011-10-25 15:49:53 -0700915 msm_hsl_write(port, msm_hsl_port->imr, regmap[vid][UARTDM_IMR]);
916 msm_hsl_write(port, 6500, regmap[vid][UARTDM_DMRX]);
917 msm_hsl_write(port, STALE_EVENT_ENABLE, regmap[vid][UARTDM_CR]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700918}
919
920static void msm_hsl_init_clock(struct uart_port *port)
921{
922 clk_en(port, 1);
923}
924
925static void msm_hsl_deinit_clock(struct uart_port *port)
926{
927 clk_en(port, 0);
928}
929
930static int msm_hsl_startup(struct uart_port *port)
931{
932 struct msm_hsl_port *msm_hsl_port = UART_TO_MSM(port);
933 struct platform_device *pdev = to_platform_device(port->dev);
934 const struct msm_serial_hslite_platform_data *pdata =
935 pdev->dev.platform_data;
936 unsigned int data, rfr_level;
Sathish Ambley99e2a242011-10-25 15:49:53 -0700937 unsigned int vid;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700938 int ret;
939 unsigned long flags;
940
941 snprintf(msm_hsl_port->name, sizeof(msm_hsl_port->name),
942 "msm_serial_hsl%d", port->line);
943
944 if (!(is_console(port)) || (!port->cons) ||
945 (port->cons && (!(port->cons->flags & CON_ENABLED)))) {
946
947 if (msm_serial_hsl_has_gsbi(port))
Mayank Rana9fc393d2012-12-04 19:10:36 +0530948 set_gsbi_uart_func_mode(port);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700949
950 if (pdata && pdata->config_gpio) {
Mayank Rana9fc393d2012-12-04 19:10:36 +0530951 ret = msm_hsl_config_uart_gpios(port);
952 if (ret) {
953 msm_hsl_unconfig_uart_gpios(port);
954 goto exit_startup;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700955 }
956 }
957 }
958#ifndef CONFIG_PM_RUNTIME
959 msm_hsl_init_clock(port);
960#endif
961 pm_runtime_get_sync(port->dev);
962
Mayank Ranaf9f90302012-12-06 17:04:28 +0530963 /*
964 * Set RFR Level as 3/4 of UARTDM FIFO Size
965 * i.e. 48 Words = 192 bytes as Rx FIFO is 64 words ( 256 bytes).
966 */
Mayank Ranaffdf5302011-08-17 20:54:34 +0530967 if (likely(port->fifosize > 48))
968 rfr_level = port->fifosize - 16;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700969 else
970 rfr_level = port->fifosize;
971
972 spin_lock_irqsave(&port->lock, flags);
973
Sathish Ambley99e2a242011-10-25 15:49:53 -0700974 vid = msm_hsl_port->ver_id;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700975 /* set automatic RFR level */
Sathish Ambley99e2a242011-10-25 15:49:53 -0700976 data = msm_hsl_read(port, regmap[vid][UARTDM_MR1]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700977 data &= ~UARTDM_MR1_AUTO_RFR_LEVEL1_BMSK;
978 data &= ~UARTDM_MR1_AUTO_RFR_LEVEL0_BMSK;
979 data |= UARTDM_MR1_AUTO_RFR_LEVEL1_BMSK & (rfr_level << 2);
980 data |= UARTDM_MR1_AUTO_RFR_LEVEL0_BMSK & rfr_level;
Sathish Ambley99e2a242011-10-25 15:49:53 -0700981 msm_hsl_write(port, data, regmap[vid][UARTDM_MR1]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700982 spin_unlock_irqrestore(&port->lock, flags);
983
984 ret = request_irq(port->irq, msm_hsl_irq, IRQF_TRIGGER_HIGH,
985 msm_hsl_port->name, port);
986 if (unlikely(ret)) {
Mayank Rana1295c082012-12-03 13:56:12 +0530987 pr_err("failed to request_irq\n");
Mayank Rana9fc393d2012-12-04 19:10:36 +0530988 msm_hsl_unconfig_uart_gpios(port);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700989 }
Mayank Rana9fc393d2012-12-04 19:10:36 +0530990
991exit_startup:
992 return ret;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700993}
994
995static void msm_hsl_shutdown(struct uart_port *port)
996{
997 struct msm_hsl_port *msm_hsl_port = UART_TO_MSM(port);
998 struct platform_device *pdev = to_platform_device(port->dev);
999 const struct msm_serial_hslite_platform_data *pdata =
1000 pdev->dev.platform_data;
1001
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001002 msm_hsl_port->imr = 0;
Sathish Ambley99e2a242011-10-25 15:49:53 -07001003 /* disable interrupts */
1004 msm_hsl_write(port, 0, regmap[msm_hsl_port->ver_id][UARTDM_IMR]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001005
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001006 free_irq(port->irq, port);
1007
1008#ifndef CONFIG_PM_RUNTIME
1009 msm_hsl_deinit_clock(port);
1010#endif
1011 pm_runtime_put_sync(port->dev);
1012 if (!(is_console(port)) || (!port->cons) ||
1013 (port->cons && (!(port->cons->flags & CON_ENABLED)))) {
Mayank Rana9fc393d2012-12-04 19:10:36 +05301014 /* Free UART GPIOs */
1015 if (pdata && pdata->config_gpio)
1016 msm_hsl_unconfig_uart_gpios(port);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001017 }
1018}
1019
1020static void msm_hsl_set_termios(struct uart_port *port,
1021 struct ktermios *termios,
1022 struct ktermios *old)
1023{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001024 unsigned int baud, mr;
Sathish Ambley99e2a242011-10-25 15:49:53 -07001025 unsigned int vid;
Mayank Rana44659372012-12-03 17:59:45 +05301026 struct msm_hsl_port *msm_hsl_port = UART_TO_MSM(port);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001027
Mayank Rana216744c2012-05-01 22:43:21 -07001028 if (!termios->c_cflag)
1029 return;
1030
Mayank Rana44659372012-12-03 17:59:45 +05301031 mutex_lock(&msm_hsl_port->clk_mutex);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001032
Mayank Rana44659372012-12-03 17:59:45 +05301033 /*
1034 * Calculate and set baud rate
1035 * 300 is the minimum and 4 Mbps is the maximum baud rate
1036 * supported by driver.
1037 */
1038 baud = uart_get_baud_rate(port, termios, old, 200, 4000000);
1039
1040 /*
1041 * Due to non-availability of 3.2 Mbps baud rate as standard baud rate
1042 * with TTY/serial core. Map 200 BAUD to 3.2 Mbps
1043 */
1044 if (baud == 200)
1045 baud = 3200000;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001046
1047 msm_hsl_set_baud_rate(port, baud);
1048
Sathish Ambley99e2a242011-10-25 15:49:53 -07001049 vid = UART_TO_MSM(port)->ver_id;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001050 /* calculate parity */
Sathish Ambley99e2a242011-10-25 15:49:53 -07001051 mr = msm_hsl_read(port, regmap[vid][UARTDM_MR2]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001052 mr &= ~UARTDM_MR2_PARITY_MODE_BMSK;
1053 if (termios->c_cflag & PARENB) {
1054 if (termios->c_cflag & PARODD)
1055 mr |= ODD_PARITY;
1056 else if (termios->c_cflag & CMSPAR)
1057 mr |= SPACE_PARITY;
1058 else
1059 mr |= EVEN_PARITY;
1060 }
1061
1062 /* calculate bits per char */
1063 mr &= ~UARTDM_MR2_BITS_PER_CHAR_BMSK;
1064 switch (termios->c_cflag & CSIZE) {
1065 case CS5:
1066 mr |= FIVE_BPC;
1067 break;
1068 case CS6:
1069 mr |= SIX_BPC;
1070 break;
1071 case CS7:
1072 mr |= SEVEN_BPC;
1073 break;
1074 case CS8:
1075 default:
1076 mr |= EIGHT_BPC;
1077 break;
1078 }
1079
1080 /* calculate stop bits */
1081 mr &= ~(STOP_BIT_ONE | STOP_BIT_TWO);
1082 if (termios->c_cflag & CSTOPB)
1083 mr |= STOP_BIT_TWO;
1084 else
1085 mr |= STOP_BIT_ONE;
1086
1087 /* set parity, bits per char, and stop bit */
Sathish Ambley99e2a242011-10-25 15:49:53 -07001088 msm_hsl_write(port, mr, regmap[vid][UARTDM_MR2]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001089
1090 /* calculate and set hardware flow control */
Sathish Ambley99e2a242011-10-25 15:49:53 -07001091 mr = msm_hsl_read(port, regmap[vid][UARTDM_MR1]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001092 mr &= ~(UARTDM_MR1_CTS_CTL_BMSK | UARTDM_MR1_RX_RDY_CTL_BMSK);
1093 if (termios->c_cflag & CRTSCTS) {
1094 mr |= UARTDM_MR1_CTS_CTL_BMSK;
1095 mr |= UARTDM_MR1_RX_RDY_CTL_BMSK;
1096 }
Sathish Ambley99e2a242011-10-25 15:49:53 -07001097 msm_hsl_write(port, mr, regmap[vid][UARTDM_MR1]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001098
1099 /* Configure status bits to ignore based on termio flags. */
1100 port->read_status_mask = 0;
1101 if (termios->c_iflag & INPCK)
1102 port->read_status_mask |= UARTDM_SR_PAR_FRAME_BMSK;
1103 if (termios->c_iflag & (BRKINT | PARMRK))
1104 port->read_status_mask |= UARTDM_SR_RX_BREAK_BMSK;
1105
1106 uart_update_timeout(port, termios->c_cflag, baud);
1107
Mayank Rana44659372012-12-03 17:59:45 +05301108 mutex_unlock(&msm_hsl_port->clk_mutex);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001109}
1110
1111static const char *msm_hsl_type(struct uart_port *port)
1112{
1113 return "MSM";
1114}
1115
1116static void msm_hsl_release_port(struct uart_port *port)
1117{
1118 struct msm_hsl_port *msm_hsl_port = UART_TO_MSM(port);
1119 struct platform_device *pdev = to_platform_device(port->dev);
1120 struct resource *uart_resource;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001121 resource_size_t size;
1122
1123 uart_resource = platform_get_resource_byname(pdev, IORESOURCE_MEM,
1124 "uartdm_resource");
Sathish Ambley3d50c762011-10-25 15:26:00 -07001125 if (!uart_resource)
1126 uart_resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001127 if (unlikely(!uart_resource))
1128 return;
1129 size = uart_resource->end - uart_resource->start + 1;
1130
1131 release_mem_region(port->mapbase, size);
1132 iounmap(port->membase);
1133 port->membase = NULL;
1134
1135 if (msm_serial_hsl_has_gsbi(port)) {
1136 iowrite32(GSBI_PROTOCOL_IDLE, msm_hsl_port->mapped_gsbi +
1137 GSBI_CONTROL_ADDR);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001138 iounmap(msm_hsl_port->mapped_gsbi);
1139 msm_hsl_port->mapped_gsbi = NULL;
1140 }
1141}
1142
1143static int msm_hsl_request_port(struct uart_port *port)
1144{
1145 struct msm_hsl_port *msm_hsl_port = UART_TO_MSM(port);
1146 struct platform_device *pdev = to_platform_device(port->dev);
1147 struct resource *uart_resource;
1148 struct resource *gsbi_resource;
1149 resource_size_t size;
1150
1151 uart_resource = platform_get_resource_byname(pdev, IORESOURCE_MEM,
1152 "uartdm_resource");
Sathish Ambley3d50c762011-10-25 15:26:00 -07001153 if (!uart_resource)
1154 uart_resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001155 if (unlikely(!uart_resource)) {
Mayank Rana1295c082012-12-03 13:56:12 +05301156 pr_err("can't get uartdm resource\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001157 return -ENXIO;
1158 }
1159 size = uart_resource->end - uart_resource->start + 1;
1160
1161 if (unlikely(!request_mem_region(port->mapbase, size,
1162 "msm_serial_hsl"))) {
Mayank Rana1295c082012-12-03 13:56:12 +05301163 pr_err("can't get mem region for uartdm\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001164 return -EBUSY;
1165 }
1166
1167 port->membase = ioremap(port->mapbase, size);
1168 if (!port->membase) {
1169 release_mem_region(port->mapbase, size);
1170 return -EBUSY;
1171 }
1172
1173 if (msm_serial_hsl_has_gsbi(port)) {
1174 gsbi_resource = platform_get_resource_byname(pdev,
1175 IORESOURCE_MEM,
1176 "gsbi_resource");
Sathish Ambley3d50c762011-10-25 15:26:00 -07001177 if (!gsbi_resource)
1178 gsbi_resource = platform_get_resource(pdev,
1179 IORESOURCE_MEM, 1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001180 if (unlikely(!gsbi_resource)) {
Mayank Rana1295c082012-12-03 13:56:12 +05301181 pr_err("can't get gsbi resource\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001182 return -ENXIO;
1183 }
1184
1185 size = gsbi_resource->end - gsbi_resource->start + 1;
1186 msm_hsl_port->mapped_gsbi = ioremap(gsbi_resource->start,
1187 size);
1188 if (!msm_hsl_port->mapped_gsbi) {
1189 return -EBUSY;
1190 }
1191 }
1192
1193 return 0;
1194}
1195
1196static void msm_hsl_config_port(struct uart_port *port, int flags)
1197{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001198 if (flags & UART_CONFIG_TYPE) {
1199 port->type = PORT_MSM;
1200 if (msm_hsl_request_port(port))
1201 return;
1202 }
Mayank Rana9fc393d2012-12-04 19:10:36 +05301203
1204 /* Configure required GSBI based UART protocol. */
1205 if (msm_serial_hsl_has_gsbi(port))
1206 set_gsbi_uart_func_mode(port);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001207}
1208
1209static int msm_hsl_verify_port(struct uart_port *port,
1210 struct serial_struct *ser)
1211{
1212 if (unlikely(ser->type != PORT_UNKNOWN && ser->type != PORT_MSM))
1213 return -EINVAL;
1214 if (unlikely(port->irq != ser->irq))
1215 return -EINVAL;
1216 return 0;
1217}
1218
1219static void msm_hsl_power(struct uart_port *port, unsigned int state,
1220 unsigned int oldstate)
1221{
1222 int ret;
1223 struct msm_hsl_port *msm_hsl_port = UART_TO_MSM(port);
1224
1225 switch (state) {
1226 case 0:
Mayank Rana1295c082012-12-03 13:56:12 +05301227 ret = clk_set_rate(msm_hsl_port->clk, port->uartclk);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001228 if (ret)
Mayank Rana1295c082012-12-03 13:56:12 +05301229 pr_err("Error setting UART clock rate to %u\n",
1230 port->uartclk);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001231 clk_en(port, 1);
1232 break;
1233 case 3:
1234 clk_en(port, 0);
Mayank Rana22e4b382012-01-11 21:35:00 +05301235 ret = clk_set_rate(msm_hsl_port->clk, 0);
1236 if (ret)
Mayank Rana1295c082012-12-03 13:56:12 +05301237 pr_err("Error setting UART clock rate to zero.\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001238 break;
1239 default:
Mayank Rana1295c082012-12-03 13:56:12 +05301240 pr_err("Unknown PM state %d\n", state);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001241 }
1242}
1243
1244static struct uart_ops msm_hsl_uart_pops = {
1245 .tx_empty = msm_hsl_tx_empty,
1246 .set_mctrl = msm_hsl_set_mctrl,
1247 .get_mctrl = msm_hsl_get_mctrl,
1248 .stop_tx = msm_hsl_stop_tx,
1249 .start_tx = msm_hsl_start_tx,
1250 .stop_rx = msm_hsl_stop_rx,
1251 .enable_ms = msm_hsl_enable_ms,
1252 .break_ctl = msm_hsl_break_ctl,
1253 .startup = msm_hsl_startup,
1254 .shutdown = msm_hsl_shutdown,
1255 .set_termios = msm_hsl_set_termios,
1256 .type = msm_hsl_type,
1257 .release_port = msm_hsl_release_port,
1258 .request_port = msm_hsl_request_port,
1259 .config_port = msm_hsl_config_port,
1260 .verify_port = msm_hsl_verify_port,
1261 .pm = msm_hsl_power,
1262};
1263
1264static struct msm_hsl_port msm_hsl_uart_ports[] = {
1265 {
1266 .uart = {
1267 .iotype = UPIO_MEM,
1268 .ops = &msm_hsl_uart_pops,
1269 .flags = UPF_BOOT_AUTOCONF,
1270 .fifosize = 64,
1271 .line = 0,
1272 },
1273 },
1274 {
1275 .uart = {
1276 .iotype = UPIO_MEM,
1277 .ops = &msm_hsl_uart_pops,
1278 .flags = UPF_BOOT_AUTOCONF,
1279 .fifosize = 64,
1280 .line = 1,
1281 },
1282 },
1283 {
1284 .uart = {
1285 .iotype = UPIO_MEM,
1286 .ops = &msm_hsl_uart_pops,
1287 .flags = UPF_BOOT_AUTOCONF,
1288 .fifosize = 64,
1289 .line = 2,
1290 },
1291 },
1292};
1293
1294#define UART_NR ARRAY_SIZE(msm_hsl_uart_ports)
1295
1296static inline struct uart_port *get_port_from_line(unsigned int line)
1297{
1298 return &msm_hsl_uart_ports[line].uart;
1299}
1300
Stepan Moskovchenko1d4731e2012-02-21 20:18:23 -08001301static unsigned int msm_hsl_console_state[8];
1302
1303static void dump_hsl_regs(struct uart_port *port)
1304{
1305 struct msm_hsl_port *msm_hsl_port = UART_TO_MSM(port);
1306 unsigned int vid = msm_hsl_port->ver_id;
1307 unsigned int sr, isr, mr1, mr2, ncf, txfs, rxfs, con_state;
1308
1309 sr = msm_hsl_read(port, regmap[vid][UARTDM_SR]);
1310 isr = msm_hsl_read(port, regmap[vid][UARTDM_ISR]);
1311 mr1 = msm_hsl_read(port, regmap[vid][UARTDM_MR1]);
1312 mr2 = msm_hsl_read(port, regmap[vid][UARTDM_MR2]);
1313 ncf = msm_hsl_read(port, regmap[vid][UARTDM_NCF_TX]);
1314 txfs = msm_hsl_read(port, regmap[vid][UARTDM_TXFS]);
1315 rxfs = msm_hsl_read(port, regmap[vid][UARTDM_RXFS]);
1316 con_state = get_console_state(port);
1317
1318 msm_hsl_console_state[0] = sr;
1319 msm_hsl_console_state[1] = isr;
1320 msm_hsl_console_state[2] = mr1;
1321 msm_hsl_console_state[3] = mr2;
1322 msm_hsl_console_state[4] = ncf;
1323 msm_hsl_console_state[5] = txfs;
1324 msm_hsl_console_state[6] = rxfs;
1325 msm_hsl_console_state[7] = con_state;
1326
Mayank Rana1295c082012-12-03 13:56:12 +05301327 pr_info("Timeout: %d uS\n", msm_hsl_port->tx_timeout);
1328 pr_info("SR: %08x\n", sr);
1329 pr_info("ISR: %08x\n", isr);
1330 pr_info("MR1: %08x\n", mr1);
1331 pr_info("MR2: %08x\n", mr2);
1332 pr_info("NCF: %08x\n", ncf);
1333 pr_info("TXFS: %08x\n", txfs);
1334 pr_info("RXFS: %08x\n", rxfs);
1335 pr_info("Console state: %d\n", con_state);
Stepan Moskovchenko1d4731e2012-02-21 20:18:23 -08001336}
1337
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001338/*
1339 * Wait for transmitter & holding register to empty
1340 * Derived from wait_for_xmitr in 8250 serial driver by Russell King */
Stepan Moskovchenko9ec24842012-05-15 13:58:58 -07001341static void wait_for_xmitr(struct uart_port *port)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001342{
Stepan Moskovchenko1d4731e2012-02-21 20:18:23 -08001343 struct msm_hsl_port *msm_hsl_port = UART_TO_MSM(port);
1344 unsigned int vid = msm_hsl_port->ver_id;
1345 int count = 0;
Sathish Ambley99e2a242011-10-25 15:49:53 -07001346
1347 if (!(msm_hsl_read(port, regmap[vid][UARTDM_SR]) &
1348 UARTDM_SR_TXEMT_BMSK)) {
Stepan Moskovchenko9ec24842012-05-15 13:58:58 -07001349 while (!(msm_hsl_read(port, regmap[vid][UARTDM_ISR]) &
Stepan Moskovchenkod4a62ab202012-05-15 14:43:31 -07001350 UARTDM_ISR_TX_READY_BMSK) &&
1351 !(msm_hsl_read(port, regmap[vid][UARTDM_SR]) &
1352 UARTDM_SR_TXEMT_BMSK)) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001353 udelay(1);
1354 touch_nmi_watchdog();
1355 cpu_relax();
Stepan Moskovchenko1d4731e2012-02-21 20:18:23 -08001356 if (++count == msm_hsl_port->tx_timeout) {
1357 dump_hsl_regs(port);
1358 panic("MSM HSL wait_for_xmitr is stuck!");
1359 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001360 }
Sathish Ambley99e2a242011-10-25 15:49:53 -07001361 msm_hsl_write(port, CLEAR_TX_READY, regmap[vid][UARTDM_CR]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001362 }
1363}
1364
1365#ifdef CONFIG_SERIAL_MSM_HSL_CONSOLE
1366static void msm_hsl_console_putchar(struct uart_port *port, int ch)
1367{
Sathish Ambley99e2a242011-10-25 15:49:53 -07001368 unsigned int vid = UART_TO_MSM(port)->ver_id;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001369
Stepan Moskovchenko9ec24842012-05-15 13:58:58 -07001370 wait_for_xmitr(port);
Sathish Ambley99e2a242011-10-25 15:49:53 -07001371 msm_hsl_write(port, 1, regmap[vid][UARTDM_NCF_TX]);
Mayank Ranaec41e932012-02-24 16:24:54 +05301372 /*
1373 * Dummy read to add 1 AHB clock delay to fix UART hardware bug.
1374 * Bug: Delay required on TX-transfer-init. after writing to
1375 * NO_CHARS_FOR_TX register.
1376 */
1377 msm_hsl_read(port, regmap[vid][UARTDM_SR]);
Sathish Ambley99e2a242011-10-25 15:49:53 -07001378 msm_hsl_write(port, ch, regmap[vid][UARTDM_TF]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001379}
1380
1381static void msm_hsl_console_write(struct console *co, const char *s,
1382 unsigned int count)
1383{
1384 struct uart_port *port;
1385 struct msm_hsl_port *msm_hsl_port;
Sathish Ambley99e2a242011-10-25 15:49:53 -07001386 unsigned int vid;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001387 int locked;
1388
1389 BUG_ON(co->index < 0 || co->index >= UART_NR);
1390
1391 port = get_port_from_line(co->index);
1392 msm_hsl_port = UART_TO_MSM(port);
Sathish Ambley99e2a242011-10-25 15:49:53 -07001393 vid = msm_hsl_port->ver_id;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001394
1395 /* not pretty, but we can end up here via various convoluted paths */
1396 if (port->sysrq || oops_in_progress)
1397 locked = spin_trylock(&port->lock);
1398 else {
1399 locked = 1;
1400 spin_lock(&port->lock);
1401 }
Sathish Ambley99e2a242011-10-25 15:49:53 -07001402 msm_hsl_write(port, 0, regmap[vid][UARTDM_IMR]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001403 uart_console_write(port, s, count, msm_hsl_console_putchar);
Sathish Ambley99e2a242011-10-25 15:49:53 -07001404 msm_hsl_write(port, msm_hsl_port->imr, regmap[vid][UARTDM_IMR]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001405 if (locked == 1)
1406 spin_unlock(&port->lock);
1407}
1408
Mayank Rana930c99c2011-09-05 18:22:02 +05301409static int msm_hsl_console_setup(struct console *co, char *options)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001410{
1411 struct uart_port *port;
Sathish Ambley99e2a242011-10-25 15:49:53 -07001412 unsigned int vid;
Stepan Moskovchenkoe4b0d792012-05-10 14:10:44 -07001413 int baud = 0, flow, bits, parity, mr2;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001414 int ret;
1415
1416 if (unlikely(co->index >= UART_NR || co->index < 0))
1417 return -ENXIO;
1418
1419 port = get_port_from_line(co->index);
Sathish Ambley99e2a242011-10-25 15:49:53 -07001420 vid = UART_TO_MSM(port)->ver_id;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001421
1422 if (unlikely(!port->membase))
1423 return -ENXIO;
1424
1425 port->cons = co;
1426
1427 pm_runtime_get_noresume(port->dev);
1428
1429#ifndef CONFIG_PM_RUNTIME
1430 msm_hsl_init_clock(port);
1431#endif
1432 pm_runtime_resume(port->dev);
1433
1434 if (options)
1435 uart_parse_options(options, &baud, &parity, &bits, &flow);
1436
1437 bits = 8;
1438 parity = 'n';
1439 flow = 'n';
1440 msm_hsl_write(port, UARTDM_MR2_BITS_PER_CHAR_8 | STOP_BIT_ONE,
Sathish Ambley99e2a242011-10-25 15:49:53 -07001441 regmap[vid][UARTDM_MR2]); /* 8N1 */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001442
1443 if (baud < 300 || baud > 115200)
1444 baud = 115200;
1445 msm_hsl_set_baud_rate(port, baud);
1446
1447 ret = uart_set_options(port, co, baud, parity, bits, flow);
Stepan Moskovchenkoe4b0d792012-05-10 14:10:44 -07001448
1449 mr2 = msm_hsl_read(port, regmap[vid][UARTDM_MR2]);
1450 mr2 |= UARTDM_MR2_RX_ERROR_CHAR_OFF;
1451 mr2 |= UARTDM_MR2_RX_BREAK_ZERO_CHAR_OFF;
1452 msm_hsl_write(port, mr2, regmap[vid][UARTDM_MR2]);
1453
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001454 msm_hsl_reset(port);
1455 /* Enable transmitter */
Sathish Ambley99e2a242011-10-25 15:49:53 -07001456 msm_hsl_write(port, CR_PROTECTION_EN, regmap[vid][UARTDM_CR]);
1457 msm_hsl_write(port, UARTDM_CR_TX_EN_BMSK, regmap[vid][UARTDM_CR]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001458
Stepan Moskovchenkof525c112012-05-15 14:10:26 -07001459 msm_hsl_write(port, 1, regmap[vid][UARTDM_NCF_TX]);
1460 msm_hsl_read(port, regmap[vid][UARTDM_NCF_TX]);
1461
Mayank Rana1295c082012-12-03 13:56:12 +05301462 pr_info("console setup on port #%d\n", port->line);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001463
1464 return ret;
1465}
1466
1467static struct uart_driver msm_hsl_uart_driver;
1468
1469static struct console msm_hsl_console = {
1470 .name = "ttyHSL",
1471 .write = msm_hsl_console_write,
1472 .device = uart_console_device,
1473 .setup = msm_hsl_console_setup,
1474 .flags = CON_PRINTBUFFER,
1475 .index = -1,
1476 .data = &msm_hsl_uart_driver,
1477};
1478
1479#define MSM_HSL_CONSOLE (&msm_hsl_console)
Mayank Rana930c99c2011-09-05 18:22:02 +05301480/*
1481 * get_console_state - check the per-port serial console state.
1482 * @port: uart_port structure describing the port
1483 *
1484 * Return the state of serial console availability on port.
1485 * return 1: If serial console is enabled on particular UART port.
1486 * return 0: If serial console is disabled on particular UART port.
1487 */
1488static int get_console_state(struct uart_port *port)
1489{
1490 if (is_console(port) && (port->cons->flags & CON_ENABLED))
1491 return 1;
1492 else
1493 return 0;
1494}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001495
Mayank Rana930c99c2011-09-05 18:22:02 +05301496/* show_msm_console - provide per-port serial console state. */
1497static ssize_t show_msm_console(struct device *dev,
1498 struct device_attribute *attr, char *buf)
1499{
1500 int enable;
1501 struct uart_port *port;
1502
1503 struct platform_device *pdev = to_platform_device(dev);
Stepan Moskovchenko798fe552012-03-29 19:47:19 -07001504 port = get_port_from_line(get_line(pdev));
Mayank Rana930c99c2011-09-05 18:22:02 +05301505
1506 enable = get_console_state(port);
1507
1508 return snprintf(buf, sizeof(enable), "%d\n", enable);
1509}
1510
1511/*
1512 * set_msm_console - allow to enable/disable serial console on port.
1513 *
1514 * writing 1 enables serial console on UART port.
1515 * writing 0 disables serial console on UART port.
1516 */
1517static ssize_t set_msm_console(struct device *dev,
1518 struct device_attribute *attr,
1519 const char *buf, size_t count)
1520{
1521 int enable, cur_state;
1522 struct uart_port *port;
1523
1524 struct platform_device *pdev = to_platform_device(dev);
Stepan Moskovchenko798fe552012-03-29 19:47:19 -07001525 port = get_port_from_line(get_line(pdev));
Mayank Rana930c99c2011-09-05 18:22:02 +05301526
1527 cur_state = get_console_state(port);
1528 enable = buf[0] - '0';
1529
1530 if (enable == cur_state)
1531 return count;
1532
1533 switch (enable) {
1534 case 0:
Mayank Rana1295c082012-12-03 13:56:12 +05301535 pr_debug("Calling stop_console\n");
Mayank Rana930c99c2011-09-05 18:22:02 +05301536 console_stop(port->cons);
Mayank Rana1295c082012-12-03 13:56:12 +05301537 pr_debug("Calling unregister_console\n");
Mayank Rana930c99c2011-09-05 18:22:02 +05301538 unregister_console(port->cons);
1539 pm_runtime_put_sync(&pdev->dev);
1540 pm_runtime_disable(&pdev->dev);
1541 /*
1542 * Disable UART Core clk
1543 * 3 - to disable the UART clock
1544 * Thid parameter is not used here, but used in serial core.
1545 */
1546 msm_hsl_power(port, 3, 1);
1547 break;
1548 case 1:
Mayank Rana1295c082012-12-03 13:56:12 +05301549 pr_debug("Calling register_console\n");
Mayank Rana930c99c2011-09-05 18:22:02 +05301550 /*
1551 * Disable UART Core clk
1552 * 0 - to enable the UART clock
1553 * Thid parameter is not used here, but used in serial core.
1554 */
1555 msm_hsl_power(port, 0, 1);
1556 pm_runtime_enable(&pdev->dev);
1557 register_console(port->cons);
1558 break;
1559 default:
1560 return -EINVAL;
1561 }
1562
1563 return count;
1564}
1565static DEVICE_ATTR(console, S_IWUSR | S_IRUGO, show_msm_console,
1566 set_msm_console);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001567#else
1568#define MSM_HSL_CONSOLE NULL
1569#endif
1570
1571static struct uart_driver msm_hsl_uart_driver = {
1572 .owner = THIS_MODULE,
1573 .driver_name = "msm_serial_hsl",
1574 .dev_name = "ttyHSL",
1575 .nr = UART_NR,
1576 .cons = MSM_HSL_CONSOLE,
1577};
1578
Mayank Rana9fc393d2012-12-04 19:10:36 +05301579static struct msm_serial_hslite_platform_data
1580 *msm_hsl_dt_to_pdata(struct platform_device *pdev)
1581{
1582 int ret;
1583 struct device_node *node = pdev->dev.of_node;
1584 struct msm_serial_hslite_platform_data *pdata;
1585
1586 pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
1587 if (!pdata) {
1588 pr_err("unable to allocate memory for platform data\n");
1589 return ERR_PTR(-ENOMEM);
1590 }
1591
1592 ret = of_property_read_u32(node, "qcom,config-gpio",
1593 &pdata->config_gpio);
1594 if (ret && ret != -EINVAL) {
1595 pr_err("Error with config_gpio property.\n");
1596 return ERR_PTR(ret);
1597 }
1598
1599 if (pdata->config_gpio) {
1600 pdata->uart_tx_gpio = of_get_named_gpio(node,
1601 "qcom,tx-gpio", 0);
1602 if (pdata->uart_tx_gpio < 0)
1603 return ERR_PTR(pdata->uart_tx_gpio);
1604
1605 pdata->uart_rx_gpio = of_get_named_gpio(node,
1606 "qcom,rx-gpio", 0);
1607 if (pdata->uart_rx_gpio < 0)
1608 return ERR_PTR(pdata->uart_rx_gpio);
1609
1610 /* check if 4-wire UART, then get cts/rfr GPIOs. */
1611 if (pdata->config_gpio == 4) {
1612 pdata->uart_cts_gpio = of_get_named_gpio(node,
1613 "qcom,cts-gpio", 0);
1614 if (pdata->uart_cts_gpio < 0)
1615 return ERR_PTR(pdata->uart_cts_gpio);
1616
1617 pdata->uart_rfr_gpio = of_get_named_gpio(node,
1618 "qcom,rfr-gpio", 0);
1619 if (pdata->uart_rfr_gpio < 0)
1620 return ERR_PTR(pdata->uart_rfr_gpio);
1621 }
1622 }
1623
1624 return pdata;
1625}
1626
Sathish Ambley3d50c762011-10-25 15:26:00 -07001627static atomic_t msm_serial_hsl_next_id = ATOMIC_INIT(0);
1628
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001629static int __devinit msm_serial_hsl_probe(struct platform_device *pdev)
1630{
1631 struct msm_hsl_port *msm_hsl_port;
1632 struct resource *uart_resource;
1633 struct resource *gsbi_resource;
1634 struct uart_port *port;
Mayank Rana9fc393d2012-12-04 19:10:36 +05301635 struct msm_serial_hslite_platform_data *pdata;
Sathish Ambley99e2a242011-10-25 15:49:53 -07001636 const struct of_device_id *match;
Stepan Moskovchenko5e023432012-10-25 18:44:17 -07001637 u32 line;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001638 int ret;
1639
Sathish Ambley3d50c762011-10-25 15:26:00 -07001640 if (pdev->id == -1)
1641 pdev->id = atomic_inc_return(&msm_serial_hsl_next_id) - 1;
1642
Stepan Moskovchenko5e023432012-10-25 18:44:17 -07001643 /* Use line (ttyHSLx) number from pdata or device tree if specified */
1644 pdata = pdev->dev.platform_data;
1645 if (pdata)
1646 line = pdata->line;
1647 else
1648 line = pdev->id;
1649
Stepan Moskovchenko37ac2582012-11-14 20:01:34 -08001650 /* Use line number from device tree alias if present */
1651 if (pdev->dev.of_node) {
Mayank Rana9fc393d2012-12-04 19:10:36 +05301652 dev_dbg(&pdev->dev, "device tree enabled\n");
Stepan Moskovchenko37ac2582012-11-14 20:01:34 -08001653 ret = of_alias_get_id(pdev->dev.of_node, "serial");
1654 if (ret >= 0)
1655 line = ret;
Mayank Rana9fc393d2012-12-04 19:10:36 +05301656
1657 pdata = msm_hsl_dt_to_pdata(pdev);
1658 if (IS_ERR(pdata))
1659 return PTR_ERR(pdata);
1660
1661 pdev->dev.platform_data = pdata;
Stepan Moskovchenko37ac2582012-11-14 20:01:34 -08001662 }
Stepan Moskovchenko5e023432012-10-25 18:44:17 -07001663
1664 if (unlikely(line < 0 || line >= UART_NR))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001665 return -ENXIO;
1666
Mayank Rana1295c082012-12-03 13:56:12 +05301667 pr_info("detected port #%d (ttyHSL%d)\n", pdev->id, line);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001668
Stepan Moskovchenko5e023432012-10-25 18:44:17 -07001669 port = get_port_from_line(line);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001670 port->dev = &pdev->dev;
Mayank Rana1295c082012-12-03 13:56:12 +05301671 port->uartclk = 7372800;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001672 msm_hsl_port = UART_TO_MSM(port);
1673
Mayank Rana9fc393d2012-12-04 19:10:36 +05301674 /* Identify UART functional mode as 2-wire or 4-wire. */
1675 if (pdata && pdata->config_gpio == 4)
1676 msm_hsl_port->func_mode = UART_FOUR_WIRE;
Sathish Ambley99e2a242011-10-25 15:49:53 -07001677 else
Mayank Rana9fc393d2012-12-04 19:10:36 +05301678 msm_hsl_port->func_mode = UART_TWO_WIRE;
1679
1680 match = of_match_device(msm_hsl_match_table, &pdev->dev);
1681 if (!match) {
1682 msm_hsl_port->ver_id = UARTDM_VERSION_11_13;
1683 } else {
Sathish Ambley99e2a242011-10-25 15:49:53 -07001684 msm_hsl_port->ver_id = (unsigned int)match->data;
Mayank Rana9fc393d2012-12-04 19:10:36 +05301685 /*
1686 * BLSP based UART configuration is available with
1687 * UARTDM v14 Revision. Hence set uart_type as UART_BLSP.
1688 */
1689 msm_hsl_port->uart_type = BLSP_HSUART;
1690 }
Sathish Ambley99e2a242011-10-25 15:49:53 -07001691
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001692 gsbi_resource = platform_get_resource_byname(pdev,
1693 IORESOURCE_MEM,
1694 "gsbi_resource");
Sathish Ambley3d50c762011-10-25 15:26:00 -07001695 if (!gsbi_resource)
1696 gsbi_resource = platform_get_resource(pdev, IORESOURCE_MEM, 1);
Matt Wagantalle2522372011-08-17 14:52:21 -07001697 msm_hsl_port->clk = clk_get(&pdev->dev, "core_clk");
Stepan Moskovchenko05d31ae2012-08-08 17:33:30 -07001698 msm_hsl_port->pclk = clk_get(&pdev->dev, "iface_clk");
1699
1700 if (gsbi_resource)
Mayank Rana9fc393d2012-12-04 19:10:36 +05301701 msm_hsl_port->uart_type = GSBI_HSUART;
Stepan Moskovchenko05d31ae2012-08-08 17:33:30 -07001702 else
Mayank Rana9fc393d2012-12-04 19:10:36 +05301703 msm_hsl_port->uart_type = LEGACY_HSUART;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001704
1705 if (unlikely(IS_ERR(msm_hsl_port->clk))) {
Mayank Rana1295c082012-12-03 13:56:12 +05301706 pr_err("Error getting clk\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001707 return PTR_ERR(msm_hsl_port->clk);
1708 }
1709 if (unlikely(IS_ERR(msm_hsl_port->pclk))) {
Mayank Rana1295c082012-12-03 13:56:12 +05301710 pr_err("Error getting pclk\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001711 return PTR_ERR(msm_hsl_port->pclk);
1712 }
1713
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001714 uart_resource = platform_get_resource_byname(pdev,
1715 IORESOURCE_MEM,
1716 "uartdm_resource");
Sathish Ambley3d50c762011-10-25 15:26:00 -07001717 if (!uart_resource)
1718 uart_resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001719 if (unlikely(!uart_resource)) {
Mayank Rana1295c082012-12-03 13:56:12 +05301720 pr_err("getting uartdm_resource failed\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001721 return -ENXIO;
1722 }
1723 port->mapbase = uart_resource->start;
1724
1725 port->irq = platform_get_irq(pdev, 0);
Mayank Rana72fef232011-09-28 12:42:57 +05301726 if (unlikely((int)port->irq < 0)) {
Mayank Rana1295c082012-12-03 13:56:12 +05301727 pr_err("getting irq failed\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001728 return -ENXIO;
1729 }
1730
1731 device_set_wakeup_capable(&pdev->dev, 1);
1732 platform_set_drvdata(pdev, port);
1733 pm_runtime_enable(port->dev);
Mayank Rana930c99c2011-09-05 18:22:02 +05301734#ifdef CONFIG_SERIAL_MSM_HSL_CONSOLE
1735 ret = device_create_file(&pdev->dev, &dev_attr_console);
1736 if (unlikely(ret))
Mayank Rana1295c082012-12-03 13:56:12 +05301737 pr_err("Can't create console attribute\n");
Mayank Rana930c99c2011-09-05 18:22:02 +05301738#endif
Stepan Moskovchenko798fe552012-03-29 19:47:19 -07001739 msm_hsl_debugfs_init(msm_hsl_port, get_line(pdev));
Mayank Rana44659372012-12-03 17:59:45 +05301740 mutex_init(&msm_hsl_port->clk_mutex);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001741
Stepan Moskovchenko72029d62011-08-23 17:08:55 -07001742 /* Temporarily increase the refcount on the GSBI clock to avoid a race
1743 * condition with the earlyprintk handover mechanism.
1744 */
1745 if (msm_hsl_port->pclk)
Mayank Rana5d0252a2012-01-24 13:58:43 +05301746 clk_prepare_enable(msm_hsl_port->pclk);
Stepan Moskovchenko72029d62011-08-23 17:08:55 -07001747 ret = uart_add_one_port(&msm_hsl_uart_driver, port);
1748 if (msm_hsl_port->pclk)
Mayank Rana5d0252a2012-01-24 13:58:43 +05301749 clk_disable_unprepare(msm_hsl_port->pclk);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001750 return ret;
1751}
1752
1753static int __devexit msm_serial_hsl_remove(struct platform_device *pdev)
1754{
1755 struct msm_hsl_port *msm_hsl_port = platform_get_drvdata(pdev);
1756 struct uart_port *port;
1757
Stepan Moskovchenko798fe552012-03-29 19:47:19 -07001758 port = get_port_from_line(get_line(pdev));
Mayank Rana930c99c2011-09-05 18:22:02 +05301759#ifdef CONFIG_SERIAL_MSM_HSL_CONSOLE
1760 device_remove_file(&pdev->dev, &dev_attr_console);
1761#endif
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001762 pm_runtime_put_sync(&pdev->dev);
1763 pm_runtime_disable(&pdev->dev);
1764
1765 device_set_wakeup_capable(&pdev->dev, 0);
1766 platform_set_drvdata(pdev, NULL);
Mayank Rana44659372012-12-03 17:59:45 +05301767 mutex_destroy(&msm_hsl_port->clk_mutex);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001768 uart_remove_one_port(&msm_hsl_uart_driver, port);
1769
1770 clk_put(msm_hsl_port->pclk);
1771 clk_put(msm_hsl_port->clk);
Mayank Rana8dddd752011-07-13 11:19:58 +05301772 debugfs_remove(msm_hsl_port->loopback_dir);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001773
1774 return 0;
1775}
1776
1777#ifdef CONFIG_PM
1778static int msm_serial_hsl_suspend(struct device *dev)
1779{
1780 struct platform_device *pdev = to_platform_device(dev);
1781 struct uart_port *port;
Stepan Moskovchenko798fe552012-03-29 19:47:19 -07001782 port = get_port_from_line(get_line(pdev));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001783
1784 if (port) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001785
1786 if (is_console(port))
1787 msm_hsl_deinit_clock(port);
Mayank Rana70a8e7d2011-09-02 14:29:18 +05301788
1789 uart_suspend_port(&msm_hsl_uart_driver, port);
1790 if (device_may_wakeup(dev))
1791 enable_irq_wake(port->irq);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001792 }
1793
1794 return 0;
1795}
1796
1797static int msm_serial_hsl_resume(struct device *dev)
1798{
1799 struct platform_device *pdev = to_platform_device(dev);
1800 struct uart_port *port;
Stepan Moskovchenko798fe552012-03-29 19:47:19 -07001801 port = get_port_from_line(get_line(pdev));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001802
1803 if (port) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001804
Mayank Rana70a8e7d2011-09-02 14:29:18 +05301805 uart_resume_port(&msm_hsl_uart_driver, port);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001806 if (device_may_wakeup(dev))
1807 disable_irq_wake(port->irq);
Mayank Rana70a8e7d2011-09-02 14:29:18 +05301808
1809 if (is_console(port))
1810 msm_hsl_init_clock(port);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001811 }
1812
1813 return 0;
1814}
1815#else
1816#define msm_serial_hsl_suspend NULL
1817#define msm_serial_hsl_resume NULL
1818#endif
1819
1820static int msm_hsl_runtime_suspend(struct device *dev)
1821{
1822 struct platform_device *pdev = to_platform_device(dev);
1823 struct uart_port *port;
Stepan Moskovchenko798fe552012-03-29 19:47:19 -07001824 port = get_port_from_line(get_line(pdev));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001825
1826 dev_dbg(dev, "pm_runtime: suspending\n");
1827 msm_hsl_deinit_clock(port);
1828 return 0;
1829}
1830
1831static int msm_hsl_runtime_resume(struct device *dev)
1832{
1833 struct platform_device *pdev = to_platform_device(dev);
1834 struct uart_port *port;
Stepan Moskovchenko798fe552012-03-29 19:47:19 -07001835 port = get_port_from_line(get_line(pdev));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001836
1837 dev_dbg(dev, "pm_runtime: resuming\n");
1838 msm_hsl_init_clock(port);
1839 return 0;
1840}
1841
1842static struct dev_pm_ops msm_hsl_dev_pm_ops = {
1843 .suspend = msm_serial_hsl_suspend,
1844 .resume = msm_serial_hsl_resume,
1845 .runtime_suspend = msm_hsl_runtime_suspend,
1846 .runtime_resume = msm_hsl_runtime_resume,
1847};
1848
1849static struct platform_driver msm_hsl_platform_driver = {
1850 .probe = msm_serial_hsl_probe,
1851 .remove = __devexit_p(msm_serial_hsl_remove),
1852 .driver = {
1853 .name = "msm_serial_hsl",
1854 .owner = THIS_MODULE,
1855 .pm = &msm_hsl_dev_pm_ops,
Sathish Ambley3d50c762011-10-25 15:26:00 -07001856 .of_match_table = msm_hsl_match_table,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001857 },
1858};
1859
1860static int __init msm_serial_hsl_init(void)
1861{
1862 int ret;
1863
1864 ret = uart_register_driver(&msm_hsl_uart_driver);
1865 if (unlikely(ret))
1866 return ret;
1867
Mayank Rana8dddd752011-07-13 11:19:58 +05301868 debug_base = debugfs_create_dir("msm_serial_hsl", NULL);
1869 if (IS_ERR_OR_NULL(debug_base))
Mayank Rana1295c082012-12-03 13:56:12 +05301870 pr_err("Cannot create debugfs dir\n");
Mayank Rana8dddd752011-07-13 11:19:58 +05301871
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001872 ret = platform_driver_register(&msm_hsl_platform_driver);
1873 if (unlikely(ret))
1874 uart_unregister_driver(&msm_hsl_uart_driver);
1875
Mayank Rana1295c082012-12-03 13:56:12 +05301876 pr_info("driver initialized\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001877
1878 return ret;
1879}
1880
1881static void __exit msm_serial_hsl_exit(void)
1882{
Mayank Rana8dddd752011-07-13 11:19:58 +05301883 debugfs_remove_recursive(debug_base);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001884#ifdef CONFIG_SERIAL_MSM_HSL_CONSOLE
1885 unregister_console(&msm_hsl_console);
1886#endif
1887 platform_driver_unregister(&msm_hsl_platform_driver);
1888 uart_unregister_driver(&msm_hsl_uart_driver);
1889}
1890
1891module_init(msm_serial_hsl_init);
1892module_exit(msm_serial_hsl_exit);
1893
1894MODULE_DESCRIPTION("Driver for msm HSUART serial device");
1895MODULE_LICENSE("GPL v2");