msm: mdm2: Add HTC modem initialization code

Change-Id: I49ca00e20fa5c335ab8f323762e91743dfaf85d7
diff --git a/arch/arm/mach-msm/mdm2.c b/arch/arm/mach-msm/mdm2.c
index 76272de..9d3b535 100644
--- a/arch/arm/mach-msm/mdm2.c
+++ b/arch/arm/mach-msm/mdm2.c
@@ -177,6 +177,30 @@
 	} else
 		gpio_direction_output(mdm_drv->ap2mdm_status_gpio, 1);
 
+#ifdef CONFIG_MACH_HTC
+	if (GPIO_IS_VALID(mdm_drv->ap2mdm_pmic_reset_n_gpio)) {
+		pr_debug("%s: Pulling AP2MDM_RESET_N gpio low\n", __func__);
+		gpio_direction_output(mdm_drv->ap2mdm_pmic_reset_n_gpio, 0);
+		usleep_range(5000, 10000);
+		pr_debug("%s: Pulling AP2MDM_RESET_N gpio high\n", __func__);
+		gpio_direction_output(mdm_drv->ap2mdm_pmic_reset_n_gpio, 1);
+		msleep(40);
+	}
+
+	if (GPIO_IS_VALID(mdm_drv->mdm2ap_hsic_ready_gpio)) {
+		i = 100;
+		while (!gpio_get_value(mdm_drv->mdm2ap_hsic_ready_gpio) &&
+				i > 0) {
+			msleep(10);
+			i -= 10;
+			pr_debug("%s: Waiting for AP2MDM_HSIC_READY gpio\n",
+					__func__);
+		};
+		if (!gpio_get_value(mdm_drv->mdm2ap_hsic_ready_gpio))
+			pr_err("%s: AP2MDM_HSIC_READY timeout!\n", __func__);
+	}
+#endif
+
 	if (!GPIO_IS_VALID(mdm_drv->mdm2ap_pblrdy))
 		goto start_mdm_peripheral;
 
@@ -264,6 +288,9 @@
 		if (GPIO_IS_VALID(mdm_drv->ap2mdm_wakeup_gpio))
 			gpio_direction_output(mdm_drv->ap2mdm_wakeup_gpio, 1);
 	}
+#ifdef CONFIG_MACH_HTC
+	mdm_drv->mdm_hsic_reconnected = 1;
+#endif
 }
 
 static void mdm_image_upgrade(struct mdm_modem_drv *mdm_drv, int type)
diff --git a/arch/arm/mach-msm/mdm_common.c b/arch/arm/mach-msm/mdm_common.c
index 167419a..fc59c80 100644
--- a/arch/arm/mach-msm/mdm_common.c
+++ b/arch/arm/mach-msm/mdm_common.c
@@ -44,6 +44,10 @@
 #include "mdm_private.h"
 #include "sysmon.h"
 
+#ifdef CONFIG_MACH_HTC
+#include <mach/board_htc.h>
+#endif
+
 #define MDM_MODEM_TIMEOUT	6000
 #define MDM_MODEM_DELTA	100
 #define MDM_BOOT_TIMEOUT	60000L
@@ -119,6 +123,11 @@
 int vddmin_gpios_sent;
 static struct mdm_ops *mdm_ops;
 
+#ifdef CONFIG_MACH_HTC
+extern void register_ap2mdm_pmic_reset_n_gpio(unsigned);
+static char modem_errmsg[MODEM_ERRMSG_LEN];
+#endif
+
 static void mdm_device_list_add(struct mdm_device *mdev)
 {
 	unsigned long flags;
@@ -587,6 +596,43 @@
 			   __func__, ret);
 		put_user(ret, (unsigned long __user *) arg);
 		break;
+#ifdef CONFIG_MACH_HTC
+	case GET_MFG_MODE:
+		put_user(board_mfg_mode(), (unsigned long __user *) arg);
+		break;
+	case SET_MODEM_ERRMSG:
+		memset(modem_errmsg, 0, sizeof(modem_errmsg));
+		if (copy_from_user(modem_errmsg, (void __user *) arg, MODEM_ERRMSG_LEN)) {
+			return -EFAULT;
+		}
+		modem_errmsg[MODEM_ERRMSG_LEN - 1] = '\0';
+		break;
+	case GET_RADIO_FLAG:
+		put_user(get_radio_flag(), (unsigned long __user *) arg);
+		break;
+	case EFS_SYNC_DONE:
+		pr_debug("%s: EFS_SYNC done\n", __func__);
+		break;
+	case NV_WRITE_DONE:
+		if (GPIO_IS_VALID(mdm_drv->ap2mdm_ipc1_gpio)) {
+			gpio_direction_output(mdm_drv->ap2mdm_ipc1_gpio, 1);
+			msleep(1);
+			gpio_direction_output(mdm_drv->ap2mdm_ipc1_gpio, 0);
+		}
+		break;
+	case HTC_POWER_OFF_CHARM:
+		atomic_set(&mdm_drv->mdm_ready, 0);
+		mdm_drv->mdm_hsic_reconnected = 0;
+		if (GPIO_IS_VALID(mdm_drv->ap2mdm_kpdpwr_n_gpio))
+			gpio_direction_output(mdm_drv->ap2mdm_kpdpwr_n_gpio, 0);
+		if (GPIO_IS_VALID(mdm_drv->ap2mdm_pmic_reset_n_gpio))
+			gpio_direction_output(mdm_drv->ap2mdm_pmic_reset_n_gpio, 0);
+		mdelay(2000);
+		break;
+	case HTC_UPDATE_CRC_RESTART_LEVEL:
+		pr_debug("%s: HTC_UPDATE_CRC_RESTART_LEVEL\n", __func__);
+		break;
+#endif
 	default:
 		pr_err("%s: invalid ioctl cmd = %d\n", __func__, _IOC_NR(cmd));
 		ret = -EINVAL;
@@ -998,6 +1044,23 @@
 							"USB_SW");
 	mdm_drv->usb_switch_gpio = pres ? pres->start : -1;
 
+#ifdef CONFIG_MACH_HTC
+	/* AP2MDM_PMIC_RESET_N */
+	pres = platform_get_resource_byname(pdev, IORESOURCE_IO,
+							"AP2MDM_PMIC_RESET_N");
+	mdm_drv->ap2mdm_pmic_reset_n_gpio = pres ? pres->start : -1;
+
+	/* MDM2AP_HSIC_READY */
+	pres = platform_get_resource_byname(pdev, IORESOURCE_IO,
+							"MDM2AP_HSIC_READY");
+	mdm_drv->mdm2ap_hsic_ready_gpio = pres ? pres->start : -1;
+
+	/* AP2MDM_IPC1 */
+	pres = platform_get_resource_byname(pdev, IORESOURCE_IO,
+							"AP2MDM_IPC1");
+	mdm_drv->ap2mdm_ipc1_gpio = pres ? pres->start : -1;
+#endif
+
 	mdm_drv->boot_type                  = CHARM_NORMAL_BOOT;
 
 	mdev->dump_timeout_ms = mdm_drv->pdata->ramdump_timeout_ms > 0 ?
@@ -1029,6 +1092,15 @@
 	if (GPIO_IS_VALID(mdm_drv->ap2mdm_wakeup_gpio))
 		gpio_free(mdm_drv->ap2mdm_wakeup_gpio);
 
+#ifdef CONFIG_MACH_HTC
+	if (GPIO_IS_VALID(mdm_drv->ap2mdm_pmic_reset_n_gpio))
+		gpio_free(mdm_drv->ap2mdm_pmic_reset_n_gpio);
+	if (GPIO_IS_VALID(mdm_drv->mdm2ap_hsic_ready_gpio))
+		gpio_free(mdm_drv->mdm2ap_hsic_ready_gpio);
+	if (GPIO_IS_VALID(mdm_drv->ap2mdm_ipc1_gpio))
+		gpio_free(mdm_drv->ap2mdm_ipc1_gpio);
+#endif
+
 	if (mdev->mdm_queue) {
 		destroy_workqueue(mdev->mdm_queue);
 		mdev->mdm_queue = NULL;
@@ -1070,6 +1142,19 @@
 		}
 	}
 
+#ifdef CONFIG_MACH_HTC
+	if (GPIO_IS_VALID(mdm_drv->ap2mdm_pmic_reset_n_gpio)) {
+		gpio_request(mdm_drv->ap2mdm_pmic_reset_n_gpio, "AP2MDM_PMIC_RESET_N");
+		register_ap2mdm_pmic_reset_n_gpio(mdm_drv->ap2mdm_pmic_reset_n_gpio);
+	}
+	if (GPIO_IS_VALID(mdm_drv->mdm2ap_hsic_ready_gpio))
+		gpio_request(mdm_drv->mdm2ap_hsic_ready_gpio, "MDM2AP_HSIC_READY");
+	if (GPIO_IS_VALID(mdm_drv->ap2mdm_ipc1_gpio)) {
+		gpio_request(mdm_drv->ap2mdm_ipc1_gpio, "AP2MDM_IPC1");
+		gpio_direction_output(mdm_drv->ap2mdm_ipc1_gpio, 0);
+	}
+#endif
+
 	gpio_direction_output(mdm_drv->ap2mdm_status_gpio, 0);
 	gpio_direction_output(mdm_drv->ap2mdm_errfatal_gpio, 0);
 
diff --git a/arch/arm/mach-msm/mdm_private.h b/arch/arm/mach-msm/mdm_private.h
index 40525f7..9e72c76 100644
--- a/arch/arm/mach-msm/mdm_private.h
+++ b/arch/arm/mach-msm/mdm_private.h
@@ -55,6 +55,12 @@
 	int peripheral_status;
 	struct mutex peripheral_status_lock;
 	int device_id;
+#ifdef CONFIG_MACH_HTC
+	int mdm_hsic_reconnected;
+	unsigned ap2mdm_pmic_reset_n_gpio;
+	unsigned mdm2ap_hsic_ready_gpio;
+	unsigned ap2mdm_ipc1_gpio;
+#endif
 
 	struct mdm_platform_data *pdata;
 };
diff --git a/arch/arm/mach-msm/restart.c b/arch/arm/mach-msm/restart.c
index 33e55e2..2e2d217 100644
--- a/arch/arm/mach-msm/restart.c
+++ b/arch/arm/mach-msm/restart.c
@@ -151,6 +151,38 @@
 EXPORT_SYMBOL(msm_set_restart_mode);
 
 #ifdef CONFIG_MACH_HTC
+static unsigned ap2mdm_pmic_reset_n_gpio = -1;
+void register_ap2mdm_pmic_reset_n_gpio(unsigned gpio)
+{
+	ap2mdm_pmic_reset_n_gpio = gpio;
+}
+EXPORT_SYMBOL(register_ap2mdm_pmic_reset_n_gpio);
+
+static void mdm_power_off(void)
+{
+	int i;
+
+	if (gpio_is_valid(ap2mdm_pmic_reset_n_gpio)) {
+		pr_info("%s: Powering off MDM", __func__);
+		gpio_direction_output(ap2mdm_pmic_reset_n_gpio, 0);
+		for (i = 0; i < 2; i++) {
+			pet_watchdog();
+			mdelay(1000);
+		}
+		pr_info("%s: Powered off MDM", __func__);
+	}
+}
+
+static void mdm_wait_self_refresh(void)
+{
+	int i;
+
+	for (i = 0; i < 2; i++) {
+		pet_watchdog();
+		mdelay(1000);
+	}
+}
+
 static void msm_flush_console(void)
 {
 	unsigned long flags;
@@ -285,6 +317,9 @@
 	set_dload_mode(0);
 #endif
 	pm8xxx_reset_pwr_off(0);
+#ifdef CONFIG_MACH_HTC
+	mdm_power_off();
+#endif
 
 	if (lower_pshold) {
 		__raw_writel(0, PSHOLD_CTL_SU);
@@ -462,6 +497,13 @@
 #endif /* CONFIG_LGE_CRASH_HANDLER */
 
 #ifdef CONFIG_MACH_HTC
+	if (!(get_radio_flag() & RADIO_FLAG_USB_UPLOAD) ||
+			((get_restart_reason() != RESTART_REASON_RAMDUMP) &&
+			 (get_restart_reason() != (RESTART_REASON_OEM_BASE | 0x99))))
+		mdm_power_off();
+	else
+		mdm_wait_self_refresh();
+
 	msm_flush_console();
 #endif
 
diff --git a/include/linux/msm_charm.h b/include/linux/msm_charm.h
index 1d1f3bb..224c32d 100644
--- a/include/linux/msm_charm.h
+++ b/include/linux/msm_charm.h
@@ -14,6 +14,18 @@
 #define IMAGE_UPGRADE		_IOW(CHARM_CODE, 9, int)
 #define SHUTDOWN_CHARM		_IOW(CHARM_CODE, 10, int)
 
+#ifdef CONFIG_MACH_HTC
+#define MODEM_ERRMSG_LEN	256
+
+#define GET_MFG_MODE		_IO(CHARM_CODE, 94)
+#define GET_RADIO_FLAG		_IO(CHARM_CODE, 95)
+#define SET_MODEM_ERRMSG	_IOW(CHARM_CODE, 96, char[MODEM_ERRMSG_LEN])
+#define EFS_SYNC_DONE		_IO(CHARM_CODE, 99)
+#define NV_WRITE_DONE		_IO(CHARM_CODE, 100)
+#define HTC_POWER_OFF_CHARM	_IOW(CHARM_CODE, 101, int)
+#define HTC_UPDATE_CRC_RESTART_LEVEL	_IOW(CHARM_CODE, 102, int)
+#endif
+
 enum charm_boot_type {
 	CHARM_NORMAL_BOOT = 0,
 	CHARM_RAM_DUMPS,
@@ -23,4 +35,5 @@
 	APQ_CONTROLLED_UPGRADE = 0,
 	MDM_CONTROLLED_UPGRADE,
 };
+
 #endif