diff --git a/arch/arm/mach-msm/smd_tty.c b/arch/arm/mach-msm/smd_tty.c index dc6ba5ca40f..c8248a7fd60 100644 --- a/arch/arm/mach-msm/smd_tty.c +++ b/arch/arm/mach-msm/smd_tty.c @@ -59,33 +59,38 @@ struct smd_tty_info { int is_open; wait_queue_head_t ch_opened_wait_queue; spinlock_t reset_lock; + struct smd_config *smd; }; +/** + * SMD port configuration. + * + * @tty_dev_index Index into smd_tty[] + * @port_name Name of the SMD port + * @dev_name Name of the TTY Device (if NULL, @port_name is used) + * @edge SMD edge + */ +struct smd_config { + uint32_t tty_dev_index; + const char *port_name; + const char *dev_name; + uint32_t edge; +}; + +static struct smd_config smd_configs[] = { + {0, "DS", NULL, SMD_APPS_MODEM}, + {1, "APPS_FM", NULL, SMD_APPS_WCNSS}, + {2, "APPS_RIVA_BT_ACL", NULL, SMD_APPS_WCNSS}, + {3, "APPS_RIVA_BT_CMD", NULL, SMD_APPS_WCNSS}, + {4, "MBALBRIDGE", NULL, SMD_APPS_MODEM}, + {7, "DATA1", NULL, SMD_APPS_MODEM}, + {11, "DATA11", NULL, SMD_APPS_MODEM}, + {21, "DATA21", NULL, SMD_APPS_MODEM}, + {27, "GPSNMEA", NULL, SMD_APPS_MODEM}, + {36, "LOOPBACK", "LOOPBACK_TTY", SMD_APPS_MODEM}, +}; +#define DS_IDX 0 #define LOOPBACK_IDX 36 -static char *smd_ch_name[] = { - [0] = "DS", - [1] = "APPS_FM", - [2] = "APPS_RIVA_BT_ACL", - [3] = "APPS_RIVA_BT_CMD", - [4] = "MBALBRIDGE", - [7] = "DATA1", - [21] = "DATA21", - [27] = "GPSNMEA", - [36] = "LOOPBACK", -}; - -static uint32_t smd_ch_edge[] = { - [0] = SMD_APPS_MODEM, - [1] = SMD_APPS_WCNSS, - [2] = SMD_APPS_WCNSS, - [3] = SMD_APPS_WCNSS, - [4] = SMD_APPS_MODEM, - [7] = SMD_APPS_MODEM, - [21] = SMD_APPS_MODEM, - [27] = SMD_APPS_MODEM, - [36] = SMD_APPS_MODEM, -}; - static struct delayed_work loopback_work; static struct smd_tty_info smd_tty[MAX_SMD_TTYS]; @@ -228,12 +233,12 @@ static uint32_t is_modem_smsm_inited(void) static int smd_tty_open(struct tty_struct *tty, struct file *f) { int res = 0; - int n = tty->index; + unsigned int n = tty->index; struct smd_tty_info *info; char *peripheral = NULL; - if (!smd_ch_name[n]) + if (n >= MAX_SMD_TTYS || !smd_tty[n].smd) return -ENODEV; info = smd_tty + n; @@ -242,11 +247,11 @@ static int smd_tty_open(struct tty_struct *tty, struct file *f) tty->driver_data = info; if (info->open_count++ == 0) { - if (smd_ch_edge[n] == SMD_APPS_MODEM) + if (smd_tty[n].smd->edge == SMD_APPS_MODEM) peripheral = "modem"; if (peripheral) { - info->pil = pil_get("modem"); + info->pil = pil_get(peripheral); if (IS_ERR(info->pil)) { res = PTR_ERR(info->pil); goto out; @@ -257,7 +262,7 @@ static int smd_tty_open(struct tty_struct *tty, struct file *f) * the wait need to be done atmost once, using msleep * doesn't degrade the performance. */ - if (n == 36) { + if (n == LOOPBACK_IDX) { if (!is_modem_smsm_inited()) msleep(5000); smsm_change_state(SMSM_APPS_STATE, @@ -297,15 +302,15 @@ static int smd_tty_open(struct tty_struct *tty, struct file *f) tasklet_init(&info->tty_tsklt, smd_tty_read, (unsigned long)info); wake_lock_init(&info->wake_lock, WAKE_LOCK_SUSPEND, - smd_ch_name[n]); + smd_tty[n].smd->port_name); if (!info->ch) { - res = smd_named_open_on_edge(smd_ch_name[n], - smd_ch_edge[n], + res = smd_named_open_on_edge(smd_tty[n].smd->port_name, + smd_tty[n].smd->edge, &info->ch, info, smd_tty_notify); if (res < 0) { pr_err("%s: %s open failed %d\n", __func__, - smd_ch_name[n], res); + smd_tty[n].smd->port_name, res); goto release_pil; } @@ -316,7 +321,8 @@ static int smd_tty_open(struct tty_struct *tty, struct file *f) res = -ETIMEDOUT; if (res < 0) { pr_err("%s: wait for %s smd_open failed %d\n", - __func__, smd_ch_name[n], res); + __func__, smd_tty[n].smd->port_name, + res); goto release_pil; } res = 0; @@ -474,35 +480,24 @@ static struct tty_operations smd_tty_ops = { static int smd_tty_dummy_probe(struct platform_device *pdev) { - if (!strncmp(pdev->name, smd_ch_name[0], - strnlen(smd_ch_name[0], SMD_MAX_CH_NAME_LEN))) - complete_all(&smd_tty[0].ch_allocated); - else if (!strncmp(pdev->name, smd_ch_name[1], - strnlen(smd_ch_name[1], SMD_MAX_CH_NAME_LEN))) - complete_all(&smd_tty[1].ch_allocated); - else if (!strncmp(pdev->name, smd_ch_name[2], - strnlen(smd_ch_name[2], SMD_MAX_CH_NAME_LEN))) - complete_all(&smd_tty[2].ch_allocated); - else if (!strncmp(pdev->name, smd_ch_name[3], - strnlen(smd_ch_name[3], SMD_MAX_CH_NAME_LEN))) - complete_all(&smd_tty[3].ch_allocated); - else if (!strncmp(pdev->name, smd_ch_name[4], - strnlen(smd_ch_name[4], SMD_MAX_CH_NAME_LEN))) - complete_all(&smd_tty[4].ch_allocated); - else if (!strncmp(pdev->name, smd_ch_name[7], - strnlen(smd_ch_name[7], SMD_MAX_CH_NAME_LEN))) - complete_all(&smd_tty[7].ch_allocated); - else if (!strncmp(pdev->name, smd_ch_name[21], - strnlen(smd_ch_name[21], SMD_MAX_CH_NAME_LEN))) - complete_all(&smd_tty[21].ch_allocated); - else if (!strncmp(pdev->name, smd_ch_name[27], - strnlen(smd_ch_name[27], SMD_MAX_CH_NAME_LEN))) - complete_all(&smd_tty[27].ch_allocated); - else if (!strncmp(pdev->name, "LOOPBACK_TTY", - strnlen("LOOPBACK_TTY", SMD_MAX_CH_NAME_LEN))) - complete_all(&smd_tty[36].ch_allocated); + int n; + int idx; - return 0; + for (n = 0; n < ARRAY_SIZE(smd_configs); ++n) { + idx = smd_configs[n].tty_dev_index; + + if (!smd_configs[n].dev_name) + continue; + + if (!strncmp(pdev->name, smd_configs[n].dev_name, + SMD_MAX_CH_NAME_LEN)) { + complete_all(&smd_tty[idx].ch_allocated); + return 0; + } + } + pr_err("%s: unknown device '%s'\n", __func__, pdev->name); + + return -ENODEV; } static struct tty_driver *smd_tty_driver; @@ -510,7 +505,8 @@ static struct tty_driver *smd_tty_driver; static int __init smd_tty_init(void) { int ret; - int ds_registered = 0; + int n; + int idx; smd_tty_driver = alloc_tty_driver(MAX_SMD_TTYS); if (smd_tty_driver == 0) @@ -533,150 +529,69 @@ static int __init smd_tty_init(void) tty_set_operations(smd_tty_driver, &smd_tty_ops); ret = tty_register_driver(smd_tty_driver); - if (ret) return ret; - - /* this should be dynamic */ - tty_register_device(smd_tty_driver, 0, 0); - tty_register_device(smd_tty_driver, 1, 0); - tty_register_device(smd_tty_driver, 2, 0); - tty_register_device(smd_tty_driver, 3, 0); - tty_register_device(smd_tty_driver, 4, 0); - tty_register_device(smd_tty_driver, 7, 0); - tty_register_device(smd_tty_driver, 21, 0); - tty_register_device(smd_tty_driver, 27, 0); - tty_register_device(smd_tty_driver, 36, 0); - - init_completion(&smd_tty[0].ch_allocated); - init_completion(&smd_tty[1].ch_allocated); - init_completion(&smd_tty[2].ch_allocated); - init_completion(&smd_tty[3].ch_allocated); - init_completion(&smd_tty[4].ch_allocated); - init_completion(&smd_tty[7].ch_allocated); - init_completion(&smd_tty[21].ch_allocated); - init_completion(&smd_tty[27].ch_allocated); - init_completion(&smd_tty[36].ch_allocated); - - smd_tty[0].driver.probe = smd_tty_dummy_probe; - smd_tty[0].driver.driver.name = smd_ch_name[0]; - smd_tty[0].driver.driver.owner = THIS_MODULE; - spin_lock_init(&smd_tty[0].reset_lock); - smd_tty[0].is_open = 0; - init_waitqueue_head(&smd_tty[0].ch_opened_wait_queue); - /* - * DS port is opened in the kernel starting with 8660 fusion. - * Only register the platform driver for targets older than that. - */ - if (cpu_is_msm7x01() || cpu_is_msm7x25() || cpu_is_msm7x27() || - cpu_is_msm7x30() || cpu_is_qsd8x50() || - cpu_is_msm8x55() || (cpu_is_msm8x60() && - socinfo_get_platform_subtype() == 0x1)) { - ret = platform_driver_register(&smd_tty[0].driver); - if (ret) - goto out; - ds_registered = 1; + if (ret) { + put_tty_driver(smd_tty_driver); + pr_err("%s: driver registration failed %d\n", __func__, ret); + return ret; } - smd_tty[1].driver.probe = smd_tty_dummy_probe; - smd_tty[1].driver.driver.name = smd_ch_name[1]; - smd_tty[1].driver.driver.owner = THIS_MODULE; - spin_lock_init(&smd_tty[1].reset_lock); - smd_tty[1].is_open = 0; - init_waitqueue_head(&smd_tty[1].ch_opened_wait_queue); - ret = platform_driver_register(&smd_tty[1].driver); - if (ret) - goto unreg0; - smd_tty[2].driver.probe = smd_tty_dummy_probe; - smd_tty[2].driver.driver.name = smd_ch_name[2]; - smd_tty[2].driver.driver.owner = THIS_MODULE; - spin_lock_init(&smd_tty[2].reset_lock); - smd_tty[2].is_open = 0; - init_waitqueue_head(&smd_tty[2].ch_opened_wait_queue); - ret = platform_driver_register(&smd_tty[2].driver); - if (ret) - goto unreg1; - smd_tty[3].driver.probe = smd_tty_dummy_probe; - smd_tty[3].driver.driver.name = smd_ch_name[3]; - smd_tty[3].driver.driver.owner = THIS_MODULE; - spin_lock_init(&smd_tty[3].reset_lock); - smd_tty[3].is_open = 0; - init_waitqueue_head(&smd_tty[3].ch_opened_wait_queue); - ret = platform_driver_register(&smd_tty[3].driver); - if (ret) - goto unreg2; - smd_tty[4].driver.probe = smd_tty_dummy_probe; - smd_tty[4].driver.driver.name = smd_ch_name[4]; - smd_tty[4].driver.driver.owner = THIS_MODULE; - spin_lock_init(&smd_tty[4].reset_lock); - smd_tty[4].is_open = 0; - init_waitqueue_head(&smd_tty[4].ch_opened_wait_queue); - ret = platform_driver_register(&smd_tty[4].driver); - if (ret) - goto unreg3; - smd_tty[7].driver.probe = smd_tty_dummy_probe; - smd_tty[7].driver.driver.name = smd_ch_name[7]; - smd_tty[7].driver.driver.owner = THIS_MODULE; - spin_lock_init(&smd_tty[7].reset_lock); - smd_tty[7].is_open = 0; - init_waitqueue_head(&smd_tty[7].ch_opened_wait_queue); - ret = platform_driver_register(&smd_tty[7].driver); - if (ret) - goto unreg4; - smd_tty[21].driver.probe = smd_tty_dummy_probe; - smd_tty[21].driver.driver.name = smd_ch_name[21]; - smd_tty[21].driver.driver.owner = THIS_MODULE; - spin_lock_init(&smd_tty[21].reset_lock); - smd_tty[21].is_open = 0; - init_waitqueue_head(&smd_tty[21].ch_opened_wait_queue); - ret = platform_driver_register(&smd_tty[21].driver); - if (ret) - goto unreg7; - smd_tty[27].driver.probe = smd_tty_dummy_probe; - smd_tty[27].driver.driver.name = smd_ch_name[27]; - smd_tty[27].driver.driver.owner = THIS_MODULE; - spin_lock_init(&smd_tty[27].reset_lock); - smd_tty[27].is_open = 0; - init_waitqueue_head(&smd_tty[27].ch_opened_wait_queue); - ret = platform_driver_register(&smd_tty[27].driver); - if (ret) - goto unreg21; - smd_tty[36].driver.probe = smd_tty_dummy_probe; - smd_tty[36].driver.driver.name = "LOOPBACK_TTY"; - smd_tty[36].driver.driver.owner = THIS_MODULE; - spin_lock_init(&smd_tty[36].reset_lock); - smd_tty[36].is_open = 0; - init_waitqueue_head(&smd_tty[36].ch_opened_wait_queue); - INIT_DELAYED_WORK(&loopback_work, loopback_probe_worker); - ret = platform_driver_register(&smd_tty[36].driver); - if (ret) - goto unreg27; + for (n = 0; n < ARRAY_SIZE(smd_configs); ++n) { + idx = smd_configs[n].tty_dev_index; + + if (smd_configs[n].dev_name == NULL) + smd_configs[n].dev_name = smd_configs[n].port_name; + + if (idx == DS_IDX) { + /* + * DS port uses the kernel API starting with + * 8660 Fusion. Only register the userspace + * platform device for older targets. + */ + int legacy_ds = 0; + + legacy_ds |= cpu_is_msm7x01() || cpu_is_msm7x25(); + legacy_ds |= cpu_is_msm7x27() || cpu_is_msm7x30(); + legacy_ds |= cpu_is_qsd8x50() || cpu_is_msm8x55(); + legacy_ds |= cpu_is_msm8x60() && + (socinfo_get_platform_subtype() == 0x1); + + if (!legacy_ds) + continue; + } + + tty_register_device(smd_tty_driver, idx, 0); + init_completion(&smd_tty[idx].ch_allocated); + + /* register platform device */ + smd_tty[idx].driver.probe = smd_tty_dummy_probe; + smd_tty[idx].driver.driver.name = smd_configs[n].dev_name; + smd_tty[idx].driver.driver.owner = THIS_MODULE; + spin_lock_init(&smd_tty[idx].reset_lock); + smd_tty[idx].is_open = 0; + init_waitqueue_head(&smd_tty[idx].ch_opened_wait_queue); + ret = platform_driver_register(&smd_tty[idx].driver); + + if (ret) { + pr_err("%s: init failed %d (%d)\n", __func__, idx, ret); + smd_tty[idx].driver.probe = NULL; + goto out; + } + smd_tty[idx].smd = &smd_configs[n]; + } + INIT_DELAYED_WORK(&loopback_work, loopback_probe_worker); return 0; -unreg27: - platform_driver_unregister(&smd_tty[27].driver); -unreg21: - platform_driver_unregister(&smd_tty[21].driver); -unreg7: - platform_driver_unregister(&smd_tty[7].driver); -unreg4: - platform_driver_unregister(&smd_tty[4].driver); -unreg3: - platform_driver_unregister(&smd_tty[3].driver); -unreg2: - platform_driver_unregister(&smd_tty[2].driver); -unreg1: - platform_driver_unregister(&smd_tty[1].driver); -unreg0: - if (ds_registered) - platform_driver_unregister(&smd_tty[0].driver); out: - tty_unregister_device(smd_tty_driver, 0); - tty_unregister_device(smd_tty_driver, 1); - tty_unregister_device(smd_tty_driver, 2); - tty_unregister_device(smd_tty_driver, 3); - tty_unregister_device(smd_tty_driver, 7); - tty_unregister_device(smd_tty_driver, 21); - tty_unregister_device(smd_tty_driver, 27); - tty_unregister_device(smd_tty_driver, 36); + /* unregister platform devices */ + for (n = 0; n < ARRAY_SIZE(smd_configs); ++n) { + idx = smd_configs[n].tty_dev_index; + + if (smd_tty[idx].driver.probe) { + platform_driver_unregister(&smd_tty[idx].driver); + tty_unregister_device(smd_tty_driver, idx); + } + } + tty_unregister_driver(smd_tty_driver); put_tty_driver(smd_tty_driver); return ret;