phonepad:add PMIC TPS65910 support
authorlw <lw@rock-chips.com>
Thu, 26 Jul 2012 13:45:55 +0000 (21:45 +0800)
committerlw <lw@rock-chips.com>
Thu, 26 Jul 2012 13:45:55 +0000 (21:45 +0800)
18 files changed:
arch/arm/configs/rk30_phonepad_defconfig
arch/arm/mach-rk30/board-rk30-phonepad.c
arch/arm/mach-rk30/board-rk30-sdk-tps65910.c [new file with mode: 0755]
drivers/gpio/Kconfig
drivers/gpio/Makefile
drivers/gpio/gpio-tps65910.c [new file with mode: 0644]
drivers/mfd/Kconfig
drivers/mfd/Makefile
drivers/mfd/tps65910-irq.c
drivers/mfd/tps65910.c
drivers/regulator/Kconfig
drivers/regulator/Makefile
drivers/regulator/tps65910-regulator.c
drivers/rtc/Kconfig
drivers/rtc/Makefile
drivers/rtc/rtc-tps65910.c [new file with mode: 0755]
include/linux/mfd/tps65910.h
include/linux/mfd/tps65912.h [new file with mode: 0644]

index bbaf22b953c02fb234e4e49c80fab77189ffb11d..bca7523e8d115dc1bce06e0a2a22c9241decc8d2 100644 (file)
@@ -224,7 +224,6 @@ CONFIG_INPUT_KEYRESET=y
 CONFIG_INPUT_JOYSTICK=y
 CONFIG_INPUT_TABLET=y
 CONFIG_INPUT_TOUCHSCREEN=y
-CONFIG_TOUCHSCREEN_GT82X_IIC=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_KEYCHORD=y
 CONFIG_INPUT_UINPUT=y
@@ -253,7 +252,6 @@ CONFIG_I2C1_CONTROLLER_RK30=y
 CONFIG_I2C2_CONTROLLER_RK30=y
 CONFIG_I2C3_CONTROLLER_RK30=y
 CONFIG_I2C4_CONTROLLER_RK30=y
-CONFIG_GPIO_WM831X=y
 CONFIG_EXPANDED_GPIO_NUM=0
 CONFIG_EXPANDED_GPIO_IRQ_NUM=0
 CONFIG_SPI_FPGA_GPIO_NUM=0
@@ -261,9 +259,9 @@ CONFIG_SPI_FPGA_GPIO_IRQ_NUM=0
 CONFIG_POWER_SUPPLY=y
 CONFIG_TEST_POWER=y
 # CONFIG_HWMON is not set
-CONFIG_MFD_WM831X_I2C=y
+CONFIG_MFD_TPS65910=y
 CONFIG_REGULATOR=y
-CONFIG_REGULATOR_WM831X=y
+CONFIG_REGULATOR_TPS65910=y
 CONFIG_MEDIA_SUPPORT=y
 CONFIG_VIDEO_DEV=y
 CONFIG_SOC_CAMERA=y
@@ -376,7 +374,7 @@ CONFIG_LEDS_GPIO=y
 CONFIG_SWITCH=y
 CONFIG_SWITCH_GPIO=y
 CONFIG_RTC_CLASS=y
-CONFIG_RTC_DRV_WM831X=y
+CONFIG_TPS65910_RTC=y
 CONFIG_STAGING=y
 CONFIG_ANDROID=y
 CONFIG_ANDROID_BINDER_IPC=y
index 8e219c9735606b7d009b0d75764e4879699465e6..f397266f6472b8713b41e0ccfdd7ab4f84d1b45e 100755 (executable)
 #include <linux/regulator/machine.h>
 #include <linux/rfkill-rk.h>
 #include <linux/sensor-dev.h>
+#include <linux/mfd/tps65910.h>
+
 #if defined(CONFIG_HDMI_RK30)
        #include "../../../drivers/video/rockchip/hdmi/rk_hdmi.h"
 #endif
 
-#define TPS65910_HOST_IRQ        RK30_PIN6_PA4
+
 #ifdef CONFIG_TOUCHSCREEN_GT82X_IIC
 #include <linux/goodix_touch_82x.h>
 #endif
@@ -77,7 +79,7 @@
 #else
 #define RK30_FB0_MEM_SIZE 8*SZ_1M
 #endif
-int PMIC_IS_WM831X = 0;
+#define PMIC_IS_WM831X  0
 
 #ifdef CONFIG_VIDEO_RK29
 /*---------------- Camera Sensor Macro Define Begin  ------------------------*/
@@ -1692,6 +1694,7 @@ static struct i2c_board_info __initdata i2c0_info[] = {
 #include "board-rk30-sdk-wm8326.c"
 #endif
 #ifdef CONFIG_MFD_TPS65910
+#define TPS65910_HOST_IRQ        RK30_PIN6_PA4
 #include "board-rk30-sdk-tps65910.c"
 #endif
 
@@ -1707,7 +1710,7 @@ static struct i2c_board_info __initdata i2c1_info[] = {
 #endif
 #if defined (CONFIG_MFD_TPS65910)
        {
-        .type           = "tps659102",
+        .type           = "tps65910",
         .addr           = TPS65910_I2C_ID0,
         .flags          = 0,
         .irq            = TPS65910_HOST_IRQ,
diff --git a/arch/arm/mach-rk30/board-rk30-sdk-tps65910.c b/arch/arm/mach-rk30/board-rk30-sdk-tps65910.c
new file mode 100755 (executable)
index 0000000..179ced8
--- /dev/null
@@ -0,0 +1,635 @@
+#include <linux/regulator/machine.h>
+#include <linux/i2c/twl.h>
+#include <linux/mfd/tps65910.h>
+#include <mach/sram.h>
+#include <linux/platform_device.h>
+
+#include <mach/gpio.h>
+#include <mach/iomux.h>
+
+#define grf_readl(offset)      readl_relaxed(RK30_GRF_BASE + offset)
+#define grf_writel(v, offset)  do { writel_relaxed(v, RK30_GRF_BASE + offset); dsb(); } while (0)
+
+#define CRU_CLKGATE5_CON_ADDR 0x00e4
+#define GRF_GPIO6L_DIR_ADDR 0x0030
+#define GRF_GPIO6L_DO_ADDR 0x0068
+#define GRF_GPIO6L_EN_ADDR 0x00a0
+#define GPIO6_PB3_DIR_OUT  0x08000800
+#define GPIO6_PB3_DO_LOW  0x08000000
+#define GPIO6_PB3_DO_HIGH  0x08000800
+#define GPIO6_PB3_EN_MASK  0x08000800
+#define GPIO6_PB3_UNEN_MASK  0x08000000
+#define GPIO6_PB1_DIR_OUT  0x02000200
+#define GPIO6_PB1_DO_LOW  0x02000000
+#define GPIO6_PB1_DO_HIGH  0x02000200
+#define GPIO6_PB1_EN_MASK  0x02000200
+#define GPIO6_PB1_UNEN_MASK  0x02000000
+
+#ifdef CONFIG_MFD_TPS65910
+#define PMU_POWER_SLEEP RK30_PIN6_PB1  
+extern int platform_device_register(struct platform_device *pdev);
+
+int tps65910_pre_init(struct tps65910 *tps65910){
+
+       u8 val  = 0;
+       int i   = 0;
+       int err = -1;
+       
+       #ifdef CONFIG_RK30_PWM_REGULATOR
+       platform_device_register(&pwm_regulator_device[0]);
+       #endif
+       
+       printk("%s,line=%d\n", __func__,__LINE__);      
+       //gpio_request(PMU_POWER_SLEEP, "NULL");
+       //gpio_direction_output(PMU_POWER_SLEEP, GPIO_HIGH);
+       
+       err = tps65910_i2c_read_u8(TPS65910_I2C_ID0, &val, TPS65910_REG_DEVCTRL2);
+       if (err) {
+               printk(KERN_ERR "Unable to read TPS65910_REG_DEVCTRL2 reg\n");
+               return -EIO;
+       }
+       /* Set sleep state active high and allow device turn-off after PWRON long press */
+       val |= (TPS65910_DEV2_SLEEPSIG_POL | TPS65910_DEV2_PWON_LP_OFF);
+
+       err = tps65910_i2c_write_u8(TPS65910_I2C_ID0, val,
+                       TPS65910_REG_DEVCTRL2);
+       if (err) {
+               printk(KERN_ERR "Unable to write TPS65910_REG_DEVCTRL2 reg\n");
+               return -EIO;
+       }
+        #if 1
+       /* set PSKIP=0 */
+        err = tps65910_i2c_read_u8(TPS65910_I2C_ID0, &val, TPS65910_REG_DCDCCTRL);
+        if (err) {
+                printk(KERN_ERR "Unable to read TPS65910_REG_DCDCCTRL reg\n");
+                return -EIO;
+        }
+       //val &= ~(1 << 4);
+               val &= 0xFC;
+       //      val |= 0x03;
+
+        err = tps65910_i2c_write_u8(TPS65910_I2C_ID0, val,
+                        TPS65910_REG_DCDCCTRL);
+        if (err) {
+                printk(KERN_ERR "Unable to write TPS65910_REG_DCDCCTRL reg\n");
+                return -EIO;
+        }
+       #endif
+       /* Set the maxinum load current */
+       /* VDD1 */
+       err = tps65910_i2c_read_u8(TPS65910_I2C_ID0, &val, TPS65910_REG_VDD1);
+       if (err) {
+               printk(KERN_ERR "Unable to read TPS65910_REG_VDD1 reg\n");
+               return -EIO;
+       }
+
+       val |= (1<<5);
+       val |= (0x07<<2);
+       err = tps65910_i2c_write_u8(TPS65910_I2C_ID0, val, TPS65910_REG_VDD1);
+       if (err) {
+               printk(KERN_ERR "Unable to write TPS65910_REG_VDD1 reg\n");
+               return -EIO;
+       }
+
+       /* VDD2 */
+       err = tps65910_i2c_read_u8(TPS65910_I2C_ID0, &val, TPS65910_REG_VDD2);
+       if (err) {
+               printk(KERN_ERR "Unable to read TPS65910_REG_VDD2 reg\n");
+               return -EIO;
+       }
+
+       val |= (1<<5);
+       err = tps65910_i2c_write_u8(TPS65910_I2C_ID0, val, TPS65910_REG_VDD2);
+       if (err) {
+               printk(KERN_ERR "Unable to write TPS65910_REG_VDD2 reg\n");
+               return -EIO;
+       }
+
+       /* VIO */
+       err = tps65910_i2c_read_u8(TPS65910_I2C_ID0, &val, TPS65910_REG_VIO);
+       if (err) {
+               printk(KERN_ERR "Unable to read TPS65910_REG_VIO reg\n");
+               return -EIO;
+       }
+
+       val |= (1<<6);
+       err = tps65910_i2c_write_u8(TPS65910_I2C_ID0, val, TPS65910_REG_VIO);
+       if (err) {
+               printk(KERN_ERR "Unable to write TPS65910_REG_VIO reg\n");
+               return -EIO;
+       }
+       #if 1
+       /* Mask ALL interrupts */
+       err = tps65910_i2c_write_u8(TPS65910_I2C_ID0, 0xFF,
+                       TPS65910_REG_INT_MSK);
+       if (err) {
+               printk(KERN_ERR "Unable to write TPS65910_REG_INT_MSK reg\n");
+               return -EIO;
+       }
+       err = tps65910_i2c_write_u8(TPS65910_I2C_ID0, 0x03,
+                       TPS65910_REG_INT_MSK2);
+       if (err) {
+               printk(KERN_ERR "Unable to write TPS65910_REG_INT_MSK2 reg\n");
+               return -EIO;
+       }
+
+       /* Set RTC Power, disable Smart Reflex in DEVCTRL_REG */
+       #if 1
+       val = 0;
+       val |= (TPS65910_SR_CTL_I2C_SEL);
+       err = tps65910_i2c_write_u8(TPS65910_I2C_ID0, val,
+                       TPS65910_REG_DEVCTRL);
+       if (err) {
+               printk(KERN_ERR "Unable to write TPS65910_REG_DEVCTRL reg\n");
+               return -EIO;
+       }
+       printk(KERN_INFO "TPS65910 Set default voltage.\n");
+       #endif
+       #if 0
+       //read sleep control register  for debug
+       for(i=0; i<6; i++)
+       {
+        err = tps65910_i2c_read_u8(TPS65910_I2C_ID0, &val, TPS65910_REG_DEVCTRL+i);
+        if (err) {
+                printk(KERN_ERR "Unable to read TPS65910_REG_DCDCCTRL reg\n");
+                return -EIO;
+        }
+               else
+               printk("%s.......is  0x%04x\n",__FUNCTION__,val);
+       }
+       #endif
+
+       #if 1
+       //sleep control register
+       /*set func when in sleep mode */
+    err = tps65910_i2c_read_u8(TPS65910_I2C_ID0, &val, TPS65910_REG_DEVCTRL);
+        if (err) {
+                printk(KERN_ERR "Unable to read TPS65910_REG_DCDCCTRL reg\n");
+                return -EIO;
+        }
+               val |= (1 << 1);
+               err = tps65910_i2c_write_u8(TPS65910_I2C_ID0, val, TPS65910_REG_DEVCTRL);
+               if (err) {
+                       printk(KERN_ERR "Unable to read TPS65910 Reg at offset 0x%x= \
+                                       \n", TPS65910_REG_VDIG1);
+                       return -EIO;
+               }
+               /* open ldo when in sleep mode */
+        err = tps65910_i2c_read_u8(TPS65910_I2C_ID0, &val, TPS65910_REG_SLEEP_KEEP_LDO_ON);
+        if (err) {
+                printk(KERN_ERR "Unable to read TPS65910_REG_DCDCCTRL reg\n");
+                return -EIO;
+        }
+               val &= 0;
+               err = tps65910_i2c_write_u8(TPS65910_I2C_ID0, val, TPS65910_REG_SLEEP_KEEP_LDO_ON);
+               if (err) {
+                       printk(KERN_ERR "Unable to read TPS65910 Reg at offset 0x%x= \
+                                       \n", TPS65910_REG_VDIG1);
+                       return -EIO;
+               }
+               /*set dc mode when in sleep mode */
+        err = tps65910_i2c_read_u8(TPS65910_I2C_ID0, &val, TPS65910_REG_SLEEP_KEEP_RES_ON);
+        if (err) {
+                printk(KERN_ERR "Unable to read TPS65910_REG_DCDCCTRL reg\n");
+                return -EIO;
+        }
+               val  |= 0xff;
+               err = tps65910_i2c_write_u8(TPS65910_I2C_ID0, val, TPS65910_REG_SLEEP_KEEP_RES_ON);
+               if (err) {
+                       printk(KERN_ERR "Unable to read TPS65910 Reg at offset 0x%x= \
+                                       \n", TPS65910_REG_VDIG1);
+                       return -EIO;
+               }
+               /*close ldo when in sleep mode */
+        err = tps65910_i2c_read_u8(TPS65910_I2C_ID0, &val, TPS65910_REG_SLEEP_SET_LDO_OFF);
+        if (err) {
+                printk(KERN_ERR "Unable to read TPS65910_REG_DCDCCTRL reg\n");
+                return -EIO;
+        }
+               val |= 0x9B;
+               err = tps65910_i2c_write_u8(TPS65910_I2C_ID0, val, TPS65910_REG_SLEEP_SET_LDO_OFF);
+               if (err) {
+                       printk(KERN_ERR "Unable to read TPS65910 Reg at offset 0x%x= \
+                                       \n", TPS65910_REG_VDIG1);
+                       return -EIO;
+               }
+       #endif
+       #if 0
+       //read sleep control register  for debug
+       for(i=0; i<6; i++)
+       {
+        err = tps65910_i2c_read_u8(TPS65910_I2C_ID0, &val, TPS65910_REG_DEVCTRL+i);
+        if (err) {
+                printk(KERN_ERR "Unable to read TPS65910_REG_DCDCCTRL reg\n");
+                return -EIO;
+        }
+               else
+               printk("%s.......is  0x%4x\n",__FUNCTION__,val);
+       }
+       #endif
+       #endif
+       printk("%s,line=%d\n", __func__,__LINE__);
+       return 0;
+
+}
+int tps65910_post_init(struct tps65910 *tps65910)
+{
+       struct regulator *dcdc;
+       struct regulator *ldo;
+       printk("%s,line=%d\n", __func__,__LINE__);
+
+       dcdc = regulator_get(NULL, "vio");      //vcc_io
+       regulator_set_voltage(dcdc, 3000000, 3000000);
+       regulator_enable(dcdc);
+       printk("%s set vio vcc_io=%dmV end\n", __func__, regulator_get_voltage(dcdc));
+       regulator_put(dcdc);
+       udelay(100);
+
+       ldo = regulator_get(NULL, "vpll");      // vdd11
+       regulator_set_voltage(ldo, 1100000, 1100000);
+       regulator_enable(ldo);
+       printk("%s set vpll vdd11=%dmV end\n", __func__, regulator_get_voltage(ldo));
+       regulator_put(ldo);
+       udelay(100);
+
+       ldo = regulator_get(NULL, "vdig2");     // vdd11_hdmi
+       regulator_set_voltage(ldo, 1100000, 1100000);
+       regulator_enable(ldo);
+       printk("%s set vdig2 vdd11_hdmi=%dmV end\n", __func__, regulator_get_voltage(ldo));
+       regulator_put(ldo);
+       udelay(100);
+
+       ldo = regulator_get(NULL, "vaux33");     //vcc33
+       regulator_set_voltage(ldo, 3300000, 3300000);
+       regulator_enable(ldo);
+       printk("%s set vaux33 vcc33=%dmV end\n", __func__, regulator_get_voltage(ldo));
+       regulator_put(ldo);
+       udelay(100);
+       
+       dcdc = regulator_get(NULL, "vdd_cpu");  //vdd_cpu
+       regulator_set_voltage(dcdc, 1100000, 1100000);
+       regulator_enable(dcdc);
+       printk("%s set vdd1 vdd_cpu=%dmV end\n", __func__, regulator_get_voltage(dcdc));
+       regulator_put(dcdc);
+       udelay(100);
+
+       dcdc = regulator_get(NULL, "vdd2");     //vcc_ddr
+       regulator_set_voltage(dcdc, 1500000, 1500000);
+       regulator_enable(dcdc);
+       printk("%s set vdd2 vcc_ddr=%dmV end\n", __func__, regulator_get_voltage(dcdc));
+       regulator_put(dcdc);
+       udelay(100);
+       
+       ldo = regulator_get(NULL, "vdig1");     //vccio_wl
+       regulator_set_voltage(ldo, 1700000, 1700000);
+       regulator_enable(ldo);
+       printk("%s set vdig1 vccio_wl=%dmV end\n", __func__, regulator_get_voltage(ldo));
+       regulator_put(ldo);
+       udelay(100);
+       
+       dcdc = regulator_get(NULL, "vaux1"); //vcc25
+       regulator_set_voltage(dcdc,2500000,2500000);
+       regulator_enable(dcdc); 
+       printk("%s set vaux1 vcc25=%dmV end\n", __func__, regulator_get_voltage(dcdc));
+       regulator_put(dcdc);
+       udelay(100);
+
+       ldo = regulator_get(NULL, "vaux2");     //vcca33
+       regulator_set_voltage(ldo, 3300000, 3300000);
+       regulator_enable(ldo);
+       printk("%s set vaux2 vcca33=%dmV end\n", __func__, regulator_get_voltage(ldo));
+       regulator_put(ldo);
+       udelay(100);
+
+       ldo = regulator_get(NULL, "vdac"); // vcc18_cif
+       regulator_set_voltage(ldo,1800000,1800000);
+       regulator_enable(ldo); 
+       printk("%s set vdac vcc18_cif=%dmV end\n", __func__, regulator_get_voltage(ldo));
+       regulator_put(ldo);
+       udelay(100);
+
+       ldo = regulator_get(NULL, "vmmc");  //vcc28_cif
+       regulator_set_voltage(ldo,2800000,2800000);
+       regulator_enable(ldo); 
+       printk("%s set vmmc vcc28_cif=%dmV end\n", __func__, regulator_get_voltage(ldo));
+       regulator_put(ldo);
+       udelay(100);
+
+       #ifdef CONFIG_RK30_PWM_REGULATOR
+       dcdc = regulator_get(NULL, "vdd_core"); // vdd_log
+       regulator_set_voltage(dcdc, 1150000, 1150000);
+       regulator_enable(dcdc);
+       printk("%s set vdd_core=%dmV end\n", __func__, regulator_get_voltage(dcdc));
+       regulator_put(dcdc);
+       udelay(100);
+       #endif
+       
+       printk("%s,line=%d END\n", __func__,__LINE__);
+       
+       return 0;
+}
+
+static struct regulator_consumer_supply tps65910_smps1_supply[] = {
+       {
+               .supply = "vdd1",
+       },
+       {
+               .supply = "vdd_cpu",
+       },
+};
+static struct regulator_consumer_supply tps65910_smps2_supply[] = {
+       {
+               .supply = "vdd2",
+       },
+       
+};
+static struct regulator_consumer_supply tps65910_smps3_supply[] = {
+       {
+               .supply = "vdd3",
+       },
+};
+static struct regulator_consumer_supply tps65910_smps4_supply[] = {
+       {
+               .supply = "vio",
+       },
+};
+static struct regulator_consumer_supply tps65910_ldo1_supply[] = {
+       {
+               .supply = "vdig1",
+       },
+};
+static struct regulator_consumer_supply tps65910_ldo2_supply[] = {
+       {
+               .supply = "vdig2",
+       },
+};
+
+static struct regulator_consumer_supply tps65910_ldo3_supply[] = {
+       {
+               .supply = "vaux1",
+       },
+};
+static struct regulator_consumer_supply tps65910_ldo4_supply[] = {
+       {
+               .supply = "vaux2",
+       },
+};
+static struct regulator_consumer_supply tps65910_ldo5_supply[] = {
+       {
+               .supply = "vaux33",
+       },
+};
+static struct regulator_consumer_supply tps65910_ldo6_supply[] = {
+       {
+               .supply = "vmmc",
+       },
+};
+static struct regulator_consumer_supply tps65910_ldo7_supply[] = {
+       {
+               .supply = "vdac",
+       },
+};
+
+static struct regulator_consumer_supply tps65910_ldo8_supply[] = {
+       {
+               .supply = "vpll",
+       },
+};
+
+static struct regulator_init_data tps65910_smps1 = {
+       .constraints = {
+               .name           = "VDD1",
+               .min_uV                 = 600000,
+               .max_uV                 = 1500000,
+               .apply_uV               = 1,
+               .always_on = 1,
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_MODE,
+               .valid_modes_mask = REGULATOR_MODE_STANDBY | REGULATOR_MODE_NORMAL,
+
+       },
+       .num_consumer_supplies = ARRAY_SIZE(tps65910_smps1_supply),
+       .consumer_supplies =  tps65910_smps1_supply,
+};
+
+/* */
+static struct regulator_init_data tps65910_smps2 = {
+       .constraints = {
+               .name           = "VDD2",
+               .min_uV                 = 600000,
+               .max_uV                 = 1500000,
+               .apply_uV               = 1,
+               .always_on = 1,
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_MODE,
+               .valid_modes_mask = REGULATOR_MODE_STANDBY | REGULATOR_MODE_NORMAL,
+
+       },
+       .num_consumer_supplies = ARRAY_SIZE(tps65910_smps2_supply),
+       .consumer_supplies =  tps65910_smps2_supply,
+};
+
+/* */
+static struct regulator_init_data tps65910_smps3 = {
+       .constraints = {
+               .name           = "VDD3",
+               .min_uV                 = 1000000,
+               .max_uV                 = 1400000,
+               .apply_uV               = 1,
+               .always_on = 1,
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_MODE,
+               .valid_modes_mask = REGULATOR_MODE_STANDBY | REGULATOR_MODE_NORMAL,
+
+       },
+       .num_consumer_supplies = ARRAY_SIZE(tps65910_smps3_supply),
+       .consumer_supplies =  tps65910_smps3_supply,
+};
+
+static struct regulator_init_data tps65910_smps4 = {
+       .constraints = {
+               .name           = "VIO",
+               .min_uV                 = 1800000,
+               .max_uV                 = 3300000,
+               .apply_uV               = 1,
+               .always_on = 1,
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_MODE,
+               .valid_modes_mask = REGULATOR_MODE_STANDBY | REGULATOR_MODE_NORMAL,
+
+       },
+       .num_consumer_supplies = ARRAY_SIZE(tps65910_smps4_supply),
+       .consumer_supplies =  tps65910_smps4_supply,
+};
+static struct regulator_init_data tps65910_ldo1 = {
+       .constraints = {
+               .name           = "VDIG1",
+               .min_uV                 = 1200000,
+               .max_uV                 = 2700000,
+               .apply_uV               = 1,
+               
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_MODE,
+               .valid_modes_mask = REGULATOR_MODE_STANDBY | REGULATOR_MODE_NORMAL,
+
+       },
+       .num_consumer_supplies = ARRAY_SIZE(tps65910_ldo1_supply),
+       .consumer_supplies =  tps65910_ldo1_supply,
+};
+
+/* */
+static struct regulator_init_data tps65910_ldo2 = {
+       .constraints = {
+               .name           = "VDIG2",
+               .min_uV                 = 1000000,
+               .max_uV                 = 1800000,
+               .apply_uV               = 1,
+               
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_MODE,
+               .valid_modes_mask = REGULATOR_MODE_STANDBY | REGULATOR_MODE_NORMAL,
+
+       },
+       .num_consumer_supplies = ARRAY_SIZE(tps65910_ldo2_supply),
+       .consumer_supplies =  tps65910_ldo2_supply,
+};
+
+/* */
+static struct regulator_init_data tps65910_ldo3 = {
+       .constraints = {
+               .name           = "VAUX1",
+               .min_uV                 = 1800000,
+               .max_uV                 = 3300000,
+               .apply_uV               = 1,
+               
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_MODE,
+               .valid_modes_mask = REGULATOR_MODE_STANDBY | REGULATOR_MODE_NORMAL,
+
+       },
+       .num_consumer_supplies = ARRAY_SIZE(tps65910_ldo3_supply),
+       .consumer_supplies =  tps65910_ldo3_supply,
+};
+
+/* */
+static struct regulator_init_data tps65910_ldo4 = {
+       .constraints = {
+               .name           = "VAUX2",
+               .min_uV                 = 1800000,
+               .max_uV                 = 3300000,
+               .apply_uV               = 1,
+               
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_MODE,
+               .valid_modes_mask = REGULATOR_MODE_STANDBY | REGULATOR_MODE_NORMAL,
+
+       },
+       .num_consumer_supplies = ARRAY_SIZE(tps65910_ldo4_supply),
+       .consumer_supplies =  tps65910_ldo4_supply,
+};
+
+/* */
+static struct regulator_init_data tps65910_ldo5 = {
+       .constraints = {
+               .name           = "VAUX33",
+               .min_uV                 = 1800000,
+               .max_uV                 = 3300000,
+               .apply_uV               = 1,
+               
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_MODE,
+               .valid_modes_mask = REGULATOR_MODE_STANDBY | REGULATOR_MODE_NORMAL,
+
+       },
+       .num_consumer_supplies = ARRAY_SIZE(tps65910_ldo5_supply),
+       .consumer_supplies =  tps65910_ldo5_supply,
+};
+
+/* */
+static struct regulator_init_data tps65910_ldo6 = {
+       .constraints = {
+               .name           = "VMMC",
+               .min_uV                 = 1800000,
+               .max_uV                 = 3300000,
+               .apply_uV               = 1,
+               
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_MODE,
+               .valid_modes_mask = REGULATOR_MODE_STANDBY | REGULATOR_MODE_NORMAL,
+
+       },
+       .num_consumer_supplies = ARRAY_SIZE(tps65910_ldo6_supply),
+       .consumer_supplies =  tps65910_ldo6_supply,
+};
+
+/* */
+static struct regulator_init_data tps65910_ldo7 = {
+       .constraints = {
+               .name           = "VDAC",
+               .min_uV                 = 1800000,
+               .max_uV                 = 2850000,
+               .apply_uV               = 1,
+               
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_MODE,
+               .valid_modes_mask = REGULATOR_MODE_STANDBY | REGULATOR_MODE_NORMAL,
+
+       },
+       .num_consumer_supplies = ARRAY_SIZE(tps65910_ldo7_supply),
+       .consumer_supplies =  tps65910_ldo7_supply,
+};
+
+/* */
+static struct regulator_init_data tps65910_ldo8 = {
+       .constraints = {
+               .name           = "VPLL",
+               .min_uV                 = 1000000,
+               .max_uV                 = 2500000,
+               .apply_uV               = 1,
+               .always_on = 1,
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_MODE,
+               .valid_modes_mask = REGULATOR_MODE_STANDBY | REGULATOR_MODE_NORMAL,
+
+       },
+       .num_consumer_supplies = ARRAY_SIZE(tps65910_ldo8_supply),
+       .consumer_supplies =  tps65910_ldo8_supply,
+};
+
+void __sramfunc board_pmu_suspend(void)
+{      
+       grf_writel(GPIO6_PB1_DIR_OUT, GRF_GPIO6L_DIR_ADDR);
+       grf_writel(GPIO6_PB1_DO_HIGH, GRF_GPIO6L_DO_ADDR);  //set gpio6_b1 output low
+       grf_writel(GPIO6_PB1_EN_MASK, GRF_GPIO6L_EN_ADDR);
+}
+void __sramfunc board_pmu_resume(void)
+{
+       grf_writel(GPIO6_PB1_DIR_OUT, GRF_GPIO6L_DIR_ADDR);
+       grf_writel(GPIO6_PB1_DO_LOW, GRF_GPIO6L_DO_ADDR);  //set gpio6_b1 output low
+       grf_writel(GPIO6_PB1_EN_MASK, GRF_GPIO6L_EN_ADDR);
+       #ifdef CONFIG_CLK_SWITCH_TO_32K                 //switch clk to 24M
+       sram_32k_udelay(10000);
+       #else
+       sram_udelay(2000);
+       #endif
+}
+
+static struct tps65910_board tps65910_data = {
+       .irq    = (unsigned)TPS65910_HOST_IRQ,          
+       .irq_base = NR_GIC_IRQS + NR_GPIO_IRQS,
+       
+       .pre_init = tps65910_pre_init,
+       .post_init = tps65910_post_init,
+
+       //TPS65910_NUM_REGS = 13
+       // Regulators
+       .tps65910_pmic_init_data = {
+               NULL,
+               &tps65910_smps4,
+               &tps65910_smps1,
+               &tps65910_smps2,
+               &tps65910_smps3,
+               
+               &tps65910_ldo1,
+               &tps65910_ldo2,
+               &tps65910_ldo3,
+               &tps65910_ldo4,
+               &tps65910_ldo5,
+               &tps65910_ldo6,
+               &tps65910_ldo7,
+               &tps65910_ldo8,         
+       },
+
+};
+
+#endif
+
index 3b8f6043bf0c4436e1ce47da74bc4f33e73b92d8..9876d32c81730877eb857670f0a532db9058bee4 100755 (executable)
@@ -261,6 +261,12 @@ config GPIO_TC3589X
          This enables support for the GPIOs found on the TC3589X
          I/O Expander.
 
+config GPIO_TPS65912
+       tristate "TI TPS65912 GPIO"
+       depends on (MFD_TPS65912_I2C || MFD_TPS65912_SPI)
+       help
+         This driver supports TPS65912 gpio chip
+
 config GPIO_TWL4030
        tristate "TWL4030, TWL5030, and TPS659x0 GPIOs"
        depends on TWL4030_CORE
index 441f198aac8630df422a00c9444cab2732df2a3c..e245db7665faac28d22efae7bc3c1828bf351441 100755 (executable)
@@ -52,4 +52,5 @@ obj-$(CONFIG_GPIO_SX150X)     += sx150x.o
 obj-$(CONFIG_GPIO_VX855)       += vx855_gpio.o
 obj-$(CONFIG_GPIO_ML_IOH)      += ml_ioh_gpio.o
 obj-$(CONFIG_AB8500_GPIO)       += ab8500-gpio.o
-obj-$(CONFIG_GPIO_TPS65910)    += tps65910-gpio.o
+obj-$(CONFIG_GPIO_TPS65910)    += gpio-tps65910.o
+obj-$(CONFIG_GPIO_TPS65912)    += gpio-tps65912.o
diff --git a/drivers/gpio/gpio-tps65910.c b/drivers/gpio/gpio-tps65910.c
new file mode 100644 (file)
index 0000000..7eef648
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * TI TPS6591x GPIO driver
+ *
+ * Copyright 2010 Texas Instruments Inc.
+ *
+ * Author: Graeme Gregory <gg@slimlogic.co.uk>
+ * Author: Jorge Eduardo Candelaria jedu@slimlogic.co.uk>
+ *
+ *  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.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/mfd/tps65910.h>
+
+static int tps65910_gpio_get(struct gpio_chip *gc, unsigned offset)
+{
+       struct tps65910 *tps65910 = container_of(gc, struct tps65910, gpio);
+       uint8_t val;
+
+       tps65910->read(tps65910, TPS65910_GPIO0 + offset, 1, &val);
+
+       if (val & GPIO_STS_MASK)
+               return 1;
+
+       return 0;
+}
+
+static void tps65910_gpio_set(struct gpio_chip *gc, unsigned offset,
+                             int value)
+{
+       struct tps65910 *tps65910 = container_of(gc, struct tps65910, gpio);
+
+       if (value)
+               tps65910_set_bits(tps65910, TPS65910_GPIO0 + offset,
+                                               GPIO_SET_MASK);
+       else
+               tps65910_clear_bits(tps65910, TPS65910_GPIO0 + offset,
+                                               GPIO_SET_MASK);
+}
+
+static int tps65910_gpio_output(struct gpio_chip *gc, unsigned offset,
+                               int value)
+{
+       struct tps65910 *tps65910 = container_of(gc, struct tps65910, gpio);
+
+       /* Set the initial value */
+       tps65910_gpio_set(gc, offset, value);
+
+       return tps65910_set_bits(tps65910, TPS65910_GPIO0 + offset,
+                                               GPIO_CFG_MASK);
+}
+
+static int tps65910_gpio_input(struct gpio_chip *gc, unsigned offset)
+{
+       struct tps65910 *tps65910 = container_of(gc, struct tps65910, gpio);
+
+       return tps65910_clear_bits(tps65910, TPS65910_GPIO0 + offset,
+                                               GPIO_CFG_MASK);
+}
+
+void tps65910_gpio_init(struct tps65910 *tps65910, int gpio_base)
+{
+       int ret;
+       struct tps65910_board *board_data;
+
+       if (!gpio_base)
+               return;
+
+       tps65910->gpio.owner            = THIS_MODULE;
+       tps65910->gpio.label            = tps65910->i2c_client->name;
+       tps65910->gpio.dev              = tps65910->dev;
+       tps65910->gpio.base             = gpio_base;
+
+       switch(tps65910_chip_id(tps65910)) {
+       case TPS65910:
+               tps65910->gpio.ngpio    = TPS65910_NUM_GPIO;
+               break;
+       case TPS65911:
+               tps65910->gpio.ngpio    = TPS65911_NUM_GPIO;
+               break;
+       default:
+               return;
+       }
+       tps65910->gpio.can_sleep        = 1;
+
+       tps65910->gpio.direction_input  = tps65910_gpio_input;
+       tps65910->gpio.direction_output = tps65910_gpio_output;
+       tps65910->gpio.set              = tps65910_gpio_set;
+       tps65910->gpio.get              = tps65910_gpio_get;
+
+       /* Configure sleep control for gpios */
+       board_data = dev_get_platdata(tps65910->dev);
+       if (board_data) {
+               int i;
+               for (i = 0; i < tps65910->gpio.ngpio; ++i) {
+                       if (board_data->en_gpio_sleep[i]) {
+                               ret = tps65910_set_bits(tps65910,
+                                       TPS65910_GPIO0 + i, GPIO_SLEEP_MASK);
+                               if (ret < 0)
+                                       dev_warn(tps65910->dev,
+                                               "GPIO Sleep setting failed\n");
+                       }
+               }
+       }
+
+       ret = gpiochip_add(&tps65910->gpio);
+
+       if (ret)
+               dev_warn(tps65910->dev, "GPIO registration failed: %d\n", ret);
+}
index 35ff8fe221835b242ddcef88509f57510fc9d3fa..43c5d038be131bc76515fad1d696252874afddff 100755 (executable)
@@ -171,6 +171,37 @@ config MFD_TPS6586X
          This driver can also be built as a module.  If so, the module
          will be called tps6586x.
 
+config MFD_TPS65910
+       bool "TPS65910 Power Management chip"
+       depends on I2C=y && GPIOLIB
+       select MFD_CORE
+       select GPIO_TPS65910
+       select REGMAP_I2C
+       help
+         if you say yes here you get support for the TPS65910 series of
+         Power Management chips.
+
+config MFD_TPS65912
+       bool
+       depends on GPIOLIB
+
+config MFD_TPS65912_I2C
+       bool "TPS65912 Power Management chip with I2C"
+       select MFD_CORE
+       select MFD_TPS65912
+       depends on I2C=y && GPIOLIB
+       help
+         If you say yes here you get support for the TPS65912 series of
+         PM chips with I2C interface.
+
+config MFD_TPS65912_SPI
+       bool "TPS65912 Power Management chip with SPI"
+       select MFD_CORE
+       select MFD_TPS65912
+       depends on SPI_MASTER && GPIOLIB
+       help
+         If you say yes here you get support for the TPS65912 series of
+         PM chips with SPI interface.
 config MENELAUS
        bool "Texas Instruments TWL92330/Menelaus PM chip"
        depends on I2C=y && ARCH_OMAP2
@@ -769,17 +800,20 @@ config MFD_PM8XXX_IRQ
          This is required to use certain other PM 8xxx features, such as GPIO
          and MPP.
 
-config MFD_TPS65910
-       bool "TPS65910 Power Management chip"
-       depends on I2C=y && GPIOLIB
+config TPS65911_COMPARATOR
+       tristate
+
+config MFD_TPS65090
+       bool "TPS65090 Power Management chips"
+       depends on I2C=y && GENERIC_HARDIRQS
        select MFD_CORE
-       select GPIO_TPS65910
+       select REGMAP_I2C
        help
-         if you say yes here you get support for the TPS65910 series of
+         If you say yes here you get support for the TPS65090 series of
          Power Management chips.
-
-config TPS65911_COMPARATOR
-       tristate
+         This driver provides common support for accessing the device,
+         additional drivers must be enabled in order to use the
+         functionality of the device.
 
 config MFD_RK610
        bool "RK610(Jetta) Multimedia support"
index bd569e97306c6daf27279bf3e2f9b7addcac6779..59d550bfe5739c24c7f7ce63d981dee2988ad163 100755 (executable)
@@ -36,6 +36,11 @@ obj-$(CONFIG_MFD_WM8994)     += wm8994-core.o wm8994-irq.o
 obj-$(CONFIG_TPS6105X)         += tps6105x.o
 obj-$(CONFIG_TPS65010)         += tps65010.o
 obj-$(CONFIG_TPS6507X)         += tps6507x.o
+obj-$(CONFIG_MFD_TPS65910)     += tps65910.o tps65910-irq.o
+tps65912-objs                   := tps65912-core.o tps65912-irq.o
+obj-$(CONFIG_MFD_TPS65912)     += tps65912.o
+obj-$(CONFIG_MFD_TPS65912_I2C) += tps65912-i2c.o
+obj-$(CONFIG_MFD_TPS65912_SPI)  += tps65912-spi.o
 obj-$(CONFIG_MENELAUS)         += menelaus.o
 
 obj-$(CONFIG_TWL4030_CORE)     += twl-core.o twl4030-irq.o twl6030-irq.o
index a56be931551c9ac7ee34e546a18891e8a2b6549d..c9ed5c00a6211bb2349858ef76161eb880e45396 100644 (file)
@@ -145,12 +145,23 @@ static void tps65910_irq_disable(struct irq_data *data)
        tps65910->irq_mask |= ( 1 << irq_to_tps65910_irq(tps65910, data->irq));
 }
 
+#ifdef CONFIG_PM_SLEEP
+static int tps65910_irq_set_wake(struct irq_data *data, unsigned int enable)
+{
+       struct tps65910 *tps65910 = irq_data_get_irq_chip_data(data);
+       return irq_set_irq_wake(tps65910->chip_irq, enable);
+}
+#else
+#define tps65910_irq_set_wake NULL
+#endif
+
 static struct irq_chip tps65910_irq_chip = {
        .name = "tps65910",
        .irq_bus_lock = tps65910_irq_lock,
        .irq_bus_sync_unlock = tps65910_irq_sync_unlock,
        .irq_disable = tps65910_irq_disable,
        .irq_enable = tps65910_irq_enable,
+       .irq_set_wake = tps65910_irq_set_wake,
 };
 
 int tps65910_irq_init(struct tps65910 *tps65910, int irq,
@@ -215,6 +226,7 @@ int tps65910_irq_init(struct tps65910 *tps65910, int irq,
 
 int tps65910_irq_exit(struct tps65910 *tps65910)
 {
-       free_irq(tps65910->chip_irq, tps65910);
+       if (tps65910->chip_irq)
+               free_irq(tps65910->chip_irq, tps65910);
        return 0;
 }
index 2229e66d80db8e4d7b11afe823295d69162f1f00..a5a7b3cf2700cdd9947c590d12e44645a77a279b 100644 (file)
@@ -22,6 +22,8 @@
 #include <linux/mfd/core.h>
 #include <linux/mfd/tps65910.h>
 
+struct tps65910 *g_tps65910;
+
 static struct mfd_cell tps65910s[] = {
        {
                .name = "tps65910-pmic",
@@ -34,6 +36,7 @@ static struct mfd_cell tps65910s[] = {
        },
 };
 
+#define TPS65910_SPEED         400 * 1000
 
 static int tps65910_i2c_read(struct tps65910 *tps65910, u8 reg,
                                  int bytes, void *dest)
@@ -41,25 +44,29 @@ static int tps65910_i2c_read(struct tps65910 *tps65910, u8 reg,
        struct i2c_client *i2c = tps65910->i2c_client;
        struct i2c_msg xfer[2];
        int ret;
+       
+       //printk("%s:reg=0x%x,value=%d\n",__func__,reg,*(char *)dest);
 
        /* Write register */
        xfer[0].addr = i2c->addr;
        xfer[0].flags = 0;
        xfer[0].len = 1;
        xfer[0].buf = &reg;
+       xfer[0].scl_rate = 200*1000;
 
        /* Read data */
        xfer[1].addr = i2c->addr;
        xfer[1].flags = I2C_M_RD;
        xfer[1].len = bytes;
        xfer[1].buf = dest;
+       xfer[1].scl_rate = 200*1000;
 
        ret = i2c_transfer(i2c->adapter, xfer, 2);
        if (ret == 2)
                ret = 0;
        else if (ret >= 0)
                ret = -EIO;
-
+       
        return ret;
 }
 
@@ -70,10 +77,12 @@ static int tps65910_i2c_write(struct tps65910 *tps65910, u8 reg,
        /* we add 1 byte for device register */
        u8 msg[TPS65910_MAX_REGISTER + 1];
        int ret;
-
+       
        if (bytes > TPS65910_MAX_REGISTER)
                return -EINVAL;
 
+       //printk("%s:reg=0x%x,value=%d\n",__func__,reg,*(char *)&src);
+       
        msg[0] = reg;
        memcpy(&msg[1], src, bytes);
 
@@ -82,6 +91,7 @@ static int tps65910_i2c_write(struct tps65910 *tps65910, u8 reg,
                return ret;
        if (ret != bytes + 1)
                return -EIO;
+
        return 0;
 }
 
@@ -93,14 +103,14 @@ int tps65910_set_bits(struct tps65910 *tps65910, u8 reg, u8 mask)
        mutex_lock(&tps65910->io_mutex);
        err = tps65910_i2c_read(tps65910, reg, 1, &data);
        if (err) {
-               dev_err(tps65910->dev, "read from reg %x failed\n", reg);
+               dev_err(tps65910->dev, "%s:read from reg %x failed\n", __func__,reg);
                goto out;
        }
 
        data |= mask;
        err = tps65910_i2c_write(tps65910, reg, 1, &data);
        if (err)
-               dev_err(tps65910->dev, "write to reg %x failed\n", reg);
+               dev_err(tps65910->dev, "%s:write to reg %x failed\n", __func__,reg);
 
 out:
        mutex_unlock(&tps65910->io_mutex);
@@ -167,6 +177,16 @@ static int tps65910_i2c_probe(struct i2c_client *i2c,
                              NULL, 0);
        if (ret < 0)
                goto err;
+       
+       g_tps65910 = tps65910;
+       
+       if (pmic_plat_data && pmic_plat_data->pre_init) {
+               ret = pmic_plat_data->pre_init(tps65910);
+               if (ret != 0) {
+                       dev_err(tps65910->dev, "pre_init() failed: %d\n", ret);
+                       goto err;
+               }
+       }
 
        tps65910_gpio_init(tps65910, pmic_plat_data->gpio_base);
 
@@ -174,6 +194,14 @@ static int tps65910_i2c_probe(struct i2c_client *i2c,
        if (ret < 0)
                goto err;
 
+       if (pmic_plat_data && pmic_plat_data->post_init) {
+               ret = pmic_plat_data->post_init(tps65910);
+               if (ret != 0) {
+                       dev_err(tps65910->dev, "post_init() failed: %d\n", ret);
+                       goto err;
+               }
+       }
+
        return ret;
 
 err:
@@ -182,6 +210,45 @@ err:
        return ret;
 }
 
+
+int tps65910_i2c_write_u8(u8 slave_addr, u8 value, u8 reg)
+{
+       struct tps65910 *tps65910 = g_tps65910;
+       return tps65910->write(g_tps65910, reg, 1, &value);
+}
+EXPORT_SYMBOL_GPL(tps65910_i2c_write_u8);
+
+
+int tps65910_i2c_read_u8(u8 slave_addr, u8 *value, u8 reg)
+{
+       struct tps65910 *tps65910 = g_tps65910;
+       return tps65910->read(g_tps65910, reg, 1, value);
+}
+EXPORT_SYMBOL_GPL(tps65910_i2c_read_u8);
+
+int tps65910_device_shutdown(void)
+{
+       u8 val  = 0;
+       int err = -1;
+       printk("%s\n",__func__);
+        err = tps65910_i2c_read_u8(TPS65910_I2C_ID0, &val, TPS65910_REG_DEVCTRL);
+        if (err) {
+                printk(KERN_ERR "Unable to read TPS65910_REG_DCDCCTRL reg\n");
+                return -EIO;
+        }
+               val |= (1 << 3)|(1 << 0);
+               err = tps65910_i2c_write_u8(TPS65910_I2C_ID0, val, TPS65910_REG_DEVCTRL);
+               if (err) {
+                       printk(KERN_ERR "Unable to read TPS65910 Reg at offset 0x%x= \
+                                       \n", TPS65910_REG_VDIG1);
+                       return -EIO;
+               }
+       return 0;       
+}
+EXPORT_SYMBOL_GPL(tps65910_device_shutdown);
+
+
+
 static int tps65910_i2c_remove(struct i2c_client *i2c)
 {
        struct tps65910 *tps65910 = i2c_get_clientdata(i2c);
@@ -215,7 +282,7 @@ static int __init tps65910_i2c_init(void)
        return i2c_add_driver(&tps65910_i2c_driver);
 }
 /* init early so consumer devices can complete system boot */
-subsys_initcall(tps65910_i2c_init);
+module_init(tps65910_i2c_init);
 
 static void __exit tps65910_i2c_exit(void)
 {
index 90c87c9797c5c5da8972d7a03f7f0f40255006ea..b425fd61c4b209bfad8c8c71de3cc045bc0677b4 100755 (executable)
@@ -125,6 +125,17 @@ config REGULATOR_MAX8998
          via I2C bus. The provided regulator is suitable for S3C6410
          and S5PC1XX chips to control VCC_CORE and VCC_USIM voltages.
 
+config REGULATOR_TPS65910
+       tristate "TI TPS65910/TPS65911 Power Regulators"
+       depends on MFD_TPS65910
+       help
+         This driver supports TPS65910/TPS65911 voltage regulator chips.
+
+config REGULATOR_TPS65912
+       tristate "TI TPS65912 Power regulator"
+       depends on (MFD_TPS65912_I2C || MFD_TPS65912_SPI)
+       help
+           This driver supports TPS65912 voltage regulator chip.
 config REGULATOR_TWL4030
        bool "TI TWL4030/TWL5030/TWL6030/TPS659x0 PMIC"
        depends on TWL4030_CORE
@@ -324,11 +335,7 @@ config REGULATOR_TPS6524X
          serial interface currently supported on the sequencer serial
          port controller.
 
-config REGULATOR_TPS65910
-       tristate "TI TPS65910 Power Regulator"
-       depends on MFD_TPS65910
-       help
-         This driver supports TPS65910 voltage regulator chips.
+
 
 endif
 
index 68db7129f878e9eaa9f30ff2985b7da524bd86dc..d4f86bae7bf97397d968feeee2552e420b615d2c 100755 (executable)
@@ -49,6 +49,7 @@ obj-$(CONFIG_REGULATOR_ISL6271A) += isl6271a-regulator.o
 obj-$(CONFIG_REGULATOR_AB8500) += ab8500.o
 obj-$(CONFIG_REGULATOR_DB8500_PRCMU) += db8500-prcmu.o
 obj-$(CONFIG_REGULATOR_TPS65910) += tps65910-regulator.o
+obj-$(CONFIG_REGULATOR_TPS65912) += tps65912-regulator.o
 obj-$(CONFIG_REGULATOR_ACT8891) += act8891.o
 
 ccflags-$(CONFIG_REGULATOR_DEBUG) += -DDEBUG
index 425aab38981e5fbad9cf4082d67809ff12175bb5..ca736adfada0c74563219ca929cc39a0e036f64b 100644 (file)
 #include <linux/gpio.h>
 #include <linux/mfd/tps65910.h>
 
-#define TPS65910_REG_VRTC              0
-#define TPS65910_REG_VIO               1
-#define TPS65910_REG_VDD1              2
-#define TPS65910_REG_VDD2              3
-#define TPS65910_REG_VDD3              4
-#define TPS65910_REG_VDIG1             5
-#define TPS65910_REG_VDIG2             6
-#define TPS65910_REG_VPLL              7
-#define TPS65910_REG_VDAC              8
-#define TPS65910_REG_VAUX1             9
-#define TPS65910_REG_VAUX2             10
-#define TPS65910_REG_VAUX33            11
-#define TPS65910_REG_VMMC              12
-
-#define TPS65911_REG_VDDCTRL           4
-#define TPS65911_REG_LDO1              5
-#define TPS65911_REG_LDO2              6
-#define TPS65911_REG_LDO3              7
-#define TPS65911_REG_LDO4              8
-#define TPS65911_REG_LDO5              9
-#define TPS65911_REG_LDO6              10
-#define TPS65911_REG_LDO7              11
-#define TPS65911_REG_LDO8              12
-
-#define TPS65910_NUM_REGULATOR         13
 #define TPS65910_SUPPLY_STATE_ENABLED  0x1
+#define EXT_SLEEP_CONTROL (TPS65910_SLEEP_CONTROL_EXT_INPUT_EN1 |      \
+                       TPS65910_SLEEP_CONTROL_EXT_INPUT_EN2 |          \
+                       TPS65910_SLEEP_CONTROL_EXT_INPUT_EN3 |          \
+                       TPS65911_SLEEP_CONTROL_EXT_INPUT_SLEEP)
 
 /* supported VIO voltages in milivolts */
 static const u16 VIO_VSEL_table[] = {
        1500, 1800, 2500, 3300,
 };
 
-/* VSEL tables for TPS65910 specific LDOs and dcdc's */
+/* TPS65910 VDD1 and VDD2 */
+/* value round off 12.5 is made as 12 */
+static const u16 VDD1_VSEL_table[] = {
+          0,  600,  600,  600,  612,  625,  637,  650,
+        662,  675,  687,  700,  712,  725,  737,  750,
+        762,  775,  787,  800,  812,  825,  837,  850,
+        862,  875,  887,  900,  912,  925,  937,  950,
+        962,  975,  987, 1000, 1012, 1025, 1037, 1050,
+       1062, 1075, 1087, 1100, 1112, 1125, 1137, 1150,
+       1162, 1175, 1187, 1200, 1212, 1225, 1237, 1250,
+       1262, 1275, 1287, 1300, 1312, 1325, 1337, 1350,
+       1362, 1375, 1387, 1400, 1412, 1425, 1437, 1450,
+       1462, 1475, 1487, 1500,
+};
+
+static const u16 VDD2_VSEL_table[] = {
+          0,  600,  600,  600,  612,  625,  637,  650,
+        662,  675,  687,  700,  712,  725,  737,  750,
+        762,  775,  787,  800,  812,  825,  837,  850,
+        862,  875,  887,  900,  912,  925,  937,  950,
+        962,  975,  987, 1000, 1012, 1025, 1037, 1050,
+       1062, 1075, 1087, 1100, 1112, 1125, 1137, 1150,
+       1162, 1175, 1187, 1200, 1212, 1225, 1237, 1250,
+       1262, 1275, 1287, 1300, 1312, 1325, 1337, 1350,
+       1362, 1375, 1387, 1400, 1412, 1425, 1437, 1450,
+       1462, 1475, 1487, 1500,
+};
 
-/* supported VDD3 voltages in milivolts */
+/* TPS65910 VDD3 */
 static const u16 VDD3_VSEL_table[] = {
-       5000,
+       1000,1400
 };
 
+
 /* supported VDIG1 voltages in milivolts */
 static const u16 VDIG1_VSEL_table[] = {
        1200, 1500, 1800, 2700,
@@ -108,169 +114,250 @@ struct tps_info {
        const char *name;
        unsigned min_uV;
        unsigned max_uV;
-       u8 table_len;
-       const u16 *table;
+       u8 n_voltages;
+       const u16 *voltage_table;
+       int enable_time_us;
 };
 
 static struct tps_info tps65910_regs[] = {
        {
                .name = "VRTC",
+               .enable_time_us = 2200,
        },
        {
                .name = "VIO",
                .min_uV = 1500000,
                .max_uV = 3300000,
-               .table_len = ARRAY_SIZE(VIO_VSEL_table),
-               .table = VIO_VSEL_table,
+               .n_voltages = ARRAY_SIZE(VIO_VSEL_table),
+               .voltage_table = VIO_VSEL_table,
+               .enable_time_us = 350,
        },
        {
                .name = "VDD1",
                .min_uV = 600000,
-               .max_uV = 4500000,
+               .max_uV = 1500000,
+               .n_voltages = ARRAY_SIZE(VDD1_VSEL_table),
+               .voltage_table = VDD1_VSEL_table,
+               .enable_time_us = 350,
        },
        {
                .name = "VDD2",
                .min_uV = 600000,
-               .max_uV = 4500000,
+               .max_uV = 1500000,
+               .n_voltages = ARRAY_SIZE(VDD2_VSEL_table),
+               .voltage_table = VDD2_VSEL_table,
+               .enable_time_us = 350,
        },
        {
                .name = "VDD3",
-               .min_uV = 5000000,
-               .max_uV = 5000000,
-               .table_len = ARRAY_SIZE(VDD3_VSEL_table),
-               .table = VDD3_VSEL_table,
+               .min_uV = 1000000,
+               .max_uV = 1400000,
+               .n_voltages = ARRAY_SIZE(VDD3_VSEL_table),
+               .voltage_table = VDD3_VSEL_table,
+               .enable_time_us = 200,
        },
        {
                .name = "VDIG1",
                .min_uV = 1200000,
                .max_uV = 2700000,
-               .table_len = ARRAY_SIZE(VDIG1_VSEL_table),
-               .table = VDIG1_VSEL_table,
+               .n_voltages = ARRAY_SIZE(VDIG1_VSEL_table),
+               .voltage_table = VDIG1_VSEL_table,
+               .enable_time_us = 100,
        },
        {
                .name = "VDIG2",
                .min_uV = 1000000,
                .max_uV = 1800000,
-               .table_len = ARRAY_SIZE(VDIG2_VSEL_table),
-               .table = VDIG2_VSEL_table,
+               .n_voltages = ARRAY_SIZE(VDIG2_VSEL_table),
+               .voltage_table = VDIG2_VSEL_table,
+               .enable_time_us = 100,
        },
        {
                .name = "VPLL",
                .min_uV = 1000000,
                .max_uV = 2500000,
-               .table_len = ARRAY_SIZE(VPLL_VSEL_table),
-               .table = VPLL_VSEL_table,
+               .n_voltages = ARRAY_SIZE(VPLL_VSEL_table),
+               .voltage_table = VPLL_VSEL_table,
+               .enable_time_us = 100,
        },
        {
                .name = "VDAC",
                .min_uV = 1800000,
                .max_uV = 2850000,
-               .table_len = ARRAY_SIZE(VDAC_VSEL_table),
-               .table = VDAC_VSEL_table,
+               .n_voltages = ARRAY_SIZE(VDAC_VSEL_table),
+               .voltage_table = VDAC_VSEL_table,
+               .enable_time_us = 100,
        },
        {
                .name = "VAUX1",
                .min_uV = 1800000,
                .max_uV = 2850000,
-               .table_len = ARRAY_SIZE(VAUX1_VSEL_table),
-               .table = VAUX1_VSEL_table,
+               .n_voltages = ARRAY_SIZE(VAUX1_VSEL_table),
+               .voltage_table = VAUX1_VSEL_table,
+               .enable_time_us = 100,
        },
        {
                .name = "VAUX2",
                .min_uV = 1800000,
                .max_uV = 3300000,
-               .table_len = ARRAY_SIZE(VAUX2_VSEL_table),
-               .table = VAUX2_VSEL_table,
+               .n_voltages = ARRAY_SIZE(VAUX2_VSEL_table),
+               .voltage_table = VAUX2_VSEL_table,
+               .enable_time_us = 100,
        },
        {
                .name = "VAUX33",
                .min_uV = 1800000,
                .max_uV = 3300000,
-               .table_len = ARRAY_SIZE(VAUX33_VSEL_table),
-               .table = VAUX33_VSEL_table,
+               .n_voltages = ARRAY_SIZE(VAUX33_VSEL_table),
+               .voltage_table = VAUX33_VSEL_table,
+               .enable_time_us = 100,
        },
        {
                .name = "VMMC",
                .min_uV = 1800000,
                .max_uV = 3300000,
-               .table_len = ARRAY_SIZE(VMMC_VSEL_table),
-               .table = VMMC_VSEL_table,
+               .n_voltages = ARRAY_SIZE(VMMC_VSEL_table),
+               .voltage_table = VMMC_VSEL_table,
+               .enable_time_us = 100,
        },
 };
 
 static struct tps_info tps65911_regs[] = {
+       {
+               .name = "VRTC",
+               .enable_time_us = 2200,
+       },
        {
                .name = "VIO",
                .min_uV = 1500000,
                .max_uV = 3300000,
-               .table_len = ARRAY_SIZE(VIO_VSEL_table),
-               .table = VIO_VSEL_table,
+               .n_voltages = ARRAY_SIZE(VIO_VSEL_table),
+               .voltage_table = VIO_VSEL_table,
+               .enable_time_us = 350,
        },
        {
                .name = "VDD1",
                .min_uV = 600000,
                .max_uV = 4500000,
+               .n_voltages = 73,
+               .enable_time_us = 350,
        },
        {
                .name = "VDD2",
                .min_uV = 600000,
                .max_uV = 4500000,
+               .n_voltages = 73,
+               .enable_time_us = 350,
        },
        {
                .name = "VDDCTRL",
                .min_uV = 600000,
                .max_uV = 1400000,
+               .n_voltages = 65,
+               .enable_time_us = 900,
        },
        {
                .name = "LDO1",
                .min_uV = 1000000,
                .max_uV = 3300000,
+               .n_voltages = 47,
+               .enable_time_us = 420,
        },
        {
                .name = "LDO2",
                .min_uV = 1000000,
                .max_uV = 3300000,
+               .n_voltages = 47,
+               .enable_time_us = 420,
        },
        {
                .name = "LDO3",
                .min_uV = 1000000,
                .max_uV = 3300000,
+               .n_voltages = 24,
+               .enable_time_us = 230,
        },
        {
                .name = "LDO4",
                .min_uV = 1000000,
                .max_uV = 3300000,
+               .n_voltages = 47,
+               .enable_time_us = 230,
        },
        {
                .name = "LDO5",
                .min_uV = 1000000,
                .max_uV = 3300000,
+               .n_voltages = 24,
+               .enable_time_us = 230,
        },
        {
                .name = "LDO6",
                .min_uV = 1000000,
                .max_uV = 3300000,
+               .n_voltages = 24,
+               .enable_time_us = 230,
        },
        {
                .name = "LDO7",
                .min_uV = 1000000,
                .max_uV = 3300000,
+               .n_voltages = 24,
+               .enable_time_us = 230,
        },
        {
                .name = "LDO8",
                .min_uV = 1000000,
                .max_uV = 3300000,
+               .n_voltages = 24,
+               .enable_time_us = 230,
        },
 };
 
+#define EXT_CONTROL_REG_BITS(id, regs_offs, bits) (((regs_offs) << 8) | (bits))
+static unsigned int tps65910_ext_sleep_control[] = {
+       0,
+       EXT_CONTROL_REG_BITS(VIO,    1, 0),
+       EXT_CONTROL_REG_BITS(VDD1,   1, 1),
+       EXT_CONTROL_REG_BITS(VDD2,   1, 2),
+       EXT_CONTROL_REG_BITS(VDD3,   1, 3),
+       EXT_CONTROL_REG_BITS(VDIG1,  0, 1),
+       EXT_CONTROL_REG_BITS(VDIG2,  0, 2),
+       EXT_CONTROL_REG_BITS(VPLL,   0, 6),
+       EXT_CONTROL_REG_BITS(VDAC,   0, 7),
+       EXT_CONTROL_REG_BITS(VAUX1,  0, 3),
+       EXT_CONTROL_REG_BITS(VAUX2,  0, 4),
+       EXT_CONTROL_REG_BITS(VAUX33, 0, 5),
+       EXT_CONTROL_REG_BITS(VMMC,   0, 0),
+};
+
+static unsigned int tps65911_ext_sleep_control[] = {
+       0,
+       EXT_CONTROL_REG_BITS(VIO,     1, 0),
+       EXT_CONTROL_REG_BITS(VDD1,    1, 1),
+       EXT_CONTROL_REG_BITS(VDD2,    1, 2),
+       EXT_CONTROL_REG_BITS(VDDCTRL, 1, 3),
+       EXT_CONTROL_REG_BITS(LDO1,    0, 1),
+       EXT_CONTROL_REG_BITS(LDO2,    0, 2),
+       EXT_CONTROL_REG_BITS(LDO3,    0, 7),
+       EXT_CONTROL_REG_BITS(LDO4,    0, 6),
+       EXT_CONTROL_REG_BITS(LDO5,    0, 3),
+       EXT_CONTROL_REG_BITS(LDO6,    0, 0),
+       EXT_CONTROL_REG_BITS(LDO7,    0, 5),
+       EXT_CONTROL_REG_BITS(LDO8,    0, 4),
+};
+
 struct tps65910_reg {
-       struct regulator_desc desc[TPS65910_NUM_REGULATOR];
+       struct regulator_desc *desc;
        struct tps65910 *mfd;
-       struct regulator_dev *rdev[TPS65910_NUM_REGULATOR];
-       struct tps_info *info[TPS65910_NUM_REGULATOR];
+       struct regulator_dev **rdev;
+       struct tps_info **info;
        struct mutex mutex;
+       int num_regulators;
        int mode;
        int  (*get_ctrl_reg)(int);
+       unsigned int *ext_sleep_control;
+       unsigned int board_ext_control[TPS65910_NUM_REGS];
 };
 
 static inline int tps65910_read(struct tps65910_reg *pmic, u8 reg)
@@ -453,6 +540,12 @@ static int tps65910_disable(struct regulator_dev *dev)
        return tps65910_clear_bits(mfd, reg, TPS65910_SUPPLY_STATE_ENABLED);
 }
 
+static int tps65910_enable_time(struct regulator_dev *dev)
+{
+       struct tps65910_reg *pmic = rdev_get_drvdata(dev);
+       int id = rdev_get_id(dev);
+       return pmic->info[id]->enable_time_us;
+}
 
 static int tps65910_set_mode(struct regulator_dev *dev, unsigned int mode)
 {
@@ -491,7 +584,7 @@ static unsigned int tps65910_get_mode(struct regulator_dev *dev)
        if (value < 0)
                return value;
 
-       if (value & LDO_ST_ON_BIT)
+       if (!(value & LDO_ST_ON_BIT))
                return REGULATOR_MODE_STANDBY;
        else if (value & LDO_ST_MODE_BIT)
                return REGULATOR_MODE_IDLE;
@@ -499,10 +592,10 @@ static unsigned int tps65910_get_mode(struct regulator_dev *dev)
                return REGULATOR_MODE_NORMAL;
 }
 
-static int tps65910_get_voltage_dcdc(struct regulator_dev *dev)
+static int tps65910_get_voltage_dcdc_sel(struct regulator_dev *dev)
 {
        struct tps65910_reg *pmic = rdev_get_drvdata(dev);
-       int id = rdev_get_id(dev), voltage = 0;
+       int id = rdev_get_id(dev);
        int opvsel = 0, srvsel = 0, vselmax = 0, mult = 0, sr = 0;
 
        switch (id) {
@@ -546,9 +639,7 @@ static int tps65910_get_voltage_dcdc(struct regulator_dev *dev)
                        srvsel = 3;
                if (srvsel > vselmax)
                        srvsel = vselmax;
-               srvsel -= 3;
-
-               voltage = (srvsel * VDD1_2_OFFSET + VDD1_2_MIN_VOLT) * 100;
+               return srvsel - 3;
        } else {
 
                /* normalise to valid range*/
@@ -556,14 +647,9 @@ static int tps65910_get_voltage_dcdc(struct regulator_dev *dev)
                        opvsel = 3;
                if (opvsel > vselmax)
                        opvsel = vselmax;
-               opvsel -= 3;
-
-               voltage = (opvsel * VDD1_2_OFFSET + VDD1_2_MIN_VOLT) * 100;
+               return opvsel - 3;
        }
-
-       voltage *= mult;
-
-       return voltage;
+       return -EINVAL;
 }
 
 static int tps65910_get_voltage(struct regulator_dev *dev)
@@ -596,7 +682,7 @@ static int tps65910_get_voltage(struct regulator_dev *dev)
                return -EINVAL;
        }
 
-       voltage = pmic->info[id]->table[value] * 1000;
+       voltage = pmic->info[id]->voltage_table[value] * 1000;
 
        return voltage;
 }
@@ -646,8 +732,9 @@ static int tps65911_get_voltage(struct regulator_dev *dev)
                step_mv = 100;
                break;
        case TPS65910_REG_VIO:
-               return pmic->info[id]->table[value] * 1000;
-               break;
+               value &= LDO_SEL_MASK;
+               value >>= LDO_SEL_SHIFT;
+               return pmic->info[id]->voltage_table[value] * 1000;
        default:
                return -EINVAL;
        }
@@ -655,8 +742,8 @@ static int tps65911_get_voltage(struct regulator_dev *dev)
        return (LDO_MIN_VOLT + value * step_mv) * 1000;
 }
 
-static int tps65910_set_voltage_dcdc(struct regulator_dev *dev,
-                               unsigned selector)
+static int tps65910_set_voltage_dcdc_sel(struct regulator_dev *dev,
+                                        unsigned selector)
 {
        struct tps65910_reg *pmic = rdev_get_drvdata(dev);
        int id = rdev_get_id(dev), vsel;
@@ -664,10 +751,10 @@ static int tps65910_set_voltage_dcdc(struct regulator_dev *dev,
 
        switch (id) {
        case TPS65910_REG_VDD1:
-               dcdc_mult = (selector / VDD1_2_NUM_VOLTS) + 1;
+               dcdc_mult = (selector / VDD1_2_NUM_VOLT_FINE) + 1;
                if (dcdc_mult == 1)
                        dcdc_mult--;
-               vsel = (selector % VDD1_2_NUM_VOLTS) + 3;
+               vsel = (selector % VDD1_2_NUM_VOLT_FINE) + 3;
 
                tps65910_modify_bits(pmic, TPS65910_VDD1,
                                (dcdc_mult << VDD1_VGAIN_SEL_SHIFT),
@@ -675,10 +762,10 @@ static int tps65910_set_voltage_dcdc(struct regulator_dev *dev,
                tps65910_reg_write(pmic, TPS65910_VDD1_OP, vsel);
                break;
        case TPS65910_REG_VDD2:
-               dcdc_mult = (selector / VDD1_2_NUM_VOLTS) + 1;
+               dcdc_mult = (selector / VDD1_2_NUM_VOLT_FINE) + 1;
                if (dcdc_mult == 1)
                        dcdc_mult--;
-               vsel = (selector % VDD1_2_NUM_VOLTS) + 3;
+               vsel = (selector % VDD1_2_NUM_VOLT_FINE) + 3;
 
                tps65910_modify_bits(pmic, TPS65910_VDD2,
                                (dcdc_mult << VDD2_VGAIN_SEL_SHIFT),
@@ -686,14 +773,15 @@ static int tps65910_set_voltage_dcdc(struct regulator_dev *dev,
                tps65910_reg_write(pmic, TPS65910_VDD2_OP, vsel);
                break;
        case TPS65911_REG_VDDCTRL:
-               vsel = selector;
+               vsel = selector + 3;
                tps65910_reg_write(pmic, TPS65911_VDDCTRL_OP, vsel);
        }
 
        return 0;
 }
 
-static int tps65910_set_voltage(struct regulator_dev *dev, unsigned selector)
+static int tps65910_set_voltage_sel(struct regulator_dev *dev,
+                                   unsigned selector)
 {
        struct tps65910_reg *pmic = rdev_get_drvdata(dev);
        int reg, id = rdev_get_id(dev);
@@ -719,7 +807,8 @@ static int tps65910_set_voltage(struct regulator_dev *dev, unsigned selector)
        return -EINVAL;
 }
 
-static int tps65911_set_voltage(struct regulator_dev *dev, unsigned selector)
+static int tps65911_set_voltage_sel(struct regulator_dev *dev,
+                                   unsigned selector)
 {
        struct tps65910_reg *pmic = rdev_get_drvdata(dev);
        int reg, id = rdev_get_id(dev);
@@ -739,9 +828,11 @@ static int tps65911_set_voltage(struct regulator_dev *dev, unsigned selector)
        case TPS65911_REG_LDO6:
        case TPS65911_REG_LDO7:
        case TPS65911_REG_LDO8:
-       case TPS65910_REG_VIO:
                return tps65910_modify_bits(pmic, reg,
                                (selector << LDO_SEL_SHIFT), LDO3_SEL_MASK);
+       case TPS65910_REG_VIO:
+               return tps65910_modify_bits(pmic, reg,
+                               (selector << LDO_SEL_SHIFT), LDO_SEL_MASK);
        }
 
        return -EINVAL;
@@ -756,9 +847,9 @@ static int tps65910_list_voltage_dcdc(struct regulator_dev *dev,
        switch (id) {
        case TPS65910_REG_VDD1:
        case TPS65910_REG_VDD2:
-               mult = (selector / VDD1_2_NUM_VOLTS) + 1;
+               mult = (selector / VDD1_2_NUM_VOLT_FINE) + 1;
                volt = VDD1_2_MIN_VOLT +
-                               (selector % VDD1_2_NUM_VOLTS) * VDD1_2_OFFSET;
+                               (selector % VDD1_2_NUM_VOLT_FINE) * VDD1_2_OFFSET;
                break;
        case TPS65911_REG_VDDCTRL:
                volt = VDDCTRL_MIN_VOLT + (selector * VDDCTRL_OFFSET);
@@ -780,11 +871,11 @@ static int tps65910_list_voltage(struct regulator_dev *dev,
        if (id < TPS65910_REG_VIO || id > TPS65910_REG_VMMC)
                return -EINVAL;
 
-       if (selector >= pmic->info[id]->table_len)
+       if (selector >= pmic->info[id]->n_voltages)
                return -EINVAL;
        else
-               voltage = pmic->info[id]->table[selector] * 1000;
-
+               voltage = pmic->info[id]->voltage_table[selector] * 1000;
+       
        return voltage;
 }
 
@@ -819,7 +910,7 @@ static int tps65911_list_voltage(struct regulator_dev *dev, unsigned selector)
                step_mv = 100;
                break;
        case TPS65910_REG_VIO:
-               return pmic->info[id]->table[selector] * 1000;
+               return pmic->info[id]->voltage_table[selector] * 1000;
        default:
                return -EINVAL;
        }
@@ -827,15 +918,42 @@ static int tps65911_list_voltage(struct regulator_dev *dev, unsigned selector)
        return (LDO_MIN_VOLT + selector * step_mv) * 1000;
 }
 
+static int tps65910_set_voltage_dcdc_time_sel(struct regulator_dev *dev,
+               unsigned int old_selector, unsigned int new_selector)
+{
+       int id = rdev_get_id(dev);
+       int old_volt, new_volt;
+
+       old_volt = tps65910_list_voltage_dcdc(dev, old_selector);
+       if (old_volt < 0)
+               return old_volt;
+
+       new_volt = tps65910_list_voltage_dcdc(dev, new_selector);
+       if (new_volt < 0)
+               return new_volt;
+
+       /* VDD1 and VDD2 are 12.5mV/us, VDDCTRL is 100mV/20us */
+       switch (id) {
+       case TPS65910_REG_VDD1:
+       case TPS65910_REG_VDD2:
+               return DIV_ROUND_UP(abs(old_volt - new_volt), 12500);
+       case TPS65911_REG_VDDCTRL:
+               return DIV_ROUND_UP(abs(old_volt - new_volt), 5000);
+       }
+       return -EINVAL;
+}
+
 /* Regulator ops (except VRTC) */
 static struct regulator_ops tps65910_ops_dcdc = {
        .is_enabled             = tps65910_is_enabled,
        .enable                 = tps65910_enable,
        .disable                = tps65910_disable,
+       .enable_time            = tps65910_enable_time,
        .set_mode               = tps65910_set_mode,
        .get_mode               = tps65910_get_mode,
-       .get_voltage            = tps65910_get_voltage_dcdc,
-       .set_voltage_sel        = tps65910_set_voltage_dcdc,
+       .get_voltage_sel        = tps65910_get_voltage_dcdc_sel,
+       .set_voltage_sel        = tps65910_set_voltage_dcdc_sel,
+       .set_voltage_time_sel   = tps65910_set_voltage_dcdc_time_sel,
        .list_voltage           = tps65910_list_voltage_dcdc,
 };
 
@@ -843,6 +961,7 @@ static struct regulator_ops tps65910_ops_vdd3 = {
        .is_enabled             = tps65910_is_enabled,
        .enable                 = tps65910_enable,
        .disable                = tps65910_disable,
+       .enable_time            = tps65910_enable_time,
        .set_mode               = tps65910_set_mode,
        .get_mode               = tps65910_get_mode,
        .get_voltage            = tps65910_get_voltage_vdd3,
@@ -853,10 +972,11 @@ static struct regulator_ops tps65910_ops = {
        .is_enabled             = tps65910_is_enabled,
        .enable                 = tps65910_enable,
        .disable                = tps65910_disable,
+       .enable_time            = tps65910_enable_time,
        .set_mode               = tps65910_set_mode,
        .get_mode               = tps65910_get_mode,
        .get_voltage            = tps65910_get_voltage,
-       .set_voltage_sel        = tps65910_set_voltage,
+       .set_voltage_sel        = tps65910_set_voltage_sel,
        .list_voltage           = tps65910_list_voltage,
 };
 
@@ -864,13 +984,147 @@ static struct regulator_ops tps65911_ops = {
        .is_enabled             = tps65910_is_enabled,
        .enable                 = tps65910_enable,
        .disable                = tps65910_disable,
+       .enable_time            = tps65910_enable_time,
        .set_mode               = tps65910_set_mode,
        .get_mode               = tps65910_get_mode,
        .get_voltage            = tps65911_get_voltage,
-       .set_voltage_sel        = tps65911_set_voltage,
+       .set_voltage_sel        = tps65911_set_voltage_sel,
        .list_voltage           = tps65911_list_voltage,
 };
 
+static int tps65910_set_ext_sleep_config(struct tps65910_reg *pmic,
+               int id, int ext_sleep_config)
+{
+       struct tps65910 *mfd = pmic->mfd;
+       u8 regoffs = (pmic->ext_sleep_control[id] >> 8) & 0xFF;
+       u8 bit_pos = (1 << pmic->ext_sleep_control[id] & 0xFF);
+       int ret;
+
+       /*
+        * Regulator can not be control from multiple external input EN1, EN2
+        * and EN3 together.
+        */
+       if (ext_sleep_config & EXT_SLEEP_CONTROL) {
+               int en_count;
+               en_count = ((ext_sleep_config &
+                               TPS65910_SLEEP_CONTROL_EXT_INPUT_EN1) != 0);
+               en_count += ((ext_sleep_config &
+                               TPS65910_SLEEP_CONTROL_EXT_INPUT_EN2) != 0);
+               en_count += ((ext_sleep_config &
+                               TPS65910_SLEEP_CONTROL_EXT_INPUT_EN3) != 0);
+               en_count += ((ext_sleep_config &
+                               TPS65911_SLEEP_CONTROL_EXT_INPUT_SLEEP) != 0);
+               if (en_count > 1) {
+                       dev_err(mfd->dev,
+                               "External sleep control flag is not proper\n");
+                       return -EINVAL;
+               }
+       }
+
+       pmic->board_ext_control[id] = ext_sleep_config;
+
+       /* External EN1 control */
+       if (ext_sleep_config & TPS65910_SLEEP_CONTROL_EXT_INPUT_EN1)
+               ret = tps65910_set_bits(mfd,
+                               TPS65910_EN1_LDO_ASS + regoffs, bit_pos);
+       else
+               ret = tps65910_clear_bits(mfd,
+                               TPS65910_EN1_LDO_ASS + regoffs, bit_pos);
+       if (ret < 0) {
+               dev_err(mfd->dev,
+                       "Error in configuring external control EN1\n");
+               return ret;
+       }
+
+       /* External EN2 control */
+       if (ext_sleep_config & TPS65910_SLEEP_CONTROL_EXT_INPUT_EN2)
+               ret = tps65910_set_bits(mfd,
+                               TPS65910_EN2_LDO_ASS + regoffs, bit_pos);
+       else
+               ret = tps65910_clear_bits(mfd,
+                               TPS65910_EN2_LDO_ASS + regoffs, bit_pos);
+       if (ret < 0) {
+               dev_err(mfd->dev,
+                       "Error in configuring external control EN2\n");
+               return ret;
+       }
+
+       /* External EN3 control for TPS65910 LDO only */
+       if ((tps65910_chip_id(mfd) == TPS65910) &&
+                       (id >= TPS65910_REG_VDIG1)) {
+               if (ext_sleep_config & TPS65910_SLEEP_CONTROL_EXT_INPUT_EN3)
+                       ret = tps65910_set_bits(mfd,
+                               TPS65910_EN3_LDO_ASS + regoffs, bit_pos);
+               else
+                       ret = tps65910_clear_bits(mfd,
+                               TPS65910_EN3_LDO_ASS + regoffs, bit_pos);
+               if (ret < 0) {
+                       dev_err(mfd->dev,
+                               "Error in configuring external control EN3\n");
+                       return ret;
+               }
+       }
+
+       /* Return if no external control is selected */
+       if (!(ext_sleep_config & EXT_SLEEP_CONTROL)) {
+               /* Clear all sleep controls */
+               ret = tps65910_clear_bits(mfd,
+                       TPS65910_SLEEP_KEEP_LDO_ON + regoffs, bit_pos);
+               if (!ret)
+                       ret = tps65910_clear_bits(mfd,
+                               TPS65910_SLEEP_SET_LDO_OFF + regoffs, bit_pos);
+               if (ret < 0)
+                       dev_err(mfd->dev,
+                               "Error in configuring SLEEP register\n");
+               return ret;
+       }
+
+       /*
+        * For regulator that has separate operational and sleep register make
+        * sure that operational is used and clear sleep register to turn
+        * regulator off when external control is inactive
+        */
+       if ((id == TPS65910_REG_VDD1) ||
+               (id == TPS65910_REG_VDD2) ||
+                       ((id == TPS65911_REG_VDDCTRL) &&
+                               (tps65910_chip_id(mfd) == TPS65911))) {
+               int op_reg_add = pmic->get_ctrl_reg(id) + 1;
+               int sr_reg_add = pmic->get_ctrl_reg(id) + 2;
+               int opvsel = tps65910_reg_read(pmic, op_reg_add);
+               int srvsel = tps65910_reg_read(pmic, sr_reg_add);
+               if (opvsel & VDD1_OP_CMD_MASK) {
+                       u8 reg_val = srvsel & VDD1_OP_SEL_MASK;
+                       ret = tps65910_reg_write(pmic, op_reg_add, reg_val);
+                       if (ret < 0) {
+                               dev_err(mfd->dev,
+                                       "Error in configuring op register\n");
+                               return ret;
+                       }
+               }
+               ret = tps65910_reg_write(pmic, sr_reg_add, 0);
+               if (ret < 0) {
+                       dev_err(mfd->dev, "Error in settting sr register\n");
+                       return ret;
+               }
+       }
+
+       ret = tps65910_clear_bits(mfd,
+                       TPS65910_SLEEP_KEEP_LDO_ON + regoffs, bit_pos);
+       if (!ret) {
+               if (ext_sleep_config & TPS65911_SLEEP_CONTROL_EXT_INPUT_SLEEP)
+                       ret = tps65910_set_bits(mfd,
+                               TPS65910_SLEEP_SET_LDO_OFF + regoffs, bit_pos);
+               else
+                       ret = tps65910_clear_bits(mfd,
+                               TPS65910_SLEEP_SET_LDO_OFF + regoffs, bit_pos);
+       }
+       if (ret < 0)
+               dev_err(mfd->dev,
+                       "Error in configuring SLEEP register\n");
+
+       return ret;
+}
+
 static __devinit int tps65910_probe(struct platform_device *pdev)
 {
        struct tps65910 *tps65910 = dev_get_drvdata(pdev->dev.parent);
@@ -885,8 +1139,6 @@ static __devinit int tps65910_probe(struct platform_device *pdev)
        if (!pmic_plat_data)
                return -EINVAL;
 
-       reg_data = pmic_plat_data->tps65910_pmic_init_data;
-
        pmic = kzalloc(sizeof(*pmic), GFP_KERNEL);
        if (!pmic)
                return -ENOMEM;
@@ -902,27 +1154,64 @@ static __devinit int tps65910_probe(struct platform_device *pdev)
        switch(tps65910_chip_id(tps65910)) {
        case TPS65910:
                pmic->get_ctrl_reg = &tps65910_get_ctrl_register;
+               pmic->num_regulators = ARRAY_SIZE(tps65910_regs);
+               pmic->ext_sleep_control = tps65910_ext_sleep_control;
                info = tps65910_regs;
                break;
        case TPS65911:
                pmic->get_ctrl_reg = &tps65911_get_ctrl_register;
+               pmic->num_regulators = ARRAY_SIZE(tps65911_regs);
+               pmic->ext_sleep_control = tps65911_ext_sleep_control;
                info = tps65911_regs;
                break;
        default:
                pr_err("Invalid tps chip version\n");
+               kfree(pmic);
                return -ENODEV;
        }
 
-       for (i = 0; i < TPS65910_NUM_REGULATOR; i++, info++, reg_data++) {
+       pmic->desc = kcalloc(pmic->num_regulators,
+                       sizeof(struct regulator_desc), GFP_KERNEL);
+       if (!pmic->desc) {
+               err = -ENOMEM;
+               goto err_free_pmic;
+       }
+
+       pmic->info = kcalloc(pmic->num_regulators,
+                       sizeof(struct tps_info *), GFP_KERNEL);
+       if (!pmic->info) {
+               err = -ENOMEM;
+               goto err_free_desc;
+       }
+
+       pmic->rdev = kcalloc(pmic->num_regulators,
+                       sizeof(struct regulator_dev *), GFP_KERNEL);
+       if (!pmic->rdev) {
+               err = -ENOMEM;
+               goto err_free_info;
+       }
+
+       for (i = 0; i < pmic->num_regulators && i < TPS65910_NUM_REGS;
+                       i++, info++) {
+
+               reg_data = pmic_plat_data->tps65910_pmic_init_data[i];
+
+               /* Regulator API handles empty constraints but not NULL
+                * constraints */
+               if (!reg_data)
+                       continue;
+
                /* Register the regulators */
                pmic->info[i] = info;
 
                pmic->desc[i].name = info->name;
                pmic->desc[i].id = i;
-               pmic->desc[i].n_voltages = info->table_len;
+               pmic->desc[i].n_voltages = info->n_voltages;
 
                if (i == TPS65910_REG_VDD1 || i == TPS65910_REG_VDD2) {
                        pmic->desc[i].ops = &tps65910_ops_dcdc;
+                       pmic->desc[i].n_voltages = VDD1_2_NUM_VOLT_FINE *
+                                                       VDD1_2_NUM_VOLT_COARSE;
                } else if (i == TPS65910_REG_VDD3) {
                        if (tps65910_chip_id(tps65910) == TPS65910)
                                pmic->desc[i].ops = &tps65910_ops_vdd3;
@@ -935,6 +1224,16 @@ static __devinit int tps65910_probe(struct platform_device *pdev)
                                pmic->desc[i].ops = &tps65911_ops;
                }
 
+               err = tps65910_set_ext_sleep_config(pmic, i,
+                               pmic_plat_data->regulator_ext_sleep_control[i]);
+               /*
+                * Failing on regulator for configuring externally control
+                * is not a serious issue, just throw warning.
+                */
+               if (err < 0)
+                       dev_warn(tps65910->dev,
+                               "Failed to initialise ext control config\n");
+
                pmic->desc[i].type = REGULATOR_VOLTAGE;
                pmic->desc[i].owner = THIS_MODULE;
 
@@ -945,7 +1244,7 @@ static __devinit int tps65910_probe(struct platform_device *pdev)
                                "failed to register %s regulator\n",
                                pdev->name);
                        err = PTR_ERR(rdev);
-                       goto err;
+                       goto err_unregister_regulator;
                }
 
                /* Save regulator for cleanup */
@@ -953,26 +1252,64 @@ static __devinit int tps65910_probe(struct platform_device *pdev)
        }
        return 0;
 
-err:
+err_unregister_regulator:
        while (--i >= 0)
                regulator_unregister(pmic->rdev[i]);
-
+       kfree(pmic->rdev);
+err_free_info:
+       kfree(pmic->info);
+err_free_desc:
+       kfree(pmic->desc);
+err_free_pmic:
        kfree(pmic);
        return err;
 }
 
 static int __devexit tps65910_remove(struct platform_device *pdev)
 {
-       struct tps65910_reg *tps65910_reg = platform_get_drvdata(pdev);
+       struct tps65910_reg *pmic = platform_get_drvdata(pdev);
        int i;
 
-       for (i = 0; i < TPS65910_NUM_REGULATOR; i++)
-               regulator_unregister(tps65910_reg->rdev[i]);
+       for (i = 0; i < pmic->num_regulators; i++)
+               regulator_unregister(pmic->rdev[i]);
 
-       kfree(tps65910_reg);
+       kfree(pmic->rdev);
+       kfree(pmic->info);
+       kfree(pmic->desc);
+       kfree(pmic);
        return 0;
 }
 
+static void tps65910_shutdown(struct platform_device *pdev)
+{
+       struct tps65910_reg *pmic = platform_get_drvdata(pdev);
+       int i;
+
+       /*
+        * Before bootloader jumps to kernel, it makes sure that required
+        * external control signals are in desired state so that given rails
+        * can be configure accordingly.
+        * If rails are configured to be controlled from external control
+        * then before shutting down/rebooting the system, the external
+        * control configuration need to be remove from the rails so that
+        * its output will be available as per register programming even
+        * if external controls are removed. This is require when the POR
+        * value of the control signals are not in active state and before
+        * bootloader initializes it, the system requires the rail output
+        * to be active for booting.
+        */
+       for (i = 0; i < pmic->num_regulators; i++) {
+               int err;
+               if (!pmic->rdev[i])
+                       continue;
+
+               err = tps65910_set_ext_sleep_config(pmic, i, 0);
+               if (err < 0)
+                       dev_err(&pdev->dev,
+                               "Error in clearing external control\n");
+       }
+}
+
 static struct platform_driver tps65910_driver = {
        .driver = {
                .name = "tps65910-pmic",
@@ -980,13 +1317,14 @@ static struct platform_driver tps65910_driver = {
        },
        .probe = tps65910_probe,
        .remove = __devexit_p(tps65910_remove),
+       .shutdown = tps65910_shutdown,
 };
 
 static int __init tps65910_init(void)
 {
        return platform_driver_register(&tps65910_driver);
 }
-subsys_initcall(tps65910_init);
+module_init(tps65910_init);
 
 static void __exit tps65910_cleanup(void)
 {
@@ -995,6 +1333,6 @@ static void __exit tps65910_cleanup(void)
 module_exit(tps65910_cleanup);
 
 MODULE_AUTHOR("Graeme Gregory <gg@slimlogic.co.uk>");
-MODULE_DESCRIPTION("TPS6507x voltage regulator driver");
+MODULE_DESCRIPTION("TPS65910/TPS65911 voltage regulator driver");
 MODULE_LICENSE("GPL v2");
 MODULE_ALIAS("platform:tps65910-pmic");
index a567a8e131e7f87aa0f0b2896ecbd279608b04a0..bfa8a408fb33e8bce7226884d7ee619fa117e522 100755 (executable)
@@ -1110,5 +1110,10 @@ config RTC_DRV_PUV3
 
          This drive can also be built as a module. If so, the module
          will be called rtc-puv3.
+config  TPS65910_RTC
+       tristate "tps65910 rtc for rk"
+       depends on MFD_TPS65910
+       help
+               enable tps65910 rtc for system
 
 endif # RTC_CLASS
index 3f5e0685673bfc2abafdef611d6a49ca88542b50..6d4c945e6b42bbde4d8c3b677ee2cfb1f5aba3ee 100755 (executable)
@@ -115,3 +115,4 @@ obj-$(CONFIG_RTC_DRV_WM8350)        += rtc-wm8350.o
 obj-$(CONFIG_RTC_DRV_X1205)    += rtc-x1205.o
 obj-$(CONFIG_RTC_HYM8563)      += rtc-HYM8563.o
 obj-$(CONFIG_RTC_M41T66)       += rtc-m41t66.o
+obj-$(CONFIG_TPS65910_RTC)  += rtc-tps65910.o
diff --git a/drivers/rtc/rtc-tps65910.c b/drivers/rtc/rtc-tps65910.c
new file mode 100755 (executable)
index 0000000..93290a1
--- /dev/null
@@ -0,0 +1,706 @@
+/*
+ * rtc-tps65910.c -- TPS65910 Real Time Clock interface
+ *
+ * Copyright (C) 2010 Mistral Solutions Pvt Ltd. <www.mistralsolutions.com>
+ * Author: Umesh K <umeshk@mistralsolutions.com>
+ *
+ * Based on rtc-twl.c
+ *
+ * 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/rtc.h>
+#include <linux/bcd.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/mfd/tps65910.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+
+#if 0
+#define DBG(x...)      printk(KERN_INFO x)
+#else
+#define DBG(x...)
+#endif
+
+/* RTC Definitions */
+/* RTC_CTRL_REG bitfields */
+#define BIT_RTC_CTRL_REG_STOP_RTC_M            0x01
+#define BIT_RTC_CTRL_REG_ROUND_30S_M           0x02
+#define BIT_RTC_CTRL_REG_AUTO_COMP_M           0x04
+#define BIT_RTC_CTRL_REG_MODE_12_24_M          0x08
+#define BIT_RTC_CTRL_REG_TEST_MODE_M           0x10
+#define BIT_RTC_CTRL_REG_SET_32_COUNTER_M      0x20
+#define BIT_RTC_CTRL_REG_GET_TIME_M            0x40
+#define BIT_RTC_CTRL_REG_RTC_V_OPT_M           0x80
+
+/* RTC_STATUS_REG bitfields */
+#define BIT_RTC_STATUS_REG_RUN_M               0x02
+#define BIT_RTC_STATUS_REG_1S_EVENT_M          0x04
+#define BIT_RTC_STATUS_REG_1M_EVENT_M          0x08
+#define BIT_RTC_STATUS_REG_1H_EVENT_M          0x10
+#define BIT_RTC_STATUS_REG_1D_EVENT_M          0x20
+#define BIT_RTC_STATUS_REG_ALARM_M             0x40
+#define BIT_RTC_STATUS_REG_POWER_UP_M          0x80
+
+/* RTC_INTERRUPTS_REG bitfields */
+#define BIT_RTC_INTERRUPTS_REG_EVERY_M         0x03
+#define BIT_RTC_INTERRUPTS_REG_IT_TIMER_M      0x04
+#define BIT_RTC_INTERRUPTS_REG_IT_ALARM_M      0x08
+
+/* DEVCTRL bitfields */
+#define BIT_RTC_PWDN                           0x40
+
+/* REG_SECONDS_REG through REG_YEARS_REG is how many registers? */
+#define ALL_TIME_REGS                          6
+
+/*
+ * Supports 1 byte read from TPS65910 RTC register.
+ */
+static int tps65910_rtc_read_u8(u8 *data, u8 reg)
+{
+       int ret;
+
+       ret = tps65910_i2c_read_u8(TPS65910_I2C_ID0, data, reg);
+
+       if (ret < 0)
+               pr_err("tps65910_rtc: Could not read TPS65910"
+                               "register %X - error %d\n", reg, ret);
+       return ret;
+}
+
+/*
+ * Supports 1 byte write to TPS65910 RTC registers.
+ */
+static int tps65910_rtc_write_u8(u8 data, u8 reg)
+{
+       int ret;
+
+       ret = tps65910_i2c_write_u8(TPS65910_I2C_ID0, data, reg);
+       if (ret < 0)
+               pr_err("tps65910_rtc: Could not write TPS65910"
+                               "register %X - error %d\n", reg, ret);
+       return ret;
+}
+
+/*
+ * Cache the value for timer/alarm interrupts register; this is
+ * only changed by callers holding rtc ops lock (or resume).
+ */
+static unsigned char rtc_irq_bits;
+
+/*
+ * Enable 1/second update and/or alarm interrupts.
+ */
+static int set_rtc_irq_bit(unsigned char bit)
+{
+       unsigned char val;
+       int ret;
+
+       val = rtc_irq_bits | bit;
+       val |= bit;
+       ret = tps65910_rtc_write_u8(val, TPS65910_REG_RTC_INTERRUPTS);
+       if (ret == 0)
+               rtc_irq_bits = val;
+
+       return ret;
+}
+
+/*
+ * Disable update and/or alarm interrupts.
+ */
+static int mask_rtc_irq_bit(unsigned char bit)
+{
+       unsigned char val;
+       int ret;
+
+       val = rtc_irq_bits & ~bit;
+       ret = tps65910_rtc_write_u8(val, TPS65910_REG_RTC_INTERRUPTS);
+       if (ret == 0)
+               rtc_irq_bits = val;
+
+       return ret;
+}
+
+static int tps65910_rtc_alarm_irq_enable(struct device *dev, unsigned enabled)
+{
+       int ret;
+
+       if (enabled)
+               ret = set_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_ALARM_M);
+       else
+               ret = mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_ALARM_M);
+
+       return ret;
+}
+
+static int tps65910_rtc_update_irq_enable(struct device *dev, unsigned enabled)
+{
+       int ret;
+
+       if (enabled)
+               ret = set_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M);
+       else
+               ret = mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M);
+
+       return ret;
+}
+
+#if 1 /* Debugging periodic interrupts */
+/*
+ * We will just handle setting the frequency and make use the framework for
+ * reading the periodic interupts.
+ *
+ * @freq: Current periodic IRQ freq:
+ * bit 0: every second
+ * bit 1: every minute
+ * bit 2: every hour
+ * bit 3: every day
+ */
+
+static int tps65910_rtc_irq_set_freq(struct device *dev, int freq)
+{
+       struct rtc_device *rtc = dev_get_drvdata(dev);
+
+       if (freq < 0 || freq > 3)
+               return -EINVAL;
+
+       rtc->irq_freq = freq;
+       /* set rtc irq freq to user defined value */
+       set_rtc_irq_bit(freq);
+
+       return 0;
+}
+#endif
+
+/*
+ * Gets current TPS65910 RTC time and date parameters.
+ *
+ * The RTC's time/alarm representation is not what gmtime(3) requires
+ * Linux to use:
+ *
+ *  - Months are 1..12 vs Linux 0-11
+ *  - Years are 0..99 vs Linux 1900..N (we assume 21st century)
+ */
+static int tps65910_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+       unsigned char rtc_data[ALL_TIME_REGS + 1];
+       int ret;
+       u8 save_control;
+
+       tps65910_rtc_read_u8(&save_control, TPS65910_REG_RTC_CTRL);
+       ret = tps65910_rtc_read_u8(&save_control, TPS65910_REG_RTC_CTRL);
+       if (ret < 0)
+               return ret;
+
+       save_control &= ~BIT_RTC_CTRL_REG_RTC_V_OPT_M;
+
+       ret = tps65910_rtc_write_u8(save_control, TPS65910_REG_RTC_CTRL);
+       if (ret < 0)
+               return ret;
+
+       ret = tps65910_rtc_read_u8(&rtc_data[0], TPS65910_REG_SECONDS);
+       if (ret < 0) {
+               dev_err(dev, "rtc_read_time error %d\n", ret);
+               return ret;
+       }
+       ret = tps65910_rtc_read_u8(&rtc_data[1], TPS65910_REG_MINUTES);
+       if (ret < 0) {
+               dev_err(dev, "rtc_read_time error %d\n", ret);
+               return ret;
+       }
+       ret = tps65910_rtc_read_u8(&rtc_data[2], TPS65910_REG_HOURS);
+       if (ret < 0) {
+               dev_err(dev, "rtc_read_time error %d\n", ret);
+               return ret;
+       }
+       ret = tps65910_rtc_read_u8(&rtc_data[3], TPS65910_REG_DAYS);
+       if (ret < 0) {
+               dev_err(dev, "rtc_read_time error %d\n", ret);
+               return ret;
+       }
+       ret = tps65910_rtc_read_u8(&rtc_data[4], TPS65910_REG_MONTHS);
+       if (ret < 0) {
+               dev_err(dev, "rtc_read_time error %d\n", ret);
+               return ret;
+       }
+       ret = tps65910_rtc_read_u8(&rtc_data[5], TPS65910_REG_YEARS);
+       if (ret < 0) {
+               dev_err(dev, "rtc_read_time error %d\n", ret);
+               return ret;
+       }
+
+       tm->tm_sec = bcd2bin(rtc_data[0]);
+       tm->tm_min = bcd2bin(rtc_data[1]);
+       tm->tm_hour = bcd2bin(rtc_data[2]);
+       tm->tm_mday = bcd2bin(rtc_data[3]);
+       tm->tm_mon = bcd2bin(rtc_data[4]) - 1;
+       tm->tm_year = bcd2bin(rtc_data[5]) + 100;
+
+       DBG("%s [%d]tm_wday=%d \n",__FUNCTION__,__LINE__,tm->tm_wday);
+       DBG("%s [%d]tm_sec=%d \n",__FUNCTION__,__LINE__,tm->tm_sec);
+       DBG("%s [%d]tm_min=%d \n",__FUNCTION__,__LINE__,tm->tm_min);
+       DBG("%s [%d]tm_hour=%d \n",__FUNCTION__,__LINE__,tm->tm_hour);
+       DBG("%s [%d]tm_mday=%d \n",__FUNCTION__,__LINE__,tm->tm_mday);
+       DBG("%s [%d]tm_mon=%d \n",__FUNCTION__,__LINE__,tm->tm_mon);
+       DBG("%s [%d]tm_year=%d \n",__FUNCTION__,__LINE__,tm->tm_year);
+
+       return ret;
+}
+
+static int tps65910_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+       unsigned char save_control;
+       unsigned char rtc_data[ALL_TIME_REGS + 1];
+       int ret;
+
+       DBG("%s [%d]tm_wday=%d \n",__FUNCTION__,__LINE__,tm->tm_wday);
+       DBG("%s [%d]tm_sec=%d \n",__FUNCTION__,__LINE__,tm->tm_sec);
+       DBG("%s [%d]tm_min=%d \n",__FUNCTION__,__LINE__,tm->tm_min);
+       DBG("%s [%d]tm_hour=%d \n",__FUNCTION__,__LINE__,tm->tm_hour);
+       DBG("%s [%d]tm_mday=%d \n",__FUNCTION__,__LINE__,tm->tm_mday);
+       DBG("%s [%d]tm_mon=%d \n",__FUNCTION__,__LINE__,tm->tm_mon);
+       DBG("%s [%d]tm_year=%d \n",__FUNCTION__,__LINE__,tm->tm_year);
+
+       rtc_data[1] = bin2bcd(tm->tm_sec);
+       rtc_data[2] = bin2bcd(tm->tm_min);
+       rtc_data[3] = bin2bcd(tm->tm_hour);
+       rtc_data[4] = bin2bcd(tm->tm_mday);
+       rtc_data[5] = bin2bcd(tm->tm_mon + 1);
+       rtc_data[6] = bin2bcd(tm->tm_year - 100);
+
+       /*Dummy read*/
+       ret = tps65910_rtc_read_u8(&save_control, TPS65910_REG_RTC_CTRL);
+
+       /* Stop RTC while updating the TC registers */
+       ret = tps65910_rtc_read_u8(&save_control, TPS65910_REG_RTC_CTRL);
+       if (ret < 0)
+               goto out;
+
+       save_control &= ~BIT_RTC_CTRL_REG_STOP_RTC_M;
+
+       tps65910_rtc_write_u8(save_control, TPS65910_REG_RTC_CTRL);
+
+       /* update all the time registers in one shot */
+       ret = tps65910_rtc_write_u8(rtc_data[1], TPS65910_REG_SECONDS);
+       if (ret < 0) {
+               dev_err(dev, "rtc_write_time error %d\n", ret);
+               return ret;
+       }
+       ret = tps65910_rtc_write_u8(rtc_data[2], TPS65910_REG_MINUTES);
+       if (ret < 0) {
+               dev_err(dev, "rtc_write_time error %d\n", ret);
+               return ret;
+       }
+       ret = tps65910_rtc_write_u8(rtc_data[3], TPS65910_REG_HOURS);
+       if (ret < 0) {
+               dev_err(dev, "rtc_write_time error %d\n", ret);
+               return ret;
+       }
+       ret = tps65910_rtc_write_u8(rtc_data[4], TPS65910_REG_DAYS);
+       if (ret < 0) {
+               dev_err(dev, "rtc_write_time error %d\n", ret);
+               return ret;
+       }
+       ret = tps65910_rtc_write_u8(rtc_data[5], TPS65910_REG_MONTHS);
+       if (ret < 0) {
+               dev_err(dev, "rtc_write_time error %d\n", ret);
+               return ret;
+       }
+       ret = tps65910_rtc_write_u8(rtc_data[6], TPS65910_REG_YEARS);
+       if (ret < 0) {
+               dev_err(dev, "rtc_write_time error %d\n", ret);
+               return ret;
+       }
+
+       /*Dummy read*/
+       ret = tps65910_rtc_read_u8(&save_control, TPS65910_REG_RTC_CTRL);
+
+       ret = tps65910_rtc_read_u8(&save_control, TPS65910_REG_RTC_CTRL);
+       if (ret < 0)
+               goto out;
+       /* Start back RTC */
+       save_control |= BIT_RTC_CTRL_REG_STOP_RTC_M;
+       ret = tps65910_rtc_write_u8(save_control, TPS65910_REG_RTC_CTRL);
+
+out:
+       return ret;
+}
+
+/*
+ * Gets current TPS65910 RTC alarm time.
+ */
+static int tps65910_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
+{
+       unsigned char rtc_data[ALL_TIME_REGS + 1];
+       int ret;
+
+       ret = tps65910_rtc_read_u8(&rtc_data[0], TPS65910_REG_ALARM_SECONDS);
+       if (ret < 0) {
+               dev_err(dev, "rtc_read_time error %d\n", ret);
+               return ret;
+       }
+       ret = tps65910_rtc_read_u8(&rtc_data[1], TPS65910_REG_ALARM_MINUTES);
+       if (ret < 0) {
+               dev_err(dev, "rtc_read_time error %d\n", ret);
+               return ret;
+       }
+       ret = tps65910_rtc_read_u8(&rtc_data[2], TPS65910_REG_ALARM_HOURS);
+       if (ret < 0) {
+               dev_err(dev, "rtc_read_time error %d\n", ret);
+               return ret;
+       }
+       ret = tps65910_rtc_read_u8(&rtc_data[3], TPS65910_REG_ALARM_DAYS);
+       if (ret < 0) {
+               dev_err(dev, "rtc_read_time error %d\n", ret);
+               return ret;
+       }
+       ret = tps65910_rtc_read_u8(&rtc_data[4], TPS65910_REG_ALARM_MONTHS);
+       if (ret < 0) {
+               dev_err(dev, "rtc_read_time error %d\n", ret);
+               return ret;
+       }
+       ret = tps65910_rtc_read_u8(&rtc_data[5], TPS65910_REG_ALARM_YEARS);
+       if (ret < 0) {
+               dev_err(dev, "rtc_read_time error %d\n", ret);
+               return ret;
+       }
+
+       /* some of these fields may be wildcard/"match all" */
+       alm->time.tm_sec = bcd2bin(rtc_data[0]);
+       alm->time.tm_min = bcd2bin(rtc_data[1]);
+       alm->time.tm_hour = bcd2bin(rtc_data[2]);
+       alm->time.tm_mday = bcd2bin(rtc_data[3]);
+       alm->time.tm_mon = bcd2bin(rtc_data[4]) - 1;
+       alm->time.tm_year = bcd2bin(rtc_data[5]) + 100;
+
+       /* report cached alarm enable state */
+       if (rtc_irq_bits & BIT_RTC_INTERRUPTS_REG_IT_ALARM_M)
+               alm->enabled = 1;
+
+       return ret;
+}
+
+static int tps65910_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
+{
+       unsigned char alarm_data[ALL_TIME_REGS + 1];
+       int ret;
+
+       ret = tps65910_rtc_alarm_irq_enable(dev, 0);
+       if (ret)
+               goto out;
+
+       alarm_data[1] = bin2bcd(alm->time.tm_sec);
+       alarm_data[2] = bin2bcd(alm->time.tm_min);
+       alarm_data[3] = bin2bcd(alm->time.tm_hour);
+       alarm_data[4] = bin2bcd(alm->time.tm_mday);
+       alarm_data[5] = bin2bcd(alm->time.tm_mon + 1);
+       alarm_data[6] = bin2bcd(alm->time.tm_year - 100);
+
+       /* update all the alarm registers in one shot */
+       ret = tps65910_rtc_write_u8(alarm_data[1], TPS65910_REG_ALARM_SECONDS);
+       if (ret < 0) {
+               dev_err(dev, "rtc_write_time error %d\n", ret);
+               return ret;
+       }
+       ret = tps65910_rtc_write_u8(alarm_data[2], TPS65910_REG_ALARM_MINUTES);
+       if (ret < 0) {
+               dev_err(dev, "rtc_write_time error %d\n", ret);
+               return ret;
+       }
+       ret = tps65910_rtc_write_u8(alarm_data[3], TPS65910_REG_ALARM_HOURS);
+       if (ret < 0) {
+               dev_err(dev, "rtc_write_time error %d\n", ret);
+               return ret;
+       }
+       ret = tps65910_rtc_write_u8(alarm_data[4], TPS65910_REG_ALARM_DAYS);
+       if (ret < 0) {
+               dev_err(dev, "rtc_write_time error %d\n", ret);
+               return ret;
+       }
+       ret = tps65910_rtc_write_u8(alarm_data[5], TPS65910_REG_ALARM_MONTHS);
+       if (ret < 0) {
+               dev_err(dev, "rtc_write_time error %d\n", ret);
+               return ret;
+       }
+       ret = tps65910_rtc_write_u8(alarm_data[6], TPS65910_REG_ALARM_YEARS);
+       if (ret < 0) {
+               dev_err(dev, "rtc_write_time error %d\n", ret);
+               return ret;
+       }
+
+       if (alm->enabled)
+               ret = tps65910_rtc_alarm_irq_enable(dev, 1);
+out:
+       return ret;
+}
+
+
+struct work_struct rtc_wq;
+unsigned long rtc_events;
+struct rtc_device *global_rtc;
+
+void tps65910_rtc_work(void  *data)
+{
+       int res;
+       u8 rd_reg;
+       unsigned long events = 0;
+
+       DBG("Enter::%s %d\n",__FUNCTION__,__LINE__);
+
+       res = tps65910_rtc_read_u8(&rd_reg, TPS65910_REG_INT_STS);
+
+       if (res < 0)
+               goto out;
+       /*
+        * Figure out source of interrupt: ALARM or TIMER in RTC_STATUS_REG.
+        * only one (ALARM or RTC) interrupt source may be enabled
+        * at time, we also could check our results
+        * by reading RTS_INTERRUPTS_REGISTER[IT_TIMER,IT_ALARM]
+        */
+       if (rd_reg & TPS65910_RTC_ALARM_IT) {
+               res = tps65910_rtc_write_u8(rd_reg | TPS65910_RTC_ALARM_IT,
+                               TPS65910_REG_INT_STS);
+               if (res < 0)
+                       goto out;
+
+               /*Dummy read -- mandatory for status register*/
+               res = tps65910_rtc_read_u8(&rd_reg, TPS65910_REG_RTC_STATUS);
+               mdelay(100);
+               res = tps65910_rtc_read_u8(&rd_reg, TPS65910_REG_RTC_STATUS);
+               res = tps65910_rtc_write_u8(rd_reg, TPS65910_REG_RTC_STATUS);
+
+               rtc_events |= RTC_IRQF | RTC_AF;
+       } else if (rd_reg & TPS65910_RTC_PERIOD_IT) {
+               res = tps65910_rtc_write_u8(rd_reg | TPS65910_RTC_PERIOD_IT,
+                               TPS65910_REG_INT_STS);
+               if (res < 0)
+                       goto out;
+
+               /*Dummy read -- mandatory for status register*/
+               res = tps65910_rtc_read_u8(&rd_reg, TPS65910_REG_RTC_STATUS);
+               mdelay(100);
+               res = tps65910_rtc_read_u8(&rd_reg, TPS65910_REG_RTC_STATUS);
+               rd_reg &= 0xC3;
+               res = tps65910_rtc_write_u8(rd_reg, TPS65910_REG_RTC_STATUS);
+               rtc_events |= RTC_IRQF | RTC_UF;
+       }
+out:
+       /* Notify RTC core on event */
+       events = rtc_events;
+       rtc_update_irq(global_rtc, 1, events);
+}
+
+static struct rtc_class_ops tps65910_rtc_ops = {
+       .read_time      = tps65910_rtc_read_time,
+       .set_time       = tps65910_rtc_set_time,
+       .read_alarm     = tps65910_rtc_read_alarm,
+       .set_alarm      = tps65910_rtc_set_alarm,
+       .alarm_irq_enable = tps65910_rtc_alarm_irq_enable,
+//     .update_irq_enable = tps65910_rtc_update_irq_enable,
+//     .irq_set_freq   = tps65910_rtc_irq_set_freq,
+};
+
+static int __devinit tps65910_rtc_probe(struct platform_device *pdev)
+{
+       struct rtc_device *rtc;
+       int ret = 0, stop_run = 0;
+       u8 rd_reg;
+       struct rtc_time tm_def = {      //      2011.1.1 12:00:00 Saturday
+               .tm_wday = 6,
+               .tm_year = 111,
+               .tm_mon = 0,
+               .tm_mday = 1,
+               .tm_hour = 12,
+               .tm_min = 0,
+               .tm_sec = 0,
+       };
+
+       rtc = rtc_device_register(pdev->name,
+                       &pdev->dev, &tps65910_rtc_ops, THIS_MODULE);
+
+       if (IS_ERR(rtc)) {
+               ret = PTR_ERR(rtc);
+               dev_err(&pdev->dev, "can't register TPS65910 RTC device,\
+                                        err %ld\n", PTR_ERR(rtc));
+               goto out0;
+
+       }
+       printk(KERN_INFO "TPS65910 RTC device successfully registered\n");
+
+       platform_set_drvdata(pdev, rtc);
+       /* Take rtc out of reset */
+       tps65910_rtc_read_u8(&rd_reg, TPS65910_REG_DEVCTRL);
+       rd_reg &= ~BIT_RTC_PWDN;
+       ret = tps65910_rtc_write_u8(rd_reg, TPS65910_REG_DEVCTRL);
+
+       /* Dummy read to ensure that the register gets updated.
+        * Please refer tps65910 TRM table:25 for details
+        */
+       stop_run = 0;
+       ret = tps65910_rtc_read_u8(&rd_reg, TPS65910_REG_RTC_STATUS);
+       if (ret < 0) {
+               printk(KERN_ERR "TPS65910 RTC STATUS REG READ FAILED\n");
+               goto out1;
+       }
+
+       if (rd_reg & BIT_RTC_STATUS_REG_POWER_UP_M) {
+               dev_warn(&pdev->dev, "Power up reset detected.\n");
+               //      cwz:if rtc power up reset, set default time.
+               printk(KERN_INFO "TPS65910 RTC set to default time\n");
+               tps65910_rtc_set_time(&rtc->dev, &tm_def);
+       }
+       if (!(rd_reg & BIT_RTC_STATUS_REG_RUN_M)) {
+               dev_warn(&pdev->dev, "RTC stop run.\n");
+               stop_run = 1;
+       }
+       if (rd_reg & BIT_RTC_STATUS_REG_ALARM_M)
+               dev_warn(&pdev->dev, "Pending Alarm interrupt detected.\n");
+
+       /* Clear RTC Power up reset and pending alarm interrupts */
+       ret = tps65910_rtc_write_u8(rd_reg, TPS65910_REG_RTC_STATUS);
+       if (ret < 0)
+               goto out1;
+
+       ret = tps65910_rtc_read_u8(&rd_reg, TPS65910_REG_INT_STS);
+       if (ret < 0) {
+               printk(KERN_ERR "TPS65910 RTC STATUS REG READ FAILED\n");
+               goto out1;
+       }
+
+       if (rd_reg & 0x40) {
+               printk(KERN_INFO "pending alarm interrupt!!! clearing!!!");
+               tps65910_rtc_write_u8(rd_reg, TPS65910_REG_INT_STS);
+       }
+
+       global_rtc = rtc;
+
+       /* Link RTC IRQ handler to TPS65910 Core */
+       //tps65910_add_irq_work(TPS65910_RTC_ALARM_IRQ, tps65910_rtc_work);
+       //tps65910_add_irq_work(TPS65910_RTC_PERIOD_IRQ, tps65910_rtc_work);
+
+       /* Check RTC module status, Enable if it is off */
+       if (stop_run) {
+               dev_info(&pdev->dev, "Enabling TPS65910-RTC.\n");
+               //      cwz:if rtc stop, set default time, then enable rtc
+               printk(KERN_INFO "TPS65910 RTC set to default time\n");
+               tps65910_rtc_set_time(&rtc->dev, &tm_def);
+               ret = tps65910_rtc_read_u8(&rd_reg, TPS65910_REG_RTC_CTRL);
+               if (ret < 0)
+                       goto out1;
+
+               rd_reg |= BIT_RTC_CTRL_REG_STOP_RTC_M;
+               ret = tps65910_rtc_write_u8(rd_reg, TPS65910_REG_RTC_CTRL);
+               if (ret < 0)
+                       goto out1;
+       }
+
+       /* init cached IRQ enable bits */
+       ret = tps65910_rtc_read_u8(&rtc_irq_bits, TPS65910_REG_RTC_INTERRUPTS);
+       if (ret < 0)
+               goto out1;
+
+       tps65910_rtc_write_u8(0x3F, TPS65910_REG_INT_MSK);
+       return ret;
+
+out1:
+       rtc_device_unregister(rtc);
+out0:
+       return ret;
+}
+
+/*
+ * Disable all TPS65910 RTC module interrupts.
+ * Sets status flag to free.
+ */
+static int __devexit tps65910_rtc_remove(struct platform_device *pdev)
+{
+       /* leave rtc running, but disable irqs */
+       struct rtc_device *rtc = platform_get_drvdata(pdev);
+       int irq = platform_get_irq(pdev, 0);
+
+       mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_ALARM_M);
+       mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M);
+
+
+       free_irq(irq, rtc);
+
+       rtc_device_unregister(rtc);
+       platform_set_drvdata(pdev, NULL);
+       return 0;
+}
+
+static void tps65910_rtc_shutdown(struct platform_device *pdev)
+{
+       /* mask timer interrupts, but leave alarm interrupts on to enable
+        * power-on when alarm is triggered
+        */
+       mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M);
+}
+
+#ifdef CONFIG_PM
+
+static unsigned char irqstat;
+
+static
+int tps65910_rtc_suspend(struct platform_device *pdev, pm_message_t state)
+{
+       irqstat = rtc_irq_bits;
+       mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M);
+       return 0;
+}
+
+static int tps65910_rtc_resume(struct platform_device *pdev)
+{
+       set_rtc_irq_bit(irqstat);
+       return 0;
+}
+
+#else
+#define tps65910_rtc_suspend NULL
+#define tps65910_rtc_resume  NULL
+#endif
+
+
+static struct platform_driver tps65910rtc_driver = {
+       .probe          = tps65910_rtc_probe,
+       .remove         = __devexit_p(tps65910_rtc_remove),
+       .shutdown       = tps65910_rtc_shutdown,
+       .suspend        = tps65910_rtc_suspend,
+       .resume         = tps65910_rtc_resume,
+       .driver         = {
+               .owner  = THIS_MODULE,
+               .name   = "tps65910_rtc",
+       },
+};
+
+//extern int board_wm831x ;
+static int __init tps65910_rtc_init(void)
+{
+//     if (board_wm831x == 1)
+//     {
+//             printk("board with wm831 not tps65910,so skip register tps65910\n");
+//             return 0;
+//     }
+
+       return platform_driver_register(&tps65910rtc_driver);
+}
+module_init(tps65910_rtc_init);
+
+static void __exit tps65910_rtc_exit(void)
+{
+       platform_driver_unregister(&tps65910rtc_driver);
+}
+module_exit(tps65910_rtc_exit);
+
+MODULE_ALIAS("platform:tps65910_rtc");
+MODULE_AUTHOR("cwz  <cwz@rockchips.com");
+MODULE_LICENSE("GPL");
index 8bb85b930c0783a5fb697a1cfa3daf3b7cd49254..c2276d67c28ae68e14e78a4a72013c71db2ceb17 100644 (file)
@@ -17,6 +17,8 @@
 #ifndef __LINUX_MFD_TPS65910_H
 #define __LINUX_MFD_TPS65910_H
 
+#include <linux/gpio.h>
+
 /* TPS chip id list */
 #define TPS65910                       0
 #define TPS65911                       1
 #define REGULATOR_LDO                  0
 #define REGULATOR_DCDC                 1
 
+/* I2C Slave Address 7-bit */
+#define TPS65910_I2C_ID0        0x2D /* general-purpose */
+#define TPS65910_I2C_ID1        0x12 /* Smart Reflex */
+
 /*
  * List of registers for component TPS65910
  *
 
 
 /*Registers VDD1, VDD2 voltage values definitions */
-#define VDD1_2_NUM_VOLTS                               73
+#define VDD1_2_NUM_VOLT_FINE                           73
+#define VDD1_2_NUM_VOLT_COARSE                         3
 #define VDD1_2_MIN_VOLT                                        6000
 #define VDD1_2_OFFSET                                  125
 
 #define LDO1_SEL_MASK                                  0xFC
 #define LDO3_SEL_MASK                                  0x7C
 #define LDO_MIN_VOLT                                   1000
-#define LDO_MAX_VOLT                                   3300;
+#define LDO_MAX_VOLT                                   3300
 
 
 /*Register VDIG1  (0x80) register.RegisterDescription */
 
 
 /*Register GPIO  (0x80) register.RegisterDescription */
+#define GPIO_SLEEP_MASK                         0x80
+#define GPIO_SLEEP_SHIFT                        7
 #define GPIO_DEB_MASK                           0x10
 #define GPIO_DEB_SHIFT                          4
 #define GPIO_PUEN_MASK                          0x08
 #define TPS65910_GPIO_STS                              BIT(1)
 #define TPS65910_GPIO_SET                              BIT(0)
 
-/**
- * struct tps65910_board
- * Board platform data may be used to initialize regulators.
+/* Max number of TPS65910/11 GPIOs */
+#define TPS65910_NUM_GPIO                              6
+#define TPS65911_NUM_GPIO                              9
+#define TPS6591X_MAX_NUM_GPIO                          9
+
+/* Regulator Index Definitions */
+#define TPS65910_REG_VRTC                              0
+#define TPS65910_REG_VIO                               1
+#define TPS65910_REG_VDD1                              2
+#define TPS65910_REG_VDD2                              3
+#define TPS65910_REG_VDD3                              4
+#define TPS65910_REG_VDIG1                             5
+#define TPS65910_REG_VDIG2                             6
+#define TPS65910_REG_VPLL                              7
+#define TPS65910_REG_VDAC                              8
+#define TPS65910_REG_VAUX1                             9
+#define TPS65910_REG_VAUX2                             10
+#define TPS65910_REG_VAUX33                            11
+#define TPS65910_REG_VMMC                              12
+
+#define TPS65911_REG_VDDCTRL                           4
+#define TPS65911_REG_LDO1                              5
+#define TPS65911_REG_LDO2                              6
+#define TPS65911_REG_LDO3                              7
+#define TPS65911_REG_LDO4                              8
+#define TPS65911_REG_LDO5                              9
+#define TPS65911_REG_LDO6                              10
+#define TPS65911_REG_LDO7                              11
+#define TPS65911_REG_LDO8                              12
+
+/* Max number of TPS65910/11 regulators */
+#define TPS65910_NUM_REGS                              13
+
+/* External sleep controls through EN1/EN2/EN3/SLEEP inputs */
+#define TPS65910_SLEEP_CONTROL_EXT_INPUT_EN1           0x1
+#define TPS65910_SLEEP_CONTROL_EXT_INPUT_EN2           0x2
+#define TPS65910_SLEEP_CONTROL_EXT_INPUT_EN3           0x4
+#define TPS65911_SLEEP_CONTROL_EXT_INPUT_SLEEP         0x8
+
+
+
+
+/*
+ * ----------------------------------------------------------------------------
+ * Registers, all 8 bits
+ * ----------------------------------------------------------------------------
  */
+#define        TPS65910_REG_SECONDS            0x00
+#define TPS65910_REG_MINUTES           0x01
+#define TPS65910_REG_HOURS             0x02
+#define TPS65910_REG_DAYS              0x03
+#define TPS65910_REG_MONTHS            0x04
+#define TPS65910_REG_YEARS             0x05
+#define TPS65910_REG_WEEKS             0x06
+#define TPS65910_REG_ALARM_SECONDS     0x08
+#define TPS65910_REG_ALARM_MINUTES     0x09
+#define TPS65910_REG_ALARM_HOURS       0x0A
+#define TPS65910_REG_ALARM_DAYS                0x0B
+#define TPS65910_REG_ALARM_MONTHS      0x0C
+#define TPS65910_REG_ALARM_YEARS       0x0D
+
+#define TPS65910_REG_RTC_CTRL          0x10
+#define TPS65910_REG_RTC_STATUS                0x11
+#define TPS65910_REG_RTC_INTERRUPTS    0x12
+#define TPS65910_REG_RTC_COMP_LSB      0x13
+#define TPS65910_REG_RTC_COMP_MSB      0x14
+#define TPS65910_REG_RTC_RES_PROG      0x15
+#define TPS65910_REG_RTC_RESET_STATUS  0x16
+#define TPS65910_REG_BCK1              0x17
+#define TPS65910_REG_BCK2              0x18
+#define TPS65910_REG_BCK3              0x19
+#define TPS65910_REG_BCK4              0x1A
+#define TPS65910_REG_BCK5              0x1B
+#define TPS65910_REG_PUADEN            0x1C
+#define TPS65910_REG_REF               0x1D
+
+#define TPS65910_REG_THERM             0x38
+#define TPS65910_REG_BBCH              0x39
+
+#define TPS65910_REG_DCDCCTRL          0x3E
+#define TPS65910_REG_DEVCTRL           0x3F
+#define TPS65910_REG_DEVCTRL2          0x40
+#define TPS65910_REG_SLEEP_KEEP_LDO_ON 0x41
+#define TPS65910_REG_SLEEP_KEEP_RES_ON 0x42
+#define TPS65910_REG_SLEEP_SET_LDO_OFF 0x43
+#define TPS65910_REG_SLEEP_SET_RES_OFF 0x44
+#define TPS65910_REG_EN1_LDO_ASS       0x45
+#define TPS65910_REG_EN1_SMPS_ASS      0x46
+#define TPS65910_REG_EN2_LDO_ASS       0x47
+#define TPS65910_REG_EN2_SMPS_ASS      0x48
+#define TPS65910_REG_EN3_LDO_ASS       0x49
+#define TPS65910_REG_SPARE             0x4A
+
+#define TPS65910_REG_INT_STS           0x50
+#define TPS65910_REG_INT_MSK           0x51
+#define TPS65910_REG_INT_STS2          0x52
+#define TPS65910_REG_INT_MSK2          0x53
+#define TPS65910_REG_INT_STS3          0x54
+#define TPS65910_REG_INT_MSK3          0x55
+
+#define TPS65910_REG_GPIO0             0x60
+
+#define TPS65910_REG_JTAGVERNUM                0x80
+
+/* TPS65910 GPIO Specific flags */
+#define TPS65910_GPIO_INT_FALLING      0
+#define TPS65910_GPIO_INT_RISING       1
+
+#define TPS65910_DEBOUNCE_91_5_MS      0
+#define TPS65910_DEBOUNCE_150_MS       1
+
+#define TPS65910_GPIO_PUDIS            (1 << 3)
+#define TPS65910_GPIO_CFG_OUTPUT       (1 << 2)
+
+
+
+/* TPS65910 Interrupt events */
+
+/* RTC Driver */
+#define TPS65910_RTC_ALARM_IT          0x80
+#define TPS65910_RTC_PERIOD_IT         0x40
+
+/*Core Driver */
+#define TPS65910_HOT_DIE_IT            0x20
+#define TPS65910_PWRHOLD_IT            0x10
+#define TPS65910_PWRON_LP_IT           0x08
+#define TPS65910_PWRON_IT              0x04
+#define TPS65910_VMBHI_IT              0x02
+#define TPS65910_VMBGCH_IT             0x01
+
+/* GPIO driver */
+#define TPS65910_GPIO_F_IT             0x02
+#define TPS65910_GPIO_R_IT             0x01
+
+
+#define TPS65910_VRTC_OFFMASK          (1<<3)
+
+/* Back-up battery charger control */
+#define TPS65910_BBCHEN                        0x01
+
+/* Back-up battery charger voltage */
+#define TPS65910_BBSEL_3P0             0x00
+#define TPS65910_BBSEL_2P52            0x02
+#define TPS65910_BBSEL_3P15            0x04
+#define TPS65910_BBSEL_VBAT            0x06
+
+/* DEVCTRL_REG flags */
+#define TPS65910_RTC_PWDNN             0x40
+#define TPS65910_CK32K_CTRL            0x20
+#define TPS65910_SR_CTL_I2C_SEL        0x10
+#define TPS65910_DEV_OFF_RST           0x08
+#define TPS65910_DEV_ON                        0x04
+#define TPS65910_DEV_SLP               0x02
+#define TPS65910_DEV_OFF               0x01
+
+/* DEVCTRL2_REG flags */
+#define TPS65910_DEV2_TSLOT_LENGTH     0x30
+#define TPS65910_DEV2_SLEEPSIG_POL     0x08
+#define TPS65910_DEV2_PWON_LP_OFF      0x04
+#define TPS65910_DEV2_PWON_LP_RST      0x02
+#define TPS65910_DEV2_IT_POL           0x01
+
+/* Number of step-down/up converters available */
+#define TPS65910_NUM_DCDC              4
+
+/* Number of LDO voltage regulators  available */
+#define TPS65910_NUM_LDO               9
+
+/* Number of total regulators available */
+#define TPS65910_NUM_REGULATOR  (TPS65910_NUM_DCDC + TPS65910_NUM_LDO)
+
+
+/* Regulator Supply state */
+#define SUPPLY_STATE_FLAG              0x03
+/* OFF States */
+#define TPS65910_REG_OFF_00            0x00
+#define TPS65910_REG_OFF_10            0x02
+/* OHP - on High Power */
+#define TPS65910_REG_OHP               0x01
+/* OLP - on Low Power */
+#define TPS65910_REG_OLP               0x03
+
+#define TPS65910_MAX_IRQS              10
+#define TPS65910_VMBDCH_IRQ            0
+#define TPS65910_VMBHI_IRQ             1
+#define TPS65910_PWRON_IRQ             2
+#define TPS65910_PWRON_LP_IRQ          3
+#define TPS65910_PWRHOLD_IRQ           4
+#define TPS65910_HOTDIE_IRQ            5
+#define TPS65910_RTC_ALARM_IRQ         6
+#define TPS65910_RTC_PERIOD_IRQ        7
+#define TPS65910_GPIO0_R_IRQ           8
+#define TPS65910_GPIO0_F_IRQ           9
 
-struct tps65910_board {
-       int gpio_base;
-       int irq;
-       int irq_base;
-       int vmbch_threshold;
-       int vmbch2_threshold;
-       struct regulator_init_data *tps65910_pmic_init_data;
-};
 
 /**
  * struct tps65910 - tps65910 sub-driver chip access routines
@@ -760,6 +950,7 @@ struct tps65910_board {
 struct tps65910 {
        struct device *dev;
        struct i2c_client *i2c_client;
+       struct regmap *regmap;
        struct mutex io_mutex;
        unsigned int id;
        int (*read)(struct tps65910 *tps65910, u8 reg, int size, void *dest);
@@ -786,11 +977,41 @@ struct tps65910_platform_data {
        int irq_base;
 };
 
+
+/**
+ * struct tps65910_board
+ * Board platform data may be used to initialize regulators.
+ */
+
+struct tps65910_board {
+       int gpio_base;
+       int irq;
+       int irq_base;
+       int vmbch_threshold;
+       int vmbch2_threshold;
+       bool en_gpio_sleep[TPS6591X_MAX_NUM_GPIO];
+       unsigned long regulator_ext_sleep_control[TPS65910_NUM_REGS];
+       struct regulator_init_data *tps65910_pmic_init_data[TPS65910_NUM_REGS];
+
+       /** Called before subdevices are set up */
+       int (*pre_init)(struct tps65910 *tps65910);
+       /** Called after subdevices are set up */
+       int (*post_init)(struct tps65910 *tps65910);
+       /** Called before subdevices are power down */
+       int (*last_deinit)(struct tps65910 *tps65910);
+};
+
+
 int tps65910_set_bits(struct tps65910 *tps65910, u8 reg, u8 mask);
 int tps65910_clear_bits(struct tps65910 *tps65910, u8 reg, u8 mask);
 void tps65910_gpio_init(struct tps65910 *tps65910, int gpio_base);
 int tps65910_irq_init(struct tps65910 *tps65910, int irq,
                struct tps65910_platform_data *pdata);
+int tps65910_irq_exit(struct tps65910 *tps65910);
+int tps65910_i2c_write_u8(u8 slave_addr, u8 value, u8 reg);
+int tps65910_i2c_read_u8(u8 slave_addr, u8 *value, u8 reg);
+int tps65910_device_shutdown(void);
+
 
 static inline int tps65910_chip_id(struct tps65910 *tps65910)
 {
diff --git a/include/linux/mfd/tps65912.h b/include/linux/mfd/tps65912.h
new file mode 100644 (file)
index 0000000..aaceab4
--- /dev/null
@@ -0,0 +1,327 @@
+/*
+ * tps65912.h  --  TI TPS6591x
+ *
+ * Copyright 2011 Texas Instruments Inc.
+ *
+ * Author: Margarita Olaya <magi@slimlogic.co.uk>
+ *
+ *  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.
+ *
+ */
+
+#ifndef __LINUX_MFD_TPS65912_H
+#define __LINUX_MFD_TPS65912_H
+
+/* TPS regulator type list */
+#define REGULATOR_LDO          0
+#define REGULATOR_DCDC         1
+
+/*
+ * List of registers for TPS65912
+ */
+
+#define TPS65912_DCDC1_CTRL            0x00
+#define TPS65912_DCDC2_CTRL            0x01
+#define TPS65912_DCDC3_CTRL            0x02
+#define TPS65912_DCDC4_CTRL            0x03
+#define TPS65912_DCDC1_OP              0x04
+#define TPS65912_DCDC1_AVS             0x05
+#define TPS65912_DCDC1_LIMIT           0x06
+#define TPS65912_DCDC2_OP              0x07
+#define TPS65912_DCDC2_AVS             0x08
+#define TPS65912_DCDC2_LIMIT           0x09
+#define TPS65912_DCDC3_OP              0x0A
+#define TPS65912_DCDC3_AVS             0x0B
+#define TPS65912_DCDC3_LIMIT           0x0C
+#define TPS65912_DCDC4_OP              0x0D
+#define TPS65912_DCDC4_AVS             0x0E
+#define TPS65912_DCDC4_LIMIT           0x0F
+#define TPS65912_LDO1_OP               0x10
+#define TPS65912_LDO1_AVS              0x11
+#define TPS65912_LDO1_LIMIT            0x12
+#define TPS65912_LDO2_OP               0x13
+#define TPS65912_LDO2_AVS              0x14
+#define TPS65912_LDO2_LIMIT            0x15
+#define TPS65912_LDO3_OP               0x16
+#define TPS65912_LDO3_AVS              0x17
+#define TPS65912_LDO3_LIMIT            0x18
+#define TPS65912_LDO4_OP               0x19
+#define TPS65912_LDO4_AVS              0x1A
+#define TPS65912_LDO4_LIMIT            0x1B
+#define TPS65912_LDO5                  0x1C
+#define TPS65912_LDO6                  0x1D
+#define TPS65912_LDO7                  0x1E
+#define TPS65912_LDO8                  0x1F
+#define TPS65912_LDO9                  0x20
+#define TPS65912_LDO10                 0x21
+#define TPS65912_THRM                  0x22
+#define TPS65912_CLK32OUT              0x23
+#define TPS65912_DEVCTRL               0x24
+#define TPS65912_DEVCTRL2              0x25
+#define TPS65912_I2C_SPI_CFG           0x26
+#define TPS65912_KEEP_ON               0x27
+#define TPS65912_KEEP_ON2              0x28
+#define TPS65912_SET_OFF1              0x29
+#define TPS65912_SET_OFF2              0x2A
+#define TPS65912_DEF_VOLT              0x2B
+#define TPS65912_DEF_VOLT_MAPPING      0x2C
+#define TPS65912_DISCHARGE             0x2D
+#define TPS65912_DISCHARGE2            0x2E
+#define TPS65912_EN1_SET1              0x2F
+#define TPS65912_EN1_SET2              0x30
+#define TPS65912_EN2_SET1              0x31
+#define TPS65912_EN2_SET2              0x32
+#define TPS65912_EN3_SET1              0x33
+#define TPS65912_EN3_SET2              0x34
+#define TPS65912_EN4_SET1              0x35
+#define TPS65912_EN4_SET2              0x36
+#define TPS65912_PGOOD                 0x37
+#define TPS65912_PGOOD2                        0x38
+#define TPS65912_INT_STS               0x39
+#define TPS65912_INT_MSK               0x3A
+#define TPS65912_INT_STS2              0x3B
+#define TPS65912_INT_MSK2              0x3C
+#define TPS65912_INT_STS3              0x3D
+#define TPS65912_INT_MSK3              0x3E
+#define TPS65912_INT_STS4              0x3F
+#define TPS65912_INT_MSK4              0x40
+#define TPS65912_GPIO1                 0x41
+#define TPS65912_GPIO2                 0x42
+#define TPS65912_GPIO3                 0x43
+#define TPS65912_GPIO4                 0x44
+#define TPS65912_GPIO5                 0x45
+#define TPS65912_VMON                  0x46
+#define TPS65912_LEDA_CTRL1            0x47
+#define TPS65912_LEDA_CTRL2            0x48
+#define TPS65912_LEDA_CTRL3            0x49
+#define TPS65912_LEDA_CTRL4            0x4A
+#define TPS65912_LEDA_CTRL5            0x4B
+#define TPS65912_LEDA_CTRL6            0x4C
+#define TPS65912_LEDA_CTRL7            0x4D
+#define TPS65912_LEDA_CTRL8            0x4E
+#define TPS65912_LEDB_CTRL1            0x4F
+#define TPS65912_LEDB_CTRL2            0x50
+#define TPS65912_LEDB_CTRL3            0x51
+#define TPS65912_LEDB_CTRL4            0x52
+#define TPS65912_LEDB_CTRL5            0x53
+#define TPS65912_LEDB_CTRL6            0x54
+#define TPS65912_LEDB_CTRL7            0x55
+#define TPS65912_LEDB_CTRL8            0x56
+#define TPS65912_LEDC_CTRL1            0x57
+#define TPS65912_LEDC_CTRL2            0x58
+#define TPS65912_LEDC_CTRL3            0x59
+#define TPS65912_LEDC_CTRL4            0x5A
+#define TPS65912_LEDC_CTRL5            0x5B
+#define TPS65912_LEDC_CTRL6            0x5C
+#define TPS65912_LEDC_CTRL7            0x5D
+#define TPS65912_LEDC_CTRL8            0x5E
+#define TPS65912_LED_RAMP_UP_TIME      0x5F
+#define TPS65912_LED_RAMP_DOWN_TIME    0x60
+#define TPS65912_LED_SEQ_EN            0x61
+#define TPS65912_LOADSWITCH            0x62
+#define TPS65912_SPARE                 0x63
+#define TPS65912_VERNUM                        0x64
+#define TPS6591X_MAX_REGISTER          0x64
+
+/* IRQ Definitions */
+#define TPS65912_IRQ_PWRHOLD_F         0
+#define TPS65912_IRQ_VMON              1
+#define TPS65912_IRQ_PWRON             2
+#define TPS65912_IRQ_PWRON_LP          3
+#define TPS65912_IRQ_PWRHOLD_R         4
+#define TPS65912_IRQ_HOTDIE            5
+#define TPS65912_IRQ_GPIO1_R           6
+#define TPS65912_IRQ_GPIO1_F           7
+#define TPS65912_IRQ_GPIO2_R           8
+#define TPS65912_IRQ_GPIO2_F           9
+#define TPS65912_IRQ_GPIO3_R           10
+#define TPS65912_IRQ_GPIO3_F           11
+#define TPS65912_IRQ_GPIO4_R           12
+#define TPS65912_IRQ_GPIO4_F           13
+#define TPS65912_IRQ_GPIO5_R           14
+#define TPS65912_IRQ_GPIO5_F           15
+#define TPS65912_IRQ_PGOOD_DCDC1       16
+#define TPS65912_IRQ_PGOOD_DCDC2       17
+#define TPS65912_IRQ_PGOOD_DCDC3       18
+#define TPS65912_IRQ_PGOOD_DCDC4       19
+#define TPS65912_IRQ_PGOOD_LDO1                20
+#define TPS65912_IRQ_PGOOD_LDO2                21
+#define TPS65912_IRQ_PGOOD_LDO3                22
+#define TPS65912_IRQ_PGOOD_LDO4                23
+#define TPS65912_IRQ_PGOOD_LDO5                24
+#define TPS65912_IRQ_PGOOD_LDO6                25
+#define TPS65912_IRQ_PGOOD_LDO7                26
+#define TPS65912_IRQ_PGOOD_LD08                27
+#define TPS65912_IRQ_PGOOD_LDO9                28
+#define TPS65912_IRQ_PGOOD_LDO10       29
+
+#define TPS65912_NUM_IRQ               30
+
+/* GPIO 1 and 2 Register Definitions */
+#define GPIO_SLEEP_MASK                        0x80
+#define GPIO_SLEEP_SHIFT               7
+#define GPIO_DEB_MASK                  0x10
+#define GPIO_DEB_SHIFT                 4
+#define GPIO_CFG_MASK                  0x04
+#define GPIO_CFG_SHIFT                 2
+#define GPIO_STS_MASK                  0x02
+#define GPIO_STS_SHIFT                 1
+#define GPIO_SET_MASK                  0x01
+#define GPIO_SET_SHIFT                 0
+
+/* GPIO 3 Register Definitions */
+#define GPIO3_SLEEP_MASK               0x80
+#define GPIO3_SLEEP_SHIFT              7
+#define GPIO3_SEL_MASK                 0x40
+#define GPIO3_SEL_SHIFT                        6
+#define GPIO3_ODEN_MASK                        0x20
+#define GPIO3_ODEN_SHIFT               5
+#define GPIO3_DEB_MASK                 0x10
+#define GPIO3_DEB_SHIFT                        4
+#define GPIO3_PDEN_MASK                        0x08
+#define GPIO3_PDEN_SHIFT               3
+#define GPIO3_CFG_MASK                 0x04
+#define GPIO3_CFG_SHIFT                        2
+#define GPIO3_STS_MASK                 0x02
+#define GPIO3_STS_SHIFT                        1
+#define GPIO3_SET_MASK                 0x01
+#define GPIO3_SET_SHIFT                        0
+
+/* GPIO 4 Register Definitions */
+#define GPIO4_SLEEP_MASK               0x80
+#define GPIO4_SLEEP_SHIFT              7
+#define GPIO4_SEL_MASK                 0x40
+#define GPIO4_SEL_SHIFT                        6
+#define GPIO4_ODEN_MASK                        0x20
+#define GPIO4_ODEN_SHIFT               5
+#define GPIO4_DEB_MASK                 0x10
+#define GPIO4_DEB_SHIFT                        4
+#define GPIO4_PDEN_MASK                        0x08
+#define GPIO4_PDEN_SHIFT               3
+#define GPIO4_CFG_MASK                 0x04
+#define GPIO4_CFG_SHIFT                        2
+#define GPIO4_STS_MASK                 0x02
+#define GPIO4_STS_SHIFT                        1
+#define GPIO4_SET_MASK                 0x01
+#define GPIO4_SET_SHIFT                        0
+
+/* Register THERM  (0x80) register.RegisterDescription */
+#define THERM_THERM_HD_MASK            0x20
+#define THERM_THERM_HD_SHIFT           5
+#define THERM_THERM_TS_MASK            0x10
+#define THERM_THERM_TS_SHIFT           4
+#define THERM_THERM_HDSEL_MASK         0x0C
+#define THERM_THERM_HDSEL_SHIFT                2
+#define THERM_RSVD1_MASK               0x02
+#define THERM_RSVD1_SHIFT              1
+#define THERM_THERM_STATE_MASK         0x01
+#define THERM_THERM_STATE_SHIFT                0
+
+/* Register DCDCCTRL1 register.RegisterDescription */
+#define DCDCCTRL_VCON_ENABLE_MASK      0x80
+#define DCDCCTRL_VCON_ENABLE_SHIFT     7
+#define DCDCCTRL_VCON_RANGE1_MASK      0x40
+#define DCDCCTRL_VCON_RANGE1_SHIFT     6
+#define DCDCCTRL_VCON_RANGE0_MASK      0x20
+#define DCDCCTRL_VCON_RANGE0_SHIFT     5
+#define DCDCCTRL_TSTEP2_MASK           0x10
+#define DCDCCTRL_TSTEP2_SHIFT          4
+#define DCDCCTRL_TSTEP1_MASK           0x08
+#define DCDCCTRL_TSTEP1_SHIFT          3
+#define DCDCCTRL_TSTEP0_MASK           0x04
+#define DCDCCTRL_TSTEP0_SHIFT          2
+#define DCDCCTRL_DCDC1_MODE_MASK       0x02
+#define DCDCCTRL_DCDC1_MODE_SHIFT      1
+
+/* Register DCDCCTRL2 and DCDCCTRL3 register.RegisterDescription */
+#define DCDCCTRL_TSTEP2_MASK           0x10
+#define DCDCCTRL_TSTEP2_SHIFT          4
+#define DCDCCTRL_TSTEP1_MASK           0x08
+#define DCDCCTRL_TSTEP1_SHIFT          3
+#define DCDCCTRL_TSTEP0_MASK           0x04
+#define DCDCCTRL_TSTEP0_SHIFT          2
+#define DCDCCTRL_DCDC_MODE_MASK                0x02
+#define DCDCCTRL_DCDC_MODE_SHIFT       1
+#define DCDCCTRL_RSVD0_MASK            0x01
+#define DCDCCTRL_RSVD0_SHIFT           0
+
+/* Register DCDCCTRL4 register.RegisterDescription */
+#define DCDCCTRL_RAMP_TIME_MASK                0x01
+#define DCDCCTRL_RAMP_TIME_SHIFT       0
+
+/* Register DCDCx_AVS */
+#define DCDC_AVS_ENABLE_MASK           0x80
+#define DCDC_AVS_ENABLE_SHIFT          7
+#define DCDC_AVS_ECO_MASK              0x40
+#define DCDC_AVS_ECO_SHIFT             6
+
+/* Register DCDCx_LIMIT */
+#define DCDC_LIMIT_RANGE_MASK          0xC0
+#define DCDC_LIMIT_RANGE_SHIFT         6
+#define DCDC_LIMIT_MAX_SEL_MASK                0x3F
+#define DCDC_LIMIT_MAX_SEL_SHIFT       0
+
+/**
+ * struct tps65912_board
+ * Board platform dat may be used to initialize regulators.
+ */
+struct tps65912_board {
+       int is_dcdc1_avs;
+       int is_dcdc2_avs;
+       int is_dcdc3_avs;
+       int is_dcdc4_avs;
+       int irq;
+       int irq_base;
+       int gpio_base;
+       struct regulator_init_data *tps65912_pmic_init_data;
+};
+
+/**
+ * struct tps65912 - tps65912 sub-driver chip access routines
+ */
+
+struct tps65912 {
+       struct device *dev;
+       /* for read/write acces */
+       struct mutex io_mutex;
+
+       /* For device IO interfaces: I2C or SPI */
+       void *control_data;
+
+       int (*read)(struct tps65912 *tps65912, u8 reg, int size, void *dest);
+       int (*write)(struct tps65912 *tps65912, u8 reg, int size, void *src);
+
+       /* Client devices */
+       struct tps65912_pmic *pmic;
+
+       /* GPIO Handling */
+       struct gpio_chip gpio;
+
+       /* IRQ Handling */
+       struct mutex irq_lock;
+       int chip_irq;
+       int irq_base;
+       int irq_num;
+       u32 irq_mask;
+};
+
+struct tps65912_platform_data {
+       int irq;
+       int irq_base;
+};
+
+unsigned int tps_chip(void);
+
+int tps65912_set_bits(struct tps65912 *tps65912, u8 reg, u8 mask);
+int tps65912_clear_bits(struct tps65912 *tps65912, u8 reg, u8 mask);
+int tps65912_reg_read(struct tps65912 *tps65912, u8 reg);
+int tps65912_reg_write(struct tps65912 *tps65912, u8 reg, u8 val);
+int tps65912_device_init(struct tps65912 *tps65912);
+void tps65912_device_exit(struct tps65912 *tps65912);
+int tps65912_irq_init(struct tps65912 *tps65912, int irq,
+                       struct tps65912_platform_data *pdata);
+
+#endif /*  __LINUX_MFD_TPS65912_H */