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
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
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
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
#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
#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 ------------------------*/
#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
#endif
#if defined (CONFIG_MFD_TPS65910)
{
- .type = "tps659102",
+ .type = "tps65910",
.addr = TPS65910_I2C_ID0,
.flags = 0,
.irq = TPS65910_HOST_IRQ,
--- /dev/null
+#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
+
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
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
--- /dev/null
+/*
+ * 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);
+}
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
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"
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
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,
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;
}
#include <linux/mfd/core.h>
#include <linux/mfd/tps65910.h>
+struct tps65910 *g_tps65910;
+
static struct mfd_cell tps65910s[] = {
{
.name = "tps65910-pmic",
},
};
+#define TPS65910_SPEED 400 * 1000
static int tps65910_i2c_read(struct tps65910 *tps65910, u8 reg,
int bytes, void *dest)
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 = ®
+ 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;
}
/* 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);
return ret;
if (ret != bytes + 1)
return -EIO;
+
return 0;
}
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);
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);
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:
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);
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)
{
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
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
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
#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,
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)
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)
{
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;
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) {
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*/
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)
return -EINVAL;
}
- voltage = pmic->info[id]->table[value] * 1000;
+ voltage = pmic->info[id]->voltage_table[value] * 1000;
return voltage;
}
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;
}
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;
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),
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),
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);
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);
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;
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);
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;
}
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;
}
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,
};
.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,
.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,
};
.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);
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;
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;
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;
"failed to register %s regulator\n",
pdev->name);
err = PTR_ERR(rdev);
- goto err;
+ goto err_unregister_regulator;
}
/* Save regulator for cleanup */
}
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",
},
.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)
{
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");
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
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
--- /dev/null
+/*
+ * 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");
#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
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);
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)
{
--- /dev/null
+/*
+ * 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 */