summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornagesh Penumarty <vpenumarty@nvidia.com>2011-04-11 14:59:28 +0530
committerDan Willemsen <dwillemsen@nvidia.com>2011-11-30 21:43:01 -0800
commitf501c93f859761f4f884a374b72179f164b2742c (patch)
tree1c9fd55d4dd5db86b2d450fa3a264d530066ea54
parentf8c8e059b8fe4c6886b00fc38b634f880249eb6d (diff)
drivers: regulator: Adding the regulator driver
Adding the TI 6025 PMU regulator driver. Original-Change-Id: I8ad675711bbe2ae942bcc0e32b711883eae215b4 Reviewed-on: http://git-master/r/27342 Tested-by: Venkata Nageswara Penumarty <vpenumarty@nvidia.com> Reviewed-by: Laxman Dewangan <ldewangan@nvidia.com> Original-Change-Id: Ib91f033c557bb7f4c87522ae4f5c7922a62f71f8 Rebase-Id: R690581a1fd604a9232474fc47982050691051f11
-rw-r--r--drivers/mfd/twl-core.c85
-rw-r--r--include/linux/i2c/twl.h56
-rw-r--r--include/linux/mfd/tps80031x.h106
3 files changed, 243 insertions, 4 deletions
diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
index b8eef462737a..712859aa86ac 100644
--- a/drivers/mfd/twl-core.c
+++ b/drivers/mfd/twl-core.c
@@ -58,6 +58,14 @@
#define DRIVER_NAME "twl"
+#if defined(CONFIG_TWL4030_BCI_BATTERY) || \
+ defined(CONFIG_TWL4030_BCI_BATTERY_MODULE) || \
+ defined(CONFIG_TWL6030_BCI_BATTERY) || \
+ defined(CONFIG_TWL6030_BCI_BATTERY_MODULE)
+#define twl_has_bci() true
+#else
+#define twl_has_bci() false
+#endif
#if defined(CONFIG_KEYBOARD_TWL4030) || defined(CONFIG_KEYBOARD_TWL4030_MODULE)
#define twl_has_keypad() true
#else
@@ -77,7 +85,8 @@
#define twl_has_regulator() false
#endif
-#if defined(CONFIG_TWL4030_MADC) || defined(CONFIG_TWL4030_MADC_MODULE)
+#if defined(CONFIG_TWL4030_MADC) || defined(CONFIG_TWL4030_MADC_MODULE) ||\
+ defined(CONFIG_TWL6030_GPADC) || defined(CONFIG_TWL6030_GPADC_MODULE)
#define twl_has_madc() true
#else
#define twl_has_madc() false
@@ -125,7 +134,7 @@
/* Triton Core internal information (BEGIN) */
/* Last - for index max*/
-#define TWL4030_MODULE_LAST TWL4030_MODULE_SECURED_REG
+#define TWL4030_MODULE_LAST TWL6025_MODULE_CHARGER
#define TWL_NUM_SLAVES 4
@@ -208,6 +217,10 @@
#define TWL6030_BASEADD_RSV 0x0000
#define TWL6030_BASEADD_ZERO 0x0000
+/* twl6030 SMPS EPROM values */
+#define TWL6030_SMPS_OFFSET 0xB0
+#define TWL6030_SMPS_MULT 0xB3
+
/* Few power values */
#define R_CFG_BOOT 0x05
@@ -240,6 +253,33 @@ unsigned int twl_rev(void)
}
EXPORT_SYMBOL(twl_rev);
+static unsigned int twl_feat;
+unsigned int twl_features(void)
+{
+ return twl_feat;
+}
+EXPORT_SYMBOL(twl_features);
+
+u8 twl_get_smps_offset(void)
+{
+ u8 value;
+
+ twl_i2c_read_u8(TWL_MODULE_PM_RECEIVER, &value,
+ TWL6030_SMPS_OFFSET);
+ return value;
+}
+EXPORT_SYMBOL(twl_get_smps_offset);
+
+u8 twl_get_smps_mult(void)
+{
+ u8 value;
+
+ twl_i2c_read_u8(TWL_MODULE_PM_RECEIVER, &value,
+ TWL6030_SMPS_MULT);
+ return value;
+}
+EXPORT_SYMBOL(twl_get_smps_mult);
+
/* Structure for each TWL4030/TWL6030 Slave */
struct twl_client {
struct i2c_client *client;
@@ -490,6 +530,19 @@ int twl_i2c_read_u8(u8 mod_no, u8 *value, u8 reg)
}
EXPORT_SYMBOL(twl_i2c_read_u8);
+
+void twl_reg_dump(int module, int start, int end)
+{
+ int i;
+ u8 val;
+
+ for (i = start; i < end; i++) {
+ twl_i2c_read_u8(module, &val, i);
+ printk(KERN_ERR "reg 0x%2x val 0x%2x\n", i, val);
+ }
+}
+EXPORT_SYMBOL(twl_reg_dump);
+
/*----------------------------------------------------------------------*/
/**
@@ -660,8 +713,16 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)
if (IS_ERR(child))
return PTR_ERR(child);
}
+ if (twl_has_bci() && pdata->bci &&
+ (features & TWL6030_CLASS)) {
+ child = add_child(1, "twl6030_bci",
+ pdata->bci, sizeof(*pdata->bci),
+ false,
+ pdata->irq_base + CHARGER_INTR_OFFSET,
+ pdata->irq_base + CHARGERFAULT_INTR_OFFSET);
+ }
- if (twl_has_madc() && pdata->madc) {
+ if (twl_has_madc() && pdata->madc && twl_class_is_4030()) {
child = add_child(2, "twl4030_madc",
pdata->madc, sizeof(*pdata->madc),
true, pdata->irq_base + MADC_INTR_OFFSET, 0);
@@ -669,6 +730,15 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)
return PTR_ERR(child);
}
+ if (twl_has_madc() && pdata->madc && twl_class_is_6030()) {
+ child = add_child(1, "twl6030_gpadc",
+ pdata->madc, sizeof(*pdata->madc),
+ true, pdata->irq_base + MADC_INTR_OFFSET,
+ pdata->irq_base + GPADCSW_INTR_OFFSET);
+ if (IS_ERR(child))
+ return PTR_ERR(child);
+ }
+
if (twl_has_rtc()) {
/*
* REVISIT platform_data here currently might expose the
@@ -1269,7 +1339,16 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
twl_i2c_write_u8(TWL4030_MODULE_INTBR, temp, REG_GPPUPDCTR1);
}
+ twl_feat = id->driver_data;
+
status = add_children(pdata, id->driver_data);
+ if (status < 0 )
+ goto fail;
+
+ /* Board Specific Init Callback */
+ if(pdata->init)
+ status = pdata->init();
+
fail:
if (status < 0)
twl_remove(client);
diff --git a/include/linux/i2c/twl.h b/include/linux/i2c/twl.h
index 114c0f6fc63d..bd126405f10f 100644
--- a/include/linux/i2c/twl.h
+++ b/include/linux/i2c/twl.h
@@ -82,6 +82,10 @@
#define TWL_MODULE_RTC TWL4030_MODULE_RTC
#define TWL_MODULE_PWM TWL4030_MODULE_PWM0
+#define TWL6030_MODULE_CHARGER TWL4030_MODULE_MAIN_CHARGE
+#define TWL6025_MODULE_CHARGER 0x18
+
+#define TWL6030_MODULE_GASGAUGE 0x0B
#define TWL6030_MODULE_ID0 0x0D
#define TWL6030_MODULE_ID1 0x0E
#define TWL6030_MODULE_ID2 0x0F
@@ -108,6 +112,7 @@
#define GASGAUGE_INTR_OFFSET 17
#define USBOTG_INTR_OFFSET 4
#define CHARGER_INTR_OFFSET 2
+#define GPADCSW_INTR_OFFSET 1
#define RSV_INTR_OFFSET 0
/* INT register offsets */
@@ -173,12 +178,21 @@ TWL_CLASS_IS(6030, TWL6030_CLASS_ID)
#define TWL6025_SUBCLASS BIT(4) /* TWL6025 has changed registers */
+/* So we can recover the features in other parts of twl stack */
+unsigned int twl_features(void);
+
+/* so we can get at the EPROM SMPS OFFSET/MULT stuff */
+u8 twl_get_smps_offset(void);
+u8 twl_get_smps_mult(void);
+
/*
* Read and write single 8-bit registers
*/
int twl_i2c_write_u8(u8 mod_no, u8 val, u8 reg);
int twl_i2c_read_u8(u8 mod_no, u8 *val, u8 reg);
+void twl_reg_dump(int module, int start, int end);
+
/*
* Read and write several 8-bit registers at once.
*
@@ -215,6 +229,10 @@ static inline int twl6030_mmc_card_detect(struct device *dev, int slot)
return -EIO;
}
#endif
+
+int twl6030_set_usb_charge_enable(int enable);
+int twl6030_set_usb_in_current(int currentmA);
+
/*----------------------------------------------------------------------*/
/*
@@ -556,7 +574,22 @@ struct twl4030_clock_init_data {
struct twl4030_bci_platform_data {
int *battery_tmp_tbl;
- unsigned int tblsize;
+ unsigned int battery_tmp_tblsize;
+ int *battery_volt_tbl;
+ unsigned int battery_volt_tblsize;
+ unsigned int monitoring_interval;
+
+ unsigned int max_charger_currentmA;
+ unsigned int max_charger_voltagemV;
+ unsigned int termination_currentmA;
+
+ unsigned int max_bat_voltagemV;
+ unsigned int low_bat_voltagemV;
+
+ /* twl6025 */
+ unsigned int use_hw_charger;
+ unsigned int use_eeprom_config;
+ unsigned int power_path;
};
/* TWL4030_GPIO_MAX (18) GPIOs, with interrupts */
@@ -621,6 +654,7 @@ struct twl4030_usb_data {
int (*phy_set_clock)(struct device *dev, int on);
/* suspend/resume of phy */
int (*phy_suspend)(struct device *dev, int suspend);
+ int (*board_control_power)(struct device *dev, int on);
};
struct twl4030_ins {
@@ -696,6 +730,10 @@ struct twl4030_audio_data {
struct twl4030_platform_data {
unsigned irq_base, irq_end;
+
+ /* Callback for boar regulator initialisation */
+ int (*init)(void);
+
struct twl4030_clock_init_data *clock;
struct twl4030_bci_platform_data *bci;
struct twl4030_gpio_platform_data *gpio;
@@ -822,6 +860,22 @@ static inline int twl4030charger_usb_en(int enable) { return 0; }
#define TWL6030_REG_VDAC 45
#define TWL6030_REG_VUSB 46
+/* These are renamed in 6025 but same registers */
+#define TWL6025_REG_LDO2 48
+#define TWL6025_REG_LDO4 49
+#define TWL6025_REG_LDO3 50
+#define TWL6025_REG_LDO5 51
+#define TWL6025_REG_LDO1 52
+#define TWL6025_REG_LDO7 53
+#define TWL6025_REG_LDO6 54
+#define TWL6025_REG_LDOLN 55
+#define TWL6025_REG_LDOUSB 56
+
+/* 6025 DCDC supplies */
+#define TWL6025_REG_SMPS3 57
+#define TWL6025_REG_SMPS4 58
+#define TWL6025_REG_VIO 59
+
/* INTERNAL LDOs */
#define TWL6030_REG_VRTC 47
#define TWL6030_REG_CLK32KG 48
diff --git a/include/linux/mfd/tps80031x.h b/include/linux/mfd/tps80031x.h
new file mode 100644
index 000000000000..8f74cbe7406e
--- /dev/null
+++ b/include/linux/mfd/tps80031x.h
@@ -0,0 +1,106 @@
+/*
+ * include/linux/mfd/tps80031x.c
+ * Core driver interface for TI TPS80031x PMIC family
+ *
+ * Copyright (C) 2011 NVIDIA Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef __LINUX_MFD_TPS80031X_H
+#define __LINUX_MFD_TPS80031X_H
+
+#define tps80031x_rails(_name) "tps80031x_"#_name
+
+enum {
+ TPS80031X_ID_SMPS4,
+ TPS80031X_ID_VIO,
+ TPS80031X_ID_SMPS1,
+ TPS80031X_ID_SMPS2,
+ TPS80031X_ID_SMPS3,
+ TPS80031X_ID_VANA,
+ TPS80031X_ID_LDO_2,
+ TPS80031X_ID_LDO_4,
+ TPS80031X_ID_LDO_3,
+ TPS80031X_ID_LDO_6,
+ TPS80031X_ID_LDO_LN,
+ TPS80031X_ID_LDO_5,
+ TPS80031X_ID_LDO_1,
+ TPS80031X_ID_LDO_USB,
+ TPS80031X_ID_LDO_7,
+ TPS80031X_ID_LDO_VRTC,
+};
+
+enum {
+ TPS80031X_INT_PWRHOLD_F,
+ TPS80031X_INT_VMBHI,
+ TPS80031X_INT_PWRON,
+ TPS80031X_INT_PWRON_LP,
+ TPS80031X_INT_PWRHOLD_R,
+ TPS80031X_INT_HOTDIE,
+ TPS80031X_INT_RTC_ALARM,
+ TPS80031X_INT_RTC_PERIOD,
+ TPS80031X_INT_GPIO0_R,
+ TPS80031X_INT_GPIO0_F,
+ TPS80031X_INT_GPIO1_R,
+ TPS80031X_INT_GPIO1_F,
+ TPS80031X_INT_GPIO2_R,
+ TPS80031X_INT_GPIO2_F,
+ TPS80031X_INT_GPIO3_R,
+ TPS80031X_INT_GPIO3_F,
+ TPS80031X_INT_GPIO4_R,
+ TPS80031X_INT_GPIO4_F,
+ TPS80031X_INT_GPIO5_R,
+ TPS80031X_INT_GPIO5_F,
+ TPS80031X_INT_WTCHDG,
+ TPS80031X_INT_VMBCH2_H,
+ TPS80031X_INT_VMBCH2_L,
+ TPS80031X_INT_PWRDN,
+};
+
+struct tps80031x_subdev_info {
+ int id;
+ const char *name;
+ void *platform_data;
+};
+
+struct tps80031x_rtc_platform_data {
+ int irq;
+};
+
+struct tps80031x_platform_data {
+ int num_subdevs;
+ struct tps80031x_subdev_info *subdevs;
+
+ int gpio_base;
+ int irq_base;
+};
+
+/*
+ * NOTE: the functions below are not intended for use outside
+ * of the TPS80031X sub-device drivers
+ */
+extern int tps80031x_write(struct device *dev, int reg, uint8_t val);
+extern int tps80031x_writes(struct device *dev, int reg, int len, uint8_t *val);
+extern int tps80031x_read(struct device *dev, int reg, uint8_t *val);
+extern int tps80031x_reads(struct device *dev, int reg, int len, uint8_t *val);
+extern int tps80031x_set_bits(struct device *dev, int reg, uint8_t bit_mask);
+extern int tps80031x_clr_bits(struct device *dev, int reg, uint8_t bit_mask);
+extern int tps80031x_update(struct device *dev, int reg, uint8_t val,
+ uint8_t mask);
+extern int tps80031x_power_off(void);
+
+#endif /*__LINUX_MFD_TPS80031X_H */