esoc: Add support for sdxpoorwills

Add support for sdxpoorwills, using mdm9x55 data as a starting point.

Change-Id: Ic1abf2997781e84ab20270d974794ed37c20d62a
Signed-off-by: Raghavendra Rao Ananta <rananta@codeaurora.org>
diff --git a/drivers/esoc/esoc-mdm-pon.c b/drivers/esoc/esoc-mdm-pon.c
index 0e85776..9624275 100644
--- a/drivers/esoc/esoc-mdm-pon.c
+++ b/drivers/esoc/esoc-mdm-pon.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2015, 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2015, 2017-2018, The Linux Foundation. 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
@@ -60,6 +60,24 @@
 	return 0;
 }
 
+/* This function can be called from atomic context. */
+static int sdxpoorwills_toggle_soft_reset(struct mdm_ctrl *mdm, bool atomic)
+{
+	int soft_reset_direction_assert = mdm->soft_reset_inverted;
+
+	gpio_direction_output(MDM_GPIO(mdm, AP2MDM_SOFT_RESET),
+			soft_reset_direction_assert);
+	/*
+	 * Allow PS hold assert to be detected
+	 */
+	if (!atomic)
+		usleep_range(80000, 180000);
+	else
+		mdelay(100);
+	gpio_direction_output(MDM_GPIO(mdm, AP2MDM_SOFT_RESET),
+			!soft_reset_direction_assert);
+	return 0;
+}
 
 static int mdm4x_do_first_power_on(struct mdm_ctrl *mdm)
 {
@@ -99,6 +117,7 @@
 {
 	struct device *dev = mdm->dev;
 	int soft_reset_direction = mdm->soft_reset_inverted ? 1 : 0;
+
 	/* Assert the soft reset line whether mdm2ap_status went low or not */
 	gpio_direction_output(MDM_GPIO(mdm, AP2MDM_SOFT_RESET),
 					soft_reset_direction);
@@ -135,6 +154,27 @@
 	return 0;
 }
 
+static int sdxpoorwills_power_down(struct mdm_ctrl *mdm)
+{
+	struct device *dev = mdm->dev;
+	int soft_reset_direction = mdm->soft_reset_inverted ? 1 : 0;
+
+	/* Assert the soft reset line whether mdm2ap_status went low or not */
+	gpio_direction_output(MDM_GPIO(mdm, AP2MDM_SOFT_RESET),
+					soft_reset_direction);
+	dev_info(dev, "Doing a hard reset\n");
+	gpio_direction_output(MDM_GPIO(mdm, AP2MDM_SOFT_RESET),
+						soft_reset_direction);
+	/*
+	 * Currently, there is a debounce timer on the charm PMIC. It is
+	 * necessary to hold the PMIC RESET low for 325ms
+	 * for the reset to fully take place. Sleep here to ensure the
+	 * reset has occurred before the function exits.
+	 */
+	mdelay(325);
+	return 0;
+}
+
 static void mdm4x_cold_reset(struct mdm_ctrl *mdm)
 {
 	if (!gpio_is_valid(MDM_GPIO(mdm, AP2MDM_SOFT_RESET)))
@@ -158,6 +198,16 @@
 			!mdm->soft_reset_inverted);
 }
 
+static void sdxpoorwills_cold_reset(struct mdm_ctrl *mdm)
+{
+	dev_info(mdm->dev, "Triggering mdm cold reset");
+	gpio_direction_output(MDM_GPIO(mdm, AP2MDM_SOFT_RESET),
+			!!mdm->soft_reset_inverted);
+	mdelay(600);
+	gpio_direction_output(MDM_GPIO(mdm, AP2MDM_SOFT_RESET),
+			!mdm->soft_reset_inverted);
+}
+
 static int mdm4x_pon_dt_init(struct mdm_ctrl *mdm)
 {
 	int val;
@@ -215,3 +265,12 @@
 	.dt_init = mdm4x_pon_dt_init,
 	.setup = mdm4x_pon_setup,
 };
+
+struct mdm_pon_ops sdxpoorwills_pon_ops = {
+	.pon = mdm4x_do_first_power_on,
+	.soft_reset = sdxpoorwills_toggle_soft_reset,
+	.poff_force = sdxpoorwills_power_down,
+	.cold_reset = sdxpoorwills_cold_reset,
+	.dt_init = mdm4x_pon_dt_init,
+	.setup = mdm4x_pon_setup,
+};