blob: a4a4f285cfe6ab1f0a1c012f4b00382fa1a8a8ea [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 Rana965e9e72013-02-22 12:14:14 +05305 * Copyright (c) 2010-2013, The Linux Foundation. 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>
Mayank Ranaa9c20892012-12-13 11:35:52 +053049#include <linux/wakelock.h>
dgaribalbccaa9a2013-07-17 15:31:52 -070050#include <linux/types.h>
51#include <asm/byteorder.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070052#include <mach/board.h>
53#include <mach/msm_serial_hs_lite.h>
Mayank Rana0e05b8b2013-01-22 17:14:40 +053054#include <mach/msm_bus.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070055#include <asm/mach-types.h>
56#include "msm_serial_hs_hwreg.h"
57
Mayank Rana9fc393d2012-12-04 19:10:36 +053058/*
59 * There are 3 different kind of UART Core available on MSM.
60 * High Speed UART (i.e. Legacy HSUART), GSBI based HSUART
61 * and BSLP based HSUART.
62 */
63enum uart_core_type {
64 LEGACY_HSUART,
65 GSBI_HSUART,
66 BLSP_HSUART,
67};
68
69/*
70 * UART can be used in 2-wire or 4-wire mode.
71 * Use uart_func_mode to set 2-wire or 4-wire mode.
72 */
73enum uart_func_mode {
74 UART_TWO_WIRE, /* can't support HW Flow control. */
75 UART_FOUR_WIRE,/* can support HW Flow control. */
76};
77
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070078struct msm_hsl_port {
79 struct uart_port uart;
80 char name[16];
81 struct clk *clk;
82 struct clk *pclk;
Mayank Rana8dddd752011-07-13 11:19:58 +053083 struct dentry *loopback_dir;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070084 unsigned int imr;
85 unsigned int *uart_csr_code;
86 unsigned int *gsbi_mapbase;
87 unsigned int *mapped_gsbi;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070088 unsigned int old_snap_state;
Sathish Ambley99e2a242011-10-25 15:49:53 -070089 unsigned int ver_id;
Stepan Moskovchenko1d4731e2012-02-21 20:18:23 -080090 int tx_timeout;
Mayank Rana44659372012-12-03 17:59:45 +053091 struct mutex clk_mutex;
Mayank Rana9fc393d2012-12-04 19:10:36 +053092 enum uart_core_type uart_type;
93 enum uart_func_mode func_mode;
Mayank Ranaa9c20892012-12-13 11:35:52 +053094 struct wake_lock port_open_wake_lock;
Mayank Rana0e05b8b2013-01-22 17:14:40 +053095 int clk_enable_count;
96 u32 bus_perf_client;
97 /* BLSP UART required BUS Scaling data */
98 struct msm_bus_scale_pdata *bus_scale_table;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070099};
100
Sathish Ambley99e2a242011-10-25 15:49:53 -0700101#define UARTDM_VERSION_11_13 0
102#define UARTDM_VERSION_14 1
103
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700104#define UART_TO_MSM(uart_port) ((struct msm_hsl_port *) uart_port)
105#define is_console(port) ((port)->cons && \
106 (port)->cons->index == (port)->line)
Sathish Ambley99e2a242011-10-25 15:49:53 -0700107
108static const unsigned int regmap[][UARTDM_LAST] = {
109 [UARTDM_VERSION_11_13] = {
110 [UARTDM_MR1] = UARTDM_MR1_ADDR,
111 [UARTDM_MR2] = UARTDM_MR2_ADDR,
112 [UARTDM_IMR] = UARTDM_IMR_ADDR,
113 [UARTDM_SR] = UARTDM_SR_ADDR,
114 [UARTDM_CR] = UARTDM_CR_ADDR,
115 [UARTDM_CSR] = UARTDM_CSR_ADDR,
116 [UARTDM_IPR] = UARTDM_IPR_ADDR,
117 [UARTDM_ISR] = UARTDM_ISR_ADDR,
118 [UARTDM_RX_TOTAL_SNAP] = UARTDM_RX_TOTAL_SNAP_ADDR,
119 [UARTDM_TFWR] = UARTDM_TFWR_ADDR,
120 [UARTDM_RFWR] = UARTDM_RFWR_ADDR,
121 [UARTDM_RF] = UARTDM_RF_ADDR,
122 [UARTDM_TF] = UARTDM_TF_ADDR,
123 [UARTDM_MISR] = UARTDM_MISR_ADDR,
124 [UARTDM_DMRX] = UARTDM_DMRX_ADDR,
125 [UARTDM_NCF_TX] = UARTDM_NCF_TX_ADDR,
126 [UARTDM_DMEN] = UARTDM_DMEN_ADDR,
Stepan Moskovchenko1d4731e2012-02-21 20:18:23 -0800127 [UARTDM_TXFS] = UARTDM_TXFS_ADDR,
128 [UARTDM_RXFS] = UARTDM_RXFS_ADDR,
Sathish Ambley99e2a242011-10-25 15:49:53 -0700129 },
130 [UARTDM_VERSION_14] = {
131 [UARTDM_MR1] = 0x0,
132 [UARTDM_MR2] = 0x4,
133 [UARTDM_IMR] = 0xb0,
134 [UARTDM_SR] = 0xa4,
135 [UARTDM_CR] = 0xa8,
136 [UARTDM_CSR] = 0xa0,
137 [UARTDM_IPR] = 0x18,
138 [UARTDM_ISR] = 0xb4,
139 [UARTDM_RX_TOTAL_SNAP] = 0xbc,
140 [UARTDM_TFWR] = 0x1c,
141 [UARTDM_RFWR] = 0x20,
142 [UARTDM_RF] = 0x140,
143 [UARTDM_TF] = 0x100,
144 [UARTDM_MISR] = 0xac,
145 [UARTDM_DMRX] = 0x34,
146 [UARTDM_NCF_TX] = 0x40,
147 [UARTDM_DMEN] = 0x3c,
Stepan Moskovchenko1d4731e2012-02-21 20:18:23 -0800148 [UARTDM_TXFS] = 0x4c,
149 [UARTDM_RXFS] = 0x50,
Sathish Ambley99e2a242011-10-25 15:49:53 -0700150 },
151};
152
Sathish Ambley3d50c762011-10-25 15:26:00 -0700153static struct of_device_id msm_hsl_match_table[] = {
Sathish Ambley99e2a242011-10-25 15:49:53 -0700154 { .compatible = "qcom,msm-lsuart-v14",
155 .data = (void *)UARTDM_VERSION_14
156 },
Sathish Ambley3d50c762011-10-25 15:26:00 -0700157 {}
158};
Stepan Moskovchenko51fc4e62012-06-19 17:04:21 -0700159
160#ifdef CONFIG_SERIAL_MSM_HSL_CONSOLE
161static int get_console_state(struct uart_port *port);
162#else
163static inline int get_console_state(struct uart_port *port) { return -ENODEV; };
164#endif
165
Mayank Rana8dddd752011-07-13 11:19:58 +0530166static struct dentry *debug_base;
Stepan Moskovchenko9ec24842012-05-15 13:58:58 -0700167static inline void wait_for_xmitr(struct uart_port *port);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700168static inline void msm_hsl_write(struct uart_port *port,
169 unsigned int val, unsigned int off)
170{
dgaribalbccaa9a2013-07-17 15:31:52 -0700171 __iowmb();
172 __raw_writel_no_log((__force __u32)cpu_to_le32(val),
173 port->membase + off);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700174}
175static inline unsigned int msm_hsl_read(struct uart_port *port,
176 unsigned int off)
177{
dgaribalbccaa9a2013-07-17 15:31:52 -0700178 unsigned int v = le32_to_cpu((__force __le32)__raw_readl_no_log(
179 port->membase + off));
180 __iormb();
181 return v;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700182}
183
184static unsigned int msm_serial_hsl_has_gsbi(struct uart_port *port)
185{
Mayank Rana9fc393d2012-12-04 19:10:36 +0530186 return (UART_TO_MSM(port)->uart_type == GSBI_HSUART);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700187}
188
Mayank Rana9fc393d2012-12-04 19:10:36 +0530189/**
190 * set_gsbi_uart_func_mode: Check the currently used GSBI UART mode
191 * and set the new required GSBI UART Mode if it is different.
192 * @port: uart port
193 */
194static void set_gsbi_uart_func_mode(struct uart_port *port)
195{
196 struct msm_hsl_port *msm_hsl_port = UART_TO_MSM(port);
197 unsigned int set_gsbi_uart_mode = GSBI_PROTOCOL_I2C_UART;
198 unsigned int cur_gsbi_uart_mode;
199
200 if (msm_hsl_port->func_mode == UART_FOUR_WIRE)
201 set_gsbi_uart_mode = GSBI_PROTOCOL_UART;
202
203 if (msm_hsl_port->pclk)
204 clk_prepare_enable(msm_hsl_port->pclk);
205
206 /* Read current used GSBI UART Mode and set only if it is different. */
207 cur_gsbi_uart_mode = ioread32(msm_hsl_port->mapped_gsbi +
208 GSBI_CONTROL_ADDR);
209 if ((cur_gsbi_uart_mode & set_gsbi_uart_mode) != set_gsbi_uart_mode)
210 /*
211 * Programmed GSBI based UART protocol mode i.e. I2C/UART
212 * Shared Mode or UART Mode.
213 */
214 iowrite32(set_gsbi_uart_mode,
215 msm_hsl_port->mapped_gsbi + GSBI_CONTROL_ADDR);
216
217 if (msm_hsl_port->pclk)
218 clk_disable_unprepare(msm_hsl_port->pclk);
219}
220
221/**
222 * msm_hsl_config_uart_tx_rx_gpios - Configures UART Tx and RX GPIOs
223 * @port: uart port
224 */
225static int msm_hsl_config_uart_tx_rx_gpios(struct uart_port *port)
226{
227 struct platform_device *pdev = to_platform_device(port->dev);
228 const struct msm_serial_hslite_platform_data *pdata =
229 pdev->dev.platform_data;
230 int ret;
231
232 if (pdata) {
233 ret = gpio_request(pdata->uart_tx_gpio,
234 "UART_TX_GPIO");
235 if (unlikely(ret)) {
236 pr_err("gpio request failed for:%d\n",
237 pdata->uart_tx_gpio);
238 goto exit_uart_config;
239 }
240
241 ret = gpio_request(pdata->uart_rx_gpio, "UART_RX_GPIO");
242 if (unlikely(ret)) {
243 pr_err("gpio request failed for:%d\n",
244 pdata->uart_rx_gpio);
245 gpio_free(pdata->uart_tx_gpio);
246 goto exit_uart_config;
247 }
248 } else {
249 pr_err("Pdata is NULL.\n");
250 ret = -EINVAL;
251 }
252
253exit_uart_config:
254 return ret;
255}
256
257/**
258 * msm_hsl_unconfig_uart_tx_rx_gpios: Unconfigures UART Tx and RX GPIOs
259 * @port: uart port
260 */
261static void msm_hsl_unconfig_uart_tx_rx_gpios(struct uart_port *port)
262{
263 struct platform_device *pdev = to_platform_device(port->dev);
264 const struct msm_serial_hslite_platform_data *pdata =
265 pdev->dev.platform_data;
266
267 if (pdata) {
268 gpio_free(pdata->uart_tx_gpio);
269 gpio_free(pdata->uart_rx_gpio);
270 } else {
271 pr_err("Error:Pdata is NULL.\n");
272 }
273}
274
275/**
276 * msm_hsl_config_uart_hwflow_gpios: Configures UART HWFlow GPIOs
277 * @port: uart port
278 */
279static int msm_hsl_config_uart_hwflow_gpios(struct uart_port *port)
280{
281 struct platform_device *pdev = to_platform_device(port->dev);
282 const struct msm_serial_hslite_platform_data *pdata =
283 pdev->dev.platform_data;
284 int ret = -EINVAL;
285
286 if (pdata) {
287 ret = gpio_request(pdata->uart_cts_gpio,
288 "UART_CTS_GPIO");
289 if (unlikely(ret)) {
290 pr_err("gpio request failed for:%d\n",
291 pdata->uart_cts_gpio);
292 goto exit_config_uart;
293 }
294
295 ret = gpio_request(pdata->uart_rfr_gpio,
296 "UART_RFR_GPIO");
297 if (unlikely(ret)) {
298 pr_err("gpio request failed for:%d\n",
299 pdata->uart_rfr_gpio);
300 gpio_free(pdata->uart_cts_gpio);
301 goto exit_config_uart;
302 }
303 } else {
304 pr_err("Error: Pdata is NULL.\n");
305 }
306
307exit_config_uart:
308 return ret;
309}
310
311/**
312 * msm_hsl_unconfig_uart_hwflow_gpios: Unonfigures UART HWFlow GPIOs
313 * @port: uart port
314 */
315static void msm_hsl_unconfig_uart_hwflow_gpios(struct uart_port *port)
316{
317 struct platform_device *pdev = to_platform_device(port->dev);
318 const struct msm_serial_hslite_platform_data *pdata =
319 pdev->dev.platform_data;
320
321 if (pdata) {
322 gpio_free(pdata->uart_cts_gpio);
323 gpio_free(pdata->uart_rfr_gpio);
324 } else {
325 pr_err("Error: Pdata is NULL.\n");
326 }
327
328}
329
330/**
331 * msm_hsl_config_uart_gpios: Configures UART GPIOs and returns success or
332 * Failure
333 * @port: uart port
334 */
335static int msm_hsl_config_uart_gpios(struct uart_port *port)
336{
337 struct msm_hsl_port *msm_hsl_port = UART_TO_MSM(port);
338 int ret;
339
340 /* Configure UART Tx and Rx GPIOs */
341 ret = msm_hsl_config_uart_tx_rx_gpios(port);
342 if (!ret) {
343 if (msm_hsl_port->func_mode == UART_FOUR_WIRE) {
344 /*if 4-wire uart, configure CTS and RFR GPIOs */
345 ret = msm_hsl_config_uart_hwflow_gpios(port);
346 if (ret)
347 msm_hsl_unconfig_uart_tx_rx_gpios(port);
348 }
349 } else {
350 msm_hsl_unconfig_uart_tx_rx_gpios(port);
351 }
352
353 return ret;
354}
355
356/**
357 * msm_hsl_unconfig_uart_gpios: Unconfigures UART GPIOs
358 * @port: uart port
359 */
360static void msm_hsl_unconfig_uart_gpios(struct uart_port *port)
361{
362 struct msm_hsl_port *msm_hsl_port = UART_TO_MSM(port);
363
364 msm_hsl_unconfig_uart_tx_rx_gpios(port);
365 if (msm_hsl_port->func_mode == UART_FOUR_WIRE)
366 msm_hsl_unconfig_uart_hwflow_gpios(port);
367}
Stepan Moskovchenko798fe552012-03-29 19:47:19 -0700368static int get_line(struct platform_device *pdev)
369{
Stepan Moskovchenko5e023432012-10-25 18:44:17 -0700370 struct msm_hsl_port *msm_hsl_port = platform_get_drvdata(pdev);
Stepan Moskovchenko5e023432012-10-25 18:44:17 -0700371 return msm_hsl_port->uart.line;
Stepan Moskovchenko798fe552012-03-29 19:47:19 -0700372}
373
Vikram Mulukutla10db36a2013-04-28 08:44:53 -0700374static int bus_vote(uint32_t client, int vector)
375{
376 int ret = 0;
377
378 if (!client)
379 return ret;
380
381 pr_debug("Voting for bus scaling:%d\n", vector);
382
383 ret = msm_bus_scale_client_update_request(client, vector);
384 if (ret)
385 pr_err("Failed to request bus bw vector %d\n", vector);
386
387 return ret;
388}
389
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700390static int clk_en(struct uart_port *port, int enable)
391{
392 struct msm_hsl_port *msm_hsl_port = UART_TO_MSM(port);
393 int ret = 0;
394
395 if (enable) {
396
Mayank Rana0e05b8b2013-01-22 17:14:40 +0530397 msm_hsl_port->clk_enable_count++;
Vikram Mulukutla10db36a2013-04-28 08:44:53 -0700398 ret = bus_vote(msm_hsl_port->bus_perf_client,
399 !!msm_hsl_port->clk_enable_count);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700400 if (ret)
401 goto err;
Vikram Mulukutla10db36a2013-04-28 08:44:53 -0700402 ret = clk_prepare_enable(msm_hsl_port->clk);
403 if (ret)
404 goto err_bus;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700405 if (msm_hsl_port->pclk) {
Mayank Rana5d0252a2012-01-24 13:58:43 +0530406 ret = clk_prepare_enable(msm_hsl_port->pclk);
Mayank Rana0e05b8b2013-01-22 17:14:40 +0530407 if (ret)
408 goto err_clk_disable;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700409 }
410 } else {
Mayank Rana5d0252a2012-01-24 13:58:43 +0530411
Mayank Rana0e05b8b2013-01-22 17:14:40 +0530412 msm_hsl_port->clk_enable_count--;
Mayank Rana5d0252a2012-01-24 13:58:43 +0530413 clk_disable_unprepare(msm_hsl_port->clk);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700414 if (msm_hsl_port->pclk)
Mayank Rana5d0252a2012-01-24 13:58:43 +0530415 clk_disable_unprepare(msm_hsl_port->pclk);
Vikram Mulukutla10db36a2013-04-28 08:44:53 -0700416 ret = bus_vote(msm_hsl_port->bus_perf_client,
Mayank Rana0e05b8b2013-01-22 17:14:40 +0530417 !!msm_hsl_port->clk_enable_count);
Mayank Rana0e05b8b2013-01-22 17:14:40 +0530418 }
419
420 return ret;
421
422err_clk_disable:
423 clk_disable_unprepare(msm_hsl_port->clk);
Vikram Mulukutla10db36a2013-04-28 08:44:53 -0700424err_bus:
425 bus_vote(msm_hsl_port->bus_perf_client,
426 !!(msm_hsl_port->clk_enable_count - 1));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700427err:
Mayank Rana0e05b8b2013-01-22 17:14:40 +0530428 msm_hsl_port->clk_enable_count--;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700429 return ret;
430}
Mayank Rana8dddd752011-07-13 11:19:58 +0530431static int msm_hsl_loopback_enable_set(void *data, u64 val)
432{
433 struct msm_hsl_port *msm_hsl_port = data;
434 struct uart_port *port = &(msm_hsl_port->uart);
Sathish Ambley99e2a242011-10-25 15:49:53 -0700435 unsigned int vid;
Mayank Rana8dddd752011-07-13 11:19:58 +0530436 unsigned long flags;
437 int ret = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700438
Mayank Rana1295c082012-12-03 13:56:12 +0530439 ret = clk_set_rate(msm_hsl_port->clk, port->uartclk);
440 if (!ret) {
Mayank Rana8dddd752011-07-13 11:19:58 +0530441 clk_en(port, 1);
Mayank Rana1295c082012-12-03 13:56:12 +0530442 } else {
443 pr_err("Error: setting uartclk rate as %u\n",
444 port->uartclk);
Mayank Rana8dddd752011-07-13 11:19:58 +0530445 return -EINVAL;
446 }
447
Sathish Ambley99e2a242011-10-25 15:49:53 -0700448 vid = msm_hsl_port->ver_id;
Mayank Rana8dddd752011-07-13 11:19:58 +0530449 if (val) {
450 spin_lock_irqsave(&port->lock, flags);
Sathish Ambley99e2a242011-10-25 15:49:53 -0700451 ret = msm_hsl_read(port, regmap[vid][UARTDM_MR2]);
Mayank Rana8dddd752011-07-13 11:19:58 +0530452 ret |= UARTDM_MR2_LOOP_MODE_BMSK;
Sathish Ambley99e2a242011-10-25 15:49:53 -0700453 msm_hsl_write(port, ret, regmap[vid][UARTDM_MR2]);
Mayank Rana8dddd752011-07-13 11:19:58 +0530454 spin_unlock_irqrestore(&port->lock, flags);
455 } else {
456 spin_lock_irqsave(&port->lock, flags);
Sathish Ambley99e2a242011-10-25 15:49:53 -0700457 ret = msm_hsl_read(port, regmap[vid][UARTDM_MR2]);
Mayank Rana8dddd752011-07-13 11:19:58 +0530458 ret &= ~UARTDM_MR2_LOOP_MODE_BMSK;
Sathish Ambley99e2a242011-10-25 15:49:53 -0700459 msm_hsl_write(port, ret, regmap[vid][UARTDM_MR2]);
Mayank Rana8dddd752011-07-13 11:19:58 +0530460 spin_unlock_irqrestore(&port->lock, flags);
461 }
462
463 clk_en(port, 0);
464 return 0;
465}
466static int msm_hsl_loopback_enable_get(void *data, u64 *val)
467{
468 struct msm_hsl_port *msm_hsl_port = data;
469 struct uart_port *port = &(msm_hsl_port->uart);
470 unsigned long flags;
471 int ret = 0;
472
Mayank Rana1295c082012-12-03 13:56:12 +0530473 ret = clk_set_rate(msm_hsl_port->clk, port->uartclk);
474 if (!ret) {
Mayank Rana8dddd752011-07-13 11:19:58 +0530475 clk_en(port, 1);
Mayank Rana1295c082012-12-03 13:56:12 +0530476 } else {
477 pr_err("Error setting uartclk rate as %u\n",
478 port->uartclk);
Mayank Rana8dddd752011-07-13 11:19:58 +0530479 return -EINVAL;
480 }
481
482 spin_lock_irqsave(&port->lock, flags);
Sathish Ambley99e2a242011-10-25 15:49:53 -0700483 ret = msm_hsl_read(port, regmap[msm_hsl_port->ver_id][UARTDM_MR2]);
Mayank Rana8dddd752011-07-13 11:19:58 +0530484 spin_unlock_irqrestore(&port->lock, flags);
485 clk_en(port, 0);
486
487 *val = (ret & UARTDM_MR2_LOOP_MODE_BMSK) ? 1 : 0;
488 return 0;
489}
490DEFINE_SIMPLE_ATTRIBUTE(loopback_enable_fops, msm_hsl_loopback_enable_get,
491 msm_hsl_loopback_enable_set, "%llu\n");
492/*
493 * msm_serial_hsl debugfs node: <debugfs_root>/msm_serial_hsl/loopback.<id>
494 * writing 1 turns on internal loopback mode in HW. Useful for automation
495 * test scripts.
496 * writing 0 disables the internal loopback mode. Default is disabled.
497 */
498static void msm_hsl_debugfs_init(struct msm_hsl_port *msm_uport,
499 int id)
500{
501 char node_name[15];
502
503 snprintf(node_name, sizeof(node_name), "loopback.%d", id);
504 msm_uport->loopback_dir = debugfs_create_file(node_name,
505 S_IRUGO | S_IWUSR,
506 debug_base,
507 msm_uport,
508 &loopback_enable_fops);
509
510 if (IS_ERR_OR_NULL(msm_uport->loopback_dir))
Mayank Rana1295c082012-12-03 13:56:12 +0530511 pr_err("Cannot create loopback.%d debug entry", id);
Mayank Rana8dddd752011-07-13 11:19:58 +0530512}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700513static void msm_hsl_stop_tx(struct uart_port *port)
514{
515 struct msm_hsl_port *msm_hsl_port = UART_TO_MSM(port);
516
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700517 msm_hsl_port->imr &= ~UARTDM_ISR_TXLEV_BMSK;
Sathish Ambley99e2a242011-10-25 15:49:53 -0700518 msm_hsl_write(port, msm_hsl_port->imr,
519 regmap[msm_hsl_port->ver_id][UARTDM_IMR]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700520}
521
522static void msm_hsl_start_tx(struct uart_port *port)
523{
524 struct msm_hsl_port *msm_hsl_port = UART_TO_MSM(port);
525
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700526 msm_hsl_port->imr |= UARTDM_ISR_TXLEV_BMSK;
Sathish Ambley99e2a242011-10-25 15:49:53 -0700527 msm_hsl_write(port, msm_hsl_port->imr,
528 regmap[msm_hsl_port->ver_id][UARTDM_IMR]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700529}
530
531static void msm_hsl_stop_rx(struct uart_port *port)
532{
533 struct msm_hsl_port *msm_hsl_port = UART_TO_MSM(port);
534
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700535 msm_hsl_port->imr &= ~(UARTDM_ISR_RXLEV_BMSK |
536 UARTDM_ISR_RXSTALE_BMSK);
Sathish Ambley99e2a242011-10-25 15:49:53 -0700537 msm_hsl_write(port, msm_hsl_port->imr,
538 regmap[msm_hsl_port->ver_id][UARTDM_IMR]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700539}
540
541static void msm_hsl_enable_ms(struct uart_port *port)
542{
543 struct msm_hsl_port *msm_hsl_port = UART_TO_MSM(port);
544
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700545 msm_hsl_port->imr |= UARTDM_ISR_DELTA_CTS_BMSK;
Sathish Ambley99e2a242011-10-25 15:49:53 -0700546 msm_hsl_write(port, msm_hsl_port->imr,
547 regmap[msm_hsl_port->ver_id][UARTDM_IMR]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700548}
549
550static void handle_rx(struct uart_port *port, unsigned int misr)
551{
552 struct tty_struct *tty = port->state->port.tty;
Sathish Ambley99e2a242011-10-25 15:49:53 -0700553 unsigned int vid;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700554 unsigned int sr;
555 int count = 0;
556 struct msm_hsl_port *msm_hsl_port = UART_TO_MSM(port);
557
Sathish Ambley99e2a242011-10-25 15:49:53 -0700558 vid = msm_hsl_port->ver_id;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700559 /*
560 * Handle overrun. My understanding of the hardware is that overrun
561 * is not tied to the RX buffer, so we handle the case out of band.
562 */
Sathish Ambley99e2a242011-10-25 15:49:53 -0700563 if ((msm_hsl_read(port, regmap[vid][UARTDM_SR]) &
564 UARTDM_SR_OVERRUN_BMSK)) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700565 port->icount.overrun++;
566 tty_insert_flip_char(tty, 0, TTY_OVERRUN);
Sathish Ambley99e2a242011-10-25 15:49:53 -0700567 msm_hsl_write(port, RESET_ERROR_STATUS,
568 regmap[vid][UARTDM_CR]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700569 }
570
571 if (misr & UARTDM_ISR_RXSTALE_BMSK) {
Sathish Ambley99e2a242011-10-25 15:49:53 -0700572 count = msm_hsl_read(port,
573 regmap[vid][UARTDM_RX_TOTAL_SNAP]) -
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700574 msm_hsl_port->old_snap_state;
575 msm_hsl_port->old_snap_state = 0;
576 } else {
Sathish Ambley99e2a242011-10-25 15:49:53 -0700577 count = 4 * (msm_hsl_read(port, regmap[vid][UARTDM_RFWR]));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700578 msm_hsl_port->old_snap_state += count;
579 }
580
581 /* and now the main RX loop */
582 while (count > 0) {
583 unsigned int c;
584 char flag = TTY_NORMAL;
585
Sathish Ambley99e2a242011-10-25 15:49:53 -0700586 sr = msm_hsl_read(port, regmap[vid][UARTDM_SR]);
587 if ((sr & UARTDM_SR_RXRDY_BMSK) == 0) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700588 msm_hsl_port->old_snap_state -= count;
589 break;
590 }
Sathish Ambley99e2a242011-10-25 15:49:53 -0700591 c = msm_hsl_read(port, regmap[vid][UARTDM_RF]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700592 if (sr & UARTDM_SR_RX_BREAK_BMSK) {
593 port->icount.brk++;
594 if (uart_handle_break(port))
595 continue;
596 } else if (sr & UARTDM_SR_PAR_FRAME_BMSK) {
597 port->icount.frame++;
598 } else {
599 port->icount.rx++;
600 }
601
602 /* Mask conditions we're ignorning. */
603 sr &= port->read_status_mask;
604 if (sr & UARTDM_SR_RX_BREAK_BMSK)
605 flag = TTY_BREAK;
606 else if (sr & UARTDM_SR_PAR_FRAME_BMSK)
607 flag = TTY_FRAME;
608
609 /* TODO: handle sysrq */
610 /* if (!uart_handle_sysrq_char(port, c)) */
611 tty_insert_flip_string(tty, (char *) &c,
612 (count > 4) ? 4 : count);
613 count -= 4;
614 }
615
616 tty_flip_buffer_push(tty);
617}
618
619static void handle_tx(struct uart_port *port)
620{
621 struct circ_buf *xmit = &port->state->xmit;
622 int sent_tx;
623 int tx_count;
624 int x;
625 unsigned int tf_pointer = 0;
Sathish Ambley99e2a242011-10-25 15:49:53 -0700626 unsigned int vid;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700627
Sathish Ambley99e2a242011-10-25 15:49:53 -0700628 vid = UART_TO_MSM(port)->ver_id;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700629 tx_count = uart_circ_chars_pending(xmit);
630
631 if (tx_count > (UART_XMIT_SIZE - xmit->tail))
632 tx_count = UART_XMIT_SIZE - xmit->tail;
633 if (tx_count >= port->fifosize)
634 tx_count = port->fifosize;
635
636 /* Handle x_char */
637 if (port->x_char) {
Stepan Moskovchenko9ec24842012-05-15 13:58:58 -0700638 wait_for_xmitr(port);
Stepan Moskovchenko4f1025f2012-05-15 13:00:05 -0700639 msm_hsl_write(port, tx_count + 1, regmap[vid][UARTDM_NCF_TX]);
640 msm_hsl_read(port, regmap[vid][UARTDM_NCF_TX]);
Sathish Ambley99e2a242011-10-25 15:49:53 -0700641 msm_hsl_write(port, port->x_char, regmap[vid][UARTDM_TF]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700642 port->icount.tx++;
643 port->x_char = 0;
644 } else if (tx_count) {
Stepan Moskovchenko9ec24842012-05-15 13:58:58 -0700645 wait_for_xmitr(port);
Sathish Ambley99e2a242011-10-25 15:49:53 -0700646 msm_hsl_write(port, tx_count, regmap[vid][UARTDM_NCF_TX]);
Stepan Moskovchenko4f1025f2012-05-15 13:00:05 -0700647 msm_hsl_read(port, regmap[vid][UARTDM_NCF_TX]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700648 }
649 if (!tx_count) {
650 msm_hsl_stop_tx(port);
651 return;
652 }
653
654 while (tf_pointer < tx_count) {
Sathish Ambley99e2a242011-10-25 15:49:53 -0700655 if (unlikely(!(msm_hsl_read(port, regmap[vid][UARTDM_SR]) &
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700656 UARTDM_SR_TXRDY_BMSK)))
657 continue;
658 switch (tx_count - tf_pointer) {
659 case 1: {
660 x = xmit->buf[xmit->tail];
661 port->icount.tx++;
662 break;
663 }
664 case 2: {
665 x = xmit->buf[xmit->tail]
666 | xmit->buf[xmit->tail+1] << 8;
667 port->icount.tx += 2;
668 break;
669 }
670 case 3: {
671 x = xmit->buf[xmit->tail]
672 | xmit->buf[xmit->tail+1] << 8
673 | xmit->buf[xmit->tail + 2] << 16;
674 port->icount.tx += 3;
675 break;
676 }
677 default: {
678 x = *((int *)&(xmit->buf[xmit->tail]));
679 port->icount.tx += 4;
680 break;
681 }
682 }
Sathish Ambley99e2a242011-10-25 15:49:53 -0700683 msm_hsl_write(port, x, regmap[vid][UARTDM_TF]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700684 xmit->tail = ((tx_count - tf_pointer < 4) ?
685 (tx_count - tf_pointer + xmit->tail) :
686 (xmit->tail + 4)) & (UART_XMIT_SIZE - 1);
687 tf_pointer += 4;
688 sent_tx = 1;
689 }
690
691 if (uart_circ_empty(xmit))
692 msm_hsl_stop_tx(port);
693
694 if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
695 uart_write_wakeup(port);
696
697}
698
699static void handle_delta_cts(struct uart_port *port)
700{
Sathish Ambley99e2a242011-10-25 15:49:53 -0700701 unsigned int vid = UART_TO_MSM(port)->ver_id;
702
703 msm_hsl_write(port, RESET_CTS, regmap[vid][UARTDM_CR]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700704 port->icount.cts++;
705 wake_up_interruptible(&port->state->port.delta_msr_wait);
706}
707
708static irqreturn_t msm_hsl_irq(int irq, void *dev_id)
709{
710 struct uart_port *port = dev_id;
711 struct msm_hsl_port *msm_hsl_port = UART_TO_MSM(port);
Sathish Ambley99e2a242011-10-25 15:49:53 -0700712 unsigned int vid;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700713 unsigned int misr;
714 unsigned long flags;
715
716 spin_lock_irqsave(&port->lock, flags);
Sathish Ambley99e2a242011-10-25 15:49:53 -0700717 vid = msm_hsl_port->ver_id;
718 misr = msm_hsl_read(port, regmap[vid][UARTDM_MISR]);
719 /* disable interrupt */
720 msm_hsl_write(port, 0, regmap[vid][UARTDM_IMR]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700721
722 if (misr & (UARTDM_ISR_RXSTALE_BMSK | UARTDM_ISR_RXLEV_BMSK)) {
723 handle_rx(port, misr);
724 if (misr & (UARTDM_ISR_RXSTALE_BMSK))
Sathish Ambley99e2a242011-10-25 15:49:53 -0700725 msm_hsl_write(port, RESET_STALE_INT,
726 regmap[vid][UARTDM_CR]);
727 msm_hsl_write(port, 6500, regmap[vid][UARTDM_DMRX]);
728 msm_hsl_write(port, STALE_EVENT_ENABLE, regmap[vid][UARTDM_CR]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700729 }
730 if (misr & UARTDM_ISR_TXLEV_BMSK)
731 handle_tx(port);
732
733 if (misr & UARTDM_ISR_DELTA_CTS_BMSK)
734 handle_delta_cts(port);
735
736 /* restore interrupt */
Sathish Ambley99e2a242011-10-25 15:49:53 -0700737 msm_hsl_write(port, msm_hsl_port->imr, regmap[vid][UARTDM_IMR]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700738 spin_unlock_irqrestore(&port->lock, flags);
739
740 return IRQ_HANDLED;
741}
742
743static unsigned int msm_hsl_tx_empty(struct uart_port *port)
744{
745 unsigned int ret;
Mayank Ranaa4ad7b32012-01-24 10:23:48 +0530746 unsigned int vid = UART_TO_MSM(port)->ver_id;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700747
Sathish Ambley99e2a242011-10-25 15:49:53 -0700748 ret = (msm_hsl_read(port, regmap[vid][UARTDM_SR]) &
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700749 UARTDM_SR_TXEMT_BMSK) ? TIOCSER_TEMT : 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700750 return ret;
751}
752
753static void msm_hsl_reset(struct uart_port *port)
754{
Sathish Ambley99e2a242011-10-25 15:49:53 -0700755 unsigned int vid = UART_TO_MSM(port)->ver_id;
756
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700757 /* reset everything */
Sathish Ambley99e2a242011-10-25 15:49:53 -0700758 msm_hsl_write(port, RESET_RX, regmap[vid][UARTDM_CR]);
759 msm_hsl_write(port, RESET_TX, regmap[vid][UARTDM_CR]);
760 msm_hsl_write(port, RESET_ERROR_STATUS, regmap[vid][UARTDM_CR]);
761 msm_hsl_write(port, RESET_BREAK_INT, regmap[vid][UARTDM_CR]);
762 msm_hsl_write(port, RESET_CTS, regmap[vid][UARTDM_CR]);
763 msm_hsl_write(port, RFR_LOW, regmap[vid][UARTDM_CR]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700764}
765
766static unsigned int msm_hsl_get_mctrl(struct uart_port *port)
767{
768 return TIOCM_CAR | TIOCM_CTS | TIOCM_DSR | TIOCM_RTS;
769}
770
771static void msm_hsl_set_mctrl(struct uart_port *port, unsigned int mctrl)
772{
Sathish Ambley99e2a242011-10-25 15:49:53 -0700773 unsigned int vid = UART_TO_MSM(port)->ver_id;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700774 unsigned int mr;
775 unsigned int loop_mode;
776
Sathish Ambley99e2a242011-10-25 15:49:53 -0700777 mr = msm_hsl_read(port, regmap[vid][UARTDM_MR1]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700778
779 if (!(mctrl & TIOCM_RTS)) {
780 mr &= ~UARTDM_MR1_RX_RDY_CTL_BMSK;
Sathish Ambley99e2a242011-10-25 15:49:53 -0700781 msm_hsl_write(port, mr, regmap[vid][UARTDM_MR1]);
782 msm_hsl_write(port, RFR_HIGH, regmap[vid][UARTDM_CR]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700783 } else {
784 mr |= UARTDM_MR1_RX_RDY_CTL_BMSK;
Sathish Ambley99e2a242011-10-25 15:49:53 -0700785 msm_hsl_write(port, mr, regmap[vid][UARTDM_MR1]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700786 }
787
788 loop_mode = TIOCM_LOOP & mctrl;
789 if (loop_mode) {
Sathish Ambley99e2a242011-10-25 15:49:53 -0700790 mr = msm_hsl_read(port, regmap[vid][UARTDM_MR2]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700791 mr |= UARTDM_MR2_LOOP_MODE_BMSK;
Sathish Ambley99e2a242011-10-25 15:49:53 -0700792 msm_hsl_write(port, mr, regmap[vid][UARTDM_MR2]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700793
794 /* Reset TX */
795 msm_hsl_reset(port);
796
797 /* Turn on Uart Receiver & Transmitter*/
798 msm_hsl_write(port, UARTDM_CR_RX_EN_BMSK
Sathish Ambley99e2a242011-10-25 15:49:53 -0700799 | UARTDM_CR_TX_EN_BMSK, regmap[vid][UARTDM_CR]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700800 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700801}
802
803static void msm_hsl_break_ctl(struct uart_port *port, int break_ctl)
804{
Sathish Ambley99e2a242011-10-25 15:49:53 -0700805 unsigned int vid = UART_TO_MSM(port)->ver_id;
806
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700807 if (break_ctl)
Sathish Ambley99e2a242011-10-25 15:49:53 -0700808 msm_hsl_write(port, START_BREAK, regmap[vid][UARTDM_CR]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700809 else
Sathish Ambley99e2a242011-10-25 15:49:53 -0700810 msm_hsl_write(port, STOP_BREAK, regmap[vid][UARTDM_CR]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700811}
812
Mayank Rana44659372012-12-03 17:59:45 +0530813/**
814 * msm_hsl_set_baud_rate: set requested baud rate
815 * @port: uart port
816 * @baud: baud rate to set (in bps)
817 */
818static void msm_hsl_set_baud_rate(struct uart_port *port,
819 unsigned int baud)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700820{
821 unsigned int baud_code, rxstale, watermark;
Mayank Ranae9a54342011-06-29 20:27:08 +0530822 unsigned int data;
Sathish Ambley99e2a242011-10-25 15:49:53 -0700823 unsigned int vid;
Mayank Ranae9a54342011-06-29 20:27:08 +0530824 struct msm_hsl_port *msm_hsl_port = UART_TO_MSM(port);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700825
826 switch (baud) {
827 case 300:
Mayank Rana9825dc62011-07-26 10:47:46 +0530828 baud_code = UARTDM_CSR_75;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700829 rxstale = 1;
830 break;
831 case 600:
Mayank Rana9825dc62011-07-26 10:47:46 +0530832 baud_code = UARTDM_CSR_150;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700833 rxstale = 1;
834 break;
835 case 1200:
Mayank Rana9825dc62011-07-26 10:47:46 +0530836 baud_code = UARTDM_CSR_300;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700837 rxstale = 1;
838 break;
839 case 2400:
Mayank Rana9825dc62011-07-26 10:47:46 +0530840 baud_code = UARTDM_CSR_600;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700841 rxstale = 1;
842 break;
843 case 4800:
Mayank Rana9825dc62011-07-26 10:47:46 +0530844 baud_code = UARTDM_CSR_1200;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700845 rxstale = 1;
846 break;
847 case 9600:
Mayank Rana9825dc62011-07-26 10:47:46 +0530848 baud_code = UARTDM_CSR_2400;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700849 rxstale = 2;
850 break;
851 case 14400:
Mayank Rana9825dc62011-07-26 10:47:46 +0530852 baud_code = UARTDM_CSR_3600;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700853 rxstale = 3;
854 break;
855 case 19200:
Mayank Rana9825dc62011-07-26 10:47:46 +0530856 baud_code = UARTDM_CSR_4800;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700857 rxstale = 4;
858 break;
859 case 28800:
Mayank Rana9825dc62011-07-26 10:47:46 +0530860 baud_code = UARTDM_CSR_7200;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700861 rxstale = 6;
862 break;
863 case 38400:
Mayank Rana9825dc62011-07-26 10:47:46 +0530864 baud_code = UARTDM_CSR_9600;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700865 rxstale = 8;
866 break;
867 case 57600:
Mayank Rana9825dc62011-07-26 10:47:46 +0530868 baud_code = UARTDM_CSR_14400;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700869 rxstale = 16;
870 break;
871 case 115200:
Mayank Rana9825dc62011-07-26 10:47:46 +0530872 baud_code = UARTDM_CSR_28800;
873 rxstale = 31;
874 break;
875 case 230400:
876 baud_code = UARTDM_CSR_57600;
877 rxstale = 31;
878 break;
879 case 460800:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700880 baud_code = UARTDM_CSR_115200;
881 rxstale = 31;
882 break;
Mayank Rana44659372012-12-03 17:59:45 +0530883 case 4000000:
884 case 3686400:
885 case 3200000:
886 case 3500000:
887 case 3000000:
888 case 2500000:
889 case 1500000:
890 case 1152000:
891 case 1000000:
892 case 921600:
893 baud_code = 0xff;
894 rxstale = 31;
895 break;
896 default: /*115200 baud rate */
Mayank Rana9825dc62011-07-26 10:47:46 +0530897 baud_code = UARTDM_CSR_28800;
898 rxstale = 31;
899 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700900 }
901
Sathish Ambley99e2a242011-10-25 15:49:53 -0700902 vid = msm_hsl_port->ver_id;
903 msm_hsl_write(port, baud_code, regmap[vid][UARTDM_CSR]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700904
Mayank Rana44659372012-12-03 17:59:45 +0530905 /*
906 * uart baud rate depends on CSR and MND Values
907 * we are updating CSR before and then calling
908 * clk_set_rate which updates MND Values. Hence
909 * dsb requires here.
910 */
911 mb();
912
913 /*
914 * Check requested baud rate and for higher baud rate than 460800,
915 * calculate required uart clock frequency and set the same.
916 */
Mayank Ranaaf409702012-12-12 18:37:24 +0530917 if (baud > 460800)
Mayank Rana44659372012-12-03 17:59:45 +0530918 port->uartclk = baud * 16;
Mayank Ranaaf409702012-12-12 18:37:24 +0530919 else
920 port->uartclk = 7372800;
921
922 if (clk_set_rate(msm_hsl_port->clk, port->uartclk)) {
923 pr_err("Error: setting uartclk rate %u\n", port->uartclk);
924 WARN_ON(1);
925 return;
Mayank Rana44659372012-12-03 17:59:45 +0530926 }
927
928 /* Set timeout to be ~600x the character transmit time */
929 msm_hsl_port->tx_timeout = (1000000000 / baud) * 6;
930
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700931 /* RX stale watermark */
932 watermark = UARTDM_IPR_STALE_LSB_BMSK & rxstale;
933 watermark |= UARTDM_IPR_STALE_TIMEOUT_MSB_BMSK & (rxstale << 2);
Sathish Ambley99e2a242011-10-25 15:49:53 -0700934 msm_hsl_write(port, watermark, regmap[vid][UARTDM_IPR]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700935
Mayank Ranaad56d5f2011-08-16 09:07:04 +0530936 /* Set RX watermark
937 * Configure Rx Watermark as 3/4 size of Rx FIFO.
938 * RFWR register takes value in Words for UARTDM Core
939 * whereas it is consider to be in Bytes for UART Core.
Mayank Ranaf9f90302012-12-06 17:04:28 +0530940 * Hence configuring Rx Watermark as 48 Words.
Mayank Ranaad56d5f2011-08-16 09:07:04 +0530941 */
Mayank Ranaf9f90302012-12-06 17:04:28 +0530942 watermark = (port->fifosize * 3) / 4;
Sathish Ambley99e2a242011-10-25 15:49:53 -0700943 msm_hsl_write(port, watermark, regmap[vid][UARTDM_RFWR]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700944
945 /* set TX watermark */
Sathish Ambley99e2a242011-10-25 15:49:53 -0700946 msm_hsl_write(port, 0, regmap[vid][UARTDM_TFWR]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700947
Sathish Ambley99e2a242011-10-25 15:49:53 -0700948 msm_hsl_write(port, CR_PROTECTION_EN, regmap[vid][UARTDM_CR]);
Mayank Ranae9a54342011-06-29 20:27:08 +0530949 msm_hsl_reset(port);
950
951 data = UARTDM_CR_TX_EN_BMSK;
952 data |= UARTDM_CR_RX_EN_BMSK;
953 /* enable TX & RX */
Sathish Ambley99e2a242011-10-25 15:49:53 -0700954 msm_hsl_write(port, data, regmap[vid][UARTDM_CR]);
Mayank Ranae9a54342011-06-29 20:27:08 +0530955
Mayank Rana9717aba2012-02-27 18:20:38 +0530956 msm_hsl_write(port, RESET_STALE_INT, regmap[vid][UARTDM_CR]);
Mayank Ranae9a54342011-06-29 20:27:08 +0530957 /* turn on RX and CTS interrupts */
958 msm_hsl_port->imr = UARTDM_ISR_RXSTALE_BMSK
959 | UARTDM_ISR_DELTA_CTS_BMSK | UARTDM_ISR_RXLEV_BMSK;
Sathish Ambley99e2a242011-10-25 15:49:53 -0700960 msm_hsl_write(port, msm_hsl_port->imr, regmap[vid][UARTDM_IMR]);
961 msm_hsl_write(port, 6500, regmap[vid][UARTDM_DMRX]);
962 msm_hsl_write(port, STALE_EVENT_ENABLE, regmap[vid][UARTDM_CR]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700963}
964
965static void msm_hsl_init_clock(struct uart_port *port)
966{
967 clk_en(port, 1);
968}
969
970static void msm_hsl_deinit_clock(struct uart_port *port)
971{
972 clk_en(port, 0);
973}
974
975static int msm_hsl_startup(struct uart_port *port)
976{
977 struct msm_hsl_port *msm_hsl_port = UART_TO_MSM(port);
978 struct platform_device *pdev = to_platform_device(port->dev);
979 const struct msm_serial_hslite_platform_data *pdata =
980 pdev->dev.platform_data;
981 unsigned int data, rfr_level;
Sathish Ambley99e2a242011-10-25 15:49:53 -0700982 unsigned int vid;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700983 int ret;
984 unsigned long flags;
985
986 snprintf(msm_hsl_port->name, sizeof(msm_hsl_port->name),
987 "msm_serial_hsl%d", port->line);
988
989 if (!(is_console(port)) || (!port->cons) ||
990 (port->cons && (!(port->cons->flags & CON_ENABLED)))) {
991
992 if (msm_serial_hsl_has_gsbi(port))
Mayank Rana9fc393d2012-12-04 19:10:36 +0530993 set_gsbi_uart_func_mode(port);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700994
Mayank Ranaa9c20892012-12-13 11:35:52 +0530995 if (pdata && pdata->use_pm)
996 wake_lock(&msm_hsl_port->port_open_wake_lock);
997
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700998 if (pdata && pdata->config_gpio) {
Mayank Rana9fc393d2012-12-04 19:10:36 +0530999 ret = msm_hsl_config_uart_gpios(port);
1000 if (ret) {
1001 msm_hsl_unconfig_uart_gpios(port);
Mayank Ranaa9c20892012-12-13 11:35:52 +05301002 goto release_wakelock;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001003 }
1004 }
1005 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001006
Mayank Ranaf9f90302012-12-06 17:04:28 +05301007 /*
1008 * Set RFR Level as 3/4 of UARTDM FIFO Size
1009 * i.e. 48 Words = 192 bytes as Rx FIFO is 64 words ( 256 bytes).
1010 */
Mayank Ranaffdf5302011-08-17 20:54:34 +05301011 if (likely(port->fifosize > 48))
1012 rfr_level = port->fifosize - 16;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001013 else
1014 rfr_level = port->fifosize;
1015
1016 spin_lock_irqsave(&port->lock, flags);
1017
Sathish Ambley99e2a242011-10-25 15:49:53 -07001018 vid = msm_hsl_port->ver_id;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001019 /* set automatic RFR level */
Sathish Ambley99e2a242011-10-25 15:49:53 -07001020 data = msm_hsl_read(port, regmap[vid][UARTDM_MR1]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001021 data &= ~UARTDM_MR1_AUTO_RFR_LEVEL1_BMSK;
1022 data &= ~UARTDM_MR1_AUTO_RFR_LEVEL0_BMSK;
1023 data |= UARTDM_MR1_AUTO_RFR_LEVEL1_BMSK & (rfr_level << 2);
1024 data |= UARTDM_MR1_AUTO_RFR_LEVEL0_BMSK & rfr_level;
Sathish Ambley99e2a242011-10-25 15:49:53 -07001025 msm_hsl_write(port, data, regmap[vid][UARTDM_MR1]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001026 spin_unlock_irqrestore(&port->lock, flags);
1027
1028 ret = request_irq(port->irq, msm_hsl_irq, IRQF_TRIGGER_HIGH,
1029 msm_hsl_port->name, port);
1030 if (unlikely(ret)) {
Mayank Rana1295c082012-12-03 13:56:12 +05301031 pr_err("failed to request_irq\n");
Mayank Rana9fc393d2012-12-04 19:10:36 +05301032 msm_hsl_unconfig_uart_gpios(port);
Mayank Ranaa9c20892012-12-13 11:35:52 +05301033 goto release_wakelock;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001034 }
Mayank Rana9fc393d2012-12-04 19:10:36 +05301035
Mayank Ranaa9c20892012-12-13 11:35:52 +05301036 return ret;
1037
1038release_wakelock:
1039 if (pdata && pdata->use_pm)
1040 wake_unlock(&msm_hsl_port->port_open_wake_lock);
1041
Mayank Rana9fc393d2012-12-04 19:10:36 +05301042 return ret;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001043}
1044
1045static void msm_hsl_shutdown(struct uart_port *port)
1046{
1047 struct msm_hsl_port *msm_hsl_port = UART_TO_MSM(port);
1048 struct platform_device *pdev = to_platform_device(port->dev);
1049 const struct msm_serial_hslite_platform_data *pdata =
1050 pdev->dev.platform_data;
1051
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001052 msm_hsl_port->imr = 0;
Sathish Ambley99e2a242011-10-25 15:49:53 -07001053 /* disable interrupts */
1054 msm_hsl_write(port, 0, regmap[msm_hsl_port->ver_id][UARTDM_IMR]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001055
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001056 free_irq(port->irq, port);
1057
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001058 if (!(is_console(port)) || (!port->cons) ||
1059 (port->cons && (!(port->cons->flags & CON_ENABLED)))) {
Mayank Rana9fc393d2012-12-04 19:10:36 +05301060 /* Free UART GPIOs */
1061 if (pdata && pdata->config_gpio)
1062 msm_hsl_unconfig_uart_gpios(port);
Mayank Ranaa9c20892012-12-13 11:35:52 +05301063
1064 if (pdata && pdata->use_pm)
1065 wake_unlock(&msm_hsl_port->port_open_wake_lock);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001066 }
1067}
1068
1069static void msm_hsl_set_termios(struct uart_port *port,
1070 struct ktermios *termios,
1071 struct ktermios *old)
1072{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001073 unsigned int baud, mr;
Sathish Ambley99e2a242011-10-25 15:49:53 -07001074 unsigned int vid;
Mayank Rana44659372012-12-03 17:59:45 +05301075 struct msm_hsl_port *msm_hsl_port = UART_TO_MSM(port);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001076
Mayank Rana216744c2012-05-01 22:43:21 -07001077 if (!termios->c_cflag)
1078 return;
1079
Mayank Rana44659372012-12-03 17:59:45 +05301080 mutex_lock(&msm_hsl_port->clk_mutex);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001081
Mayank Rana44659372012-12-03 17:59:45 +05301082 /*
1083 * Calculate and set baud rate
1084 * 300 is the minimum and 4 Mbps is the maximum baud rate
1085 * supported by driver.
1086 */
1087 baud = uart_get_baud_rate(port, termios, old, 200, 4000000);
1088
1089 /*
1090 * Due to non-availability of 3.2 Mbps baud rate as standard baud rate
1091 * with TTY/serial core. Map 200 BAUD to 3.2 Mbps
1092 */
1093 if (baud == 200)
1094 baud = 3200000;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001095
1096 msm_hsl_set_baud_rate(port, baud);
1097
Sathish Ambley99e2a242011-10-25 15:49:53 -07001098 vid = UART_TO_MSM(port)->ver_id;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001099 /* calculate parity */
Sathish Ambley99e2a242011-10-25 15:49:53 -07001100 mr = msm_hsl_read(port, regmap[vid][UARTDM_MR2]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001101 mr &= ~UARTDM_MR2_PARITY_MODE_BMSK;
1102 if (termios->c_cflag & PARENB) {
1103 if (termios->c_cflag & PARODD)
1104 mr |= ODD_PARITY;
1105 else if (termios->c_cflag & CMSPAR)
1106 mr |= SPACE_PARITY;
1107 else
1108 mr |= EVEN_PARITY;
1109 }
1110
1111 /* calculate bits per char */
1112 mr &= ~UARTDM_MR2_BITS_PER_CHAR_BMSK;
1113 switch (termios->c_cflag & CSIZE) {
1114 case CS5:
1115 mr |= FIVE_BPC;
1116 break;
1117 case CS6:
1118 mr |= SIX_BPC;
1119 break;
1120 case CS7:
1121 mr |= SEVEN_BPC;
1122 break;
1123 case CS8:
1124 default:
1125 mr |= EIGHT_BPC;
1126 break;
1127 }
1128
1129 /* calculate stop bits */
1130 mr &= ~(STOP_BIT_ONE | STOP_BIT_TWO);
1131 if (termios->c_cflag & CSTOPB)
1132 mr |= STOP_BIT_TWO;
1133 else
1134 mr |= STOP_BIT_ONE;
1135
1136 /* set parity, bits per char, and stop bit */
Sathish Ambley99e2a242011-10-25 15:49:53 -07001137 msm_hsl_write(port, mr, regmap[vid][UARTDM_MR2]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001138
1139 /* calculate and set hardware flow control */
Sathish Ambley99e2a242011-10-25 15:49:53 -07001140 mr = msm_hsl_read(port, regmap[vid][UARTDM_MR1]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001141 mr &= ~(UARTDM_MR1_CTS_CTL_BMSK | UARTDM_MR1_RX_RDY_CTL_BMSK);
1142 if (termios->c_cflag & CRTSCTS) {
1143 mr |= UARTDM_MR1_CTS_CTL_BMSK;
1144 mr |= UARTDM_MR1_RX_RDY_CTL_BMSK;
1145 }
Sathish Ambley99e2a242011-10-25 15:49:53 -07001146 msm_hsl_write(port, mr, regmap[vid][UARTDM_MR1]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001147
1148 /* Configure status bits to ignore based on termio flags. */
1149 port->read_status_mask = 0;
1150 if (termios->c_iflag & INPCK)
1151 port->read_status_mask |= UARTDM_SR_PAR_FRAME_BMSK;
1152 if (termios->c_iflag & (BRKINT | PARMRK))
1153 port->read_status_mask |= UARTDM_SR_RX_BREAK_BMSK;
1154
1155 uart_update_timeout(port, termios->c_cflag, baud);
1156
Mayank Rana44659372012-12-03 17:59:45 +05301157 mutex_unlock(&msm_hsl_port->clk_mutex);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001158}
1159
1160static const char *msm_hsl_type(struct uart_port *port)
1161{
1162 return "MSM";
1163}
1164
1165static void msm_hsl_release_port(struct uart_port *port)
1166{
1167 struct msm_hsl_port *msm_hsl_port = UART_TO_MSM(port);
1168 struct platform_device *pdev = to_platform_device(port->dev);
1169 struct resource *uart_resource;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001170 resource_size_t size;
1171
1172 uart_resource = platform_get_resource_byname(pdev, IORESOURCE_MEM,
1173 "uartdm_resource");
Sathish Ambley3d50c762011-10-25 15:26:00 -07001174 if (!uart_resource)
1175 uart_resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001176 if (unlikely(!uart_resource))
1177 return;
1178 size = uart_resource->end - uart_resource->start + 1;
1179
1180 release_mem_region(port->mapbase, size);
1181 iounmap(port->membase);
1182 port->membase = NULL;
1183
1184 if (msm_serial_hsl_has_gsbi(port)) {
1185 iowrite32(GSBI_PROTOCOL_IDLE, msm_hsl_port->mapped_gsbi +
1186 GSBI_CONTROL_ADDR);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001187 iounmap(msm_hsl_port->mapped_gsbi);
1188 msm_hsl_port->mapped_gsbi = NULL;
1189 }
1190}
1191
1192static int msm_hsl_request_port(struct uart_port *port)
1193{
1194 struct msm_hsl_port *msm_hsl_port = UART_TO_MSM(port);
1195 struct platform_device *pdev = to_platform_device(port->dev);
1196 struct resource *uart_resource;
1197 struct resource *gsbi_resource;
1198 resource_size_t size;
1199
1200 uart_resource = platform_get_resource_byname(pdev, IORESOURCE_MEM,
1201 "uartdm_resource");
Sathish Ambley3d50c762011-10-25 15:26:00 -07001202 if (!uart_resource)
1203 uart_resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001204 if (unlikely(!uart_resource)) {
Mayank Rana1295c082012-12-03 13:56:12 +05301205 pr_err("can't get uartdm resource\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001206 return -ENXIO;
1207 }
1208 size = uart_resource->end - uart_resource->start + 1;
1209
1210 if (unlikely(!request_mem_region(port->mapbase, size,
1211 "msm_serial_hsl"))) {
Mayank Rana1295c082012-12-03 13:56:12 +05301212 pr_err("can't get mem region for uartdm\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001213 return -EBUSY;
1214 }
1215
1216 port->membase = ioremap(port->mapbase, size);
1217 if (!port->membase) {
1218 release_mem_region(port->mapbase, size);
1219 return -EBUSY;
1220 }
1221
1222 if (msm_serial_hsl_has_gsbi(port)) {
1223 gsbi_resource = platform_get_resource_byname(pdev,
1224 IORESOURCE_MEM,
1225 "gsbi_resource");
Sathish Ambley3d50c762011-10-25 15:26:00 -07001226 if (!gsbi_resource)
1227 gsbi_resource = platform_get_resource(pdev,
1228 IORESOURCE_MEM, 1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001229 if (unlikely(!gsbi_resource)) {
Mayank Rana1295c082012-12-03 13:56:12 +05301230 pr_err("can't get gsbi resource\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001231 return -ENXIO;
1232 }
1233
1234 size = gsbi_resource->end - gsbi_resource->start + 1;
1235 msm_hsl_port->mapped_gsbi = ioremap(gsbi_resource->start,
1236 size);
1237 if (!msm_hsl_port->mapped_gsbi) {
1238 return -EBUSY;
1239 }
1240 }
1241
1242 return 0;
1243}
1244
1245static void msm_hsl_config_port(struct uart_port *port, int flags)
1246{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001247 if (flags & UART_CONFIG_TYPE) {
1248 port->type = PORT_MSM;
1249 if (msm_hsl_request_port(port))
1250 return;
1251 }
Mayank Rana9fc393d2012-12-04 19:10:36 +05301252
1253 /* Configure required GSBI based UART protocol. */
1254 if (msm_serial_hsl_has_gsbi(port))
1255 set_gsbi_uart_func_mode(port);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001256}
1257
1258static int msm_hsl_verify_port(struct uart_port *port,
1259 struct serial_struct *ser)
1260{
1261 if (unlikely(ser->type != PORT_UNKNOWN && ser->type != PORT_MSM))
1262 return -EINVAL;
1263 if (unlikely(port->irq != ser->irq))
1264 return -EINVAL;
1265 return 0;
1266}
1267
1268static void msm_hsl_power(struct uart_port *port, unsigned int state,
1269 unsigned int oldstate)
1270{
1271 int ret;
1272 struct msm_hsl_port *msm_hsl_port = UART_TO_MSM(port);
Mayank Rana965e9e72013-02-22 12:14:14 +05301273 struct platform_device *pdev = to_platform_device(port->dev);
1274 const struct msm_serial_hslite_platform_data *pdata =
1275 pdev->dev.platform_data;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001276
1277 switch (state) {
1278 case 0:
Mayank Rana1295c082012-12-03 13:56:12 +05301279 ret = clk_set_rate(msm_hsl_port->clk, port->uartclk);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001280 if (ret)
Mayank Rana1295c082012-12-03 13:56:12 +05301281 pr_err("Error setting UART clock rate to %u\n",
1282 port->uartclk);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001283 clk_en(port, 1);
1284 break;
1285 case 3:
1286 clk_en(port, 0);
Mayank Rana965e9e72013-02-22 12:14:14 +05301287 if (pdata && pdata->set_uart_clk_zero) {
1288 ret = clk_set_rate(msm_hsl_port->clk, 0);
1289 if (ret)
1290 pr_err("Error setting UART clock rate to zero.\n");
1291 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001292 break;
1293 default:
Mayank Rana1295c082012-12-03 13:56:12 +05301294 pr_err("Unknown PM state %d\n", state);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001295 }
1296}
1297
1298static struct uart_ops msm_hsl_uart_pops = {
1299 .tx_empty = msm_hsl_tx_empty,
1300 .set_mctrl = msm_hsl_set_mctrl,
1301 .get_mctrl = msm_hsl_get_mctrl,
1302 .stop_tx = msm_hsl_stop_tx,
1303 .start_tx = msm_hsl_start_tx,
1304 .stop_rx = msm_hsl_stop_rx,
1305 .enable_ms = msm_hsl_enable_ms,
1306 .break_ctl = msm_hsl_break_ctl,
1307 .startup = msm_hsl_startup,
1308 .shutdown = msm_hsl_shutdown,
1309 .set_termios = msm_hsl_set_termios,
1310 .type = msm_hsl_type,
1311 .release_port = msm_hsl_release_port,
1312 .request_port = msm_hsl_request_port,
1313 .config_port = msm_hsl_config_port,
1314 .verify_port = msm_hsl_verify_port,
1315 .pm = msm_hsl_power,
1316};
1317
1318static struct msm_hsl_port msm_hsl_uart_ports[] = {
1319 {
1320 .uart = {
1321 .iotype = UPIO_MEM,
1322 .ops = &msm_hsl_uart_pops,
1323 .flags = UPF_BOOT_AUTOCONF,
1324 .fifosize = 64,
1325 .line = 0,
1326 },
1327 },
1328 {
1329 .uart = {
1330 .iotype = UPIO_MEM,
1331 .ops = &msm_hsl_uart_pops,
1332 .flags = UPF_BOOT_AUTOCONF,
1333 .fifosize = 64,
1334 .line = 1,
1335 },
1336 },
1337 {
1338 .uart = {
1339 .iotype = UPIO_MEM,
1340 .ops = &msm_hsl_uart_pops,
1341 .flags = UPF_BOOT_AUTOCONF,
1342 .fifosize = 64,
1343 .line = 2,
1344 },
1345 },
1346};
1347
1348#define UART_NR ARRAY_SIZE(msm_hsl_uart_ports)
1349
1350static inline struct uart_port *get_port_from_line(unsigned int line)
1351{
1352 return &msm_hsl_uart_ports[line].uart;
1353}
1354
Stepan Moskovchenko1d4731e2012-02-21 20:18:23 -08001355static unsigned int msm_hsl_console_state[8];
1356
1357static void dump_hsl_regs(struct uart_port *port)
1358{
1359 struct msm_hsl_port *msm_hsl_port = UART_TO_MSM(port);
1360 unsigned int vid = msm_hsl_port->ver_id;
1361 unsigned int sr, isr, mr1, mr2, ncf, txfs, rxfs, con_state;
1362
1363 sr = msm_hsl_read(port, regmap[vid][UARTDM_SR]);
1364 isr = msm_hsl_read(port, regmap[vid][UARTDM_ISR]);
1365 mr1 = msm_hsl_read(port, regmap[vid][UARTDM_MR1]);
1366 mr2 = msm_hsl_read(port, regmap[vid][UARTDM_MR2]);
1367 ncf = msm_hsl_read(port, regmap[vid][UARTDM_NCF_TX]);
1368 txfs = msm_hsl_read(port, regmap[vid][UARTDM_TXFS]);
1369 rxfs = msm_hsl_read(port, regmap[vid][UARTDM_RXFS]);
1370 con_state = get_console_state(port);
1371
1372 msm_hsl_console_state[0] = sr;
1373 msm_hsl_console_state[1] = isr;
1374 msm_hsl_console_state[2] = mr1;
1375 msm_hsl_console_state[3] = mr2;
1376 msm_hsl_console_state[4] = ncf;
1377 msm_hsl_console_state[5] = txfs;
1378 msm_hsl_console_state[6] = rxfs;
1379 msm_hsl_console_state[7] = con_state;
1380
Mayank Rana1295c082012-12-03 13:56:12 +05301381 pr_info("Timeout: %d uS\n", msm_hsl_port->tx_timeout);
1382 pr_info("SR: %08x\n", sr);
1383 pr_info("ISR: %08x\n", isr);
1384 pr_info("MR1: %08x\n", mr1);
1385 pr_info("MR2: %08x\n", mr2);
1386 pr_info("NCF: %08x\n", ncf);
1387 pr_info("TXFS: %08x\n", txfs);
1388 pr_info("RXFS: %08x\n", rxfs);
1389 pr_info("Console state: %d\n", con_state);
Stepan Moskovchenko1d4731e2012-02-21 20:18:23 -08001390}
1391
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001392/*
1393 * Wait for transmitter & holding register to empty
1394 * Derived from wait_for_xmitr in 8250 serial driver by Russell King */
Stepan Moskovchenko9ec24842012-05-15 13:58:58 -07001395static void wait_for_xmitr(struct uart_port *port)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001396{
Stepan Moskovchenko1d4731e2012-02-21 20:18:23 -08001397 struct msm_hsl_port *msm_hsl_port = UART_TO_MSM(port);
1398 unsigned int vid = msm_hsl_port->ver_id;
1399 int count = 0;
Sathish Ambley99e2a242011-10-25 15:49:53 -07001400
1401 if (!(msm_hsl_read(port, regmap[vid][UARTDM_SR]) &
1402 UARTDM_SR_TXEMT_BMSK)) {
Stepan Moskovchenko9ec24842012-05-15 13:58:58 -07001403 while (!(msm_hsl_read(port, regmap[vid][UARTDM_ISR]) &
Stepan Moskovchenkod4a62ab202012-05-15 14:43:31 -07001404 UARTDM_ISR_TX_READY_BMSK) &&
1405 !(msm_hsl_read(port, regmap[vid][UARTDM_SR]) &
1406 UARTDM_SR_TXEMT_BMSK)) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001407 udelay(1);
1408 touch_nmi_watchdog();
1409 cpu_relax();
Stepan Moskovchenko1d4731e2012-02-21 20:18:23 -08001410 if (++count == msm_hsl_port->tx_timeout) {
1411 dump_hsl_regs(port);
1412 panic("MSM HSL wait_for_xmitr is stuck!");
1413 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001414 }
Sathish Ambley99e2a242011-10-25 15:49:53 -07001415 msm_hsl_write(port, CLEAR_TX_READY, regmap[vid][UARTDM_CR]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001416 }
1417}
1418
1419#ifdef CONFIG_SERIAL_MSM_HSL_CONSOLE
1420static void msm_hsl_console_putchar(struct uart_port *port, int ch)
1421{
Sathish Ambley99e2a242011-10-25 15:49:53 -07001422 unsigned int vid = UART_TO_MSM(port)->ver_id;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001423
Stepan Moskovchenko9ec24842012-05-15 13:58:58 -07001424 wait_for_xmitr(port);
Sathish Ambley99e2a242011-10-25 15:49:53 -07001425 msm_hsl_write(port, 1, regmap[vid][UARTDM_NCF_TX]);
Mayank Ranaec41e932012-02-24 16:24:54 +05301426 /*
1427 * Dummy read to add 1 AHB clock delay to fix UART hardware bug.
1428 * Bug: Delay required on TX-transfer-init. after writing to
1429 * NO_CHARS_FOR_TX register.
1430 */
1431 msm_hsl_read(port, regmap[vid][UARTDM_SR]);
Sathish Ambley99e2a242011-10-25 15:49:53 -07001432 msm_hsl_write(port, ch, regmap[vid][UARTDM_TF]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001433}
1434
1435static void msm_hsl_console_write(struct console *co, const char *s,
1436 unsigned int count)
1437{
1438 struct uart_port *port;
1439 struct msm_hsl_port *msm_hsl_port;
Sathish Ambley99e2a242011-10-25 15:49:53 -07001440 unsigned int vid;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001441 int locked;
1442
1443 BUG_ON(co->index < 0 || co->index >= UART_NR);
1444
1445 port = get_port_from_line(co->index);
1446 msm_hsl_port = UART_TO_MSM(port);
Sathish Ambley99e2a242011-10-25 15:49:53 -07001447 vid = msm_hsl_port->ver_id;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001448
1449 /* not pretty, but we can end up here via various convoluted paths */
1450 if (port->sysrq || oops_in_progress)
1451 locked = spin_trylock(&port->lock);
1452 else {
1453 locked = 1;
1454 spin_lock(&port->lock);
1455 }
Sathish Ambley99e2a242011-10-25 15:49:53 -07001456 msm_hsl_write(port, 0, regmap[vid][UARTDM_IMR]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001457 uart_console_write(port, s, count, msm_hsl_console_putchar);
Sathish Ambley99e2a242011-10-25 15:49:53 -07001458 msm_hsl_write(port, msm_hsl_port->imr, regmap[vid][UARTDM_IMR]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001459 if (locked == 1)
1460 spin_unlock(&port->lock);
1461}
1462
Mayank Rana930c99c2011-09-05 18:22:02 +05301463static int msm_hsl_console_setup(struct console *co, char *options)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001464{
1465 struct uart_port *port;
Sathish Ambley99e2a242011-10-25 15:49:53 -07001466 unsigned int vid;
Stepan Moskovchenkoe4b0d792012-05-10 14:10:44 -07001467 int baud = 0, flow, bits, parity, mr2;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001468 int ret;
1469
1470 if (unlikely(co->index >= UART_NR || co->index < 0))
1471 return -ENXIO;
1472
1473 port = get_port_from_line(co->index);
Sathish Ambley99e2a242011-10-25 15:49:53 -07001474 vid = UART_TO_MSM(port)->ver_id;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001475
1476 if (unlikely(!port->membase))
1477 return -ENXIO;
1478
1479 port->cons = co;
1480
1481 pm_runtime_get_noresume(port->dev);
1482
1483#ifndef CONFIG_PM_RUNTIME
1484 msm_hsl_init_clock(port);
1485#endif
1486 pm_runtime_resume(port->dev);
1487
1488 if (options)
1489 uart_parse_options(options, &baud, &parity, &bits, &flow);
1490
1491 bits = 8;
1492 parity = 'n';
1493 flow = 'n';
1494 msm_hsl_write(port, UARTDM_MR2_BITS_PER_CHAR_8 | STOP_BIT_ONE,
Sathish Ambley99e2a242011-10-25 15:49:53 -07001495 regmap[vid][UARTDM_MR2]); /* 8N1 */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001496
1497 if (baud < 300 || baud > 115200)
1498 baud = 115200;
1499 msm_hsl_set_baud_rate(port, baud);
1500
1501 ret = uart_set_options(port, co, baud, parity, bits, flow);
Stepan Moskovchenkoe4b0d792012-05-10 14:10:44 -07001502
1503 mr2 = msm_hsl_read(port, regmap[vid][UARTDM_MR2]);
1504 mr2 |= UARTDM_MR2_RX_ERROR_CHAR_OFF;
1505 mr2 |= UARTDM_MR2_RX_BREAK_ZERO_CHAR_OFF;
1506 msm_hsl_write(port, mr2, regmap[vid][UARTDM_MR2]);
1507
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001508 msm_hsl_reset(port);
1509 /* Enable transmitter */
Sathish Ambley99e2a242011-10-25 15:49:53 -07001510 msm_hsl_write(port, CR_PROTECTION_EN, regmap[vid][UARTDM_CR]);
1511 msm_hsl_write(port, UARTDM_CR_TX_EN_BMSK, regmap[vid][UARTDM_CR]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001512
Stepan Moskovchenkof525c112012-05-15 14:10:26 -07001513 msm_hsl_write(port, 1, regmap[vid][UARTDM_NCF_TX]);
1514 msm_hsl_read(port, regmap[vid][UARTDM_NCF_TX]);
1515
Mayank Rana1295c082012-12-03 13:56:12 +05301516 pr_info("console setup on port #%d\n", port->line);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001517
1518 return ret;
1519}
1520
1521static struct uart_driver msm_hsl_uart_driver;
1522
1523static struct console msm_hsl_console = {
1524 .name = "ttyHSL",
1525 .write = msm_hsl_console_write,
1526 .device = uart_console_device,
1527 .setup = msm_hsl_console_setup,
1528 .flags = CON_PRINTBUFFER,
1529 .index = -1,
1530 .data = &msm_hsl_uart_driver,
1531};
1532
1533#define MSM_HSL_CONSOLE (&msm_hsl_console)
Mayank Rana930c99c2011-09-05 18:22:02 +05301534/*
1535 * get_console_state - check the per-port serial console state.
1536 * @port: uart_port structure describing the port
1537 *
1538 * Return the state of serial console availability on port.
1539 * return 1: If serial console is enabled on particular UART port.
1540 * return 0: If serial console is disabled on particular UART port.
1541 */
1542static int get_console_state(struct uart_port *port)
1543{
1544 if (is_console(port) && (port->cons->flags & CON_ENABLED))
1545 return 1;
1546 else
1547 return 0;
1548}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001549
Mayank Rana930c99c2011-09-05 18:22:02 +05301550/* show_msm_console - provide per-port serial console state. */
1551static ssize_t show_msm_console(struct device *dev,
1552 struct device_attribute *attr, char *buf)
1553{
1554 int enable;
1555 struct uart_port *port;
1556
1557 struct platform_device *pdev = to_platform_device(dev);
Stepan Moskovchenko798fe552012-03-29 19:47:19 -07001558 port = get_port_from_line(get_line(pdev));
Mayank Rana930c99c2011-09-05 18:22:02 +05301559
1560 enable = get_console_state(port);
1561
1562 return snprintf(buf, sizeof(enable), "%d\n", enable);
1563}
1564
1565/*
1566 * set_msm_console - allow to enable/disable serial console on port.
1567 *
1568 * writing 1 enables serial console on UART port.
1569 * writing 0 disables serial console on UART port.
1570 */
1571static ssize_t set_msm_console(struct device *dev,
1572 struct device_attribute *attr,
1573 const char *buf, size_t count)
1574{
1575 int enable, cur_state;
1576 struct uart_port *port;
1577
1578 struct platform_device *pdev = to_platform_device(dev);
Stepan Moskovchenko798fe552012-03-29 19:47:19 -07001579 port = get_port_from_line(get_line(pdev));
Mayank Rana930c99c2011-09-05 18:22:02 +05301580
1581 cur_state = get_console_state(port);
1582 enable = buf[0] - '0';
1583
1584 if (enable == cur_state)
1585 return count;
1586
1587 switch (enable) {
1588 case 0:
Mayank Rana1295c082012-12-03 13:56:12 +05301589 pr_debug("Calling stop_console\n");
Mayank Rana930c99c2011-09-05 18:22:02 +05301590 console_stop(port->cons);
Mayank Rana1295c082012-12-03 13:56:12 +05301591 pr_debug("Calling unregister_console\n");
Mayank Rana930c99c2011-09-05 18:22:02 +05301592 unregister_console(port->cons);
1593 pm_runtime_put_sync(&pdev->dev);
1594 pm_runtime_disable(&pdev->dev);
1595 /*
1596 * Disable UART Core clk
1597 * 3 - to disable the UART clock
1598 * Thid parameter is not used here, but used in serial core.
1599 */
1600 msm_hsl_power(port, 3, 1);
1601 break;
1602 case 1:
Mayank Rana1295c082012-12-03 13:56:12 +05301603 pr_debug("Calling register_console\n");
Mayank Rana930c99c2011-09-05 18:22:02 +05301604 /*
1605 * Disable UART Core clk
1606 * 0 - to enable the UART clock
1607 * Thid parameter is not used here, but used in serial core.
1608 */
1609 msm_hsl_power(port, 0, 1);
1610 pm_runtime_enable(&pdev->dev);
1611 register_console(port->cons);
1612 break;
1613 default:
1614 return -EINVAL;
1615 }
1616
1617 return count;
1618}
1619static DEVICE_ATTR(console, S_IWUSR | S_IRUGO, show_msm_console,
1620 set_msm_console);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001621#else
1622#define MSM_HSL_CONSOLE NULL
1623#endif
1624
1625static struct uart_driver msm_hsl_uart_driver = {
1626 .owner = THIS_MODULE,
1627 .driver_name = "msm_serial_hsl",
1628 .dev_name = "ttyHSL",
1629 .nr = UART_NR,
1630 .cons = MSM_HSL_CONSOLE,
1631};
1632
Mayank Rana9fc393d2012-12-04 19:10:36 +05301633static struct msm_serial_hslite_platform_data
1634 *msm_hsl_dt_to_pdata(struct platform_device *pdev)
1635{
1636 int ret;
1637 struct device_node *node = pdev->dev.of_node;
1638 struct msm_serial_hslite_platform_data *pdata;
1639
1640 pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
1641 if (!pdata) {
1642 pr_err("unable to allocate memory for platform data\n");
1643 return ERR_PTR(-ENOMEM);
1644 }
1645
1646 ret = of_property_read_u32(node, "qcom,config-gpio",
1647 &pdata->config_gpio);
1648 if (ret && ret != -EINVAL) {
1649 pr_err("Error with config_gpio property.\n");
1650 return ERR_PTR(ret);
1651 }
1652
1653 if (pdata->config_gpio) {
1654 pdata->uart_tx_gpio = of_get_named_gpio(node,
1655 "qcom,tx-gpio", 0);
1656 if (pdata->uart_tx_gpio < 0)
1657 return ERR_PTR(pdata->uart_tx_gpio);
1658
1659 pdata->uart_rx_gpio = of_get_named_gpio(node,
1660 "qcom,rx-gpio", 0);
1661 if (pdata->uart_rx_gpio < 0)
1662 return ERR_PTR(pdata->uart_rx_gpio);
1663
1664 /* check if 4-wire UART, then get cts/rfr GPIOs. */
1665 if (pdata->config_gpio == 4) {
1666 pdata->uart_cts_gpio = of_get_named_gpio(node,
1667 "qcom,cts-gpio", 0);
1668 if (pdata->uart_cts_gpio < 0)
1669 return ERR_PTR(pdata->uart_cts_gpio);
1670
1671 pdata->uart_rfr_gpio = of_get_named_gpio(node,
1672 "qcom,rfr-gpio", 0);
1673 if (pdata->uart_rfr_gpio < 0)
1674 return ERR_PTR(pdata->uart_rfr_gpio);
1675 }
1676 }
1677
Mayank Ranaa9c20892012-12-13 11:35:52 +05301678 pdata->use_pm = of_property_read_bool(node, "qcom,use-pm");
1679
Mayank Rana9fc393d2012-12-04 19:10:36 +05301680 return pdata;
1681}
1682
Sathish Ambley3d50c762011-10-25 15:26:00 -07001683static atomic_t msm_serial_hsl_next_id = ATOMIC_INIT(0);
1684
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001685static int __devinit msm_serial_hsl_probe(struct platform_device *pdev)
1686{
1687 struct msm_hsl_port *msm_hsl_port;
1688 struct resource *uart_resource;
1689 struct resource *gsbi_resource;
1690 struct uart_port *port;
Mayank Rana9fc393d2012-12-04 19:10:36 +05301691 struct msm_serial_hslite_platform_data *pdata;
Sathish Ambley99e2a242011-10-25 15:49:53 -07001692 const struct of_device_id *match;
Stepan Moskovchenko5e023432012-10-25 18:44:17 -07001693 u32 line;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001694 int ret;
1695
Sathish Ambley3d50c762011-10-25 15:26:00 -07001696 if (pdev->id == -1)
1697 pdev->id = atomic_inc_return(&msm_serial_hsl_next_id) - 1;
1698
Stepan Moskovchenko5e023432012-10-25 18:44:17 -07001699 /* Use line (ttyHSLx) number from pdata or device tree if specified */
1700 pdata = pdev->dev.platform_data;
1701 if (pdata)
1702 line = pdata->line;
1703 else
1704 line = pdev->id;
1705
Stepan Moskovchenko37ac2582012-11-14 20:01:34 -08001706 /* Use line number from device tree alias if present */
1707 if (pdev->dev.of_node) {
Mayank Rana9fc393d2012-12-04 19:10:36 +05301708 dev_dbg(&pdev->dev, "device tree enabled\n");
Stepan Moskovchenko37ac2582012-11-14 20:01:34 -08001709 ret = of_alias_get_id(pdev->dev.of_node, "serial");
1710 if (ret >= 0)
1711 line = ret;
Mayank Rana9fc393d2012-12-04 19:10:36 +05301712
1713 pdata = msm_hsl_dt_to_pdata(pdev);
1714 if (IS_ERR(pdata))
1715 return PTR_ERR(pdata);
1716
1717 pdev->dev.platform_data = pdata;
Stepan Moskovchenko37ac2582012-11-14 20:01:34 -08001718 }
Stepan Moskovchenko5e023432012-10-25 18:44:17 -07001719
1720 if (unlikely(line < 0 || line >= UART_NR))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001721 return -ENXIO;
1722
Mayank Rana1295c082012-12-03 13:56:12 +05301723 pr_info("detected port #%d (ttyHSL%d)\n", pdev->id, line);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001724
Stepan Moskovchenko5e023432012-10-25 18:44:17 -07001725 port = get_port_from_line(line);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001726 port->dev = &pdev->dev;
Mayank Rana1295c082012-12-03 13:56:12 +05301727 port->uartclk = 7372800;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001728 msm_hsl_port = UART_TO_MSM(port);
1729
Saket Saurabh4e885be2013-03-29 17:39:51 +05301730 msm_hsl_port->clk = clk_get(&pdev->dev, "core_clk");
1731 if (unlikely(IS_ERR(msm_hsl_port->clk))) {
1732 ret = PTR_ERR(msm_hsl_port->clk);
1733 if (ret != -EPROBE_DEFER)
1734 pr_err("Error getting clk\n");
1735 return ret;
1736 }
1737
1738 /* Interface clock is not required by all UART configurations.
1739 * GSBI UART and BLSP UART needs interface clock but Legacy UART
1740 * do not require interface clock. Hence, do not fail probe with
1741 * iface clk_get failure.
1742 */
1743 msm_hsl_port->pclk = clk_get(&pdev->dev, "iface_clk");
1744 if (unlikely(IS_ERR(msm_hsl_port->pclk))) {
1745 ret = PTR_ERR(msm_hsl_port->pclk);
1746 if (ret == -EPROBE_DEFER) {
1747 clk_put(msm_hsl_port->clk);
1748 return ret;
1749 } else {
1750 msm_hsl_port->pclk = NULL;
1751 }
1752 }
1753
Mayank Rana9fc393d2012-12-04 19:10:36 +05301754 /* Identify UART functional mode as 2-wire or 4-wire. */
1755 if (pdata && pdata->config_gpio == 4)
1756 msm_hsl_port->func_mode = UART_FOUR_WIRE;
Sathish Ambley99e2a242011-10-25 15:49:53 -07001757 else
Mayank Rana9fc393d2012-12-04 19:10:36 +05301758 msm_hsl_port->func_mode = UART_TWO_WIRE;
1759
1760 match = of_match_device(msm_hsl_match_table, &pdev->dev);
1761 if (!match) {
1762 msm_hsl_port->ver_id = UARTDM_VERSION_11_13;
1763 } else {
Sathish Ambley99e2a242011-10-25 15:49:53 -07001764 msm_hsl_port->ver_id = (unsigned int)match->data;
Mayank Rana9fc393d2012-12-04 19:10:36 +05301765 /*
1766 * BLSP based UART configuration is available with
1767 * UARTDM v14 Revision. Hence set uart_type as UART_BLSP.
1768 */
1769 msm_hsl_port->uart_type = BLSP_HSUART;
Mayank Rana0e05b8b2013-01-22 17:14:40 +05301770
1771 msm_hsl_port->bus_scale_table = msm_bus_cl_get_pdata(pdev);
1772 if (!msm_hsl_port->bus_scale_table) {
1773 pr_err("Bus scaling is disabled\n");
1774 } else {
1775 msm_hsl_port->bus_perf_client =
1776 msm_bus_scale_register_client(
1777 msm_hsl_port->bus_scale_table);
1778 if (IS_ERR(&msm_hsl_port->bus_perf_client)) {
1779 pr_err("Bus client register failed.\n");
1780 ret = -EINVAL;
1781 goto err;
1782 }
1783 }
Mayank Rana9fc393d2012-12-04 19:10:36 +05301784 }
Sathish Ambley99e2a242011-10-25 15:49:53 -07001785
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001786 gsbi_resource = platform_get_resource_byname(pdev,
1787 IORESOURCE_MEM,
1788 "gsbi_resource");
Sathish Ambley3d50c762011-10-25 15:26:00 -07001789 if (!gsbi_resource)
1790 gsbi_resource = platform_get_resource(pdev, IORESOURCE_MEM, 1);
Stepan Moskovchenko05d31ae2012-08-08 17:33:30 -07001791
1792 if (gsbi_resource)
Mayank Rana9fc393d2012-12-04 19:10:36 +05301793 msm_hsl_port->uart_type = GSBI_HSUART;
Stepan Moskovchenko05d31ae2012-08-08 17:33:30 -07001794 else
Mayank Rana9fc393d2012-12-04 19:10:36 +05301795 msm_hsl_port->uart_type = LEGACY_HSUART;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001796
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001797
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001798 uart_resource = platform_get_resource_byname(pdev,
1799 IORESOURCE_MEM,
1800 "uartdm_resource");
Sathish Ambley3d50c762011-10-25 15:26:00 -07001801 if (!uart_resource)
1802 uart_resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001803 if (unlikely(!uart_resource)) {
Mayank Rana1295c082012-12-03 13:56:12 +05301804 pr_err("getting uartdm_resource failed\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001805 return -ENXIO;
1806 }
1807 port->mapbase = uart_resource->start;
1808
1809 port->irq = platform_get_irq(pdev, 0);
Mayank Rana72fef232011-09-28 12:42:57 +05301810 if (unlikely((int)port->irq < 0)) {
Mayank Rana1295c082012-12-03 13:56:12 +05301811 pr_err("getting irq failed\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001812 return -ENXIO;
1813 }
1814
1815 device_set_wakeup_capable(&pdev->dev, 1);
1816 platform_set_drvdata(pdev, port);
1817 pm_runtime_enable(port->dev);
Mayank Rana930c99c2011-09-05 18:22:02 +05301818#ifdef CONFIG_SERIAL_MSM_HSL_CONSOLE
1819 ret = device_create_file(&pdev->dev, &dev_attr_console);
1820 if (unlikely(ret))
Mayank Rana1295c082012-12-03 13:56:12 +05301821 pr_err("Can't create console attribute\n");
Mayank Rana930c99c2011-09-05 18:22:02 +05301822#endif
Stepan Moskovchenko798fe552012-03-29 19:47:19 -07001823 msm_hsl_debugfs_init(msm_hsl_port, get_line(pdev));
Mayank Rana44659372012-12-03 17:59:45 +05301824 mutex_init(&msm_hsl_port->clk_mutex);
Mayank Ranaa9c20892012-12-13 11:35:52 +05301825 if (pdata && pdata->use_pm)
1826 wake_lock_init(&msm_hsl_port->port_open_wake_lock,
1827 WAKE_LOCK_SUSPEND,
1828 "msm_serial_hslite_port_open");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001829
Stepan Moskovchenko72029d62011-08-23 17:08:55 -07001830 /* Temporarily increase the refcount on the GSBI clock to avoid a race
1831 * condition with the earlyprintk handover mechanism.
1832 */
1833 if (msm_hsl_port->pclk)
Mayank Rana5d0252a2012-01-24 13:58:43 +05301834 clk_prepare_enable(msm_hsl_port->pclk);
Stepan Moskovchenko72029d62011-08-23 17:08:55 -07001835 ret = uart_add_one_port(&msm_hsl_uart_driver, port);
1836 if (msm_hsl_port->pclk)
Mayank Rana5d0252a2012-01-24 13:58:43 +05301837 clk_disable_unprepare(msm_hsl_port->pclk);
Mayank Rana0e05b8b2013-01-22 17:14:40 +05301838
1839err:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001840 return ret;
1841}
1842
1843static int __devexit msm_serial_hsl_remove(struct platform_device *pdev)
1844{
1845 struct msm_hsl_port *msm_hsl_port = platform_get_drvdata(pdev);
Mayank Ranaa9c20892012-12-13 11:35:52 +05301846 const struct msm_serial_hslite_platform_data *pdata =
1847 pdev->dev.platform_data;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001848 struct uart_port *port;
1849
Stepan Moskovchenko798fe552012-03-29 19:47:19 -07001850 port = get_port_from_line(get_line(pdev));
Mayank Rana930c99c2011-09-05 18:22:02 +05301851#ifdef CONFIG_SERIAL_MSM_HSL_CONSOLE
1852 device_remove_file(&pdev->dev, &dev_attr_console);
1853#endif
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001854 pm_runtime_put_sync(&pdev->dev);
1855 pm_runtime_disable(&pdev->dev);
1856
Mayank Ranaa9c20892012-12-13 11:35:52 +05301857 if (pdata && pdata->use_pm)
1858 wake_lock_destroy(&msm_hsl_port->port_open_wake_lock);
1859
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001860 device_set_wakeup_capable(&pdev->dev, 0);
1861 platform_set_drvdata(pdev, NULL);
Mayank Rana44659372012-12-03 17:59:45 +05301862 mutex_destroy(&msm_hsl_port->clk_mutex);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001863 uart_remove_one_port(&msm_hsl_uart_driver, port);
1864
1865 clk_put(msm_hsl_port->pclk);
1866 clk_put(msm_hsl_port->clk);
Mayank Rana8dddd752011-07-13 11:19:58 +05301867 debugfs_remove(msm_hsl_port->loopback_dir);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001868
1869 return 0;
1870}
1871
1872#ifdef CONFIG_PM
1873static int msm_serial_hsl_suspend(struct device *dev)
1874{
1875 struct platform_device *pdev = to_platform_device(dev);
1876 struct uart_port *port;
Stepan Moskovchenko798fe552012-03-29 19:47:19 -07001877 port = get_port_from_line(get_line(pdev));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001878
1879 if (port) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001880
1881 if (is_console(port))
1882 msm_hsl_deinit_clock(port);
Mayank Rana70a8e7d2011-09-02 14:29:18 +05301883
1884 uart_suspend_port(&msm_hsl_uart_driver, port);
1885 if (device_may_wakeup(dev))
1886 enable_irq_wake(port->irq);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001887 }
1888
1889 return 0;
1890}
1891
1892static int msm_serial_hsl_resume(struct device *dev)
1893{
1894 struct platform_device *pdev = to_platform_device(dev);
1895 struct uart_port *port;
Stepan Moskovchenko798fe552012-03-29 19:47:19 -07001896 port = get_port_from_line(get_line(pdev));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001897
1898 if (port) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001899
Mayank Rana70a8e7d2011-09-02 14:29:18 +05301900 uart_resume_port(&msm_hsl_uart_driver, port);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001901 if (device_may_wakeup(dev))
1902 disable_irq_wake(port->irq);
Mayank Rana70a8e7d2011-09-02 14:29:18 +05301903
1904 if (is_console(port))
1905 msm_hsl_init_clock(port);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001906 }
1907
1908 return 0;
1909}
1910#else
1911#define msm_serial_hsl_suspend NULL
1912#define msm_serial_hsl_resume NULL
1913#endif
1914
1915static int msm_hsl_runtime_suspend(struct device *dev)
1916{
1917 struct platform_device *pdev = to_platform_device(dev);
1918 struct uart_port *port;
Stepan Moskovchenko798fe552012-03-29 19:47:19 -07001919 port = get_port_from_line(get_line(pdev));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001920
1921 dev_dbg(dev, "pm_runtime: suspending\n");
1922 msm_hsl_deinit_clock(port);
1923 return 0;
1924}
1925
1926static int msm_hsl_runtime_resume(struct device *dev)
1927{
1928 struct platform_device *pdev = to_platform_device(dev);
1929 struct uart_port *port;
Stepan Moskovchenko798fe552012-03-29 19:47:19 -07001930 port = get_port_from_line(get_line(pdev));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001931
1932 dev_dbg(dev, "pm_runtime: resuming\n");
1933 msm_hsl_init_clock(port);
1934 return 0;
1935}
1936
1937static struct dev_pm_ops msm_hsl_dev_pm_ops = {
1938 .suspend = msm_serial_hsl_suspend,
1939 .resume = msm_serial_hsl_resume,
1940 .runtime_suspend = msm_hsl_runtime_suspend,
1941 .runtime_resume = msm_hsl_runtime_resume,
1942};
1943
1944static struct platform_driver msm_hsl_platform_driver = {
1945 .probe = msm_serial_hsl_probe,
1946 .remove = __devexit_p(msm_serial_hsl_remove),
1947 .driver = {
1948 .name = "msm_serial_hsl",
1949 .owner = THIS_MODULE,
1950 .pm = &msm_hsl_dev_pm_ops,
Sathish Ambley3d50c762011-10-25 15:26:00 -07001951 .of_match_table = msm_hsl_match_table,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001952 },
1953};
1954
1955static int __init msm_serial_hsl_init(void)
1956{
1957 int ret;
1958
1959 ret = uart_register_driver(&msm_hsl_uart_driver);
1960 if (unlikely(ret))
1961 return ret;
1962
Mayank Rana8dddd752011-07-13 11:19:58 +05301963 debug_base = debugfs_create_dir("msm_serial_hsl", NULL);
1964 if (IS_ERR_OR_NULL(debug_base))
Mayank Rana1295c082012-12-03 13:56:12 +05301965 pr_err("Cannot create debugfs dir\n");
Mayank Rana8dddd752011-07-13 11:19:58 +05301966
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001967 ret = platform_driver_register(&msm_hsl_platform_driver);
1968 if (unlikely(ret))
1969 uart_unregister_driver(&msm_hsl_uart_driver);
1970
Mayank Rana1295c082012-12-03 13:56:12 +05301971 pr_info("driver initialized\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001972
1973 return ret;
1974}
1975
1976static void __exit msm_serial_hsl_exit(void)
1977{
Mayank Rana8dddd752011-07-13 11:19:58 +05301978 debugfs_remove_recursive(debug_base);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001979#ifdef CONFIG_SERIAL_MSM_HSL_CONSOLE
1980 unregister_console(&msm_hsl_console);
1981#endif
1982 platform_driver_unregister(&msm_hsl_platform_driver);
1983 uart_unregister_driver(&msm_hsl_uart_driver);
1984}
1985
1986module_init(msm_serial_hsl_init);
1987module_exit(msm_serial_hsl_exit);
1988
1989MODULE_DESCRIPTION("Driver for msm HSUART serial device");
1990MODULE_LICENSE("GPL v2");