dev/pmic: adds pm8921 gpio config api

Change-Id: I995b23be5b45d75a518fc1f010aeeefba692124b
diff --git a/dev/pmic/pm8921/include/dev/pm8921.h b/dev/pmic/pm8921/include/dev/pm8921.h
index faca8e2..db95b71 100644
--- a/dev/pmic/pm8921/include/dev/pm8921.h
+++ b/dev/pmic/pm8921/include/dev/pm8921.h
@@ -31,6 +31,26 @@
 
 #include <sys/types.h>
 
+
+#define PM_GPIO_DIR_OUT         0x01
+#define PM_GPIO_DIR_IN          0x02
+#define PM_GPIO_DIR_BOTH        (PM_GPIO_DIR_OUT | PM_GPIO_DIR_IN)
+
+#define PM_GPIO_PULL_UP1        2
+#define PM_GPIO_PULL_UP2        3
+#define PM_GPIO_PULL_DN         4
+#define PM_GPIO_PULL_NO         5
+
+#define PM_GPIO_STRENGTH_NO     0
+#define PM_GPIO_STRENGTH_HIGH   1
+#define PM_GPIO_STRENGTH_MED    2
+#define PM_GPIO_STRENGTH_LOW    3
+
+#define PM_GPIO_FUNC_NORMAL     0
+#define PM_GPIO_FUNC_PAIRED     1
+#define PM_GPIO_FUNC_1          2
+#define PM_GPIO_FUNC_2          3
+
 typedef struct
 {
 	uint32_t initialized;
@@ -41,7 +61,20 @@
 } pm8921_dev_t;
 
 
+struct pm8921_gpio {
+	int direction;
+	int output_buffer;
+	int output_value;
+	int pull;
+	int vin_sel;
+	int out_strength;
+	int function;
+	int inv_int_pol;
+	int disable_pin;
+};
+
 void pm8921_init(pm8921_dev_t *);
+int  pm8921_gpio_config(int gpio, struct pm8921_gpio *param);
 void pm8921_boot_done(void);
 
 #endif
diff --git a/dev/pmic/pm8921/pm8921.c b/dev/pmic/pm8921/pm8921.c
index 6a47e05..bc7e7d4 100644
--- a/dev/pmic/pm8921/pm8921.c
+++ b/dev/pmic/pm8921/pm8921.c
@@ -65,3 +65,75 @@
 	val |= (SYS_CONFIG_2_BOOT_DONE | SYS_CONFIG_2_ADAPTIVE_BOOT_DISABLE);
 	dev->write(&val, 1, SYS_CONFIG_2);
 }
+
+/* Configure PMIC GPIO */
+int pm8921_gpio_config(int gpio, struct pm8921_gpio *param)
+{
+	int ret;
+	uint8_t bank[6];
+	uint8_t output_buf_config;
+	uint8_t output_value;
+
+	static uint8_t dir_map[] = {
+		PM_GPIO_MODE_OFF,
+		PM_GPIO_MODE_OUTPUT,
+		PM_GPIO_MODE_INPUT,
+		PM_GPIO_MODE_BOTH,
+	};
+
+	if (param == NULL) {
+	  dprintf (INFO, "pm8291_gpio struct not defined\n");
+          return -1;
+	}
+
+	/* Select banks and configure the gpio */
+	bank[0] = PM_GPIO_WRITE |
+		((param->vin_sel << PM_GPIO_VIN_SHIFT) &
+			PM_GPIO_VIN_MASK) |
+		PM_GPIO_MODE_ENABLE;
+
+	/* bank1 */
+	if ((param->direction & PM_GPIO_DIR_OUT) && param->output_buffer)
+		output_buf_config = PM_GPIO_OUT_BUFFER_OPEN_DRAIN;
+	else
+		output_buf_config = 0;
+
+	if ((param->direction & PM_GPIO_DIR_OUT) && param->output_value)
+		output_value = 1;
+	else
+		output_value = 0;
+
+	bank[1] = PM_GPIO_WRITE |
+		((1 << PM_GPIO_BANK_SHIFT) & PM_GPIO_BANK_MASK) |
+		((dir_map[param->direction] << PM_GPIO_MODE_SHIFT)
+						& PM_GPIO_MODE_MASK) |
+		output_buf_config |
+		output_value;
+
+	bank[2] = PM_GPIO_WRITE |
+		((2 << PM_GPIO_BANK_SHIFT) & PM_GPIO_BANK_MASK) |
+		((param->pull << PM_GPIO_PULL_SHIFT) &
+			PM_GPIO_PULL_MASK);
+
+	bank[3] = PM_GPIO_WRITE |
+		((3 << PM_GPIO_BANK_SHIFT) & PM_GPIO_BANK_MASK) |
+		((param->out_strength << PM_GPIO_OUT_STRENGTH_SHIFT) &
+			PM_GPIO_OUT_STRENGTH_MASK) |
+		(param->disable_pin ? PM_GPIO_PIN_DISABLE : PM_GPIO_PIN_ENABLE);
+
+	bank[4] = PM_GPIO_WRITE |
+		((4 << PM_GPIO_BANK_SHIFT) & PM_GPIO_BANK_MASK) |
+		((param->function << PM_GPIO_FUNC_SHIFT) &
+			PM_GPIO_FUNC_MASK);
+
+	bank[5] = PM_GPIO_WRITE |
+		((5 << PM_GPIO_BANK_SHIFT) & PM_GPIO_BANK_MASK) |
+		(param->inv_int_pol ? 0 : PM_GPIO_NON_INT_POL_INV);
+
+	ret = dev->write(bank, 6, GPIO_CNTL(gpio));
+	if (ret) {
+		dprintf(INFO, "Failed to write to PM8921 ret=%d.\n", ret);
+		return -1;
+	}
+	return 0;
+}
diff --git a/dev/pmic/pm8921/pm8921_hw.h b/dev/pmic/pm8921/pm8921_hw.h
index 49069ee..1fba8f2 100644
--- a/dev/pmic/pm8921/pm8921_hw.h
+++ b/dev/pmic/pm8921/pm8921_hw.h
@@ -27,9 +27,51 @@
  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#define PBL_ACCESS_2 0x005
-#define PBL_ACCESS_2_ENUM_TIMER_STOP      (1 << 1)
+#define PBL_ACCESS_2                          0x005
+#define PBL_ACCESS_2_ENUM_TIMER_STOP          (1 << 1)
 
-#define SYS_CONFIG_2 0x007
-#define SYS_CONFIG_2_BOOT_DONE             (1 << 6)
-#define SYS_CONFIG_2_ADAPTIVE_BOOT_DISABLE (1 << 7)
+#define SYS_CONFIG_2                          0x007
+#define SYS_CONFIG_2_BOOT_DONE                (1 << 6)
+#define SYS_CONFIG_2_ADAPTIVE_BOOT_DISABLE    (1 << 7)
+
+#define GPIO_CNTL_BASE                        0x150
+#define GPIO_CNTL(n)                          (GPIO_CNTL_BASE + n)
+
+/* GPIO Bank register programming */
+#define PM_GPIO_BANK_MASK                0x70
+#define PM_GPIO_BANK_SHIFT               4
+#define PM_GPIO_WRITE                    0x80
+
+/* Bank 0 */
+#define PM_GPIO_VIN_MASK                 0x0E
+#define PM_GPIO_VIN_SHIFT                1
+#define PM_GPIO_MODE_ENABLE              0x01
+
+/* Bank 1 */
+#define PM_GPIO_MODE_MASK                0x0C
+#define PM_GPIO_MODE_SHIFT               2
+#define PM_GPIO_OUT_BUFFER_OPEN_DRAIN    0x02
+#define PM_GPIO_OUT_INVERT               0x01
+
+#define PM_GPIO_MODE_OFF                 3
+#define PM_GPIO_MODE_OUTPUT              2
+#define PM_GPIO_MODE_INPUT               0
+#define PM_GPIO_MODE_BOTH                1
+
+/* Bank 2 */
+#define PM_GPIO_PULL_MASK                0x0E
+#define PM_GPIO_PULL_SHIFT               1
+
+/* Bank 3 */
+#define PM_GPIO_OUT_STRENGTH_MASK        0x0C
+#define PM_GPIO_OUT_STRENGTH_SHIFT       2
+#define PM_GPIO_PIN_ENABLE               0x00
+#define PM_GPIO_PIN_DISABLE              0x01
+
+/* Bank 4 */
+#define PM_GPIO_FUNC_MASK                0x0E
+#define PM_GPIO_FUNC_SHIFT               1
+
+/* Bank 5 */
+#define PM_GPIO_NON_INT_POL_INV          0x08
+