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