summaryrefslogtreecommitdiff
path: root/drivers/char/modem_interface/modem_gpio_drv.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/modem_interface/modem_gpio_drv.c')
-rw-r--r--drivers/char/modem_interface/modem_gpio_drv.c358
1 files changed, 358 insertions, 0 deletions
diff --git a/drivers/char/modem_interface/modem_gpio_drv.c b/drivers/char/modem_interface/modem_gpio_drv.c
new file mode 100644
index 00000000..7851fb00
--- /dev/null
+++ b/drivers/char/modem_interface/modem_gpio_drv.c
@@ -0,0 +1,358 @@
+/*
+ * kernel/driver/char/modem_interface/modem_gpio_drv.c
+ *
+ * Generic modem interface gpio handling.
+ *
+ * Author: Jiayong Yang(Jiayong.Yang@spreadtrum.com)
+ * Created: Jul 27, 2012
+ * Copyright: Spreadtrum Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/mutex.h>
+#include <linux/dma-mapping.h>
+#include <linux/proc_fs.h>
+#include <linux/gpio.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <mach/modem_interface.h>
+#include <mach/globalregs.h>
+#include "modem_buffer.h"
+#include "modem_interface_driver.h"
+
+#define GPIO_INVALID 0xFFFFFFFF
+
+extern void free_irq(unsigned int irq, void *dev_id);
+extern void modem_intf_send_GPIO_message(int gpio_no,int status,int index);
+extern void modem_intf_send_ctrl_gpio_message(enum MSG_CTRL_GPIO_TYPE gpio_type, int gpio_value);
+extern void on_modem_poweron(void);
+static unsigned int cp_to_ap_rdy_irq;
+static unsigned int cp_alive_gpio_irq;
+static unsigned int cp_crash_gpio_irq;
+static unsigned int cp_watchdog_gpio_irq;
+static unsigned int modem_power_gpio;
+static unsigned int modem_reset_gpio;
+static int cp_to_ap_rdy ;
+static int cp_alive_gpio;
+static int cp_crash_gpio;
+static int cp_watchdog_gpio;
+
+
+int get_alive_status(void)
+{
+ int status = gpio_get_value(cp_alive_gpio);
+ if(status != 0)
+ return 1;
+ return 0;
+}
+int get_assert_status(void)
+{
+ int status = gpio_get_value(cp_crash_gpio);
+ if(status != 0)
+ return 1;
+ return 0;
+}
+static irqreturn_t cp_to_ap_rdy_handle(int irq, void *handle)
+{
+ int status ;
+
+ status = gpio_get_value(cp_to_ap_rdy);
+ pr_debug("modem_boot_irq: %d \n",status);
+ if(status == 0)
+ modem_intf_send_GPIO_message(cp_to_ap_rdy,status,0);
+ else
+ modem_intf_send_GPIO_message(cp_to_ap_rdy,1,0);
+ return IRQ_HANDLED;
+}
+
+int modem_intf_get_watchdog_gpio_value()
+{
+
+ return gpio_get_value(cp_watchdog_gpio);
+}
+static irqreturn_t cp_watchdog_gpio_handle(int irq, void * handle)
+{
+ int wdg_reset_status;
+
+ wdg_reset_status = gpio_get_value(cp_watchdog_gpio);
+ printk("cp_watchdog_gpio: %d \n",wdg_reset_status);
+
+ if(wdg_reset_status == 0) {
+ irq_set_irq_type(cp_watchdog_gpio_irq, IRQ_TYPE_LEVEL_HIGH);
+ } else {
+ irq_set_irq_type(cp_watchdog_gpio_irq, IRQ_TYPE_LEVEL_LOW);
+ }
+
+ modem_intf_send_ctrl_gpio_message(GPIO_WATCHDOG, wdg_reset_status);
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t cp_alive_gpio_handle(int irq, void *handle)
+{
+ int alive_status;
+
+ alive_status = gpio_get_value(cp_alive_gpio);
+ printk("cp_alive_gpio: %d \n",alive_status);
+
+ if(alive_status == 0) {
+ irq_set_irq_type(cp_alive_gpio_irq, IRQ_TYPE_LEVEL_HIGH);
+ } else {
+ irq_set_irq_type(cp_alive_gpio_irq, IRQ_TYPE_LEVEL_LOW);
+ }
+
+ modem_intf_send_ctrl_gpio_message(GPIO_ALIVE, alive_status);
+ return IRQ_HANDLED;
+}
+
+
+static irqreturn_t cp_crash_gpio_handle(int irq, void *handle)
+{
+ int assert_status;
+
+ assert_status = gpio_get_value(cp_crash_gpio);
+ printk("cp_crash_gpio: %d \n",assert_status);
+
+ if(assert_status == 0) {
+ irq_set_irq_type(cp_crash_gpio_irq, IRQ_TYPE_LEVEL_HIGH);
+ } else {
+ irq_set_irq_type(cp_crash_gpio_irq, IRQ_TYPE_LEVEL_LOW);
+ }
+
+ modem_intf_send_ctrl_gpio_message(GPIO_RESET, assert_status);
+ return IRQ_HANDLED;
+}
+
+int modem_share_gpio_init(void *para)
+{
+ struct modem_intf_platform_data *modem_config = (struct modem_intf_platform_data *)para;
+ int error = 0;
+ int status = 0;
+
+ pr_debug("modem_share_gpio_init start!!! \n");
+ cp_to_ap_rdy = modem_config->modem_boot_gpio;
+
+ error = gpio_request(cp_to_ap_rdy, "modem_boot_gpio");
+ if (error) {
+ pr_err("Cannot request GPIO %d\n", cp_to_ap_rdy);
+ gpio_free(cp_to_ap_rdy);
+ return error;
+ }
+
+ gpio_direction_input(cp_to_ap_rdy);
+ gpio_export(cp_to_ap_rdy,0);
+ cp_to_ap_rdy_irq = gpio_to_irq(cp_to_ap_rdy);
+ if (cp_to_ap_rdy_irq < 0)
+ return -1;
+ error = request_threaded_irq(cp_to_ap_rdy_irq, cp_to_ap_rdy_handle,
+ NULL, IRQF_DISABLED|IRQF_TRIGGER_RISING |IRQF_TRIGGER_FALLING, "modem_boot", para);
+ if (error) {
+ printk("lee :cannot alloc cp_to_ap_rdy_irq, err %d\r\n", error);
+ gpio_free(cp_to_ap_rdy);
+ return error;
+ }
+
+ status = gpio_get_value(cp_to_ap_rdy);
+ if(status == 0)
+ modem_intf_send_GPIO_message(cp_to_ap_rdy,status,0);
+ else
+ modem_intf_send_GPIO_message(cp_to_ap_rdy,1,0);
+
+ return 0;
+}
+
+int modem_share_gpio_uninit(void *para)
+{
+ struct modem_intf_platform_data *modem_config = (struct nodem_intf_platform_data *)para;
+
+ pr_debug("modem_gpio_init start!!! \n");
+ cp_to_ap_rdy = modem_config->modem_boot_gpio;
+
+ cp_to_ap_rdy_irq = gpio_to_irq(cp_to_ap_rdy);
+ if (cp_to_ap_rdy_irq < 0)
+ return -1;
+ free_irq( cp_to_ap_rdy_irq, para);
+ gpio_free(cp_to_ap_rdy);
+
+ return 0;
+}
+
+int modem_gpio_irq_init(void *para)
+{
+ int error = 0;
+
+ cp_watchdog_gpio_irq = gpio_to_irq(cp_watchdog_gpio);
+ if(cp_watchdog_gpio_irq < 0)
+ return -1;
+ error = request_threaded_irq(cp_watchdog_gpio_irq, cp_watchdog_gpio_handle,
+ NULL, IRQF_DISABLED|IRQF_NO_SUSPEND |IRQF_TRIGGER_LOW, "modem_watchdog", para);
+ if (error) {
+ printk("modem_intf :cannot alloc cp_watchdog irq, err %d\r\n", error);
+ gpio_free(cp_watchdog_gpio);
+ return error;
+ }
+
+ enable_irq_wake(cp_watchdog_gpio_irq);
+
+ cp_alive_gpio_irq = gpio_to_irq(cp_alive_gpio);
+ if (cp_alive_gpio_irq < 0)
+ return -1;
+ error = request_threaded_irq(cp_alive_gpio_irq, cp_alive_gpio_handle,
+ NULL, IRQF_DISABLED|IRQF_NO_SUSPEND |IRQF_TRIGGER_HIGH, "modem_alive", para);
+ if (error) {
+ printk("modem_intf :cannot alloc cp_alive irq, err %d\r\n", error);
+ gpio_free(cp_alive_gpio);
+ return error;
+ }
+
+ enable_irq_wake(cp_alive_gpio_irq);
+
+ cp_crash_gpio_irq = gpio_to_irq(cp_crash_gpio);
+ if (cp_crash_gpio_irq < 0)
+ return -1;
+ error = request_threaded_irq(cp_crash_gpio_irq, cp_crash_gpio_handle,
+ NULL, IRQF_DISABLED|IRQF_NO_SUSPEND |IRQF_TRIGGER_HIGH, "modem_crash", para);
+ if (error) {
+ printk("modem_intf :cannot alloc cp_crash irq, err %d\r\n", error);
+ gpio_free(cp_crash_gpio);
+ return error;
+ }
+
+ enable_irq_wake(cp_crash_gpio_irq);
+}
+
+
+int modem_gpio_init(void *para)
+{
+ struct modem_intf_platform_data *modem_config = (struct modem_intf_platform_data *)para;
+ int error = 0;
+
+ pr_debug("modem_gpio_init start!!! \n");
+ cp_to_ap_rdy = modem_config->modem_boot_gpio;
+ cp_watchdog_gpio = modem_config->modem_watchdog_gpio;
+ cp_alive_gpio = modem_config->modem_alive_gpio;
+ cp_crash_gpio = modem_config->modem_crash_gpio;
+ modem_power_gpio = modem_config->modem_power_gpio;
+ modem_reset_gpio = modem_config->modem_reset_gpio;
+
+ if(GPIO_INVALID != modem_power_gpio) {
+ gpio_request(modem_power_gpio, "modem_power_gpio");
+ gpio_export(modem_power_gpio,0);
+ }
+
+ if(GPIO_INVALID != modem_reset_gpio) {
+ gpio_request(modem_reset_gpio, "modem_reset_gpio");
+ gpio_export(modem_reset_gpio,0);
+ }
+
+ //watchdog gpio
+ error = gpio_request(cp_watchdog_gpio, "modem_watchdog_gpio");
+ if (error) {
+ pr_err("Cannot request GPIO %d\n", cp_watchdog_gpio);
+ gpio_free(cp_watchdog_gpio);
+ return error;
+ }
+ gpio_export(cp_watchdog_gpio,0);
+ gpio_direction_input(cp_watchdog_gpio);
+
+
+//////////////////////////////////////////////////
+ //alive gpio
+ error = gpio_request(cp_alive_gpio, "modem_alive_gpio");
+ if (error) {
+ pr_err("Cannot request GPIO %d\n", cp_alive_gpio);
+ gpio_free(cp_alive_gpio);
+ return error;
+ }
+ gpio_export(cp_alive_gpio,0);
+ gpio_direction_input(cp_alive_gpio);
+
+ //crash gpio
+ error = gpio_request(cp_crash_gpio, "modem_crash_gpio");
+ if (error) {
+ pr_err("Cannot request GPIO %d\n", cp_crash_gpio);
+ gpio_free(cp_crash_gpio);
+ return error;
+ }
+ gpio_export(cp_crash_gpio,0);
+ gpio_direction_input(cp_crash_gpio);
+
+/////////////////////////////////////////////////
+
+ return 0;
+}
+
+int modem_gpio_uninit(void *para)
+{
+ modem_share_gpio_uninit(para);
+ return 0;
+}
+
+void modem_poweron_async_step1(void)
+{
+ if(GPIO_INVALID != modem_power_gpio) {
+ printk(KERN_ERR "modem_poweron_async_step1!!! \n");
+ gpio_direction_output(modem_power_gpio, 1);
+ } else {
+ printk(KERN_ERR "modem_poweron_async_step1 modem_power_gpio == GPIO_INVALID!!! \n");
+ }
+}
+
+void modem_poweron_async_step2(void)
+{
+ if(GPIO_INVALID != modem_power_gpio) {
+ gpio_set_value(modem_power_gpio, 0);
+ printk(KERN_ERR "modem_poweron_async_step2!!! \n");
+ } else {
+ printk(KERN_ERR "modem_poweron_async_step2 modem_power_gpio == GPIO_INVALID!!! \n");
+ }
+}
+
+void modem_poweron(void)
+{
+ printk("modem power on!!! \n");
+ if(GPIO_INVALID != modem_power_gpio) {
+ gpio_direction_output(modem_power_gpio, 1); //2012.1.10
+ //gpio_set_value(modem_power_gpio, 1);
+ msleep(2000);
+ gpio_set_value(modem_power_gpio, 0);
+ } else {
+ //sprd_greg_clear_bits(REG_TYPE_GLOBAL, 0x00000040, 0x4C);
+ }
+}
+void modem_poweroff(void)
+{
+ printk("modem power off!!! \n");
+ if (GPIO_INVALID != modem_power_gpio) {
+ gpio_direction_output(modem_power_gpio, 1); //2012.1.10
+ //gpio_set_value(modem_power_gpio, 1);
+ msleep(3500);//should be matched with Adie config of cp
+ gpio_set_value(modem_power_gpio, 0);
+ } else {
+ //sprd_greg_set_bits(REG_TYPE_GLOBAL, 0x00000040, 0x4C);
+ }
+}
+
+void modem_soft_reset(void)
+{
+ printk(KERN_INFO "modem soft reset enter \n");
+ if (GPIO_INVALID != modem_reset_gpio) {
+ gpio_direction_output(modem_reset_gpio, 1); //2012.1.10
+ //gpio_set_value(modem_power_gpio, 1);
+ msleep(50);
+ gpio_set_value(modem_reset_gpio, 0);
+ }
+}
+
+void modem_hard_reset(void)
+{
+ printk(KERN_INFO "modem hard reset enter \n");
+ if (GPIO_INVALID != modem_power_gpio) {
+ gpio_direction_output(modem_power_gpio, 1); //2012.1.10
+ //gpio_set_value(modem_power_gpio, 1);
+ msleep(7100);
+ gpio_set_value(modem_power_gpio, 0);
+ }
+}