msm: sdio: Add a new sdio tty csvt device.
This tty device exposes the SDIO_CSVT channel to user space.
It serves as a data channel for video telephony.
Change-Id: Idc3dd892a0fcb450084a2af9da8e95c2d842c5ab
Signed-off-by: Venkat Gopalakrishnan <venkatg@codeaurora.org>
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 7e29383..05f4ab4 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -103,7 +103,7 @@
endif
endif
endif
-obj-$(CONFIG_MSM_SDIO_TTY) += sdio_tty.o sdio_tty_ciq.o
+obj-$(CONFIG_MSM_SDIO_TTY) += sdio_tty.o
obj-$(CONFIG_MSM_SMD_TTY) += smd_tty.o
obj-$(CONFIG_MSM_SMD_QMI) += smd_qmi.o
obj-$(CONFIG_MSM_SMD_PKT) += smd_pkt.o
diff --git a/arch/arm/mach-msm/include/mach/sdio_tty.h b/arch/arm/mach-msm/include/mach/sdio_tty.h
deleted file mode 100644
index 86746b3..0000000
--- a/arch/arm/mach-msm/include/mach/sdio_tty.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-/*
- * SDIO TTY interface.
- */
-
-#ifndef __SDIO_TTY__
-#define __SDIO_TTY__
-
-/**
- * sdio_tty_init_tty - Initialize the SDIO TTY driver.
- *
- * @tty_name: tty name - identify the tty device.
- * @sdio_ch_name: channel name - identify the channel.
- * @return sdio_tty handle on success, NULL on error.
- *
- */
-void *sdio_tty_init_tty(char *tty_name, char* sdio_ch_name);
-
-/**
- * sdio_tty_uninit_tty - Uninitialize the SDIO TTY driver.
- *
- * @sdio_tty_handle: sdio_tty handle.
- * @return 0 on success, negative value on error.
- */
-int sdio_tty_uninit_tty(void *sdio_tty_handle);
-
-/**
- * sdio_tty_enable_debug_msg - Enable/Disable sdio_tty debug
- * messages.
- *
- * @enable: A flag to indicate if to enable or disable the debug
- * messages.
- * @return 0 on success, negative value on error.
- */
-void sdio_tty_enable_debug_msg(void *sdio_tty_handle, int enable);
-
-#endif /* __SDIO_TTY__ */
diff --git a/arch/arm/mach-msm/sdio_al_test.c b/arch/arm/mach-msm/sdio_al_test.c
index 8b9abcf..a71aae3 100644
--- a/arch/arm/mach-msm/sdio_al_test.c
+++ b/arch/arm/mach-msm/sdio_al_test.c
@@ -298,6 +298,7 @@
uint32_t smem_counter;
struct platform_device *ciq_app_pdev;
+ struct platform_device *csvt_app_pdev;
wait_queue_head_t wait_q;
int test_completed;
@@ -6162,7 +6163,7 @@
int ret;
pr_debug(TEST_MODULE_NAME ":%s.\n", __func__);
- pr_info(TEST_MODULE_NAME ": init test cahnnel %s.\n", name);
+ pr_info(TEST_MODULE_NAME ": init test channel %s.\n", name);
ch_id = channel_name_to_id(name);
pr_debug(TEST_MODULE_NAME ":id = %d.\n", ch_id);
@@ -6324,6 +6325,35 @@
return sdio_test_channel_remove(pdev);
}
+static int sdio_test_channel_csvt_probe(struct platform_device *pdev)
+{
+ int ret = 0;
+
+ if (!pdev)
+ return -ENODEV;
+
+ test_ctx->csvt_app_pdev = platform_device_alloc("SDIO_CSVT_TEST_APP",
+ -1);
+ ret = platform_device_add(test_ctx->csvt_app_pdev);
+ if (ret) {
+ pr_err(MODULE_NAME ":platform_device_add failed, "
+ "ret=%d\n", ret);
+ return ret;
+ }
+
+ return sdio_test_channel_probe(pdev);
+}
+
+static int sdio_test_channel_csvt_remove(struct platform_device *pdev)
+{
+ if (!pdev)
+ return -ENODEV;
+
+ platform_device_unregister(test_ctx->csvt_app_pdev);
+
+ return sdio_test_channel_remove(pdev);
+}
+
static struct platform_driver sdio_rpc_drv = {
.probe = sdio_test_channel_probe,
.remove = sdio_test_channel_remove,
@@ -6388,8 +6418,8 @@
};
static struct platform_driver sdio_csvt_drv = {
- .probe = sdio_test_channel_probe,
- .remove = sdio_test_channel_remove,
+ .probe = sdio_test_channel_csvt_probe,
+ .remove = sdio_test_channel_csvt_remove,
.driver = {
.name = "SDIO_CSVT_TEST",
.owner = THIS_MODULE,
diff --git a/arch/arm/mach-msm/sdio_tty.c b/arch/arm/mach-msm/sdio_tty.c
index fca88d8..e249d06 100644
--- a/arch/arm/mach-msm/sdio_tty.c
+++ b/arch/arm/mach-msm/sdio_tty.c
@@ -17,6 +17,7 @@
#include <linux/platform_device.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
+#include <linux/module.h>
#include <mach/sdio_al.h>
#define INPUT_SPEED 4800
@@ -24,6 +25,19 @@
#define SDIO_TTY_MODULE_NAME "sdio_tty"
#define SDIO_TTY_MAX_PACKET_SIZE 4096
#define MAX_SDIO_TTY_DRV 1
+#define MAX_SDIO_TTY_DEVS 2
+#define MAX_SDIO_TTY_DEV_NAME_SIZE 25
+
+/* Configurations per channel device */
+/* CIQ */
+#define SDIO_TTY_CIQ_DEV "sdio_tty_ciq_0"
+#define SDIO_TTY_CIQ_TEST_DEV "sdio_tty_ciq_test_0"
+#define SDIO_TTY_CH_CIQ "SDIO_CIQ"
+
+/* CSVT */
+#define SDIO_TTY_CSVT_DEV "sdio_tty_csvt_0"
+#define SDIO_TTY_CSVT_TEST_DEV "sdio_tty_csvt_test_0"
+#define SDIO_TTY_CH_CSVT "SDIO_CSVT"
enum sdio_tty_state {
TTY_INITIAL = 0,
@@ -32,9 +46,27 @@
TTY_CLOSED = 3,
};
+enum sdio_tty_devices {
+ SDIO_CIQ,
+ SDIO_CIQ_TEST_APP,
+ SDIO_CSVT,
+ SDIO_CSVT_TEST_APP,
+};
+
+static const struct platform_device_id sdio_tty_id_table[] = {
+ { "SDIO_CIQ", SDIO_CIQ },
+ { "SDIO_CIQ_TEST_APP", SDIO_CIQ_TEST_APP },
+ { "SDIO_CSVT", SDIO_CSVT },
+ { "SDIO_CSVT_TEST_APP", SDIO_CSVT_TEST_APP },
+ { },
+};
+MODULE_DEVICE_TABLE(platform, sdio_tty_id_table);
+
struct sdio_tty {
struct sdio_channel *ch;
char *sdio_ch_name;
+ char tty_dev_name[MAX_SDIO_TTY_DEV_NAME_SIZE];
+ int device_id;
struct workqueue_struct *workq;
struct work_struct work_read;
wait_queue_head_t waitq;
@@ -44,11 +76,21 @@
char *read_buf;
enum sdio_tty_state sdio_tty_state;
int is_sdio_open;
+ int tty_open_count;
};
-static struct sdio_tty *sdio_tty;
+static struct sdio_tty *sdio_tty[MAX_SDIO_TTY_DEVS];
-#define DEBUG_MSG(sdio_tty, x...) if (sdio_tty->debug_msg_on) pr_info(x)
+#define DEBUG_MSG(sdio_tty_drv, x...) if (sdio_tty_drv->debug_msg_on) pr_info(x)
+
+/*
+ * Enable sdio_tty debug messages
+ * By default the sdio_tty debug messages are turned off
+ */
+static int ciq_debug_msg_on;
+module_param(ciq_debug_msg_on, int, 0);
+static int csvt_debug_msg_on;
+module_param(csvt_debug_msg_on, int, 0);
static void sdio_tty_read(struct work_struct *work)
{
@@ -62,30 +104,30 @@
sdio_tty_drv = container_of(work, struct sdio_tty, work_read);
if (!sdio_tty_drv) {
- pr_err(SDIO_TTY_MODULE_NAME ": %s: NULL sdio_tty",
- __func__);
+ pr_err(SDIO_TTY_MODULE_NAME ": %s: NULL sdio_tty", __func__);
return ;
}
if (sdio_tty_drv->sdio_tty_state != TTY_OPENED) {
pr_err(SDIO_TTY_MODULE_NAME ": %s: sdio_tty_state = %d",
- __func__, sdio_tty_drv->sdio_tty_state);
+ __func__, sdio_tty_drv->sdio_tty_state);
return;
}
if (!sdio_tty_drv->read_buf) {
- pr_err(SDIO_TTY_MODULE_NAME ": %s: NULL read_buf", __func__);
+ pr_err(SDIO_TTY_MODULE_NAME ": %s: NULL read_buf for dev %s",
+ __func__, sdio_tty_drv->tty_dev_name);
return;
}
- /* Read the data from teh SDIO channel as long as there is available
+ /* Read the data from the SDIO channel as long as there is available
data */
while (1) {
if (test_bit(TTY_THROTTLED, &sdio_tty_drv->tty_str->flags)) {
- DEBUG_MSG(sdio_tty_drv,
- SDIO_TTY_MODULE_NAME ": %s: TTY_THROTTLED bit"
- " is set, exit",
- __func__);
+ DEBUG_MSG(sdio_tty_drv, SDIO_TTY_MODULE_NAME
+ ": %s: TTY_THROTTLED bit is set for "
+ "dev %s, exit", __func__,
+ sdio_tty_drv->tty_dev_name);
return;
}
@@ -93,20 +135,22 @@
read_avail = sdio_read_avail(sdio_tty_drv->ch);
DEBUG_MSG(sdio_tty_drv, SDIO_TTY_MODULE_NAME
- ": %s: read_avail is %d", __func__,
- read_avail);
+ ": %s: read_avail is %d for dev %s", __func__,
+ read_avail, sdio_tty_drv->tty_dev_name);
if (read_avail == 0) {
- DEBUG_MSG(sdio_tty_drv,
- SDIO_TTY_MODULE_NAME ": %s: read_avail is 0",
- __func__);
+ DEBUG_MSG(sdio_tty_drv, SDIO_TTY_MODULE_NAME
+ ": %s: read_avail is 0 for dev %s",
+ __func__, sdio_tty_drv->tty_dev_name);
return;
}
if (read_avail > SDIO_TTY_MAX_PACKET_SIZE) {
pr_err(SDIO_TTY_MODULE_NAME ": %s: read_avail(%d) is "
- "bigger than SDIO_TTY_MAX_PACKET_SIZE(%d)",
- __func__, read_avail, SDIO_TTY_MAX_PACKET_SIZE);
+ "bigger than SDIO_TTY_MAX_PACKET_SIZE(%d) "
+ "for dev %s", __func__, read_avail,
+ SDIO_TTY_MAX_PACKET_SIZE,
+ sdio_tty_drv->tty_dev_name);
return;
}
@@ -114,8 +158,9 @@
sdio_tty_drv->read_buf,
read_avail);
if (ret < 0) {
- pr_err(SDIO_TTY_MODULE_NAME ": %s: sdio_read error(%d)",
- __func__, ret);
+ pr_err(SDIO_TTY_MODULE_NAME ": %s: sdio_read error(%d) "
+ "for dev %s", __func__, ret,
+ sdio_tty_drv->tty_dev_name);
return;
}
@@ -132,15 +177,17 @@
if (total_push != read_avail) {
pr_err(SDIO_TTY_MODULE_NAME ": %s: failed, total_push"
- "(%d) != read_avail(%d)\n",
- __func__, total_push, read_avail);
+ "(%d) != read_avail(%d) for dev %s\n",
+ __func__, total_push, read_avail,
+ sdio_tty_drv->tty_dev_name);
}
tty_flip_buffer_push(sdio_tty_drv->tty_str);
- DEBUG_MSG(sdio_tty_drv,
- SDIO_TTY_MODULE_NAME ": %s: End of read %d bytes",
- __func__, read_avail);
+ DEBUG_MSG(sdio_tty_drv, SDIO_TTY_MODULE_NAME
+ ": %s: End of read %d bytes for dev %s",
+ __func__, read_avail,
+ sdio_tty_drv->tty_dev_name);
}
}
@@ -159,27 +206,26 @@
struct sdio_tty *sdio_tty_drv = NULL;
if (!tty) {
- pr_err(SDIO_TTY_MODULE_NAME ": %s: NULL tty",
- __func__);
+ pr_err(SDIO_TTY_MODULE_NAME ": %s: NULL tty", __func__);
return -ENODEV;
}
sdio_tty_drv = tty->driver_data;
if (!sdio_tty_drv) {
pr_err(SDIO_TTY_MODULE_NAME ": %s: NULL sdio_tty_drv",
- __func__);
+ __func__);
return -ENODEV;
}
if (sdio_tty_drv->sdio_tty_state != TTY_OPENED) {
pr_err(SDIO_TTY_MODULE_NAME ": %s: sdio_tty_state = %d",
- __func__, sdio_tty_drv->sdio_tty_state);
+ __func__, sdio_tty_drv->sdio_tty_state);
return -EPERM;
}
write_avail = sdio_write_avail(sdio_tty_drv->ch);
- DEBUG_MSG(sdio_tty_drv,
- SDIO_TTY_MODULE_NAME ": %s: write_avail=%d",
- __func__, write_avail);
+ DEBUG_MSG(sdio_tty_drv, SDIO_TTY_MODULE_NAME ": %s: write_avail=%d "
+ "for dev %s", __func__, write_avail,
+ sdio_tty_drv->tty_dev_name);
return write_avail;
}
@@ -205,60 +251,60 @@
struct sdio_tty *sdio_tty_drv = NULL;
if (!tty) {
- pr_err(SDIO_TTY_MODULE_NAME ": %s: NULL tty",
- __func__);
+ pr_err(SDIO_TTY_MODULE_NAME ": %s: NULL tty", __func__);
return -ENODEV;
}
sdio_tty_drv = tty->driver_data;
if (!sdio_tty_drv) {
pr_err(SDIO_TTY_MODULE_NAME ": %s: NULL sdio_tty_drv",
- __func__);
+ __func__);
return -ENODEV;
}
if (sdio_tty_drv->sdio_tty_state != TTY_OPENED) {
pr_err(SDIO_TTY_MODULE_NAME ": %s: sdio_tty_state = %d",
- __func__, sdio_tty_drv->sdio_tty_state);
+ __func__, sdio_tty_drv->sdio_tty_state);
return -EPERM;
}
- DEBUG_MSG(sdio_tty_drv,
- SDIO_TTY_MODULE_NAME ": %s: WRITING CALLBACK CALLED WITH "
- "%d bytes\n",
- __func__, count);
+ DEBUG_MSG(sdio_tty_drv, SDIO_TTY_MODULE_NAME ": %s: Write Callback "
+ "called with %d bytes for dev %s\n", __func__, count,
+ sdio_tty_drv->tty_dev_name);
write_avail = sdio_write_avail(sdio_tty_drv->ch);
if (write_avail == 0) {
- DEBUG_MSG(sdio_tty_drv,
- SDIO_TTY_MODULE_NAME ": %s: write_avail is 0\n",
- __func__);
+ DEBUG_MSG(sdio_tty_drv, SDIO_TTY_MODULE_NAME ": %s: "
+ "write_avail is 0 for dev %s\n",
+ __func__, sdio_tty_drv->tty_dev_name);
return 0;
}
if (write_avail > SDIO_TTY_MAX_PACKET_SIZE) {
- DEBUG_MSG(sdio_tty_drv,
- SDIO_TTY_MODULE_NAME ": %s: write_avail(%d) is "
- "bigger than max packet size,(%d), setting to "
- "max_packet_size\n",
- __func__, write_avail, SDIO_TTY_MAX_PACKET_SIZE);
+ DEBUG_MSG(sdio_tty_drv, SDIO_TTY_MODULE_NAME ": %s: "
+ "write_avail(%d) is bigger than max packet "
+ "size(%d) for dev %s, setting to "
+ "max_packet_size\n", __func__, write_avail,
+ SDIO_TTY_MAX_PACKET_SIZE,
+ sdio_tty_drv->tty_dev_name);
write_avail = SDIO_TTY_MAX_PACKET_SIZE;
}
if (write_avail < count) {
- DEBUG_MSG(sdio_tty_drv,
- SDIO_TTY_MODULE_NAME ": %s: write_avail(%d) is "
- "smaller than "
- "required(%d), writing only %d bytes\n",
- __func__, write_avail, count, write_avail);
+ DEBUG_MSG(sdio_tty_drv, SDIO_TTY_MODULE_NAME ": %s: "
+ "write_avail(%d) is smaller than required(%d) "
+ "for dev %s, writing only %d bytes\n",
+ __func__, write_avail, count,
+ sdio_tty_drv->tty_dev_name, write_avail);
len = write_avail;
}
ret = sdio_write(sdio_tty_drv->ch, buf, len);
if (ret) {
- pr_err(SDIO_TTY_MODULE_NAME ": %s: sdio_write failed, ret=%d\n",
- __func__, ret);
+ pr_err(SDIO_TTY_MODULE_NAME ": %s: sdio_write failed for "
+ "dev %s, ret=%d\n", __func__,
+ sdio_tty_drv->tty_dev_name, ret);
return 0;
}
- DEBUG_MSG(sdio_tty_drv,
- SDIO_TTY_MODULE_NAME ": %s: End of function, len=%d bytes\n",
- __func__, len);
+ DEBUG_MSG(sdio_tty_drv, SDIO_TTY_MODULE_NAME ": %s: End of function, "
+ "dev=%s, len=%d bytes\n", __func__,
+ sdio_tty_drv->tty_dev_name, len);
return len;
}
@@ -269,18 +315,18 @@
if (!sdio_tty_drv) {
pr_err(SDIO_TTY_MODULE_NAME ": %s: NULL sdio_tty_drv",
- __func__);
+ __func__);
}
if (sdio_tty_drv->sdio_tty_state != TTY_OPENED) {
pr_err(SDIO_TTY_MODULE_NAME ": %s: sdio_tty_state = %d",
- __func__, sdio_tty_drv->sdio_tty_state);
+ __func__, sdio_tty_drv->sdio_tty_state);
return;
}
- DEBUG_MSG(sdio_tty_drv,
- SDIO_TTY_MODULE_NAME ": %s: event %d received\n", __func__,
- event);
+ DEBUG_MSG(sdio_tty_drv, SDIO_TTY_MODULE_NAME ": %s: event %d "
+ "received for dev %s\n", __func__, event,
+ sdio_tty_drv->tty_dev_name);
if (event == SDIO_EVENT_DATA_READ_AVAIL)
queue_work(sdio_tty_drv->workq, &sdio_tty_drv->work_read);
@@ -298,20 +344,37 @@
static int sdio_tty_open(struct tty_struct *tty, struct file *file)
{
int ret = 0;
+ int i = 0;
struct sdio_tty *sdio_tty_drv = NULL;
if (!tty) {
- pr_err(SDIO_TTY_MODULE_NAME ": %s: NULL tty",
- __func__);
+ pr_err(SDIO_TTY_MODULE_NAME ": %s: NULL tty", __func__);
return -ENODEV;
}
- sdio_tty_drv = sdio_tty;
+
+ for (i = 0; i < MAX_SDIO_TTY_DEVS; i++) {
+ if (sdio_tty[i] == NULL)
+ continue;
+ if (!strncmp(sdio_tty[i]->tty_dev_name, tty->name,
+ MAX_SDIO_TTY_DEV_NAME_SIZE)) {
+ sdio_tty_drv = sdio_tty[i];
+ break;
+ }
+ }
+
if (!sdio_tty_drv) {
pr_err(SDIO_TTY_MODULE_NAME ": %s: NULL sdio_tty_drv",
__func__);
return -ENODEV;
}
+ sdio_tty_drv->tty_open_count++;
+ if (sdio_tty_drv->sdio_tty_state == TTY_OPENED) {
+ pr_err(SDIO_TTY_MODULE_NAME ": %s: tty dev(%s) is already open",
+ __func__, sdio_tty_drv->tty_dev_name);
+ return -EBUSY;
+ }
+
tty->driver_data = sdio_tty_drv;
sdio_tty_drv->tty_str = tty;
@@ -321,36 +384,31 @@
sdio_tty_drv->read_buf = kzalloc(SDIO_TTY_MAX_PACKET_SIZE, GFP_KERNEL);
if (sdio_tty_drv->read_buf == NULL) {
- pr_err(SDIO_TTY_MODULE_NAME ": %s: failed to allocate read_buf",
- __func__);
+ pr_err(SDIO_TTY_MODULE_NAME ": %s: failed to allocate read_buf "
+ "for dev %s", __func__, sdio_tty_drv->tty_dev_name);
return -ENOMEM;
}
sdio_tty_drv->workq = create_singlethread_workqueue("sdio_tty_read");
if (!sdio_tty_drv->workq) {
- pr_err(SDIO_TTY_MODULE_NAME ": %s: failed to create workq",
- __func__);
+ pr_err(SDIO_TTY_MODULE_NAME ": %s: failed to create workq "
+ "for dev %s", __func__, sdio_tty_drv->tty_dev_name);
return -ENOMEM;
}
- if (sdio_tty_drv->sdio_tty_state == TTY_OPENED) {
- pr_err(SDIO_TTY_MODULE_NAME ": %s: tty is already open",
- __func__);
- return -EBUSY;
- }
-
if (!sdio_tty_drv->is_sdio_open) {
ret = sdio_open(sdio_tty_drv->sdio_ch_name, &sdio_tty_drv->ch,
sdio_tty_drv, sdio_tty_notify);
if (ret < 0) {
- pr_err(SDIO_TTY_MODULE_NAME ": %s: sdio_open err=%d\n",
- __func__, ret);
+ pr_err(SDIO_TTY_MODULE_NAME ": %s: sdio_open err=%d "
+ "for dev %s\n", __func__, ret,
+ sdio_tty_drv->tty_dev_name);
destroy_workqueue(sdio_tty_drv->workq);
return ret;
}
- pr_info(SDIO_TTY_MODULE_NAME ": %s: SDIO_TTY channel opened\n",
- __func__);
+ pr_info(SDIO_TTY_MODULE_NAME ": %s: SDIO_TTY channel(%s) opened "
+ "\n", __func__, sdio_tty_drv->sdio_ch_name);
sdio_tty_drv->is_sdio_open = 1;
} else {
@@ -363,8 +421,8 @@
sdio_tty_drv->sdio_tty_state = TTY_OPENED;
- pr_info(SDIO_TTY_MODULE_NAME ": %s: TTY device opened\n",
- __func__);
+ pr_info(SDIO_TTY_MODULE_NAME ": %s: TTY device(%s) opened\n",
+ __func__, sdio_tty_drv->tty_dev_name);
return ret;
}
@@ -385,8 +443,7 @@
struct sdio_tty *sdio_tty_drv = NULL;
if (!tty) {
- pr_err(SDIO_TTY_MODULE_NAME ": %s: NULL tty",
- __func__);
+ pr_err(SDIO_TTY_MODULE_NAME ": %s: NULL tty", __func__);
return;
}
sdio_tty_drv = tty->driver_data;
@@ -397,10 +454,11 @@
}
if (sdio_tty_drv->sdio_tty_state != TTY_OPENED) {
pr_err(SDIO_TTY_MODULE_NAME ": %s: trying to close a "
- "TTY device that was not opened\n",
- __func__);
+ "TTY device that was not opened\n", __func__);
return;
}
+ if (--sdio_tty_drv->tty_open_count != 0)
+ return;
flush_workqueue(sdio_tty_drv->workq);
destroy_workqueue(sdio_tty_drv->workq);
@@ -410,8 +468,8 @@
sdio_tty_drv->sdio_tty_state = TTY_CLOSED;
- pr_info(SDIO_TTY_MODULE_NAME ": %s: SDIO_TTY channel closed\n",
- __func__);
+ pr_info(SDIO_TTY_MODULE_NAME ": %s: SDIO_TTY device(%s) closed\n",
+ __func__, sdio_tty_drv->tty_dev_name);
}
static void sdio_tty_unthrottle(struct tty_struct *tty)
@@ -419,8 +477,7 @@
struct sdio_tty *sdio_tty_drv = NULL;
if (!tty) {
- pr_err(SDIO_TTY_MODULE_NAME ": %s: NULL tty",
- __func__);
+ pr_err(SDIO_TTY_MODULE_NAME ": %s: NULL tty", __func__);
return;
}
sdio_tty_drv = tty->driver_data;
@@ -448,33 +505,53 @@
.unthrottle = sdio_tty_unthrottle,
};
-void *sdio_tty_init_tty(char *tty_name, char *sdio_ch_name)
+int sdio_tty_init_tty(char *tty_name, char *sdio_ch_name,
+ enum sdio_tty_devices device_id, int debug_msg_on)
{
int ret = 0;
- struct device *tty_dev;
- struct sdio_tty *sdio_tty_drv;
-
- pr_info(SDIO_TTY_MODULE_NAME ": %s\n", __func__);
+ int i = 0;
+ struct device *tty_dev = NULL;
+ struct sdio_tty *sdio_tty_drv = NULL;
sdio_tty_drv = kzalloc(sizeof(struct sdio_tty), GFP_KERNEL);
if (sdio_tty_drv == NULL) {
- pr_err(SDIO_TTY_MODULE_NAME "%s: failed to allocate sdio_tty",
- __func__);
- return NULL;
+ pr_err(SDIO_TTY_MODULE_NAME ": %s: failed to allocate sdio_tty "
+ "for dev %s", __func__, tty_name);
+ return -ENOMEM;
}
- sdio_tty = sdio_tty_drv;
+ for (i = 0; i < MAX_SDIO_TTY_DEVS; i++) {
+ if (sdio_tty[i] == NULL) {
+ sdio_tty[i] = sdio_tty_drv;
+ break;
+ }
+ }
+
+ if (i == MAX_SDIO_TTY_DEVS) {
+ pr_err(SDIO_TTY_MODULE_NAME ": %s: tty dev(%s) creation failed,"
+ " max limit(%d) reached.", __func__, tty_name,
+ MAX_SDIO_TTY_DEVS);
+ kfree(sdio_tty_drv);
+ return -ENODEV;
+ }
+
+ snprintf(sdio_tty_drv->tty_dev_name, MAX_SDIO_TTY_DEV_NAME_SIZE,
+ "%s%d", tty_name, 0);
sdio_tty_drv->sdio_ch_name = sdio_ch_name;
+ sdio_tty_drv->device_id = device_id;
+ pr_info(SDIO_TTY_MODULE_NAME ": %s: dev=%s, id=%d, channel=%s\n",
+ __func__, sdio_tty_drv->tty_dev_name, sdio_tty_drv->device_id,
+ sdio_tty_drv->sdio_ch_name);
INIT_WORK(&sdio_tty_drv->work_read, sdio_tty_read);
sdio_tty_drv->tty_drv = alloc_tty_driver(MAX_SDIO_TTY_DRV);
if (!sdio_tty_drv->tty_drv) {
- pr_err(SDIO_TTY_MODULE_NAME ": %s - tty_drv is NULL",
- __func__);
+ pr_err(SDIO_TTY_MODULE_NAME ": %s - tty_drv is NULL for dev %s",
+ __func__, sdio_tty_drv->tty_dev_name);
kfree(sdio_tty_drv);
- return NULL;
+ return -ENODEV;
}
sdio_tty_drv->tty_drv->name = tty_name;
@@ -500,31 +577,38 @@
if (ret) {
put_tty_driver(sdio_tty_drv->tty_drv);
pr_err(SDIO_TTY_MODULE_NAME ": %s: tty_register_driver() "
- "failed\n", __func__);
+ "failed for dev %s\n", __func__,
+ sdio_tty_drv->tty_dev_name);
sdio_tty_drv->tty_drv = NULL;
kfree(sdio_tty_drv);
- return NULL;
+ return -ENODEV;
}
tty_dev = tty_register_device(sdio_tty_drv->tty_drv, 0, NULL);
if (IS_ERR(tty_dev)) {
pr_err(SDIO_TTY_MODULE_NAME ": %s: tty_register_device() "
- "failed\n", __func__);
+ "failed for dev %s\n", __func__,
+ sdio_tty_drv->tty_dev_name);
tty_unregister_driver(sdio_tty_drv->tty_drv);
put_tty_driver(sdio_tty_drv->tty_drv);
kfree(sdio_tty_drv);
- return NULL;
+ return -ENODEV;
}
sdio_tty_drv->sdio_tty_state = TTY_REGISTERED;
- return sdio_tty_drv;
+ if (debug_msg_on) {
+ pr_info(SDIO_TTY_MODULE_NAME ": %s: turn on debug msg for %s",
+ __func__, sdio_tty_drv->tty_dev_name);
+ sdio_tty_drv->debug_msg_on = debug_msg_on;
+ }
+ return 0;
}
-EXPORT_SYMBOL(sdio_tty_init_tty);
int sdio_tty_uninit_tty(void *sdio_tty_handle)
{
int ret = 0;
+ int i = 0;
struct sdio_tty *sdio_tty_drv = sdio_tty_handle;
if (!sdio_tty_drv) {
@@ -546,51 +630,151 @@
ret = tty_unregister_driver(sdio_tty_drv->tty_drv);
if (ret) {
pr_err(SDIO_TTY_MODULE_NAME ": %s: "
- "tty_unregister_driver() failed\n", __func__);
+ "tty_unregister_driver() failed for dev %s\n",
+ __func__, sdio_tty_drv->tty_dev_name);
}
put_tty_driver(sdio_tty_drv->tty_drv);
sdio_tty_drv->sdio_tty_state = TTY_INITIAL;
sdio_tty_drv->tty_drv = NULL;
}
- pr_info(SDIO_TTY_MODULE_NAME ": %s: Freeing sdio_tty structure",
- __func__);
+ for (i = 0; i < MAX_SDIO_TTY_DEVS; i++) {
+ if (sdio_tty[i] == NULL)
+ continue;
+ if (sdio_tty[i]->device_id == sdio_tty_drv->device_id) {
+ sdio_tty[i] = NULL;
+ break;
+ }
+ }
+
+ DEBUG_MSG(sdio_tty_drv, SDIO_TTY_MODULE_NAME ": %s: Freeing sdio_tty "
+ "structure, dev=%s", __func__,
+ sdio_tty_drv->tty_dev_name);
kfree(sdio_tty_drv);
return 0;
}
-EXPORT_SYMBOL(sdio_tty_uninit_tty);
-
-void sdio_tty_enable_debug_msg(void *sdio_tty_handle, int enable)
+static int sdio_tty_probe(struct platform_device *pdev)
{
- struct sdio_tty *sdio_tty_drv = sdio_tty_handle;
+ const struct platform_device_id *id = platform_get_device_id(pdev);
+ enum sdio_tty_devices device_id = id->driver_data;
+ char *device_name = NULL;
+ char *channel_name = NULL;
+ int debug_msg_on = 0;
+ int ret = 0;
+
+ pr_debug(SDIO_TTY_MODULE_NAME ": %s for %s", __func__, pdev->name);
+
+ switch (device_id) {
+ case SDIO_CIQ:
+ device_name = SDIO_TTY_CIQ_DEV;
+ channel_name = SDIO_TTY_CH_CIQ;
+ debug_msg_on = ciq_debug_msg_on;
+ break;
+ case SDIO_CIQ_TEST_APP:
+ device_name = SDIO_TTY_CIQ_TEST_DEV;
+ channel_name = SDIO_TTY_CH_CIQ;
+ debug_msg_on = ciq_debug_msg_on;
+ break;
+ case SDIO_CSVT:
+ device_name = SDIO_TTY_CSVT_DEV;
+ channel_name = SDIO_TTY_CH_CSVT;
+ debug_msg_on = csvt_debug_msg_on;
+ break;
+ case SDIO_CSVT_TEST_APP:
+ device_name = SDIO_TTY_CSVT_TEST_DEV;
+ channel_name = SDIO_TTY_CH_CSVT;
+ debug_msg_on = csvt_debug_msg_on;
+ break;
+ default:
+ pr_err(SDIO_TTY_MODULE_NAME ": %s Invalid device:%s, id:%d",
+ __func__, pdev->name, device_id);
+ ret = -ENODEV;
+ break;
+ }
+
+ if (device_name) {
+ ret = sdio_tty_init_tty(device_name, channel_name,
+ device_id, debug_msg_on);
+ if (ret) {
+ pr_err(SDIO_TTY_MODULE_NAME ": %s: sdio_tty_init_tty "
+ "failed for dev:%s", __func__, device_name);
+ }
+ }
+ return ret;
+}
+
+static int sdio_tty_remove(struct platform_device *pdev)
+{
+ const struct platform_device_id *id = platform_get_device_id(pdev);
+ enum sdio_tty_devices device_id = id->driver_data;
+ struct sdio_tty *sdio_tty_drv = NULL;
+ int i = 0;
+ int ret = 0;
+
+ pr_debug(SDIO_TTY_MODULE_NAME ": %s for %s", __func__, pdev->name);
+
+ for (i = 0; i < MAX_SDIO_TTY_DEVS; i++) {
+ if (sdio_tty[i] == NULL)
+ continue;
+ if (sdio_tty[i]->device_id == device_id) {
+ sdio_tty_drv = sdio_tty[i];
+ break;
+ }
+ }
if (!sdio_tty_drv) {
pr_err(SDIO_TTY_MODULE_NAME ": %s: NULL sdio_tty_drv",
__func__);
- return;
+ return -ENODEV;
}
- pr_info(SDIO_TTY_MODULE_NAME ": %s: setting debug_msg_on to %d",
- __func__, enable);
- sdio_tty_drv->debug_msg_on = enable;
+
+ ret = sdio_tty_uninit_tty(sdio_tty_drv);
+ if (ret) {
+ pr_err(SDIO_TTY_MODULE_NAME ": %s: sdio_tty_uninit_tty "
+ "failed for %s", __func__, pdev->name);
+ }
+ return ret;
}
-EXPORT_SYMBOL(sdio_tty_enable_debug_msg);
+static struct platform_driver sdio_tty_pdrv = {
+ .probe = sdio_tty_probe,
+ .remove = sdio_tty_remove,
+ .id_table = sdio_tty_id_table,
+ .driver = {
+ .name = "SDIO_TTY",
+ .owner = THIS_MODULE,
+ },
+};
+/*
+ * Module Init.
+ *
+ * Register SDIO TTY driver.
+ *
+ */
static int __init sdio_tty_init(void)
{
- return 0;
+ int ret = 0;
+
+ ret = platform_driver_register(&sdio_tty_pdrv);
+ if (ret) {
+ pr_err(SDIO_TTY_MODULE_NAME ": %s: platform_driver_register "
+ "failed", __func__);
+ }
+ return ret;
};
/*
* Module Exit.
*
- * Unregister SDIO driver.
+ * Unregister SDIO TTY driver.
*
*/
static void __exit sdio_tty_exit(void)
{
+ platform_driver_unregister(&sdio_tty_pdrv);
}
module_init(sdio_tty_init);
diff --git a/arch/arm/mach-msm/sdio_tty_ciq.c b/arch/arm/mach-msm/sdio_tty_ciq.c
deleted file mode 100644
index 64b772d..0000000
--- a/arch/arm/mach-msm/sdio_tty_ciq.c
+++ /dev/null
@@ -1,134 +0,0 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include <linux/slab.h>
-#include <linux/platform_device.h>
-#include <linux/debugfs.h>
-#include <mach/sdio_al.h>
-#include <mach/sdio_tty.h>
-
-#define SDIO_TTY_DEV "sdio_tty_ciq_0"
-#define SDIO_CIQ "sdio_ciq"
-#define SDIO_TTY_DEV_TEST "sdio_tty_ciq_test_0"
-#define TTY_CIQ_MODULE_NAME "sdio_tty_ciq"
-
-struct sdio_tty_ciq {
- void *sdio_tty_handle;
-};
-
-static struct sdio_tty_ciq sdio_tty_ciq;
-
-/*
- * Enable sdio_tty debug messages
- * By default the sdio_tty debug messages are turned off
- */
-static int debug_msg_on;
-module_param(debug_msg_on, int, 0);
-
-static int sdio_tty_probe(struct platform_device *pdev)
-{
- sdio_tty_ciq.sdio_tty_handle = sdio_tty_init_tty(SDIO_TTY_DEV,
- "SDIO_CIQ");
- if (!sdio_tty_ciq.sdio_tty_handle) {
- pr_err(TTY_CIQ_MODULE_NAME ": %s: NULL sdio_tty_handle",
- __func__);
- return -ENODEV;
- }
-
- if (debug_msg_on)
- sdio_tty_enable_debug_msg(sdio_tty_ciq.sdio_tty_handle,
- debug_msg_on);
-
- return 0;
-}
-
-static int sdio_tty_test_probe(struct platform_device *pdev)
-{
- sdio_tty_ciq.sdio_tty_handle = sdio_tty_init_tty(SDIO_TTY_DEV_TEST,
- "SDIO_CIQ");
- if (!sdio_tty_ciq.sdio_tty_handle) {
- pr_err(TTY_CIQ_MODULE_NAME ": %s: NULL sdio_tty_handle",
- __func__);
- return -ENODEV;
- }
-
- if (debug_msg_on)
- sdio_tty_enable_debug_msg(sdio_tty_ciq.sdio_tty_handle,
- debug_msg_on);
-
- return 0;
-}
-
-static int sdio_tty_remove(struct platform_device *pdev)
-{
- int ret = 0;
-
- pr_info(TTY_CIQ_MODULE_NAME ": %s", __func__);
- ret = sdio_tty_uninit_tty(sdio_tty_ciq.sdio_tty_handle);
- if (ret) {
- pr_err(TTY_CIQ_MODULE_NAME ": %s: sdio_tty_uninit_tty failed",
- __func__);
- return ret;
- }
-
- return 0;
-}
-
-static struct platform_driver sdio_tty_pdrv = {
- .probe = sdio_tty_probe,
- .remove = sdio_tty_remove,
- .driver = {
- .name = "SDIO_CIQ",
- .owner = THIS_MODULE,
- },
-};
-
-static struct platform_driver sdio_tty_test_pdrv = {
- .probe = sdio_tty_test_probe,
- .remove = sdio_tty_remove,
- .driver = {
- .name = "SDIO_CIQ_TEST_APP",
- .owner = THIS_MODULE,
- },
-};
-
-static int __init sdio_tty_ciq_init(void)
-{
- int ret = 0;
-
- ret = platform_driver_register(&sdio_tty_pdrv);
- if (ret) {
- pr_err(TTY_CIQ_MODULE_NAME ": %s: platform_driver_register "
- "failed", __func__);
- return ret;
- }
- return platform_driver_register(&sdio_tty_test_pdrv);
-};
-
-/*
- * Module Exit.
- *
- * Unregister SDIO driver.
- *
- */
-static void __exit sdio_tty_ciq_exit(void)
-{
- platform_driver_unregister(&sdio_tty_pdrv);
- platform_driver_unregister(&sdio_tty_test_pdrv);
-}
-
-module_init(sdio_tty_ciq_init);
-module_exit(sdio_tty_ciq_exit);
-
-MODULE_DESCRIPTION("SDIO TTY CIQ");
-MODULE_LICENSE("GPL v2");
-MODULE_AUTHOR("Maya Erez <merez@codeaurora.org>");