pmic: 8917: Add support for new APIs
Add support for APIs to read battery voltage level, vbus status
and new LDO api.
Change-Id: I6205113b515768b96a50960fb4081f534c5382bf
diff --git a/dev/pmic/pm8921/include/dev/pm8921.h b/dev/pmic/pm8921/include/dev/pm8921.h
index 715e474..7200eb0 100644
--- a/dev/pmic/pm8921/include/dev/pm8921.h
+++ b/dev/pmic/pm8921/include/dev/pm8921.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-2012, Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -10,7 +10,7 @@
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
- * * Neither the name of Code Aurora Forum, Inc. nor the names of its
+ * * Neither the name of Linux Foundation, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
@@ -61,6 +61,25 @@
mpp_end = mpp_12,
};
+typedef enum {
+ BAT_VOL_2_8 = 0,
+ BAT_VOL_2_9,
+ BAT_VOL_3_0,
+ BAT_VOL_3_1,
+ BAT_VOL_3_2,
+ BAT_VOL_3_3,
+ BAT_VOL_3_4,
+ BAT_VOL_3_5,
+ BAT_VOL_3_6,
+ BAT_VOL_3_7,
+ BAT_VOL_3_8,
+ BAT_VOL_3_9,
+ BAT_VOL_4_0,
+ BAT_VOL_4_1,
+ BAT_VOL_4_2,
+ BAT_VOL_4_3,
+} bat_vol_t;
+
#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)
@@ -139,6 +158,13 @@
int disable_pin;
};
+struct pm89xx_vreg {
+ const char *name;
+ uint8_t type;
+ uint16_t test_reg;
+ uint16_t ctrl_reg;
+};
+
void pm8921_init(pm8921_dev_t *);
int pm8921_gpio_config(int gpio, struct pm8921_gpio *param);
void pm8921_boot_done(void);
@@ -156,4 +182,8 @@
int pm8921_low_voltage_switch_enable(uint8_t lvs_id);
int pm8921_mpp_set_digital_output(uint8_t mpp_id);
int pm8921_rtc_alarm_disable(void);
+int pm89xx_bat_alarm_set(bat_vol_t, bat_vol_t);
+int pm89xx_bat_alarm_status(uint8_t *, uint8_t *);
+int pm89xx_vbus_status(void);
+int pm89xx_ldo_set_voltage(const char * , uint32_t);
#endif
diff --git a/dev/pmic/pm8921/pm8921.c b/dev/pmic/pm8921/pm8921.c
index 1acc021..231b8b6 100644
--- a/dev/pmic/pm8921/pm8921.c
+++ b/dev/pmic/pm8921/pm8921.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-2012, Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -10,7 +10,7 @@
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
- * * Neither the name of Code Aurora Forum, Inc. nor the names of its
+ * * Neither the name of Linux Foundation, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
@@ -27,9 +27,11 @@
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <assert.h>
+#include <string.h>
#include <sys/types.h>
#include <err.h>
#include <dev/pm8921.h>
+#include <platform/timer.h>
#include "pm8921_hw.h"
static pm8921_dev_t *dev;
@@ -539,3 +541,191 @@
return rc;
}
+
+/*
+ * Set battery alarm with low & high threshold values
+ */
+int pm89xx_bat_alarm_set(bat_vol_t up_thresh_vol, bat_vol_t low_thresh_vol)
+{
+ int rc;
+ uint8_t reg = 0;
+
+ if ((up_thresh_vol > BAT_VOL_4_3) || (low_thresh_vol > BAT_VOL_4_3)) {
+ dprintf(CRITICAL, "Input voltage not in permissible range\n");
+ return 1;
+ }
+
+ /*
+ * Write upper & lower threshold values
+ */
+ reg = (up_thresh_vol << PM89XX_BAT_UP_THRESH_VOL) | low_thresh_vol;
+
+ rc = dev->write(®, 1, PM89XX_BAT_ALRM_THRESH);
+ if (rc) {
+ dprintf(CRITICAL, "Failed to set BAT_THRESH reg = %d\n", rc);
+ return rc;
+ }
+
+ /* Read Alarm control to use the existing hysteresis values */
+ rc = dev->read(®, 1, PM89XX_BAT_ALRM_CTRL);
+ if (rc) {
+ dprintf(CRITICAL, "Failed to read BAT_ALARM reg = %d\n", rc);
+ return rc;
+ }
+
+ /* Enable battery alarm */
+ reg |= PM89XX_BAT_ALRM_ENABLE;
+ rc = dev->write(®, 1, PM89XX_BAT_ALRM_CTRL);
+ if (rc) {
+ dprintf(CRITICAL, "Failed to enable BAT_ALARM reg = %d\n", rc);
+ return rc;
+ }
+
+ /* Wait for the comparator o/p to settle */
+ mdelay(10);
+
+ return rc;
+}
+
+/*
+ * API to return status of battery
+ * if the vbatt is below upper threshold return 0
+ * if the vbatt is below lower threshold return 1
+ */
+int pm89xx_bat_alarm_status(uint8_t *high_status, uint8_t *low_status)
+{
+ int rc = 0;
+ uint8_t reg = 0;
+
+ /* Read the battery status */
+ rc = dev->read(®, 1, PM89XX_BAT_ALRM_CTRL);
+ if (rc) {
+ dprintf(CRITICAL, "Failed to read BAT_ALARM reg = %d\n", rc);
+ return rc;
+ }
+
+ /* Return the status if battery alarm is enabled */
+ if (reg & PM89XX_BAT_ALRM_ENABLE) {
+ *high_status = (reg & PM89XX_BAT_UPR_STATUS);
+ *low_status = (reg & PM89XX_BAT_LWR_STATUS);
+ } else {
+ dprintf(CRITICAL, "Battery alarm is not enabled\n");
+ return 1;
+ }
+
+ return rc;
+}
+
+/*
+ * Return 1 if VBUS is connected, 0 otherwise
+ */
+int pm89xx_vbus_status(void)
+{
+ int rc;
+ uint8_t reg = 0;
+
+ rc = dev->read(®, 1, PM89XX_USB_OVP_CTRL);
+ if (rc) {
+ dprintf(CRITICAL, "Failed to read USB OVP CTRL = %d\n", rc);
+ return rc;
+ }
+
+ reg &= PM89XX_VBUS_INPUT_STATUS;
+
+ return reg;
+}
+
+static struct pm89xx_vreg *ldo_get(const char *ldo_name)
+{
+ uint8_t i;
+ struct pm89xx_vreg *ldo = NULL;
+
+ for (i = 0; i < ARRAY_SIZE(ldo_data); i++) {
+ ldo = &ldo_data[i];
+ if (!strncmp(ldo->name, ldo_name, strlen(ldo_name)))
+ break;
+ }
+
+ return ldo;
+}
+
+/*
+ * API takes LDO name & voltage as input
+ * Input voltage is taken in mVs
+ * PLDO voltage ranging from 1500mV to 3000mV
+ * NLDO voltage ranging from 750mV to 1525mV
+ */
+int pm89xx_ldo_set_voltage(const char *ldo_name, uint32_t voltage)
+{
+ uint8_t mult;
+ uint8_t val = 0;
+ int32_t ret = 0;
+ struct pm89xx_vreg *ldo;
+
+ /* Find the LDO info from table */
+ ldo = ldo_get(ldo_name);
+
+ if (!ldo) {
+ dprintf(CRITICAL, "Requested LDO is not supported : \
+ %s\n", ldo_name);
+ return -1;
+ }
+
+ /* Find the voltage multiplying factor */
+ if (ldo->type == PLDO_TYPE) {
+ if (voltage < PLDO_MV_VMIN)
+ voltage = PLDO_MV_VMIN;
+ else if (voltage > PLDO_MV_VMAX)
+ voltage = PLDO_MV_VMAX;
+ mult = (voltage - PLDO_MV_VMIN) / PLDO_MV_VSTEP;
+ } else {
+ if (voltage < NLDO_MV_VMIN)
+ voltage = NLDO_MV_VMIN;
+ else if (voltage > NLDO_MV_VMAX)
+ voltage = NLDO_MV_VMAX;
+ mult = (voltage - NLDO_MV_VMIN) / NLDO_MV_VSTEP;
+ }
+
+ /* Program the TEST reg */
+ if (ldo->type == PLDO_TYPE) {
+ /* Bank 2, only for p ldo, use 1.25V reference */
+ val = 0x0;
+ val |= (1 << PM8921_LDO_TEST_REG_RW);
+ val |= (2 << PM8921_LDO_TEST_REG_BANK_SEL);
+ ret = dev->write(&val, 1, ldo->test_reg);
+ if (ret) {
+ dprintf(CRITICAL, "Failed to write to PM8921 LDO Test \
+ Reg ret=%d.\n", ret);
+ return -1;
+ }
+
+ /*
+ * Bank 4, only for p ldo, disable output range ext,
+ * normal capacitance
+ */
+ val = 0x0;
+ val |= (1 << PM8921_LDO_TEST_REG_RW);
+ val |= (4 << PM8921_LDO_TEST_REG_BANK_SEL);
+ ret = dev->write(&val, 1, ldo->test_reg);
+ if (ret) {
+ dprintf(CRITICAL, "Failed to write to PM8921 LDO Test \
+ Reg ret=%d.\n", ret);
+ return -1;
+ }
+ }
+
+ /* Program the CTRL reg */
+ val = 0x0;
+ val |= (1 << PM8921_LDO_CTRL_REG_ENABLE);
+ val |= (1 << PM8921_LDO_CTRL_REG_PULL_DOWN);
+ val |= (0 << PM8921_LDO_CTRL_REG_POWER_MODE);
+ val |= (mult << PM8921_LDO_CTRL_REG_VOLTAGE);
+ ret = dev->write(&val, 1, ldo->ctrl_reg);
+ if (ret) {
+ dprintf(CRITICAL, "Failed to write to PM8921 LDO Ctrl Reg \
+ 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 bf43543..e75026e 100644
--- a/dev/pmic/pm8921/pm8921_hw.h
+++ b/dev/pmic/pm8921/pm8921_hw.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-2012, Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -10,7 +10,7 @@
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
- * * Neither the name of Code Aurora Forum, Inc. nor the names of its
+ * * Neither the name of Linux Foundation, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
@@ -26,6 +26,7 @@
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include <bits.h>
#define PBL_ACCESS_2 0x005
#define PBL_ACCESS_2_ENUM_TIMER_STOP (1 << 1)
@@ -129,3 +130,44 @@
#define PM8921_MPP_CTRL_DIGITAL_OUTPUT (1 << 5)
#define PM8921_MPP_CTRL_VIO_1 (1 << 2)
#define PM8921_MPP_CTRL_OUTPUT_HIGH (1 << 0)
+
+#define PM89XX_BAT_UP_THRESH_VOL 4
+#define PM89XX_BAT_ALRM_THRESH 0x23
+#define PM89XX_BAT_ALRM_CTRL 0x24
+#define PM89XX_USB_OVP_CTRL 0x21C
+
+#define PM89XX_BAT_ALRM_ENABLE BIT(7)
+#define PM89XX_BAT_UPR_STATUS BIT(1)
+#define PM89XX_BAT_LWR_STATUS BIT(0)
+
+#define PM89XX_VBUS_INPUT_STATUS BIT(0)
+
+/* voltages are specified in mV */
+#define PLDO_MV_VMIN 1500
+#define PLDO_MV_VMAX 3000
+#define PLDO_MV_VSTEP 50
+
+#define NLDO_MV_VMIN 750
+#define NLDO_MV_VMAX 1525
+#define NLDO_MV_VSTEP 25
+
+#define PLDO_TYPE 0
+#define NLDO_TYPE 1
+
+#define LDO(_name, _type, _test_reg, _ctrl_reg) \
+{\
+ .name = _name,\
+ .type = _type,\
+ .test_reg = _test_reg,\
+ .ctrl_reg = _ctrl_reg, \
+}
+
+struct pm89xx_vreg ldo_data[] = {
+ LDO("LDO30", PLDO_TYPE, 0x0A3, 0x0A4),
+ LDO("LDO31", PLDO_TYPE, 0x0A5, 0x0A6),
+ LDO("LDO32", PLDO_TYPE, 0x0A7, 0x0A8),
+ LDO("LDO33", PLDO_TYPE, 0x0C6, 0x0C7),
+ LDO("LDO34", PLDO_TYPE, 0x0D2, 0x0D3),
+ LDO("LDO35", PLDO_TYPE, 0x0D4, 0x0D5),
+ LDO("LDO36", PLDO_TYPE, 0x0A9, 0x0AA),
+};