pmic: 8x41: Add support ldo set voltage API.
Change-Id: Ia35d2f64842ddc1f5bf82d93c81305e099e84151
diff --git a/dev/pmic/pm8x41/include/pm8x41.h b/dev/pmic/pm8x41/include/pm8x41.h
index 3816325..94436b1 100644
--- a/dev/pmic/pm8x41/include/pm8x41.h
+++ b/dev/pmic/pm8x41/include/pm8x41.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012, The 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
@@ -9,7 +9,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 The 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.
*
@@ -29,6 +29,8 @@
#ifndef _PM8x41_H_
#define _PM8x41_H_
+#include <sys/types.h>
+
#define PM_GPIO_DIR_OUT 0x01
#define PM_GPIO_DIR_IN 0x00
#define PM_GPIO_DIR_BOTH 0x02
@@ -60,5 +62,15 @@
void pm8x41_set_boot_done();
int pm8x41_vol_down_key_status();
void pm8x41_reset_configure(uint8_t);
+int pm8x41_ldo_set_voltage(const char *, uint32_t);
+int pm8x41_ldo_control(const char *, uint8_t);
+struct pm8x41_ldo {
+ const char *name;
+ uint8_t type;
+ uint32_t base;
+ uint32_t range_reg;
+ uint32_t step_reg;
+ uint32_t enable_reg;
+};
#endif
diff --git a/dev/pmic/pm8x41/include/pm8x41_hw.h b/dev/pmic/pm8x41/include/pm8x41_hw.h
index 4886a8e..01fd07f 100644
--- a/dev/pmic/pm8x41/include/pm8x41_hw.h
+++ b/dev/pmic/pm8x41/include/pm8x41_hw.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012, The 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
@@ -9,7 +9,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 The 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.
*
@@ -29,7 +29,6 @@
#ifndef _PM8x41_HW_H_
#define _PM8x41_HW_H_
-
/* SMBB Registers */
#define SMBB_MISC_BOOT_DONE 0x1642
@@ -76,4 +75,44 @@
#define S2_RESET_TYPE_WARM 0x1
#define PON_RESIN_N_RESET_S2_TIMER_MAX_VALUE 0x7
+/* LDO voltage ranges */
+#define NLDO_UV_MIN 375000
+#define NLDO_UV_MAX 1537500
+#define NLDO_UV_STEP 12500
+#define NLDO_UV_VMIN_LOW 750000
+
+#define PLDO_UV_VMIN_LOW 750000
+#define PLDO_UV_VMIN_MID 1500000
+#define PLDO_UV_VMIN_HIGH 1750000
+
+#define PLDO_UV_MIN 1537500
+#define PDLO_UV_MID 3075000
+#define PLDO_UV_MAX 4900000
+#define PLDO_UV_STEP_LOW 12500
+#define PLDO_UV_STEP_MID 25000
+#define PLDO_UV_STEP_HIGH 50000
+
+#define LDO_RANGE_SEL_BIT 0
+#define LDO_VSET_SEL_BIT 0
+#define LDO_VREG_ENABLE_BIT 7
+#define LDO_NORMAL_PWR_BIT 7
+
+#define LDO_RANGE_CTRL 0x40
+#define LDO_STEP_CTRL 0x41
+#define LDO_POWER_MODE 0x45
+#define LDO_EN_CTL_REG 0x46
+
+#define PLDO_TYPE 0
+#define NLDO_TYPE 1
+
+#define LDO(_name, _type, _base, _range, _step, _enable) \
+{ \
+ .name = _name, \
+ .type = _type, \
+ .base = _base, \
+ .range_reg = _range, \
+ .step_reg = _step, \
+ .enable_reg = _enable, \
+}
+
#endif
diff --git a/dev/pmic/pm8x41/pm8x41.c b/dev/pmic/pm8x41/pm8x41.c
index f6804ec..31b13cb 100644
--- a/dev/pmic/pm8x41/pm8x41.c
+++ b/dev/pmic/pm8x41/pm8x41.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012, The 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
@@ -9,7 +9,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 The 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.
*
@@ -30,6 +30,7 @@
#include <debug.h>
#include <reg.h>
#include <spmi.h>
+#include <string.h>
#include <pm8x41_hw.h>
#include <pm8x41.h>
#include <platform/timer.h>
@@ -42,6 +43,11 @@
#define PERIPH_ID(_addr) (((_addr) & 0xFF00) >> 8)
#define SLAVE_ID(_addr) ((_addr) >> 16)
+struct pm8x41_ldo ldo_data[] = {
+ LDO("LDO2", NLDO_TYPE, 0x14100, LDO_RANGE_CTRL, LDO_STEP_CTRL, LDO_EN_CTL_REG),
+ LDO("LDO12", PLDO_TYPE, 0x14B00, LDO_RANGE_CTRL, LDO_STEP_CTRL, LDO_EN_CTL_REG),
+ LDO("LDO22", PLDO_TYPE, 0x15500, LDO_RANGE_CTRL, LDO_STEP_CTRL, LDO_EN_CTL_REG),
+};
/* Local functions */
static uint8_t pm8x41_reg_read(uint32_t addr)
@@ -219,3 +225,103 @@
val |= BIT(S2_RESET_EN_BIT);
REG_WRITE(PON_PS_HOLD_RESET_CTL, val);
}
+
+static struct pm8x41_ldo *ldo_get(const char *ldo_name)
+{
+ uint8_t i;
+ struct pm8x41_ldo *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;
+}
+
+/*
+ * LDO set voltage, takes ldo name & voltage in UV as input
+ */
+int pm8x41_ldo_set_voltage(const char *name, uint32_t voltage)
+{
+ uint32_t range = 0;
+ uint32_t step = 0;
+ uint32_t mult = 0;
+ uint32_t val = 0;
+ uint32_t vmin = 0;
+ struct pm8x41_ldo *ldo;
+
+ ldo = ldo_get(name);
+ if (!ldo) {
+ dprintf(CRITICAL, "LDO requsted is not supported: %s\n", name);
+ return 1;
+ }
+
+ /* Program Normal power mode */
+ val = 0x0;
+ val = (1 << LDO_NORMAL_PWR_BIT);
+ REG_WRITE((ldo->base + LDO_POWER_MODE), val);
+
+ /*
+ * Select range, step & vmin based on input voltage & type of LDO
+ * LDO can operate in low, mid, high power mode
+ */
+ if (ldo->type == PLDO_TYPE) {
+ if (voltage < PLDO_UV_MIN) {
+ range = 2;
+ step = PLDO_UV_STEP_LOW;
+ vmin = PLDO_UV_VMIN_LOW;
+ } else if (voltage < PDLO_UV_MID) {
+ range = 3;
+ step = PLDO_UV_STEP_MID;
+ vmin = PLDO_UV_VMIN_MID;
+ } else {
+ range = 4;
+ step = PLDO_UV_STEP_HIGH;
+ vmin = PLDO_UV_VMIN_HIGH;
+ }
+ } else {
+ range = 2;
+ step = NLDO_UV_STEP;
+ vmin = NLDO_UV_VMIN_LOW;
+ }
+
+ mult = (voltage - vmin) / step;
+
+ /* Set Range in voltage ctrl register */
+ val = 0x0;
+ val = range << LDO_RANGE_SEL_BIT;
+ REG_WRITE((ldo->base + ldo->range_reg), val);
+
+ /* Set multiplier in voltage ctrl register */
+ val = 0x0;
+ val = mult << LDO_VSET_SEL_BIT;
+ REG_WRITE((ldo->base + ldo->step_reg), val);
+
+ return 0;
+}
+
+/*
+ * Enable or Disable LDO
+ */
+int pm8x41_ldo_control(const char *name, uint8_t enable)
+{
+ uint32_t val = 0;
+ struct pm8x41_ldo *ldo;
+
+ ldo = ldo_get(name);
+ if (!ldo) {
+ dprintf(CRITICAL, "Requested LDO is not supported : %s\n", name);
+ return 1;
+ }
+
+ /* Enable LDO */
+ if (enable)
+ val = (1 << LDO_VREG_ENABLE_BIT);
+ else
+ val = (0 << LDO_VREG_ENABLE_BIT);
+
+ REG_WRITE((ldo->base + ldo->enable_reg), val);
+
+ return 0;
+}