mirror of
https://github.com/torvalds/linux.git
synced 2026-06-08 14:42:37 +02:00
rk30☎️add pmu tps80032
This commit is contained in:
parent
5022feddeb
commit
50276f7c94
|
|
@ -1282,7 +1282,7 @@ static struct i2c_board_info __initdata i2c0_info[] = {
|
|||
|
||||
#ifdef CONFIG_I2C1_RK30
|
||||
#include "board-rk30-sdk-wm8326.c"
|
||||
|
||||
#include "board-rk30-sdk-twl80032.c"
|
||||
static struct i2c_board_info __initdata i2c1_info[] = {
|
||||
#if defined (CONFIG_MFD_WM831X_I2C)
|
||||
{
|
||||
|
|
@ -1293,6 +1293,17 @@ static struct i2c_board_info __initdata i2c1_info[] = {
|
|||
.platform_data = &wm831x_platdata,
|
||||
},
|
||||
#endif
|
||||
#if defined (CONFIG_TWL4030_CORE)
|
||||
{
|
||||
.type = "twl6032",
|
||||
.addr = 0x48,
|
||||
.flags = 0,
|
||||
.irq = RK30_PIN6_PA4,
|
||||
.platform_data = &tps80032_data,
|
||||
|
||||
},
|
||||
|
||||
#endif
|
||||
};
|
||||
#endif
|
||||
|
||||
|
|
@ -1320,7 +1331,10 @@ static struct i2c_board_info __initdata i2c2_info[] = {
|
|||
#endif
|
||||
|
||||
#ifdef CONFIG_I2C3_RK30
|
||||
|
||||
static struct i2c_board_info __initdata i2c3_info[] = {
|
||||
|
||||
|
||||
};
|
||||
#endif
|
||||
|
||||
|
|
|
|||
496
arch/arm/mach-rk30/board-rk30-sdk-twl80032.c
Executable file
496
arch/arm/mach-rk30/board-rk30-sdk-twl80032.c
Executable file
|
|
@ -0,0 +1,496 @@
|
|||
#include <linux/regulator/machine.h>
|
||||
#include <linux/i2c/twl.h>
|
||||
|
||||
#include <mach/sram.h>
|
||||
|
||||
#ifdef CONFIG_TWL4030_CORE
|
||||
#define VREG_VOLTAGE 3
|
||||
#define VREG_VOLTAGE_DVS_SMPS 3
|
||||
static inline int twl_reg_read(unsigned base, unsigned slave_subgp, unsigned offset)
|
||||
{
|
||||
u8 value;
|
||||
int status;
|
||||
status = twl_i2c_read_u8(slave_subgp,&value, base + offset);
|
||||
return (status < 0) ? status : value;
|
||||
}
|
||||
|
||||
|
||||
static inline int twl_reg_write(unsigned base, unsigned slave_subgp, unsigned offset,
|
||||
u8 value)
|
||||
{
|
||||
return twl_i2c_write_u8(slave_subgp,value, base + offset);
|
||||
}
|
||||
|
||||
int tps80032_pre_init(void){
|
||||
int ret;
|
||||
u8 value;
|
||||
printk("--------------------\n");
|
||||
printk("%s\n", __func__);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
int tps80032_set_init(void)
|
||||
{
|
||||
struct regulator *dcdc;
|
||||
struct regulator *ldo;
|
||||
printk("++++++++++++++++++++++++++++++++++++++\n");
|
||||
printk("%s\n", __func__);
|
||||
|
||||
ldo = regulator_get(NULL, "tps_ldo1"); //vcca_33
|
||||
regulator_set_voltage(ldo, 3300000, 3300000);
|
||||
regulator_enable(ldo);
|
||||
printk("%s set ldo1 vcca_33=%dmV end\n", __func__, regulator_get_voltage(ldo));
|
||||
regulator_put(ldo);
|
||||
udelay(100);
|
||||
|
||||
ldo = regulator_get(NULL, "tps_ldo4"); // vdd_11
|
||||
regulator_set_voltage(ldo, 1100000, 1100000);
|
||||
regulator_enable(ldo);
|
||||
printk("%s set ldo4 vdd_11=%dmV end\n", __func__, regulator_get_voltage(ldo));
|
||||
regulator_put(ldo);
|
||||
udelay(100);
|
||||
|
||||
dcdc = regulator_get(NULL, "tps_smps4");
|
||||
regulator_set_voltage(dcdc,3000000,3000000);
|
||||
regulator_enable(dcdc);
|
||||
printk("%s set dcdc4 vcc_io=%dmV end\n", __func__, regulator_get_voltage(dcdc));
|
||||
regulator_put(dcdc);
|
||||
udelay(100);
|
||||
|
||||
ldo = regulator_get(NULL, "tps_ldo2"); // vdd_usb11
|
||||
regulator_set_voltage(ldo, 1100000, 1100000);
|
||||
regulator_enable(ldo);
|
||||
printk("%s set ldo2 vdd_usb11=%dmV end\n", __func__, regulator_get_voltage(ldo));
|
||||
regulator_put(ldo);
|
||||
udelay(100);
|
||||
|
||||
ldo = regulator_get(NULL, "tps_ldo5"); // vcc_25
|
||||
regulator_set_voltage(ldo, 2500000, 2500000);
|
||||
regulator_enable(ldo);
|
||||
printk("%s set ldo5 vcc_25=%dmV end\n", __func__, regulator_get_voltage(ldo));
|
||||
regulator_put(ldo);
|
||||
udelay(100);
|
||||
|
||||
ldo = regulator_get(NULL, "tps_ldousb"); // vcc_usb33
|
||||
regulator_set_voltage(ldo, 3300000, 3300000);
|
||||
regulator_enable(ldo);
|
||||
printk("%s set ldousb vcc_usb33=%dmV end\n", __func__, regulator_get_voltage(ldo));
|
||||
regulator_put(ldo);
|
||||
udelay(100);
|
||||
|
||||
dcdc = regulator_get(NULL, "tps_smps1"); // vdd_arm
|
||||
regulator_set_voltage(dcdc,1100000,1100000);
|
||||
regulator_enable(dcdc);
|
||||
printk("%s set dcdc1 vdd_cpu=%dmV end\n", __func__, regulator_get_voltage(dcdc));
|
||||
regulator_put(dcdc);
|
||||
udelay(100);
|
||||
|
||||
dcdc = regulator_get(NULL, "tps_smps2"); //vdd_log
|
||||
regulator_set_voltage(dcdc,1100000,1100000);
|
||||
regulator_enable(dcdc);
|
||||
printk("%s set dcdc2 vdd_core=%dmV end\n", __func__, regulator_get_voltage(dcdc));
|
||||
regulator_put(dcdc);
|
||||
udelay(100);
|
||||
|
||||
dcdc = regulator_get(NULL, "tps_smps3"); //vcc_ddr
|
||||
regulator_set_voltage(dcdc,1500000,1500000);
|
||||
regulator_enable(dcdc);
|
||||
printk("%s set dcdc3 vcc_ddr=%dmV end\n", __func__, regulator_get_voltage(dcdc));
|
||||
regulator_put(dcdc);
|
||||
udelay(100);
|
||||
/*
|
||||
dcdc = regulator_get(NULL, "tps_smps5");
|
||||
regulator_set_voltage(dcdc,1800000,1800000);
|
||||
// regulator_set_suspend_voltage(dcdc, 1800000);
|
||||
regulator_enable(dcdc);
|
||||
printk("%s set dcdc5 vcc_lpddr2_1v8=%dmV end\n", __func__, regulator_get_voltage(dcdc));
|
||||
regulator_put(dcdc);
|
||||
udelay(100);
|
||||
*/
|
||||
|
||||
ldo = regulator_get(NULL, "tps_ldo3"); //vcc_nandflash
|
||||
regulator_set_voltage(ldo, 3300000, 3300000);
|
||||
regulator_enable(ldo);
|
||||
printk("%s set ldo3 vcc_nandflash=%dmV end\n", __func__, regulator_get_voltage(ldo));
|
||||
regulator_put(ldo);
|
||||
udelay(100);
|
||||
|
||||
ldo = regulator_get(NULL, "tps_ldo6"); //codecvdd_1v8
|
||||
regulator_set_voltage(ldo, 1800000, 1800000);
|
||||
regulator_enable(ldo);
|
||||
printk("%s set ldo6 codecvdd_1v8=%dmV end\n", __func__, regulator_get_voltage(ldo));
|
||||
regulator_put(ldo);
|
||||
udelay(100);
|
||||
|
||||
ldo = regulator_get(NULL, "tps_ldo7"); //vcc_lcd
|
||||
regulator_set_voltage(ldo, 3000000, 3000000);
|
||||
regulator_enable(ldo);
|
||||
printk("%s set ldo7 vcc_lcd=%dmV end\n", __func__, regulator_get_voltage(ldo));
|
||||
regulator_put(ldo);
|
||||
udelay(100);
|
||||
|
||||
ldo = regulator_get(NULL, "tps_ldoln"); //vcccodec_io
|
||||
regulator_set_voltage(ldo, 3300000, 3300000);
|
||||
regulator_enable(ldo);
|
||||
printk("%s set ldoln vcccodec_io=%dmV end\n", __func__, regulator_get_voltage(ldo));
|
||||
regulator_put(ldo);
|
||||
udelay(100);
|
||||
/*
|
||||
ldo = regulator_get(NULL, "tps_vana"); //vana_out
|
||||
regulator_set_voltage(ldo, 2500000, 2500000);
|
||||
// regulator_set_suspend_voltage(ldo, 2500000);
|
||||
regulator_enable(ldo);
|
||||
printk("%s set vana vana_out=%dmV end\n", __func__, regulator_get_voltage(ldo));
|
||||
regulator_put(ldo);
|
||||
udelay(100);
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static struct regulator_consumer_supply tps80032_smps1_supply[] = {
|
||||
{
|
||||
.supply = "tps_smps1",
|
||||
},
|
||||
};
|
||||
static struct regulator_consumer_supply tps80032_smps2_supply[] = {
|
||||
{
|
||||
.supply = "tps_smps2",
|
||||
},
|
||||
};
|
||||
static struct regulator_consumer_supply tps80032_smps3_supply[] = {
|
||||
{
|
||||
.supply = "tps_smps3",
|
||||
},
|
||||
};
|
||||
static struct regulator_consumer_supply tps80032_smps4_supply[] = {
|
||||
{
|
||||
.supply = "tps_smps4",
|
||||
},
|
||||
};
|
||||
static struct regulator_consumer_supply tps80032_smps5_supply[] = {
|
||||
{
|
||||
.supply = "tps_smps5",
|
||||
},
|
||||
};
|
||||
static struct regulator_consumer_supply tps80032_ldo1_supply[] = {
|
||||
{
|
||||
.supply = "tps_ldo1",
|
||||
},
|
||||
};
|
||||
static struct regulator_consumer_supply tps80032_ldo2_supply[] = {
|
||||
{
|
||||
.supply = "tps_ldo2",
|
||||
},
|
||||
};
|
||||
|
||||
static struct regulator_consumer_supply tps80032_ldo3_supply[] = {
|
||||
{
|
||||
.supply = "tps_ldo3",
|
||||
},
|
||||
};
|
||||
static struct regulator_consumer_supply tps80032_ldo4_supply[] = {
|
||||
{
|
||||
.supply = "tps_ldo4",
|
||||
},
|
||||
};
|
||||
static struct regulator_consumer_supply tps80032_ldo5_supply[] = {
|
||||
{
|
||||
.supply = "tps_ldo5",
|
||||
},
|
||||
};
|
||||
static struct regulator_consumer_supply tps80032_ldo6_supply[] = {
|
||||
{
|
||||
.supply = "tps_ldo6",
|
||||
},
|
||||
};
|
||||
static struct regulator_consumer_supply tps80032_ldo7_supply[] = {
|
||||
{
|
||||
.supply = "tps_ldo7",
|
||||
},
|
||||
};
|
||||
|
||||
static struct regulator_consumer_supply tps80032_ldoln_supply[] = {
|
||||
{
|
||||
.supply = "tps_ldoln",
|
||||
},
|
||||
};
|
||||
static struct regulator_consumer_supply tps80032_ldousb_supply[] = {
|
||||
{
|
||||
.supply = "tps_ldousb",
|
||||
},
|
||||
};
|
||||
static struct regulator_consumer_supply tps80032_ldovana_supply[] = {
|
||||
{
|
||||
.supply = "tps_vana",
|
||||
},
|
||||
};
|
||||
/* */
|
||||
static struct regulator_init_data tps80032_smps1 = {
|
||||
.constraints = {
|
||||
.name = "TPS_SMPS1",
|
||||
.min_uV = 600000,
|
||||
.max_uV = 2100000,
|
||||
.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(tps80032_smps1_supply),
|
||||
.consumer_supplies = tps80032_smps1_supply,
|
||||
};
|
||||
|
||||
/* */
|
||||
static struct regulator_init_data tps80032_smps2 = {
|
||||
.constraints = {
|
||||
.name = "TPS_SMPS2",
|
||||
.min_uV = 600000,
|
||||
.max_uV = 2100000,
|
||||
.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(tps80032_smps2_supply),
|
||||
.consumer_supplies = tps80032_smps2_supply,
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* */
|
||||
static struct regulator_init_data tps80032_smps3 = {
|
||||
.constraints = {
|
||||
.name = "TPS_SMPS3",
|
||||
.min_uV = 600000,
|
||||
.max_uV = 2100000,
|
||||
.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(tps80032_smps3_supply),
|
||||
.consumer_supplies = tps80032_smps3_supply,
|
||||
};
|
||||
|
||||
|
||||
/* */
|
||||
static struct regulator_init_data tps80032_smps4 = {
|
||||
.constraints = {
|
||||
.name = "TPS_SMPS4",
|
||||
.min_uV = 600000,
|
||||
.max_uV = 2100000,
|
||||
.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(tps80032_smps4_supply),
|
||||
.consumer_supplies = tps80032_smps4_supply,
|
||||
};
|
||||
/* */
|
||||
static struct regulator_init_data tps80032_smps5 = {
|
||||
.constraints = {
|
||||
.name = "TPS_SMPS5",
|
||||
.min_uV = 600000,
|
||||
.max_uV = 2100000,
|
||||
.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(tps80032_smps5_supply),
|
||||
.consumer_supplies = tps80032_smps5_supply,
|
||||
};
|
||||
static struct regulator_init_data tps80032_ldo1 = {
|
||||
.constraints = {
|
||||
.name = "TPS_LDO1",
|
||||
.min_uV = 1200000,
|
||||
.max_uV = 3000000,
|
||||
.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(tps80032_ldo1_supply),
|
||||
.consumer_supplies = tps80032_ldo1_supply,
|
||||
};
|
||||
|
||||
/* */
|
||||
static struct regulator_init_data tps80032_ldo2 = {
|
||||
.constraints = {
|
||||
.name = "TPS_LDO2",
|
||||
.min_uV = 1200000,
|
||||
.max_uV = 3000000,
|
||||
.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(tps80032_ldo2_supply),
|
||||
.consumer_supplies = tps80032_ldo2_supply,
|
||||
};
|
||||
|
||||
/* */
|
||||
static struct regulator_init_data tps80032_ldo3 = {
|
||||
.constraints = {
|
||||
.name = "TPS_LDO3",
|
||||
.min_uV = 1200000,
|
||||
.max_uV = 3000000,
|
||||
.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(tps80032_ldo3_supply),
|
||||
.consumer_supplies = tps80032_ldo3_supply,
|
||||
};
|
||||
|
||||
/* */
|
||||
static struct regulator_init_data tps80032_ldo4 = {
|
||||
.constraints = {
|
||||
.name = "TPS_LDO4",
|
||||
.min_uV = 1200000,
|
||||
.max_uV = 3000000,
|
||||
.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(tps80032_ldo4_supply),
|
||||
.consumer_supplies = tps80032_ldo4_supply,
|
||||
};
|
||||
|
||||
/* */
|
||||
static struct regulator_init_data tps80032_ldo5 = {
|
||||
.constraints = {
|
||||
.name = "TPS_LDO5",
|
||||
.min_uV = 1200000,
|
||||
.max_uV = 3000000,
|
||||
.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(tps80032_ldo5_supply),
|
||||
.consumer_supplies = tps80032_ldo5_supply,
|
||||
};
|
||||
|
||||
/* */
|
||||
static struct regulator_init_data tps80032_ldo6 = {
|
||||
.constraints = {
|
||||
.name = "TPS_LDO6",
|
||||
.min_uV = 1200000,
|
||||
.max_uV = 3000000,
|
||||
.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(tps80032_ldo6_supply),
|
||||
.consumer_supplies = tps80032_ldo6_supply,
|
||||
};
|
||||
|
||||
/* */
|
||||
static struct regulator_init_data tps80032_ldo7 = {
|
||||
.constraints = {
|
||||
.name = "TPS_LDO7",
|
||||
.min_uV = 1200000,
|
||||
.max_uV = 3000000,
|
||||
.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(tps80032_ldo7_supply),
|
||||
.consumer_supplies = tps80032_ldo7_supply,
|
||||
};
|
||||
|
||||
/* */
|
||||
static struct regulator_init_data tps80032_ldoln = {
|
||||
.constraints = {
|
||||
.name = "TPS_LDOLN",
|
||||
.min_uV = 1200000,
|
||||
.max_uV = 3000000,
|
||||
.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(tps80032_ldoln_supply),
|
||||
.consumer_supplies = tps80032_ldoln_supply,
|
||||
};
|
||||
|
||||
/* */
|
||||
static struct regulator_init_data tps80032_ldousb = {
|
||||
.constraints = {
|
||||
.name = "TPS_LDOUSB",
|
||||
.min_uV = 3300000,
|
||||
.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(tps80032_ldousb_supply),
|
||||
.consumer_supplies = tps80032_ldousb_supply,
|
||||
};
|
||||
|
||||
/* */
|
||||
static struct regulator_init_data tps80032_ldovana = {
|
||||
.constraints = {
|
||||
.name = "TPS_LDOVANA",
|
||||
.min_uV = 600000,
|
||||
.max_uV = 2500000,
|
||||
.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(tps80032_ldovana_supply),
|
||||
.consumer_supplies = tps80032_ldovana_supply,
|
||||
};
|
||||
|
||||
static struct twl4030_platform_data tps80032_data = {
|
||||
.irq_base = RK30_PIN0_PA1,
|
||||
.irq_end = RK30_PIN0_PA1,
|
||||
//.irq = RK29_PIN0_PA1,
|
||||
.pre_init = tps80032_pre_init,
|
||||
.set_init = tps80032_set_init,
|
||||
|
||||
/* Regulators */
|
||||
.ldo1 = &tps80032_ldo1,
|
||||
.ldo2 = &tps80032_ldo2,
|
||||
.ldo3 = &tps80032_ldo3,
|
||||
.ldo4 = &tps80032_ldo4,
|
||||
.ldo5 = &tps80032_ldo5,
|
||||
.ldo6 = &tps80032_ldo6,
|
||||
.ldo7 = &tps80032_ldo7,
|
||||
.ldoln = &tps80032_ldoln,
|
||||
.ldousb =&tps80032_ldousb,
|
||||
.vana = &tps80032_ldovana,
|
||||
|
||||
.smps1 = &tps80032_smps1,
|
||||
.smps2= &tps80032_smps2,
|
||||
.smps3 = &tps80032_smps3,
|
||||
.smps4 = &tps80032_smps4,
|
||||
.smps5 = &tps80032_smps5,
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
360
drivers/mfd/twl-core.c
Normal file → Executable file
360
drivers/mfd/twl-core.c
Normal file → Executable file
|
|
@ -33,11 +33,13 @@
|
|||
#include <linux/platform_device.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
#include <linux/regulator/machine.h>
|
||||
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c/twl.h>
|
||||
#include "twl-core.h"
|
||||
|
||||
#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
|
||||
#include <plat/cpu.h>
|
||||
|
|
@ -83,7 +85,13 @@
|
|||
#define twl_has_madc() false
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_TWL4030_POWER
|
||||
#if defined(CONFIG_TWL6030_GPADC) || defined(CONFIG_TWL6030_GPADC_MODULE)
|
||||
#define twl_has_gpadc() true
|
||||
#else
|
||||
#define twl_has_gpadc() false
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_TWL4030_POWER) || defined(CONFIG_TWL6030_POWER)
|
||||
#define twl_has_power() true
|
||||
#else
|
||||
#define twl_has_power() false
|
||||
|
|
@ -116,7 +124,10 @@
|
|||
#define twl_has_codec() false
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_CHARGER_TWL4030) || defined(CONFIG_CHARGER_TWL4030_MODULE)
|
||||
#if defined(CONFIG_CHARGER_TWL4030) || \
|
||||
defined(CONFIG_CHARGER_TWL4030_MODULE) || \
|
||||
defined(CONFIG_TWL6030_BCI_BATTERY) || \
|
||||
defined(CONFIG_TWL6030_BCI_BATTERY_MODULE)
|
||||
#define twl_has_bci() true
|
||||
#else
|
||||
#define twl_has_bci() false
|
||||
|
|
@ -126,7 +137,8 @@
|
|||
|
||||
/* Last - for index max*/
|
||||
#define TWL4030_MODULE_LAST TWL4030_MODULE_SECURED_REG
|
||||
|
||||
#define TWL6030_MODULE_LAST TWL6030_MODULE_SLAVE_RES //xsf
|
||||
#define TWL6030_MODULE_LAST TWL_MODULE_PM_DVS //add
|
||||
#define TWL_NUM_SLAVES 4
|
||||
|
||||
#if defined(CONFIG_INPUT_TWL4030_PWRBUTTON) \
|
||||
|
|
@ -136,12 +148,19 @@
|
|||
#define twl_has_pwrbutton() false
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_INPUT_TWL6030_PWRBUTTON) \
|
||||
|| defined(CONFIG_INPUT_TWL6030_PWRBUTTON_MODULE)
|
||||
#define twl6030_has_pwrbutton() true
|
||||
#else
|
||||
#define twl6030_has_pwrbutton() false
|
||||
#endif
|
||||
|
||||
#define SUB_CHIP_ID0 0
|
||||
#define SUB_CHIP_ID1 1
|
||||
#define SUB_CHIP_ID2 2
|
||||
#define SUB_CHIP_ID3 3
|
||||
|
||||
#define TWL_MODULE_LAST TWL4030_MODULE_LAST
|
||||
#define SUB_DVS_ID 3 //add
|
||||
#define TWL_MODULE_LAST TWL6030_MODULE_LAST
|
||||
|
||||
/* Base Address defns for twl4030_map[] */
|
||||
|
||||
|
|
@ -187,6 +206,7 @@
|
|||
#define TWL6030_BASEADD_MEM 0x0017
|
||||
#define TWL6030_BASEADD_PM_MASTER 0x001F
|
||||
#define TWL6030_BASEADD_PM_SLAVE_MISC 0x0030 /* PM_RECEIVER */
|
||||
#define TWL6030_BASEADD_PM_SLAVE_RES 0x00AD
|
||||
#define TWL6030_BASEADD_PM_MISC 0x00E2
|
||||
#define TWL6030_BASEADD_PM_PUPD 0x00F0
|
||||
|
||||
|
|
@ -198,7 +218,7 @@
|
|||
#define TWL6030_BASEADD_GASGAUGE 0x00C0
|
||||
#define TWL6030_BASEADD_PIH 0x00D0
|
||||
#define TWL6030_BASEADD_CHARGER 0x00E0
|
||||
#define TWL6025_BASEADD_CHARGER 0x00DA
|
||||
#define TWL6032_BASEADD_CHARGER 0x00DA
|
||||
|
||||
/* subchip/slave 2 0x4A - DFT */
|
||||
#define TWL6030_BASEADD_DIEID 0x00C0
|
||||
|
|
@ -225,6 +245,13 @@
|
|||
#define TWL5031 BIT(2) /* twl5031 has different registers */
|
||||
#define TWL6030_CLASS BIT(3) /* TWL6030 class */
|
||||
|
||||
/* need to access USB_PRODUCT_ID_LSB to identify which 6030 varient we are */
|
||||
#define USB_PRODUCT_ID_LSB 0x02
|
||||
|
||||
/* need to check eeprom revision and jtagver number */
|
||||
#define TWL6030_REG_EPROM_REV 0xdf
|
||||
#define TWL6030_REG_JTAGVERNUM 0x87
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
/* is driver active, bound to a chip? */
|
||||
|
|
@ -332,7 +359,11 @@ static struct twl_mapping twl6030_map[] = {
|
|||
|
||||
{ SUB_CHIP_ID0, TWL6030_BASEADD_RTC },
|
||||
{ SUB_CHIP_ID0, TWL6030_BASEADD_MEM },
|
||||
{ SUB_CHIP_ID1, TWL6025_BASEADD_CHARGER },
|
||||
{ SUB_CHIP_ID1, TWL6032_BASEADD_CHARGER },
|
||||
{ SUB_CHIP_ID0, TWL6030_BASEADD_PM_SLAVE_RES },
|
||||
{ SUB_DVS_ID, TWL6030_BASEADD_PM_SLAVE_MISC }, //add
|
||||
|
||||
|
||||
};
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
|
@ -362,23 +393,38 @@ int twl_i2c_write(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes)
|
|||
pr_err("%s: invalid module number %d\n", DRIVER_NAME, mod_no);
|
||||
return -EPERM;
|
||||
}
|
||||
if (unlikely(!inuse)) {
|
||||
pr_err("%s: not initialized\n", DRIVER_NAME);
|
||||
return -EPERM;
|
||||
}
|
||||
sid = twl_map[mod_no].sid;
|
||||
twl = &twl_modules[sid];
|
||||
|
||||
if (unlikely(!inuse)) {
|
||||
pr_err("%s: client %d is not initialized\n", DRIVER_NAME, sid);
|
||||
return -EPERM;
|
||||
}
|
||||
mutex_lock(&twl->xfer_lock);
|
||||
/*
|
||||
* [MSG1]: fill the register address data
|
||||
* fill the data Tx buffer
|
||||
*/
|
||||
msg = &twl->xfer_msg[0];
|
||||
#if 1 //add
|
||||
if((reg == 0x26)||(reg == 0x2C)||(reg == 0x2A))
|
||||
{
|
||||
msg->addr = 0x12;
|
||||
reg--;
|
||||
}
|
||||
else
|
||||
{
|
||||
msg->addr = twl->address;
|
||||
|
||||
}
|
||||
#else
|
||||
msg->addr = twl->address;
|
||||
#endif
|
||||
|
||||
msg->len = num_bytes + 1;
|
||||
msg->flags = 0;
|
||||
msg->buf = value;
|
||||
msg->scl_rate = 100*1000; //add
|
||||
/* over write the first byte of buffer with the register address */
|
||||
*value = twl_map[mod_no].base + reg;
|
||||
ret = i2c_transfer(twl->client->adapter, twl->xfer_msg, 1);
|
||||
|
|
@ -386,8 +432,9 @@ int twl_i2c_write(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes)
|
|||
|
||||
/* i2c_transfer returns number of messages transferred */
|
||||
if (ret != 1) {
|
||||
pr_err("%s: i2c_write failed to transfer all messages\n",
|
||||
DRIVER_NAME);
|
||||
pr_err("%s: i2c_write failed to transfer all messages "
|
||||
"(addr 0x%04x, reg %d, len %d)\n",
|
||||
DRIVER_NAME, twl->address, reg, msg->len);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
else
|
||||
|
|
@ -414,18 +461,17 @@ int twl_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes)
|
|||
int sid;
|
||||
struct twl_client *twl;
|
||||
struct i2c_msg *msg;
|
||||
|
||||
if (unlikely(mod_no > TWL_MODULE_LAST)) {
|
||||
pr_err("%s: invalid module number %d\n", DRIVER_NAME, mod_no);
|
||||
return -EPERM;
|
||||
}
|
||||
if (unlikely(!inuse)) {
|
||||
pr_err("%s: not initialized\n", DRIVER_NAME);
|
||||
return -EPERM;
|
||||
}
|
||||
sid = twl_map[mod_no].sid;
|
||||
twl = &twl_modules[sid];
|
||||
|
||||
if (unlikely(!inuse)) {
|
||||
pr_err("%s: client %d is not initialized\n", DRIVER_NAME, sid);
|
||||
return -EPERM;
|
||||
}
|
||||
mutex_lock(&twl->xfer_lock);
|
||||
/* [MSG1] fill the register address data */
|
||||
msg = &twl->xfer_msg[0];
|
||||
|
|
@ -434,6 +480,7 @@ int twl_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes)
|
|||
msg->flags = 0; /* Read the register value */
|
||||
val = twl_map[mod_no].base + reg;
|
||||
msg->buf = &val;
|
||||
msg->scl_rate = 100*1000; //add
|
||||
/* [MSG2] fill the data rx buffer */
|
||||
msg = &twl->xfer_msg[1];
|
||||
msg->addr = twl->address;
|
||||
|
|
@ -445,8 +492,9 @@ int twl_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes)
|
|||
|
||||
/* i2c_transfer returns number of messages transferred */
|
||||
if (ret != 2) {
|
||||
pr_err("%s: i2c_read failed to transfer all messages\n",
|
||||
DRIVER_NAME);
|
||||
pr_err("%s: i2c_read failed to transfer all messages "
|
||||
"(addr 0x%04x, reg %d, len %d)\n",
|
||||
DRIVER_NAME, twl->address, reg, msg->len);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
else
|
||||
|
|
@ -470,6 +518,20 @@ int twl_i2c_write_u8(u8 mod_no, u8 value, u8 reg)
|
|||
|
||||
/* 2 bytes offset 1 contains the data offset 0 is used by i2c_write */
|
||||
u8 temp_buffer[2] = { 0 };
|
||||
|
||||
#if 1 //add
|
||||
if(reg == 0x26)
|
||||
{
|
||||
temp_buffer[1] = 0x43;
|
||||
twl_i2c_write(mod_no, temp_buffer, 0x25, 1);
|
||||
|
||||
temp_buffer[1] = 0x07;
|
||||
twl_i2c_write(mod_no, temp_buffer, reg, 1);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* offset 1 contains the data */
|
||||
temp_buffer[1] = value;
|
||||
return twl_i2c_write(mod_no, temp_buffer, reg, 1);
|
||||
|
|
@ -552,7 +614,6 @@ add_numbered_child(unsigned chip, const char *name, int num,
|
|||
struct platform_device *pdev;
|
||||
struct twl_client *twl = &twl_modules[chip];
|
||||
int status;
|
||||
|
||||
pdev = platform_device_alloc(name, num);
|
||||
if (!pdev) {
|
||||
dev_dbg(&twl->client->dev, "can't alloc dev\n");
|
||||
|
|
@ -633,6 +694,9 @@ add_regulator(int num, struct regulator_init_data *pdata,
|
|||
return add_regulator_linked(num, pdata, NULL, 0, features);
|
||||
}
|
||||
|
||||
#define SET_LDO_STATE_MEM(ldo, state) \
|
||||
ldo->constraints.state_mem.disabled = state
|
||||
|
||||
/*
|
||||
* NOTE: We know the first 8 IRQs after pdata->base_irq are
|
||||
* for the PIH, and the next are for the PWR_INT SIH, since
|
||||
|
|
@ -644,6 +708,8 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)
|
|||
{
|
||||
struct device *child;
|
||||
unsigned sub_chip_id;
|
||||
u8 eepromrev = 0;
|
||||
u8 twlrev = 0;
|
||||
|
||||
if (twl_has_gpio() && pdata->gpio) {
|
||||
child = add_child(SUB_CHIP_ID1, "twl4030_gpio",
|
||||
|
|
@ -660,6 +726,15 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)
|
|||
if (IS_ERR(child))
|
||||
return PTR_ERR(child);
|
||||
}
|
||||
if (twl_has_bci() && pdata->bci) {
|
||||
pdata->bci->features = features;
|
||||
child = add_child(1, "twl6030_bci",
|
||||
pdata->bci, sizeof(*pdata->bci),
|
||||
false,
|
||||
pdata->irq_base + CHARGER_INTR_OFFSET,
|
||||
pdata->irq_base + CHARGERFAULT_INTR_OFFSET);
|
||||
}
|
||||
|
||||
|
||||
if (twl_has_madc() && pdata->madc) {
|
||||
child = add_child(2, "twl4030_madc",
|
||||
|
|
@ -669,6 +744,16 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)
|
|||
return PTR_ERR(child);
|
||||
}
|
||||
|
||||
if (twl_has_gpadc() && pdata->madc) {
|
||||
pdata->madc->features = features;
|
||||
child = add_child(1, "twl6030_gpadc",
|
||||
pdata->madc, sizeof(*pdata->madc),
|
||||
true, pdata->irq_base + MADC_INTR_OFFSET,
|
||||
pdata->irq_base + GPADCSW_INTR_OFFSET);
|
||||
if (IS_ERR(child))
|
||||
return PTR_ERR(child);
|
||||
}
|
||||
|
||||
if (twl_has_rtc()) {
|
||||
/*
|
||||
* REVISIT platform_data here currently might expose the
|
||||
|
|
@ -750,28 +835,23 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)
|
|||
|
||||
static struct regulator_consumer_supply usb3v3;
|
||||
int regulator;
|
||||
|
||||
if (twl_has_regulator()) {
|
||||
/* this is a template that gets copied */
|
||||
struct regulator_init_data usb_fixed = {
|
||||
.constraints.valid_modes_mask =
|
||||
REGULATOR_MODE_NORMAL
|
||||
| REGULATOR_MODE_STANDBY,
|
||||
.constraints.valid_ops_mask =
|
||||
REGULATOR_CHANGE_MODE
|
||||
| REGULATOR_CHANGE_STATUS,
|
||||
};
|
||||
|
||||
if (features & TWL6025_SUBCLASS) {
|
||||
if (features & TWL6032_SUBCLASS) {
|
||||
usb3v3.supply = "ldousb";
|
||||
regulator = TWL6025_REG_LDOUSB;
|
||||
regulator = TWL6032_REG_LDOUSB;
|
||||
child = add_regulator_linked(regulator,
|
||||
pdata->ldousb,
|
||||
&usb3v3, 1,
|
||||
features);
|
||||
} else {
|
||||
usb3v3.supply = "vusb";
|
||||
regulator = TWL6030_REG_VUSB;
|
||||
child = add_regulator_linked(regulator,
|
||||
pdata->vusb,
|
||||
&usb3v3, 1,
|
||||
features);
|
||||
}
|
||||
child = add_regulator_linked(regulator, &usb_fixed,
|
||||
&usb3v3, 1,
|
||||
features);
|
||||
|
||||
if (IS_ERR(child))
|
||||
return PTR_ERR(child);
|
||||
}
|
||||
|
|
@ -791,8 +871,8 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)
|
|||
if (twl_has_regulator() && child)
|
||||
usb3v3.dev = child;
|
||||
} else if (twl_has_regulator() && twl_class_is_6030()) {
|
||||
if (features & TWL6025_SUBCLASS)
|
||||
child = add_regulator(TWL6025_REG_LDOUSB,
|
||||
if (features & TWL6032_SUBCLASS)
|
||||
child = add_regulator(TWL6032_REG_LDOUSB,
|
||||
pdata->ldousb, features);
|
||||
else
|
||||
child = add_regulator(TWL6030_REG_VUSB,
|
||||
|
|
@ -815,6 +895,13 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)
|
|||
return PTR_ERR(child);
|
||||
}
|
||||
|
||||
if (twl6030_has_pwrbutton()) {
|
||||
child = add_child(1, "twl6030_pwrbutton",
|
||||
NULL, 0, true, pdata->irq_base, 0);
|
||||
if (IS_ERR(child))
|
||||
return PTR_ERR(child);
|
||||
}
|
||||
|
||||
if (twl_has_codec() && pdata->codec && twl_class_is_4030()) {
|
||||
sub_chip_id = twl_map[TWL_MODULE_AUDIO_VOICE].sid;
|
||||
child = add_child(sub_chip_id, "twl4030-audio",
|
||||
|
|
@ -827,7 +914,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)
|
|||
/* Phoenix codec driver is probed directly atm */
|
||||
if (twl_has_codec() && pdata->codec && twl_class_is_6030()) {
|
||||
sub_chip_id = twl_map[TWL_MODULE_AUDIO_VOICE].sid;
|
||||
child = add_child(sub_chip_id, "twl6040-codec",
|
||||
child = add_child(sub_chip_id, "twl6040-audio",
|
||||
pdata->codec, sizeof(*pdata->codec),
|
||||
false, 0, 0);
|
||||
if (IS_ERR(child))
|
||||
|
|
@ -923,9 +1010,36 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)
|
|||
return PTR_ERR(child);
|
||||
}
|
||||
|
||||
if (twl_has_regulator() && twl_class_is_6030()) {
|
||||
/*
|
||||
* For TWL6032 revision < ES1.1 with EEPROM revision < rev56.0
|
||||
* LDO6 and LDOLN must be always ON
|
||||
* if LDO6 or LDOLN is always on then SYSEN must be always on
|
||||
* for TWL6030 or TWL6032 revision >= ES1.1 with EEPROM
|
||||
* revision >= rev56.0 those LDOs can be off in sleep-mode
|
||||
*/
|
||||
if (features & TWL6032_SUBCLASS) {
|
||||
twl_i2c_read_u8(TWL6030_MODULE_ID2, &eepromrev,
|
||||
TWL6030_REG_EPROM_REV);
|
||||
|
||||
twl_i2c_read_u8(TWL6030_MODULE_ID2, &twlrev,
|
||||
TWL6030_REG_JTAGVERNUM);
|
||||
|
||||
if ((eepromrev < 56) && (twlrev < 1)) {
|
||||
SET_LDO_STATE_MEM(pdata->ldo6, false);
|
||||
SET_LDO_STATE_MEM(pdata->ldoln, false);
|
||||
SET_LDO_STATE_MEM(pdata->sysen, false);
|
||||
WARN(1, "This TWL6032 is an older revision that "
|
||||
"does not support low power "
|
||||
"measurements\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* twl6030 regulators */
|
||||
if (twl_has_regulator() && twl_class_is_6030() &&
|
||||
!(features & TWL6025_SUBCLASS)) {
|
||||
!(features & TWL6032_SUBCLASS)) {
|
||||
|
||||
child = add_regulator(TWL6030_REG_VMMC, pdata->vmmc,
|
||||
features);
|
||||
if (IS_ERR(child))
|
||||
|
|
@ -966,82 +1080,137 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)
|
|||
if (IS_ERR(child))
|
||||
return PTR_ERR(child);
|
||||
|
||||
child = add_regulator(TWL6030_REG_CLK32KG, pdata->clk32kg,
|
||||
child = add_regulator(TWL6030_REG_VDD1, pdata->vdd1,
|
||||
features);
|
||||
if (IS_ERR(child))
|
||||
return PTR_ERR(child);
|
||||
|
||||
child = add_regulator(TWL6030_REG_VDD2, pdata->vdd2,
|
||||
features);
|
||||
if (IS_ERR(child))
|
||||
return PTR_ERR(child);
|
||||
|
||||
child = add_regulator(TWL6030_REG_VDD3, pdata->vdd3,
|
||||
features);
|
||||
if (IS_ERR(child))
|
||||
return PTR_ERR(child);
|
||||
|
||||
child = add_regulator(TWL6030_REG_VMEM, pdata->vmem,
|
||||
features);
|
||||
if (IS_ERR(child))
|
||||
return PTR_ERR(child);
|
||||
|
||||
child = add_regulator(TWL6030_REG_V2V1, pdata->v2v1,
|
||||
features);
|
||||
if (IS_ERR(child))
|
||||
return PTR_ERR(child);
|
||||
}
|
||||
|
||||
/* 6030 and 6025 share this regulator */
|
||||
/* 6030 and 6032 share this regulator */
|
||||
if (twl_has_regulator() && twl_class_is_6030()) {
|
||||
child = add_regulator(TWL6030_REG_VANA, pdata->vana,
|
||||
features);
|
||||
if (IS_ERR(child))
|
||||
return PTR_ERR(child);
|
||||
child = add_regulator(TWL6030_REG_CLK32KG, pdata->clk32kg,
|
||||
features);
|
||||
if (IS_ERR(child))
|
||||
return PTR_ERR(child);
|
||||
|
||||
child = add_regulator(TWL6030_REG_CLK32KAUDIO,
|
||||
pdata->clk32kaudio, features);
|
||||
if (IS_ERR(child))
|
||||
return PTR_ERR(child);
|
||||
|
||||
child = add_regulator(TWL6030_REG_SYSEN,
|
||||
pdata->sysen, features);
|
||||
if (IS_ERR(child))
|
||||
return PTR_ERR(child);
|
||||
|
||||
child = add_regulator(TWL6030_REG_REGEN1,
|
||||
pdata->sysen, features);
|
||||
if (IS_ERR(child))
|
||||
return PTR_ERR(child);
|
||||
|
||||
}
|
||||
|
||||
/* twl6025 regulators */
|
||||
/* twl6032 regulators */
|
||||
if (twl_has_regulator() && twl_class_is_6030() &&
|
||||
(features & TWL6025_SUBCLASS)) {
|
||||
child = add_regulator(TWL6025_REG_LDO5, pdata->ldo5,
|
||||
(features & TWL6032_SUBCLASS)) {
|
||||
child = add_regulator(TWL6032_REG_LDO5, pdata->ldo5,
|
||||
features);
|
||||
if (IS_ERR(child))
|
||||
return PTR_ERR(child);
|
||||
|
||||
child = add_regulator(TWL6032_REG_LDO1, pdata->ldo1,
|
||||
features);
|
||||
if (IS_ERR(child))
|
||||
return PTR_ERR(child);
|
||||
|
||||
child = add_regulator(TWL6032_REG_LDO7, pdata->ldo7,
|
||||
features);
|
||||
if (IS_ERR(child))
|
||||
return PTR_ERR(child);
|
||||
|
||||
child = add_regulator(TWL6025_REG_LDO1, pdata->ldo1,
|
||||
child = add_regulator(TWL6032_REG_LDO6, pdata->ldo6,
|
||||
features);
|
||||
if (IS_ERR(child))
|
||||
return PTR_ERR(child);
|
||||
|
||||
child = add_regulator(TWL6025_REG_LDO7, pdata->ldo7,
|
||||
child = add_regulator(TWL6032_REG_LDOLN, pdata->ldoln,
|
||||
features);
|
||||
if (IS_ERR(child))
|
||||
return PTR_ERR(child);
|
||||
|
||||
child = add_regulator(TWL6025_REG_LDO6, pdata->ldo6,
|
||||
child = add_regulator(TWL6032_REG_LDO2, pdata->ldo2,
|
||||
features);
|
||||
if (IS_ERR(child))
|
||||
return PTR_ERR(child);
|
||||
|
||||
child = add_regulator(TWL6025_REG_LDOLN, pdata->ldoln,
|
||||
child = add_regulator(TWL6032_REG_LDO4, pdata->ldo4,
|
||||
features);
|
||||
if (IS_ERR(child))
|
||||
return PTR_ERR(child);
|
||||
|
||||
child = add_regulator(TWL6025_REG_LDO2, pdata->ldo2,
|
||||
child = add_regulator(TWL6032_REG_LDO3, pdata->ldo3,
|
||||
features);
|
||||
if (IS_ERR(child))
|
||||
return PTR_ERR(child);
|
||||
|
||||
child = add_regulator(TWL6025_REG_LDO4, pdata->ldo4,
|
||||
child = add_regulator(TWL6032_REG_SMPS3, pdata->smps3,
|
||||
features);
|
||||
if (IS_ERR(child))
|
||||
return PTR_ERR(child);
|
||||
|
||||
child = add_regulator(TWL6025_REG_LDO3, pdata->ldo3,
|
||||
child = add_regulator(TWL6032_REG_SMPS4, pdata->smps4,
|
||||
features);
|
||||
if (IS_ERR(child))
|
||||
return PTR_ERR(child);
|
||||
|
||||
child = add_regulator(TWL6025_REG_SMPS3, pdata->smps3,
|
||||
child = add_regulator(TWL6032_REG_SMPS1, pdata->smps1,
|
||||
features);
|
||||
if (IS_ERR(child))
|
||||
return PTR_ERR(child);
|
||||
|
||||
child = add_regulator(TWL6025_REG_SMPS4, pdata->smps4,
|
||||
child = add_regulator(TWL6032_REG_SMPS2, pdata->smps2,
|
||||
features);
|
||||
if (IS_ERR(child))
|
||||
return PTR_ERR(child);
|
||||
|
||||
child = add_regulator(TWL6032_REG_SMPS5, pdata->smps5,
|
||||
features);
|
||||
if (IS_ERR(child))
|
||||
return PTR_ERR(child);
|
||||
|
||||
child = add_regulator(TWL6025_REG_VIO, pdata->vio6025,
|
||||
|
||||
child = add_regulator(TWL6032_REG_VIO, pdata->vio6032,
|
||||
features);
|
||||
if (IS_ERR(child))
|
||||
return PTR_ERR(child);
|
||||
|
||||
}
|
||||
|
||||
if (twl_has_bci() && pdata->bci &&
|
||||
!(features & (TPS_SUBSET | TWL5031))) {
|
||||
!(features & (TPS_SUBSET | TWL5031)) && (features & TWL6030_CLASS)) {
|
||||
child = add_child(3, "twl4030_bci",
|
||||
pdata->bci, sizeof(*pdata->bci), false,
|
||||
/* irq0 = CHG_PRES, irq1 = BCI */
|
||||
|
|
@ -1146,13 +1315,22 @@ static void clocks_init(struct device *dev,
|
|||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
int twl4030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end);
|
||||
int twl4030_exit_irq(void);
|
||||
int twl4030_init_chip_irq(const char *chip);
|
||||
int twl6030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end);
|
||||
int twl6030_exit_irq(void);
|
||||
#ifdef CONFIG_PM
|
||||
static int twl_suspend(struct i2c_client *client, pm_message_t mesg)
|
||||
{
|
||||
return irq_set_irq_wake(client->irq, 1);
|
||||
}
|
||||
|
||||
static int twl_remove(struct i2c_client *client)
|
||||
static int twl_resume(struct i2c_client *client)
|
||||
{
|
||||
return irq_set_irq_wake(client->irq, 0);
|
||||
}
|
||||
#else
|
||||
#define twl_suspend NULL
|
||||
#define twl_resume NULL
|
||||
#endif
|
||||
|
||||
static int __devexit twl_remove(struct i2c_client *client)
|
||||
{
|
||||
unsigned i;
|
||||
int status;
|
||||
|
|
@ -1184,7 +1362,7 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
|||
unsigned i;
|
||||
struct twl4030_platform_data *pdata = client->dev.platform_data;
|
||||
u8 temp;
|
||||
int ret = 0;
|
||||
int ret = 0, features;
|
||||
|
||||
if (!pdata) {
|
||||
dev_dbg(&client->dev, "no platform data?\n");
|
||||
|
|
@ -1203,8 +1381,16 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
|||
|
||||
for (i = 0; i < TWL_NUM_SLAVES; i++) {
|
||||
struct twl_client *twl = &twl_modules[i];
|
||||
|
||||
|
||||
#if 0
|
||||
twl->address = client->addr + i;
|
||||
#else
|
||||
if( i <TWL_NUM_SLAVES-1 )
|
||||
twl->address = client->addr + i;
|
||||
else
|
||||
twl->address = 0x12; //DVS i2s address
|
||||
#endif
|
||||
|
||||
if (i == 0)
|
||||
twl->client = client;
|
||||
else {
|
||||
|
|
@ -1237,9 +1423,20 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
|||
WARN(ret < 0, "Error: reading twl_idcode register value\n");
|
||||
}
|
||||
|
||||
features = id->driver_data;
|
||||
if (twl_class_is_6030()) {
|
||||
twl_i2c_read_u8(TWL_MODULE_USB, &temp, USB_PRODUCT_ID_LSB);
|
||||
if (temp == 0x32)
|
||||
features |= TWL6032_SUBCLASS;
|
||||
}
|
||||
|
||||
/* load power event scripts */
|
||||
if (twl_has_power() && pdata->power)
|
||||
twl4030_power_init(pdata->power);
|
||||
if (twl_has_power()) {
|
||||
if (twl_class_is_4030() && pdata->power)
|
||||
twl4030_power_init(pdata->power);
|
||||
if (twl_class_is_6030())
|
||||
twl6030_power_init(pdata->power, features);
|
||||
}
|
||||
|
||||
/* Maybe init the T2 Interrupt subsystem */
|
||||
if (client->irq
|
||||
|
|
@ -1251,7 +1448,7 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
|||
pdata->irq_end);
|
||||
} else {
|
||||
status = twl6030_init_irq(client->irq, pdata->irq_base,
|
||||
pdata->irq_end);
|
||||
pdata->irq_end, features);
|
||||
}
|
||||
|
||||
if (status < 0)
|
||||
|
|
@ -1269,8 +1466,23 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
|||
I2C_SDA_CTRL_PU | I2C_SCL_CTRL_PU);
|
||||
twl_i2c_write_u8(TWL4030_MODULE_INTBR, temp, REG_GPPUPDCTR1);
|
||||
}
|
||||
|
||||
status = add_children(pdata, features);
|
||||
|
||||
status = add_children(pdata, id->driver_data);
|
||||
if (pdata && pdata->pre_init) {
|
||||
ret = pdata->pre_init();
|
||||
if (ret != 0) {
|
||||
printk(" tps80032 pre_init() failed: %d\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (pdata && pdata->set_init) {
|
||||
ret = pdata->set_init();
|
||||
if (ret != 0) {
|
||||
printk(" tps80032 set_init() failed: %d\n");
|
||||
}
|
||||
}
|
||||
|
||||
fail:
|
||||
if (status < 0)
|
||||
twl_remove(client);
|
||||
|
|
@ -1285,7 +1497,7 @@ static const struct i2c_device_id twl_ids[] = {
|
|||
{ "tps65930", TPS_SUBSET }, /* fewer LDOs and DACs; no charger */
|
||||
{ "tps65920", TPS_SUBSET }, /* fewer LDOs; no codec or charger */
|
||||
{ "twl6030", TWL6030_CLASS }, /* "Phoenix power chip" */
|
||||
{ "twl6025", TWL6030_CLASS | TWL6025_SUBCLASS }, /* "Phoenix lite" */
|
||||
{ "twl6032", TWL6030_CLASS | TWL6032_SUBCLASS }, /* Phoenix lite */
|
||||
{ /* end of list */ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, twl_ids);
|
||||
|
|
@ -1295,14 +1507,16 @@ static struct i2c_driver twl_driver = {
|
|||
.driver.name = DRIVER_NAME,
|
||||
.id_table = twl_ids,
|
||||
.probe = twl_probe,
|
||||
.remove = twl_remove,
|
||||
.remove = __devexit_p(twl_remove),
|
||||
.suspend = twl_suspend,
|
||||
.resume = twl_resume,
|
||||
};
|
||||
|
||||
static int __init twl_init(void)
|
||||
{
|
||||
return i2c_add_driver(&twl_driver);
|
||||
}
|
||||
subsys_initcall(twl_init);
|
||||
subsys_initcall_sync(twl_init);
|
||||
|
||||
static void __exit twl_exit(void)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
#ifndef __TWL_CORE_H__
|
||||
#define __TWL_CORE_H__
|
||||
|
||||
extern int twl6030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end);
|
||||
extern int twl6030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end,
|
||||
unsigned long features);
|
||||
extern int twl6030_exit_irq(void);
|
||||
extern int twl4030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end);
|
||||
extern int twl4030_exit_irq(void);
|
||||
|
|
|
|||
1446
drivers/mfd/twl6030-gpadc.c
Normal file
1446
drivers/mfd/twl6030-gpadc.c
Normal file
File diff suppressed because it is too large
Load Diff
|
|
@ -37,6 +37,8 @@
|
|||
#include <linux/kthread.h>
|
||||
#include <linux/i2c/twl.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/suspend.h>
|
||||
#include <linux/reboot.h>
|
||||
|
||||
#include "twl-core.h"
|
||||
|
||||
|
|
@ -52,10 +54,10 @@
|
|||
*
|
||||
*/
|
||||
|
||||
static int twl6030_interrupt_mapping[24] = {
|
||||
static int twl6030_interrupt_mapping_table[24] = {
|
||||
PWR_INTR_OFFSET, /* Bit 0 PWRON */
|
||||
PWR_INTR_OFFSET, /* Bit 1 RPWRON */
|
||||
PWR_INTR_OFFSET, /* Bit 2 BAT_VLOW */
|
||||
TWL_VLOW_INTR_OFFSET, /* Bit 2 BAT_VLOW */
|
||||
RTC_INTR_OFFSET, /* Bit 3 RTC_ALARM */
|
||||
RTC_INTR_OFFSET, /* Bit 4 RTC_PERIOD */
|
||||
HOTDIE_INTR_OFFSET, /* Bit 5 HOT_DIE */
|
||||
|
|
@ -68,7 +70,7 @@ static int twl6030_interrupt_mapping[24] = {
|
|||
MMCDETECT_INTR_OFFSET, /* Bit 11 MMC */
|
||||
RSV_INTR_OFFSET, /* Bit 12 Reserved */
|
||||
MADC_INTR_OFFSET, /* Bit 13 GPADC_RT_EOC */
|
||||
MADC_INTR_OFFSET, /* Bit 14 GPADC_SW_EOC */
|
||||
GPADCSW_INTR_OFFSET, /* Bit 14 GPADC_SW_EOC */
|
||||
GASGAUGE_INTR_OFFSET, /* Bit 15 CC_AUTOCAL */
|
||||
|
||||
USBOTG_INTR_OFFSET, /* Bit 16 ID_WKUP */
|
||||
|
|
@ -80,11 +82,85 @@ static int twl6030_interrupt_mapping[24] = {
|
|||
CHARGERFAULT_INTR_OFFSET, /* Bit 22 INT_CHRG */
|
||||
RSV_INTR_OFFSET, /* Bit 23 Reserved */
|
||||
};
|
||||
|
||||
static int twl6032_interrupt_mapping_table[24] = {
|
||||
PWR_INTR_OFFSET, /* Bit 0 PWRON */
|
||||
PWR_INTR_OFFSET, /* Bit 1 RPWRON */
|
||||
TWL_VLOW_INTR_OFFSET, /* Bit 2 SYS_VLOW */
|
||||
RTC_INTR_OFFSET, /* Bit 3 RTC_ALARM */
|
||||
RTC_INTR_OFFSET, /* Bit 4 RTC_PERIOD */
|
||||
HOTDIE_INTR_OFFSET, /* Bit 5 HOT_DIE */
|
||||
SMPSLDO_INTR_OFFSET, /* Bit 6 VXXX_SHORT */
|
||||
PWR_INTR_OFFSET, /* Bit 7 SPDURATION */
|
||||
|
||||
PWR_INTR_OFFSET, /* Bit 8 WATCHDOG */
|
||||
BATDETECT_INTR_OFFSET, /* Bit 9 BAT */
|
||||
SIMDETECT_INTR_OFFSET, /* Bit 10 SIM */
|
||||
MMCDETECT_INTR_OFFSET, /* Bit 11 MMC */
|
||||
MADC_INTR_OFFSET, /* Bit 12 GPADC_RT_EOC */
|
||||
GPADCSW_INTR_OFFSET, /* Bit 13 GPADC_SW_EOC */
|
||||
GASGAUGE_INTR_OFFSET, /* Bit 14 CC_EOC */
|
||||
GASGAUGE_INTR_OFFSET, /* Bit 15 CC_AUTOCAL */
|
||||
|
||||
USBOTG_INTR_OFFSET, /* Bit 16 ID_WKUP */
|
||||
USBOTG_INTR_OFFSET, /* Bit 17 VBUS_WKUP */
|
||||
USBOTG_INTR_OFFSET, /* Bit 18 ID */
|
||||
USB_PRES_INTR_OFFSET, /* Bit 19 VBUS */
|
||||
CHARGER_INTR_OFFSET, /* Bit 20 CHRG_CTRL */
|
||||
CHARGERFAULT_INTR_OFFSET, /* Bit 21 EXT_CHRG */
|
||||
CHARGERFAULT_INTR_OFFSET, /* Bit 22 INT_CHRG */
|
||||
RSV_INTR_OFFSET, /* Bit 23 Reserved */
|
||||
};
|
||||
|
||||
static int *twl6030_interrupt_mapping = twl6030_interrupt_mapping_table;
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
static unsigned twl6030_irq_base;
|
||||
static unsigned twl6030_irq_base, twl6030_irq_end;
|
||||
static int twl_irq;
|
||||
static bool twl_irq_wake_enabled;
|
||||
|
||||
static struct task_struct *task;
|
||||
static struct completion irq_event;
|
||||
static atomic_t twl6030_wakeirqs = ATOMIC_INIT(0);
|
||||
|
||||
static u8 vbatmin_hi_threshold;
|
||||
|
||||
static int twl6030_irq_pm_notifier(struct notifier_block *notifier,
|
||||
unsigned long pm_event, void *unused)
|
||||
{
|
||||
int chained_wakeups;
|
||||
|
||||
switch (pm_event) {
|
||||
case PM_SUSPEND_PREPARE:
|
||||
chained_wakeups = atomic_read(&twl6030_wakeirqs);
|
||||
|
||||
if (chained_wakeups && !twl_irq_wake_enabled) {
|
||||
if (enable_irq_wake(twl_irq))
|
||||
pr_err("twl6030 IRQ wake enable failed\n");
|
||||
else
|
||||
twl_irq_wake_enabled = true;
|
||||
} else if (!chained_wakeups && twl_irq_wake_enabled) {
|
||||
disable_irq_wake(twl_irq);
|
||||
twl_irq_wake_enabled = false;
|
||||
}
|
||||
|
||||
disable_irq(twl_irq);
|
||||
break;
|
||||
|
||||
case PM_POST_SUSPEND:
|
||||
enable_irq(twl_irq);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
static struct notifier_block twl6030_irq_pm_notifier_block = {
|
||||
.notifier_call = twl6030_irq_pm_notifier,
|
||||
};
|
||||
|
||||
/*
|
||||
* This thread processes interrupts reported by the Primary Interrupt Handler.
|
||||
|
|
@ -104,6 +180,7 @@ static int twl6030_irq_thread(void *data)
|
|||
u8 bytes[4];
|
||||
u32 int_sts;
|
||||
} sts;
|
||||
u32 int_sts; /* sts.int_sts converted to CPU endianness */
|
||||
|
||||
/* Wait for IRQ, then read PIH irq status (also blocking) */
|
||||
wait_for_completion_interruptible(&irq_event);
|
||||
|
|
@ -135,9 +212,10 @@ static int twl6030_irq_thread(void *data)
|
|||
if (sts.bytes[2] & 0x10)
|
||||
sts.bytes[2] |= 0x08;
|
||||
|
||||
for (i = 0; sts.int_sts; sts.int_sts >>= 1, i++) {
|
||||
int_sts = le32_to_cpu(sts.int_sts);
|
||||
for (i = 0; int_sts; int_sts >>= 1, i++) {
|
||||
local_irq_disable();
|
||||
if (sts.int_sts & 0x1) {
|
||||
if (int_sts & 0x1) {
|
||||
int module_irq = twl6030_irq_base +
|
||||
twl6030_interrupt_mapping[i];
|
||||
generic_handle_irq(module_irq);
|
||||
|
|
@ -145,8 +223,17 @@ static int twl6030_irq_thread(void *data)
|
|||
}
|
||||
local_irq_enable();
|
||||
}
|
||||
ret = twl_i2c_write(TWL_MODULE_PIH, sts.bytes,
|
||||
REG_INT_STS_A, 3); /* clear INT_STS_A */
|
||||
|
||||
/*
|
||||
* NOTE:
|
||||
* Simulation confirms that documentation is wrong w.r.t the
|
||||
* interrupt status clear operation. A single *byte* write to
|
||||
* any one of STS_A to STS_C register results in all three
|
||||
* STS registers being reset. Since it does not matter which
|
||||
* value is written, all three registers are cleared on a
|
||||
* single byte write, so we just use 0x0 to clear.
|
||||
*/
|
||||
ret = twl_i2c_write_u8(TWL_MODULE_PIH, 0x00, REG_INT_STS_A);
|
||||
if (ret)
|
||||
pr_warning("twl6030: I2C error in clearing PIH ISR\n");
|
||||
|
||||
|
|
@ -172,6 +259,26 @@ static irqreturn_t handle_twl6030_pih(int irq, void *devid)
|
|||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
/*
|
||||
* handle_twl6030_vlow() is a threaded BAT_VLOW interrupt handler. BAT_VLOW
|
||||
* is a secondary interrupt generated in twl6030_irq_thread().
|
||||
*/
|
||||
static irqreturn_t handle_twl6030_vlow(int irq, void *unused)
|
||||
{
|
||||
pr_err("twl6030: BAT_VLOW interrupt; threshold=%dmV\n",
|
||||
2300 + (vbatmin_hi_threshold - 0b110) * 50);
|
||||
|
||||
#if 1 /* temporary */
|
||||
pr_err("%s: disabling BAT_VLOW interrupt\n", __func__);
|
||||
disable_irq_nosync(twl6030_irq_base + TWL_VLOW_INTR_OFFSET);
|
||||
WARN_ON(1);
|
||||
#else
|
||||
pr_emerg("handle_twl6030_vlow: kernel_power_off()\n");
|
||||
kernel_power_off();
|
||||
#endif
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
static inline void activate_irq(int irq)
|
||||
|
|
@ -187,6 +294,16 @@ static inline void activate_irq(int irq)
|
|||
#endif
|
||||
}
|
||||
|
||||
int twl6030_irq_set_wake(struct irq_data *d, unsigned int on)
|
||||
{
|
||||
if (on)
|
||||
atomic_inc(&twl6030_wakeirqs);
|
||||
else
|
||||
atomic_dec(&twl6030_wakeirqs);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
static unsigned twl6030_irq_next;
|
||||
|
|
@ -261,6 +378,16 @@ int twl6030_mmc_card_detect_config(void)
|
|||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = twl_i2c_write_u8(TWL6030_MODULE_ID0,
|
||||
(MMC_MINS_DEB_MASK | MMC_MEXT_DEB_MASK),
|
||||
TWL6030_MMCDEBOUNCING);
|
||||
if (ret < 0){
|
||||
pr_err("twl6030: Failed to write MMC_MEXT_DEB_MASK %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(twl6030_mmc_card_detect_config);
|
||||
|
|
@ -290,16 +417,87 @@ int twl6030_mmc_card_detect(struct device *dev, int slot)
|
|||
}
|
||||
EXPORT_SYMBOL(twl6030_mmc_card_detect);
|
||||
|
||||
int twl6030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end)
|
||||
int twl6030_vlow_init(int vlow_irq)
|
||||
{
|
||||
int status;
|
||||
u8 val;
|
||||
|
||||
status = twl_i2c_read_u8(TWL_MODULE_PM_SLAVE_RES, &val,
|
||||
REG_VBATMIN_HI_CFG_STATE);
|
||||
if (status < 0) {
|
||||
pr_err("twl6030: I2C err reading REG_VBATMIN_HI_CFG_STATE: %d\n",
|
||||
status);
|
||||
return status;
|
||||
}
|
||||
|
||||
status = twl_i2c_write_u8(TWL_MODULE_PM_SLAVE_RES,
|
||||
val | VBATMIN_VLOW_EN, REG_VBATMIN_HI_CFG_STATE);
|
||||
if (status < 0) {
|
||||
pr_err("twl6030: I2C err writing REG_VBATMIN_HI_CFG_STATE: %d\n",
|
||||
status);
|
||||
return status;
|
||||
}
|
||||
|
||||
status = twl_i2c_read_u8(TWL_MODULE_PIH, &val, REG_INT_MSK_LINE_A);
|
||||
if (status < 0) {
|
||||
pr_err("twl6030: I2C err reading REG_INT_MSK_LINE_A: %d\n",
|
||||
status);
|
||||
return status;
|
||||
}
|
||||
|
||||
status = twl_i2c_write_u8(TWL_MODULE_PIH, val & ~VLOW_INT_MASK,
|
||||
REG_INT_MSK_LINE_A);
|
||||
if (status < 0) {
|
||||
pr_err("twl6030: I2C err writing REG_INT_MSK_LINE_A: %d\n",
|
||||
status);
|
||||
return status;
|
||||
}
|
||||
|
||||
status = twl_i2c_read_u8(TWL_MODULE_PIH, &val, REG_INT_MSK_STS_A);
|
||||
if (status < 0) {
|
||||
pr_err("twl6030: I2C err reading REG_INT_MSK_STS_A: %d\n",
|
||||
status);
|
||||
return status;
|
||||
}
|
||||
|
||||
status = twl_i2c_write_u8(TWL_MODULE_PIH, val & ~VLOW_INT_MASK,
|
||||
REG_INT_MSK_STS_A);
|
||||
if (status < 0) {
|
||||
pr_err("twl6030: I2C err writing REG_INT_MSK_STS_A: %d\n",
|
||||
status);
|
||||
return status;
|
||||
}
|
||||
|
||||
twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &vbatmin_hi_threshold,
|
||||
TWL6030_VBATMIN_HI_THRESHOLD);
|
||||
|
||||
/* install an irq handler for vlow */
|
||||
status = request_threaded_irq(vlow_irq, NULL, handle_twl6030_vlow,
|
||||
IRQF_ONESHOT,
|
||||
"TWL6030-VLOW", handle_twl6030_vlow);
|
||||
if (status < 0) {
|
||||
pr_err("twl6030: could not claim vlow irq %d: %d\n", vlow_irq,
|
||||
status);
|
||||
return status;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int twl6030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end,
|
||||
unsigned long features)
|
||||
{
|
||||
|
||||
int status = 0;
|
||||
int i;
|
||||
struct task_struct *task;
|
||||
int ret;
|
||||
u8 mask[4];
|
||||
|
||||
static struct irq_chip twl6030_irq_chip;
|
||||
|
||||
if (features & TWL6032_SUBCLASS)
|
||||
twl6030_interrupt_mapping = twl6032_interrupt_mapping_table;
|
||||
|
||||
mask[1] = 0xFF;
|
||||
mask[2] = 0xFF;
|
||||
mask[3] = 0xFF;
|
||||
|
|
@ -311,6 +509,7 @@ int twl6030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end)
|
|||
REG_INT_STS_A, 3); /* clear INT_STS_A,B,C */
|
||||
|
||||
twl6030_irq_base = irq_base;
|
||||
twl6030_irq_end = irq_end;
|
||||
|
||||
/* install an irq handler for each of the modules;
|
||||
* clone dummy irq_chip since PIH can't *do* anything
|
||||
|
|
@ -318,10 +517,12 @@ int twl6030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end)
|
|||
twl6030_irq_chip = dummy_irq_chip;
|
||||
twl6030_irq_chip.name = "twl6030";
|
||||
twl6030_irq_chip.irq_set_type = NULL;
|
||||
twl6030_irq_chip.irq_set_wake = twl6030_irq_set_wake;
|
||||
|
||||
for (i = irq_base; i < irq_end; i++) {
|
||||
irq_set_chip_and_handler(i, &twl6030_irq_chip,
|
||||
handle_simple_irq);
|
||||
irq_set_chip_data(i, (void *)irq_num);
|
||||
activate_irq(i);
|
||||
}
|
||||
|
||||
|
|
@ -344,10 +545,22 @@ int twl6030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end)
|
|||
pr_err("twl6030: could not claim irq%d: %d\n", irq_num, status);
|
||||
goto fail_irq;
|
||||
}
|
||||
|
||||
twl_irq = irq_num;
|
||||
register_pm_notifier(&twl6030_irq_pm_notifier_block);
|
||||
|
||||
status = twl6030_vlow_init(twl6030_irq_base + TWL_VLOW_INTR_OFFSET);
|
||||
if (status < 0)
|
||||
goto fail_vlow;
|
||||
|
||||
return status;
|
||||
fail_irq:
|
||||
|
||||
fail_vlow:
|
||||
free_irq(irq_num, &irq_event);
|
||||
|
||||
fail_irq:
|
||||
kthread_stop(task);
|
||||
|
||||
fail_kthread:
|
||||
for (i = irq_base; i < irq_end; i++)
|
||||
irq_set_chip_and_handler(i, NULL, NULL);
|
||||
|
|
@ -356,11 +569,25 @@ int twl6030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end)
|
|||
|
||||
int twl6030_exit_irq(void)
|
||||
{
|
||||
int i;
|
||||
unregister_pm_notifier(&twl6030_irq_pm_notifier_block);
|
||||
|
||||
if (twl6030_irq_base) {
|
||||
if (task)
|
||||
kthread_stop(task);
|
||||
|
||||
if (!twl6030_irq_base || !twl6030_irq_end) {
|
||||
pr_err("twl6030: can't yet clean up IRQs?\n");
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
free_irq(twl6030_irq_base + TWL_VLOW_INTR_OFFSET,
|
||||
handle_twl6030_vlow);
|
||||
|
||||
free_irq(twl_irq, &irq_event);
|
||||
|
||||
for (i = twl6030_irq_base; i < twl6030_irq_end; i++)
|
||||
irq_set_chip_and_handler(i, NULL, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
354
drivers/mfd/twl6030-madc.c
Normal file
354
drivers/mfd/twl6030-madc.c
Normal file
|
|
@ -0,0 +1,354 @@
|
|||
/*
|
||||
*
|
||||
* TWL6030 MADC module driver-This driver only implements the ADC read
|
||||
* functions
|
||||
*
|
||||
* Copyright (C) 2011 Samsung Telecommunications of America
|
||||
*
|
||||
* Based on twl4030-madc.c
|
||||
* Copyright (C) 2008 Nokia Corporation
|
||||
* Mikko Ylinen <mikko.k.ylinen@nokia.com>
|
||||
*
|
||||
* Amit Kucheria <amit.kucheria@canonical.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/i2c/twl.h>
|
||||
#include <linux/i2c/twl6030-madc.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/gfp.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/wakelock.h>
|
||||
|
||||
#define GPADCS (1 << 1)
|
||||
#define GPADCR (1 << 0)
|
||||
#define REG_TOGGLE1 0x90
|
||||
|
||||
#define DRIVER_NAME (twl6030_madc_driver.driver.name)
|
||||
static struct platform_driver twl6030_madc_driver;
|
||||
|
||||
/*
|
||||
* struct twl6030_madc_data - a container for madc info
|
||||
* @dev - pointer to device structure for madc
|
||||
* @lock - mutex protecting this data structure
|
||||
*/
|
||||
struct twl6030_madc_data {
|
||||
struct device *dev;
|
||||
struct mutex lock;
|
||||
struct dentry *file;
|
||||
struct wake_lock wakelock;
|
||||
};
|
||||
|
||||
static struct twl6030_madc_data *twl6030_madc;
|
||||
static u8 gpadc_ctrl_reg;
|
||||
|
||||
static inline int twl6030_madc_start_conversion(struct twl6030_madc_data *madc)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, GPADCS, REG_TOGGLE1);
|
||||
if (ret) {
|
||||
dev_err(madc->dev, "unable to write register 0x%X\n",
|
||||
REG_TOGGLE1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
udelay(100);
|
||||
ret = twl_i2c_write_u8(TWL_MODULE_MADC, TWL6030_MADC_SP1,
|
||||
TWL6030_MADC_CTRL_P1);
|
||||
if (ret) {
|
||||
dev_err(madc->dev, "unable to write register 0x%X\n",
|
||||
TWL6030_MADC_CTRL_P1);
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function that waits for conversion to be ready
|
||||
* @madc - pointer to twl4030_madc_data struct
|
||||
* @timeout_ms - timeout value in milliseconds
|
||||
* @status_reg - ctrl register
|
||||
* returns 0 if succeeds else a negative error value
|
||||
*/
|
||||
static int twl6030_madc_wait_conversion_ready(struct twl6030_madc_data *madc,
|
||||
unsigned int timeout_ms,
|
||||
u8 status_reg)
|
||||
{
|
||||
unsigned long timeout;
|
||||
unsigned long delta;
|
||||
u8 reg;
|
||||
int ret;
|
||||
|
||||
delta = msecs_to_jiffies(timeout_ms);
|
||||
|
||||
if (delta < 2)
|
||||
delta = 2;
|
||||
|
||||
wake_lock(&madc->wakelock);
|
||||
timeout = jiffies + delta;
|
||||
do {
|
||||
ret = twl_i2c_read_u8(TWL6030_MODULE_MADC, ®, status_reg);
|
||||
if (ret) {
|
||||
dev_err(madc->dev,
|
||||
"unable to read status register 0x%X\n",
|
||||
status_reg);
|
||||
goto unlock;
|
||||
}
|
||||
if (!(reg & TWL6030_MADC_BUSY) && (reg & TWL6030_MADC_EOCP1)) {
|
||||
ret = 0;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
if (time_after(jiffies, timeout))
|
||||
break;
|
||||
|
||||
usleep_range(500, 2000);
|
||||
} while (1);
|
||||
|
||||
dev_err(madc->dev, "conversion timeout, ctrl_px=0x%08x\n", reg);
|
||||
ret = -EAGAIN;
|
||||
|
||||
unlock:
|
||||
wake_unlock(&madc->wakelock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function to read a particular channel value.
|
||||
* @madc - pointer to struct twl6030_madc_data
|
||||
* @reg - lsb of ADC Channel
|
||||
* If the i2c read fails it returns an error else returns 0.
|
||||
*/
|
||||
static int twl6030_madc_channel_raw_read(struct twl6030_madc_data *madc,
|
||||
u8 reg)
|
||||
{
|
||||
u8 msb, lsb;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&madc->lock);
|
||||
ret = twl6030_madc_start_conversion(twl6030_madc);
|
||||
if (ret)
|
||||
goto unlock;
|
||||
|
||||
ret = twl6030_madc_wait_conversion_ready(twl6030_madc, 5,
|
||||
TWL6030_MADC_CTRL_P1);
|
||||
if (ret)
|
||||
goto unlock;
|
||||
|
||||
/*
|
||||
* For each ADC channel, we have MSB and LSB register
|
||||
* pair. MSB address is always LSB address+1. reg parameter is
|
||||
* the address of LSB register
|
||||
*/
|
||||
ret = twl_i2c_read_u8(TWL6030_MODULE_MADC, &msb, reg + 1);
|
||||
if (ret) {
|
||||
dev_err(madc->dev, "unable to read MSB register 0x%X\n",
|
||||
reg + 1);
|
||||
goto unlock;
|
||||
}
|
||||
ret = twl_i2c_read_u8(TWL6030_MODULE_MADC, &lsb, reg);
|
||||
if (ret) {
|
||||
dev_err(madc->dev, "unable to read LSB register 0x%X\n", reg);
|
||||
goto unlock;
|
||||
}
|
||||
ret = (int)((msb << 8) | lsb);
|
||||
unlock:
|
||||
/* Disable GPADC for power savings. */
|
||||
twl_i2c_write_u8(TWL6030_MODULE_ID1, GPADCR, REG_TOGGLE1);
|
||||
mutex_unlock(&madc->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return channel value
|
||||
* Or < 0 on failure.
|
||||
*/
|
||||
int twl6030_get_madc_conversion(int channel_no)
|
||||
{
|
||||
u8 reg = TWL6030_MADC_GPCH0_LSB + (2 * channel_no);
|
||||
if (!twl6030_madc) {
|
||||
pr_err("%s: No ADC device\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (channel_no >= TWL6030_MADC_MAX_CHANNELS) {
|
||||
dev_err(twl6030_madc->dev,
|
||||
"%s: Channel number (%d) exceeds max (%d)\n",
|
||||
__func__, channel_no, TWL6030_MADC_MAX_CHANNELS);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return twl6030_madc_channel_raw_read(twl6030_madc, reg);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(twl6030_get_madc_conversion);
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
|
||||
static int debug_twl6030_madc_show(struct seq_file *s, void *_)
|
||||
{
|
||||
int i, result;
|
||||
for (i = 0; i < TWL6030_MADC_MAX_CHANNELS; i++) {
|
||||
result = twl6030_get_madc_conversion(i);
|
||||
seq_printf(s, "channel %3d returns result %d\n",
|
||||
i, result);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int debug_twl6030_madc_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, debug_twl6030_madc_show, inode->i_private);
|
||||
}
|
||||
|
||||
static const struct file_operations debug_fops = {
|
||||
.open = debug_twl6030_madc_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
|
||||
#define DEBUG_FOPS (&debug_fops)
|
||||
|
||||
#else
|
||||
#define DEBUG_FOPS NULL
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Initialize MADC
|
||||
*/
|
||||
static int __devinit twl6030_madc_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct twl6030_madc_data *madc;
|
||||
struct twl4030_madc_platform_data *pdata = pdev->dev.platform_data;
|
||||
|
||||
if (!pdata) {
|
||||
dev_err(&pdev->dev, "platform_data not available\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
madc = kzalloc(sizeof(*madc), GFP_KERNEL);
|
||||
if (!madc)
|
||||
return -ENOMEM;
|
||||
|
||||
platform_set_drvdata(pdev, madc);
|
||||
madc->dev = &pdev->dev;
|
||||
mutex_init(&madc->lock);
|
||||
madc->file = debugfs_create_file(DRIVER_NAME, S_IRUGO, NULL,
|
||||
madc, DEBUG_FOPS);
|
||||
wake_lock_init(&madc->wakelock, WAKE_LOCK_SUSPEND, "twl6030 adc");
|
||||
twl6030_madc = madc;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devexit twl6030_madc_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct twl6030_madc_data *madc = platform_get_drvdata(pdev);
|
||||
|
||||
wake_lock_destroy(&madc->wakelock);
|
||||
mutex_destroy(&madc->lock);
|
||||
free_irq(platform_get_irq(pdev, 0), madc);
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
twl6030_madc = NULL;
|
||||
debugfs_remove(madc->file);
|
||||
kfree(madc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int twl6030_madc_suspend(struct device *pdev)
|
||||
{
|
||||
int ret;
|
||||
u8 reg_val;
|
||||
|
||||
ret = twl_i2c_read_u8(TWL_MODULE_MADC, ®_val, TWL6030_MADC_CTRL);
|
||||
if (!ret) {
|
||||
reg_val &= ~(TWL6030_MADC_TEMP1_EN);
|
||||
ret = twl_i2c_write_u8(TWL_MODULE_MADC, reg_val,
|
||||
TWL6030_MADC_CTRL);
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
dev_err(twl6030_madc->dev, "unable to disable madc temp1!\n");
|
||||
gpadc_ctrl_reg = TWL6030_MADC_TEMP1_EN;
|
||||
} else
|
||||
gpadc_ctrl_reg = reg_val;
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
static int twl6030_madc_resume(struct device *pdev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!(gpadc_ctrl_reg & TWL6030_MADC_TEMP1_EN)) {
|
||||
gpadc_ctrl_reg |= TWL6030_MADC_TEMP1_EN;
|
||||
ret = twl_i2c_write_u8(TWL_MODULE_MADC, gpadc_ctrl_reg,
|
||||
TWL6030_MADC_CTRL);
|
||||
if (ret)
|
||||
dev_err(twl6030_madc->dev,
|
||||
"unable to enable madc temp1!\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
static const struct dev_pm_ops twl6030_madc_pm_ops = {
|
||||
.suspend = twl6030_madc_suspend,
|
||||
.resume = twl6030_madc_resume,
|
||||
};
|
||||
|
||||
static struct platform_driver twl6030_madc_driver = {
|
||||
.probe = twl6030_madc_probe,
|
||||
.remove = __exit_p(twl6030_madc_remove),
|
||||
.driver = {
|
||||
.name = "twl6030_madc",
|
||||
.owner = THIS_MODULE,
|
||||
.pm = &twl6030_madc_pm_ops,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init twl6030_madc_init(void)
|
||||
{
|
||||
return platform_driver_register(&twl6030_madc_driver);
|
||||
}
|
||||
|
||||
module_init(twl6030_madc_init);
|
||||
|
||||
static void __exit twl6030_madc_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&twl6030_madc_driver);
|
||||
}
|
||||
|
||||
module_exit(twl6030_madc_exit);
|
||||
|
||||
MODULE_DESCRIPTION("TWL6030 ADC driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("J Keerthy");
|
||||
MODULE_ALIAS("platform:twl6030_madc");
|
||||
362
drivers/mfd/twl6030-power.c
Normal file
362
drivers/mfd/twl6030-power.c
Normal file
|
|
@ -0,0 +1,362 @@
|
|||
/*
|
||||
* Handling for Resource Mapping for TWL6030 Family of chips
|
||||
*
|
||||
* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
|
||||
* Nishanth Menon
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
|
||||
* This program is distributed "as is" WITHOUT ANY WARRANTY of any
|
||||
* kind, whether express or implied; without even the implied warranty
|
||||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/i2c/twl.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/suspend.h>
|
||||
#include <linux/string.h>
|
||||
|
||||
#include <asm/mach-types.h>
|
||||
|
||||
#define VREG_GRP 0
|
||||
#define MSK_TRANSITION_APP_SHIFT 0x5
|
||||
|
||||
static u8 dev_on_group;
|
||||
|
||||
/**
|
||||
* struct twl6030_resource_map - describe the resource mapping for TWL6030
|
||||
* @name: name of the resource
|
||||
* @res_id: resource ID
|
||||
* @base_addr: base address for TWL6030
|
||||
* @base_addr: type of the Resources Assignment register for TWL6032
|
||||
* base_addr = 0 for PREQx_RES_ASS_A register
|
||||
* base_addr = 1 for PREQx_RES_ASS_B register
|
||||
* base_addr = 2 for PREQx_RES_ASS_C register
|
||||
* @group: which device group can control this resource?
|
||||
* @mask: unused for TWL6030
|
||||
* @mask: bit mask of the resource in PREQx_RES_ASS_x registers for TWL6032
|
||||
*/
|
||||
struct twl6030_resource_map {
|
||||
char *name;
|
||||
u8 res_id;
|
||||
u8 base_addr;
|
||||
u8 group;
|
||||
u8 mask;
|
||||
};
|
||||
|
||||
#define TWL6030_RES_DATA(ID, NAME, BASE_ADDR, GROUP) \
|
||||
{.res_id = ID, .name = NAME, .base_addr = BASE_ADDR,\
|
||||
.group = GROUP, .mask = 0,}
|
||||
|
||||
#define TWL6032_RES_DATA(ID, NAME, BASE_ADDR, GROUP, MASK) \
|
||||
{.res_id = ID, .name = NAME, .base_addr = BASE_ADDR,\
|
||||
.group = GROUP, .mask = MASK,}
|
||||
|
||||
/* list of all s/w modifiable resources in TWL6030 */
|
||||
static __initdata struct twl6030_resource_map twl6030_res_map[] = {
|
||||
TWL6030_RES_DATA(RES_V1V29, "V1V29", 0x40, DEV_GRP_P1),
|
||||
TWL6030_RES_DATA(RES_V1V8, "V1V8", 0x46, DEV_GRP_P1),
|
||||
TWL6030_RES_DATA(RES_V2V1, "V2V1", 0x4c, DEV_GRP_P1),
|
||||
TWL6030_RES_DATA(RES_VDD1, "CORE1", 0x52, DEV_GRP_P1),
|
||||
TWL6030_RES_DATA(RES_VDD2, "CORE2", 0x58, DEV_GRP_P1),
|
||||
TWL6030_RES_DATA(RES_VDD3, "CORE3", 0x5e, DEV_GRP_P1),
|
||||
TWL6030_RES_DATA(RES_VMEM, "VMEM", 0x64, DEV_GRP_P1),
|
||||
/* VANA cannot be modified */
|
||||
TWL6030_RES_DATA(RES_VUAX1, "VUAX1", 0x84, DEV_GRP_P1),
|
||||
TWL6030_RES_DATA(RES_VAUX2, "VAUX2", 0x88, DEV_GRP_P1),
|
||||
TWL6030_RES_DATA(RES_VAUX3, "VAUX3", 0x8c, DEV_GRP_P1),
|
||||
TWL6030_RES_DATA(RES_VCXIO, "VCXIO", 0x90, DEV_GRP_P1),
|
||||
TWL6030_RES_DATA(RES_VDAC, "VDAC", 0x94, DEV_GRP_P1),
|
||||
TWL6030_RES_DATA(RES_VMMC1, "VMMC", 0x98, DEV_GRP_P1),
|
||||
TWL6030_RES_DATA(RES_VPP, "VPP", 0x9c, DEV_GRP_P1),
|
||||
/* VRTC cannot be modified */
|
||||
TWL6030_RES_DATA(RES_VUSBCP, "VUSB", 0xa0, DEV_GRP_P1),
|
||||
TWL6030_RES_DATA(RES_VSIM, "VSIM", 0xa4, DEV_GRP_P1),
|
||||
TWL6030_RES_DATA(RES_REGEN, "REGEN1", 0xad, DEV_GRP_P1),
|
||||
TWL6030_RES_DATA(RES_REGEN2, "REGEN2", 0xb0, DEV_GRP_P1),
|
||||
TWL6030_RES_DATA(RES_SYSEN, "SYSEN", 0xb3, DEV_GRP_P1),
|
||||
/* NRES_PWRON cannot be modified */
|
||||
/* 32KCLKAO cannot be modified */
|
||||
TWL6030_RES_DATA(RES_32KCLKG, "32KCLKG", 0xbc, DEV_GRP_P1),
|
||||
TWL6030_RES_DATA(RES_32KCLKAUDIO, "32KCLKAUDIO", 0xbf, DEV_GRP_P1),
|
||||
/* BIAS cannot be modified */
|
||||
/* VBATMIN_HI cannot be modified */
|
||||
/* RC6MHZ cannot be modified */
|
||||
/* TEMP cannot be modified */
|
||||
};
|
||||
|
||||
/* list of all s/w modifiable resources in TWL6032 */
|
||||
static __initdata struct twl6030_resource_map twl6032_res_map[] = {
|
||||
/* PREQx_RES_ASS_A register resources */
|
||||
TWL6032_RES_DATA(RES_LDOUSB, "VUSB", 0, DEV_GRP_P1, BIT(5)),
|
||||
TWL6032_RES_DATA(RES_SMPS5, "SMPS5", 0, DEV_GRP_P1, BIT(4)),
|
||||
TWL6032_RES_DATA(RES_SMPS5, "SMPS4", 0, DEV_GRP_P1, BIT(3)),
|
||||
TWL6032_RES_DATA(RES_SMPS5, "SMPS3", 0, DEV_GRP_P1, BIT(2)),
|
||||
TWL6032_RES_DATA(RES_SMPS5, "SMPS2", 0, DEV_GRP_P1, BIT(1)),
|
||||
TWL6032_RES_DATA(RES_SMPS5, "SMPS1", 0, DEV_GRP_P1, BIT(0)),
|
||||
/* PREQx_RES_ASS_B register resources */
|
||||
TWL6032_RES_DATA(RES_LDOLN, "LDOLN", 1, DEV_GRP_P1, BIT(7)),
|
||||
TWL6032_RES_DATA(RES_LDO7, "LDO7", 1, DEV_GRP_P1, BIT(6)),
|
||||
TWL6032_RES_DATA(RES_LDO6, "LDO6", 1, DEV_GRP_P1, BIT(5)),
|
||||
TWL6032_RES_DATA(RES_LDO5, "LDO5", 1, DEV_GRP_P1, BIT(4)),
|
||||
TWL6032_RES_DATA(RES_LDO4, "LDO4", 1, DEV_GRP_P1, BIT(3)),
|
||||
TWL6032_RES_DATA(RES_LDO3, "LDO3", 1, DEV_GRP_P1, BIT(2)),
|
||||
TWL6032_RES_DATA(RES_LDO2, "LDO2", 1, DEV_GRP_P1, BIT(1)),
|
||||
TWL6032_RES_DATA(RES_LDO1, "LDO1", 1, DEV_GRP_P1, BIT(0)),
|
||||
/* PREQx_RES_ASS_C register resources */
|
||||
TWL6032_RES_DATA(RES_VSYSMIN_HI, "VSYSMIN_HI", 2, DEV_GRP_P1, BIT(5)),
|
||||
TWL6032_RES_DATA(RES_32KCLKG, "32KCLKG", 2, DEV_GRP_P1, BIT(4)),
|
||||
TWL6032_RES_DATA(RES_32KCLKAUDIO, "32KCLKAUDIO", 2, DEV_GRP_P1, BIT(3)),
|
||||
TWL6032_RES_DATA(RES_SYSEN, "SYSEN", 2, DEV_GRP_P1, BIT(2)),
|
||||
TWL6032_RES_DATA(RES_REGEN2, "REGEN2", 2, DEV_GRP_P1, BIT(1)),
|
||||
TWL6032_RES_DATA(RES_REGEN, "REGEN1", 2, DEV_GRP_P1, BIT(0)),
|
||||
};
|
||||
|
||||
static struct twl4030_system_config twl6030_sys_config[] = {
|
||||
{.name = "DEV_ON", .group = DEV_GRP_P1,},
|
||||
};
|
||||
|
||||
/* Actual power groups that TWL understands */
|
||||
#define P3_GRP_6030 BIT(2) /* secondary processor, modem, etc */
|
||||
#define P2_GRP_6030 BIT(1) /* "peripherals" */
|
||||
#define P1_GRP_6030 BIT(0) /* CPU/Linux */
|
||||
|
||||
static __init void twl6030_process_system_config(void)
|
||||
{
|
||||
u8 grp;
|
||||
int r;
|
||||
bool i = false;
|
||||
|
||||
struct twl4030_system_config *sys_config;
|
||||
sys_config = twl6030_sys_config;
|
||||
|
||||
while (sys_config && sys_config->name) {
|
||||
if (!strcmp(sys_config->name, "DEV_ON")) {
|
||||
dev_on_group = sys_config->group;
|
||||
i = true;
|
||||
break;
|
||||
}
|
||||
sys_config++;
|
||||
}
|
||||
if (!i)
|
||||
pr_err("%s: Couldn't find DEV_ON resource configuration!"
|
||||
" MOD & CON group would be kept active.\n", __func__);
|
||||
|
||||
if (dev_on_group) {
|
||||
r = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &grp,
|
||||
TWL6030_PHOENIX_DEV_ON);
|
||||
if (r) {
|
||||
pr_err("%s: Error(%d) reading {addr=0x%02x}",
|
||||
__func__, r, TWL6030_PHOENIX_DEV_ON);
|
||||
/*
|
||||
* On error resetting to 0, so that all the process
|
||||
* groups are kept active.
|
||||
*/
|
||||
dev_on_group = 0;
|
||||
} else {
|
||||
/*
|
||||
* Unmapped processor groups are disabled by writing
|
||||
* 1 to corresponding group in DEV_ON.
|
||||
*/
|
||||
grp |= (dev_on_group & DEV_GRP_P1) ? 0 : P1_GRP_6030;
|
||||
grp |= (dev_on_group & DEV_GRP_P2) ? 0 : P2_GRP_6030;
|
||||
grp |= (dev_on_group & DEV_GRP_P3) ? 0 : P3_GRP_6030;
|
||||
dev_on_group = grp;
|
||||
}
|
||||
|
||||
/*
|
||||
* unmask PREQ transition Executes ACT2SLP and SLP2ACT sleep
|
||||
* sequence
|
||||
*/
|
||||
r = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &grp,
|
||||
TWL6030_PM_MASTER_MSK_TRANSITION);
|
||||
if (r) {
|
||||
pr_err("%s: Error (%d) reading"
|
||||
" TWL6030_MSK_TRANSITION\n", __func__, r);
|
||||
return;
|
||||
}
|
||||
|
||||
grp &= (dev_on_group << MSK_TRANSITION_APP_SHIFT);
|
||||
|
||||
r = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, grp,
|
||||
TWL6030_PM_MASTER_MSK_TRANSITION);
|
||||
if (r)
|
||||
pr_err("%s: Error (%d) writing to"
|
||||
" TWL6030_MSK_TRANSITION\n", __func__, r);
|
||||
}
|
||||
}
|
||||
|
||||
#define DEV_GRP_P1_OFFSET 1
|
||||
#define DEV_GRP_P2_OFFSET 4
|
||||
#define DEV_GRP_P3_OFFSET 7
|
||||
|
||||
static __init void twl6030_program_map(unsigned long features)
|
||||
{
|
||||
struct twl6030_resource_map *res;
|
||||
int r, i;
|
||||
|
||||
if (features & TWL6032_SUBCLASS) {
|
||||
/**
|
||||
* mask[0] = 0 for twl_i2c_write
|
||||
* mask[1]-mask[3]: PREQ1_RES_ASS_A - PREQ1_RES_ASS_C
|
||||
* mask[4]-mask[6]: PREQ2_RES_ASS_A - PREQ2_RES_ASS_C
|
||||
* mask[7]-mask[9]: PREQ3_RES_ASS_A - PREQ3_RES_ASS_C
|
||||
*/
|
||||
u8 mask[10];
|
||||
|
||||
res = twl6032_res_map;
|
||||
memset(&mask[0], 0, 10);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(twl6032_res_map); i++) {
|
||||
/* map back from generic device id to TWL6032 mask */
|
||||
mask[DEV_GRP_P1_OFFSET + res->base_addr] |= \
|
||||
(res->group & DEV_GRP_P1) ? res->mask : 0;
|
||||
mask[DEV_GRP_P2_OFFSET + res->base_addr] |= \
|
||||
(res->group & DEV_GRP_P2) ? res->mask : 0;
|
||||
mask[DEV_GRP_P3_OFFSET + res->base_addr] |= \
|
||||
(res->group & DEV_GRP_P3) ? res->mask : 0;
|
||||
res++;
|
||||
}
|
||||
|
||||
r = twl_i2c_write(TWL6030_MODULE_ID0, &mask[0],
|
||||
TWL6032_PREQ1_RES_ASS_A, 9);
|
||||
|
||||
if (r)
|
||||
pr_err("%s: Error(%d) programming TWL6032 PREQ "
|
||||
"Assignment Registers {start addr=0xd7}\n",
|
||||
__func__, r);
|
||||
} else {
|
||||
res = twl6030_res_map;
|
||||
for (i = 0; i < ARRAY_SIZE(twl6030_res_map); i++) {
|
||||
u8 grp = 0;
|
||||
|
||||
/* map back from generic device id to TWL6030 ID */
|
||||
grp |= (res->group & DEV_GRP_P1) ? P1_GRP_6030 : 0;
|
||||
grp |= (res->group & DEV_GRP_P2) ? P2_GRP_6030 : 0;
|
||||
grp |= (res->group & DEV_GRP_P3) ? P3_GRP_6030 : 0;
|
||||
|
||||
r = twl_i2c_write_u8(TWL6030_MODULE_ID0, res->group,
|
||||
res->base_addr);
|
||||
if (r)
|
||||
pr_err("%s: Error(%d) programming map %s {"
|
||||
"addr=0x%02x},grp=0x%02X\n", __func__,
|
||||
r, res->name, res->base_addr,
|
||||
res->group);
|
||||
res++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static __init void twl6030_update_system_map
|
||||
(struct twl4030_system_config *sys_list)
|
||||
{
|
||||
int i;
|
||||
struct twl4030_system_config *sys_res;
|
||||
|
||||
while (sys_list && sys_list->name) {
|
||||
sys_res = twl6030_sys_config;
|
||||
for (i = 0; i < ARRAY_SIZE(twl6030_sys_config); i++) {
|
||||
if (!strcmp(sys_res->name, sys_list->name))
|
||||
sys_res->group = sys_list->group &
|
||||
(DEV_GRP_P1 | DEV_GRP_P2 | DEV_GRP_P3);
|
||||
sys_res++;
|
||||
}
|
||||
sys_list++;
|
||||
}
|
||||
}
|
||||
|
||||
static __init void twl6030_update_map(struct twl4030_resconfig *res_list, \
|
||||
unsigned long features)
|
||||
{
|
||||
int i, res_idx = 0;
|
||||
struct twl6030_resource_map *res;
|
||||
struct twl6030_resource_map *cur_twl6030_res = twl6030_res_map;
|
||||
int twl6030_res_cnt = ARRAY_SIZE(twl6030_res_map);
|
||||
|
||||
if (features & TWL6032_SUBCLASS) {
|
||||
cur_twl6030_res = twl6032_res_map;
|
||||
twl6030_res_cnt = ARRAY_SIZE(twl6032_res_map);
|
||||
}
|
||||
|
||||
while (res_list->resource != TWL4030_RESCONFIG_UNDEF) {
|
||||
res = cur_twl6030_res;
|
||||
for (i = 0; i < twl6030_res_cnt; i++) {
|
||||
if (res->res_id == res_list->resource) {
|
||||
res->group = res_list->devgroup &
|
||||
(DEV_GRP_P1 | DEV_GRP_P2 | DEV_GRP_P3);
|
||||
break;
|
||||
}
|
||||
res++;
|
||||
}
|
||||
|
||||
if (i == twl6030_res_cnt) {
|
||||
pr_err("%s: in platform_data resource index %d, cannot"
|
||||
" find match for resource 0x%02x. NO Update!\n",
|
||||
__func__, res_idx, res_list->resource);
|
||||
}
|
||||
res_list++;
|
||||
res_idx++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int twl6030_power_notifier_cb(struct notifier_block *notifier,
|
||||
unsigned long pm_event, void *unused)
|
||||
{
|
||||
int r = 0;
|
||||
|
||||
switch (pm_event) {
|
||||
case PM_SUSPEND_PREPARE:
|
||||
r = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, dev_on_group,
|
||||
TWL6030_PHOENIX_DEV_ON);
|
||||
if (r)
|
||||
pr_err("%s: Error(%d) programming {addr=0x%02x}",
|
||||
__func__, r, TWL6030_PHOENIX_DEV_ON);
|
||||
break;
|
||||
}
|
||||
|
||||
return notifier_from_errno(r);
|
||||
}
|
||||
|
||||
static struct notifier_block twl6030_power_pm_notifier = {
|
||||
.notifier_call = twl6030_power_notifier_cb,
|
||||
};
|
||||
|
||||
/**
|
||||
* twl6030_power_init() - Update the power map to reflect connectivity of board
|
||||
* @power_data: power resource map to update (OPTIONAL) - use this if a resource
|
||||
* is used by other devices other than APP (DEV_GRP_P1)
|
||||
*/
|
||||
void __init twl6030_power_init(struct twl4030_power_data *power_data, \
|
||||
unsigned long features)
|
||||
{
|
||||
int r;
|
||||
|
||||
if (power_data && (!power_data->resource_config &&
|
||||
!power_data->sys_config)) {
|
||||
pr_err("%s: power data from platform without configuration!\n",
|
||||
__func__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (power_data && power_data->resource_config)
|
||||
twl6030_update_map(power_data->resource_config, features);
|
||||
|
||||
if (power_data && power_data->sys_config)
|
||||
twl6030_update_system_map(power_data->sys_config);
|
||||
|
||||
twl6030_process_system_config();
|
||||
|
||||
twl6030_program_map(features);
|
||||
|
||||
r = register_pm_notifier(&twl6030_power_pm_notifier);
|
||||
if (r)
|
||||
pr_err("%s: twl6030 power registration failed!\n", __func__);
|
||||
|
||||
return;
|
||||
}
|
||||
74
drivers/mfd/twl6030-poweroff.c
Normal file
74
drivers/mfd/twl6030-poweroff.c
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* /drivers/mfd/twl6030-poweroff.c
|
||||
*
|
||||
* Power off device
|
||||
*
|
||||
* Copyright (C) 2011 Texas Instruments Corporation
|
||||
*
|
||||
* Written by Rajeev Kulkarni <rajeevk@ti.com>
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General
|
||||
* Public License. See the file "COPYING" in the main directory of this
|
||||
* archive for more details.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/i2c/twl.h>
|
||||
|
||||
#define APP_DEVOFF (1<<0)
|
||||
#define CON_DEVOFF (1<<1)
|
||||
#define MOD_DEVOFF (1<<2)
|
||||
|
||||
void twl6030_poweroff(void)
|
||||
{
|
||||
u8 val = 0;
|
||||
int err = 0;
|
||||
|
||||
err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &val,
|
||||
TWL6030_PHOENIX_DEV_ON);
|
||||
if (err) {
|
||||
pr_warning("I2C error %d reading PHOENIX_DEV_ON\n", err);
|
||||
return;
|
||||
}
|
||||
|
||||
val |= APP_DEVOFF | CON_DEVOFF | MOD_DEVOFF;
|
||||
|
||||
err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, val,
|
||||
TWL6030_PHOENIX_DEV_ON);
|
||||
|
||||
if (err) {
|
||||
pr_warning("I2C error %d writing PHOENIX_DEV_ON\n", err);
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static int __init twl6030_poweroff_init(void)
|
||||
{
|
||||
pm_power_off = twl6030_poweroff;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit twl6030_poweroff_exit(void)
|
||||
{
|
||||
pm_power_off = NULL;
|
||||
}
|
||||
|
||||
module_init(twl6030_poweroff_init);
|
||||
module_exit(twl6030_poweroff_exit);
|
||||
|
||||
MODULE_DESCRIPTION("TLW6030 device power off");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Rajeev Kulkarni");
|
||||
401
drivers/regulator/twl-regulator.c
Normal file → Executable file
401
drivers/regulator/twl-regulator.c
Normal file → Executable file
|
|
@ -76,12 +76,25 @@ struct twlreg_info {
|
|||
#define VREG_STATE 2
|
||||
#define VREG_VOLTAGE 3
|
||||
#define VREG_VOLTAGE_SMPS 4
|
||||
#define VREG_VOLTAGE_DVS_SMPS 3 //add
|
||||
/* TWL6030 Misc register offsets */
|
||||
#define VREG_BC_ALL 1
|
||||
#define VREG_BC_REF 2
|
||||
#define VREG_BC_PROC 3
|
||||
#define VREG_BC_CLK_RST 4
|
||||
|
||||
/* TWL6030 LDO register values for CFG_TRANS */
|
||||
#define TWL6030_CFG_TRANS_STATE_MASK 0x03
|
||||
#define TWL6030_CFG_TRANS_STATE_OFF 0x00
|
||||
/*
|
||||
* Auto means the following:
|
||||
* SMPS: AUTO(PWM/PFM)
|
||||
* LDO: AMS(SLP/ACT)
|
||||
* resource: ON
|
||||
*/
|
||||
#define TWL6030_CFG_TRANS_STATE_AUTO 0x01
|
||||
#define TWL6030_CFG_TRANS_SLEEP_SHIFT 2
|
||||
|
||||
/* TWL6030 LDO register values for CFG_STATE */
|
||||
#define TWL6030_CFG_STATE_OFF 0x00
|
||||
#define TWL6030_CFG_STATE_ON 0x01
|
||||
|
|
@ -89,7 +102,9 @@ struct twlreg_info {
|
|||
#define TWL6030_CFG_STATE_SLEEP 0x03
|
||||
#define TWL6030_CFG_STATE_GRP_SHIFT 5
|
||||
#define TWL6030_CFG_STATE_APP_SHIFT 2
|
||||
#define TWL6030_CFG_STATE_APP_MASK (0x03 << TWL6030_CFG_STATE_APP_SHIFT)
|
||||
#define TWL6030_CFG_STATE_MASK 0x03
|
||||
#define TWL6030_CFG_STATE_APP_MASK (TWL6030_CFG_STATE_MASK << \
|
||||
TWL6030_CFG_STATE_APP_SHIFT)
|
||||
#define TWL6030_CFG_STATE_APP(v) (((v) & TWL6030_CFG_STATE_APP_MASK) >>\
|
||||
TWL6030_CFG_STATE_APP_SHIFT)
|
||||
|
||||
|
|
@ -97,19 +112,32 @@ struct twlreg_info {
|
|||
#define SMPS_OFFSET_EN BIT(0)
|
||||
#define SMPS_EXTENDED_EN BIT(1)
|
||||
|
||||
/* twl6025 SMPS EPROM values */
|
||||
/* twl6032 SMPS EPROM values */
|
||||
#define TWL6030_SMPS_OFFSET 0xB0
|
||||
#define TWL6030_SMPS_MULT 0xB3
|
||||
#define SMPS_MULTOFFSET_SMPS4 BIT(0)
|
||||
#define SMPS_MULTOFFSET_VIO BIT(1)
|
||||
#define SMPS_MULTOFFSET_SMPS3 BIT(6)
|
||||
|
||||
|
||||
|
||||
/* TWL6030 VUSB supplemental config registers */
|
||||
#define TWL6030_MISC2 0xE5
|
||||
#define TWL6030_CFG_LDO_PD2 0xF5
|
||||
|
||||
/*
|
||||
* TWL603X SMPS has 6 bits xxxx_CFG_VOLTAGE.VSEL[5:0] to configure voltages and
|
||||
* each bit combination corresponds to a particular voltage (value 63 is
|
||||
* reserved).
|
||||
*/
|
||||
#define TWL603X_SMPS_VSEL_MASK 0x3F
|
||||
#define TWL603X_SMPS_NUMBER_VOLTAGES TWL603X_SMPS_VSEL_MASK
|
||||
|
||||
static inline int
|
||||
twlreg_read(struct twlreg_info *info, unsigned slave_subgp, unsigned offset)
|
||||
{
|
||||
u8 value;
|
||||
int status;
|
||||
|
||||
status = twl_i2c_read_u8(slave_subgp,
|
||||
&value, info->base + offset);
|
||||
return (status < 0) ? status : value;
|
||||
|
|
@ -161,22 +189,49 @@ static int twl6030reg_is_enabled(struct regulator_dev *rdev)
|
|||
struct twlreg_info *info = rdev_get_drvdata(rdev);
|
||||
int grp = 0, val;
|
||||
|
||||
if (!(twl_class_is_6030() && (info->features & TWL6025_SUBCLASS)))
|
||||
if (!(info->features & TWL6032_SUBCLASS)) {
|
||||
grp = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_GRP);
|
||||
if (grp < 0)
|
||||
return grp;
|
||||
if (grp < 0)
|
||||
return grp;
|
||||
|
||||
if (!(twl_class_is_6030() && (info->features & TWL6025_SUBCLASS)))
|
||||
grp &= P1_GRP_6030;
|
||||
else
|
||||
val = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_STATE);
|
||||
val = TWL6030_CFG_STATE_APP(val);
|
||||
} else {
|
||||
val = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_STATE);
|
||||
val &= TWL6030_CFG_STATE_MASK;
|
||||
grp = 1;
|
||||
|
||||
val = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_STATE);
|
||||
val = TWL6030_CFG_STATE_APP(val);
|
||||
}
|
||||
|
||||
return grp && (val == TWL6030_CFG_STATE_ON);
|
||||
}
|
||||
|
||||
static int twl6030reg_set_trans_state(struct regulator_dev *rdev,
|
||||
u8 shift, u8 val)
|
||||
{
|
||||
struct twlreg_info *info = rdev_get_drvdata(rdev);
|
||||
int rval;
|
||||
u8 mask;
|
||||
|
||||
/* Read CFG_TRANS register of TWL6030 */
|
||||
rval = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_TRANS);
|
||||
|
||||
if (rval < 0)
|
||||
return rval;
|
||||
|
||||
mask = TWL6030_CFG_TRANS_STATE_MASK << shift;
|
||||
val = (val << shift) & mask;
|
||||
|
||||
/* If value is already set, no need to write to reg */
|
||||
if (val == (rval & mask))
|
||||
return 0;
|
||||
|
||||
rval &= ~mask;
|
||||
rval |= val;
|
||||
|
||||
return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_TRANS, rval);
|
||||
}
|
||||
|
||||
static int twl4030reg_enable(struct regulator_dev *rdev)
|
||||
{
|
||||
struct twlreg_info *info = rdev_get_drvdata(rdev);
|
||||
|
|
@ -202,7 +257,7 @@ static int twl6030reg_enable(struct regulator_dev *rdev)
|
|||
int grp = 0;
|
||||
int ret;
|
||||
|
||||
if (!(twl_class_is_6030() && (info->features & TWL6025_SUBCLASS)))
|
||||
if (!(twl_class_is_6030() && (info->features & TWL6032_SUBCLASS)))
|
||||
grp = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_GRP);
|
||||
if (grp < 0)
|
||||
return grp;
|
||||
|
|
@ -210,7 +265,14 @@ static int twl6030reg_enable(struct regulator_dev *rdev)
|
|||
ret = twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_STATE,
|
||||
grp << TWL6030_CFG_STATE_GRP_SHIFT |
|
||||
TWL6030_CFG_STATE_ON);
|
||||
|
||||
/*
|
||||
* Ensure it stays in Auto mode when we enter suspend state.
|
||||
* (TWL6030 in sleep mode).
|
||||
*/
|
||||
if (!ret)
|
||||
ret = twl6030reg_set_trans_state(rdev,
|
||||
TWL6030_CFG_TRANS_SLEEP_SHIFT,
|
||||
TWL6030_CFG_TRANS_STATE_AUTO);
|
||||
udelay(info->delay);
|
||||
|
||||
return ret;
|
||||
|
|
@ -239,7 +301,7 @@ static int twl6030reg_disable(struct regulator_dev *rdev)
|
|||
int grp = 0;
|
||||
int ret;
|
||||
|
||||
if (!(twl_class_is_6030() && (info->features & TWL6025_SUBCLASS)))
|
||||
if (!(twl_class_is_6030() && (info->features & TWL6032_SUBCLASS)))
|
||||
grp = P1_GRP_6030 | P2_GRP_6030 | P3_GRP_6030;
|
||||
|
||||
/* For 6030, set the off state for all grps enabled */
|
||||
|
|
@ -247,6 +309,11 @@ static int twl6030reg_disable(struct regulator_dev *rdev)
|
|||
(grp) << TWL6030_CFG_STATE_GRP_SHIFT |
|
||||
TWL6030_CFG_STATE_OFF);
|
||||
|
||||
/* Ensure it remains OFF when we enter suspend (TWL6030 in sleep). */
|
||||
if (!ret)
|
||||
ret = twl6030reg_set_trans_state(rdev,
|
||||
TWL6030_CFG_TRANS_SLEEP_SHIFT,
|
||||
TWL6030_CFG_TRANS_STATE_OFF);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -277,7 +344,12 @@ static int twl6030reg_get_status(struct regulator_dev *rdev)
|
|||
|
||||
val = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_STATE);
|
||||
|
||||
switch (TWL6030_CFG_STATE_APP(val)) {
|
||||
if (info->features & TWL6032_SUBCLASS)
|
||||
val &= TWL6030_CFG_STATE_MASK;
|
||||
else
|
||||
val = TWL6030_CFG_STATE_APP(val);
|
||||
|
||||
switch (val) {
|
||||
case TWL6030_CFG_STATE_ON:
|
||||
return REGULATOR_STATUS_NORMAL;
|
||||
|
||||
|
|
@ -333,7 +405,7 @@ static int twl6030reg_set_mode(struct regulator_dev *rdev, unsigned mode)
|
|||
int grp = 0;
|
||||
int val;
|
||||
|
||||
if (!(twl_class_is_6030() && (info->features & TWL6025_SUBCLASS)))
|
||||
if (!(twl_class_is_6030() && (info->features & TWL6032_SUBCLASS)))
|
||||
grp = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_GRP);
|
||||
|
||||
if (grp < 0)
|
||||
|
|
@ -357,6 +429,18 @@ static int twl6030reg_set_mode(struct regulator_dev *rdev, unsigned mode)
|
|||
return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_STATE, val);
|
||||
}
|
||||
|
||||
static int twl6030ldo_suspend_enable(struct regulator_dev *rdev)
|
||||
{
|
||||
return twl6030reg_set_trans_state(rdev, TWL6030_CFG_TRANS_SLEEP_SHIFT,
|
||||
TWL6030_CFG_TRANS_STATE_AUTO);
|
||||
}
|
||||
|
||||
static int twl6030ldo_suspend_disable(struct regulator_dev *rdev)
|
||||
{
|
||||
return twl6030reg_set_trans_state(rdev, TWL6030_CFG_TRANS_SLEEP_SHIFT,
|
||||
TWL6030_CFG_TRANS_STATE_OFF);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
|
|
@ -570,6 +654,9 @@ static struct regulator_ops twl6030ldo_ops = {
|
|||
.set_mode = twl6030reg_set_mode,
|
||||
|
||||
.get_status = twl6030reg_get_status,
|
||||
|
||||
.set_suspend_enable = twl6030ldo_suspend_enable,
|
||||
.set_suspend_disable = twl6030ldo_suspend_disable,
|
||||
};
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
|
@ -617,6 +704,9 @@ static struct regulator_ops twl6030fixed_ops = {
|
|||
.set_mode = twl6030reg_set_mode,
|
||||
|
||||
.get_status = twl6030reg_get_status,
|
||||
|
||||
.set_suspend_enable = twl6030ldo_suspend_enable,
|
||||
.set_suspend_disable = twl6030ldo_suspend_disable,
|
||||
};
|
||||
|
||||
static struct regulator_ops twl6030_fixed_resource = {
|
||||
|
|
@ -806,7 +896,104 @@ twl6030smps_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV,
|
|||
return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE_SMPS,
|
||||
vsel);
|
||||
}
|
||||
//add
|
||||
#if 1
|
||||
static int twl6030dvssmps_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV,
|
||||
unsigned int *selector)
|
||||
{
|
||||
struct twlreg_info *info = rdev_get_drvdata(rdev);
|
||||
int vsel = 0;
|
||||
|
||||
switch (info->flags) {
|
||||
case 0:
|
||||
if (min_uV == 0)
|
||||
vsel = 0;
|
||||
else if ((min_uV >= 600000) && (max_uV <= 1300000)) {
|
||||
vsel = (min_uV - 600000) / 125;
|
||||
if (vsel % 100)
|
||||
vsel += 100;
|
||||
vsel /= 100;
|
||||
vsel++;
|
||||
}
|
||||
/* Values 1..57 for vsel are linear and can be calculated
|
||||
* values 58..62 are non linear.
|
||||
*/
|
||||
else if ((min_uV > 1900000) && (max_uV >= 2100000))
|
||||
vsel = 62;
|
||||
else if ((min_uV > 1800000) && (max_uV >= 1900000))
|
||||
vsel = 61;
|
||||
else if ((min_uV > 1500000) && (max_uV >= 1800000))
|
||||
vsel = 60;
|
||||
else if ((min_uV > 1350000) && (max_uV >= 1500000))
|
||||
vsel = 59;
|
||||
else if ((min_uV > 1300000) && (max_uV >= 1350000))
|
||||
vsel = 58;
|
||||
else
|
||||
return -EINVAL;
|
||||
break;
|
||||
case SMPS_OFFSET_EN:
|
||||
if (min_uV == 0)
|
||||
vsel = 0;
|
||||
else if ((min_uV >= 700000) && (max_uV <= 1420000)) {
|
||||
vsel = (min_uV - 700000) / 125;
|
||||
if (vsel % 100)
|
||||
vsel += 100;
|
||||
vsel /= 100;
|
||||
vsel++;
|
||||
}
|
||||
/* Values 1..57 for vsel are linear and can be calculated
|
||||
* values 58..62 are non linear.
|
||||
*/
|
||||
else if ((min_uV > 1900000) && (max_uV >= 2100000))
|
||||
vsel = 62;
|
||||
else if ((min_uV > 1800000) && (max_uV >= 1900000))
|
||||
vsel = 61;
|
||||
else if ((min_uV > 1350000) && (max_uV >= 1800000))
|
||||
vsel = 60;
|
||||
else if ((min_uV > 1350000) && (max_uV >= 1500000))
|
||||
vsel = 59;
|
||||
else if ((min_uV > 1300000) && (max_uV >= 1350000))
|
||||
vsel = 58;
|
||||
else
|
||||
return -EINVAL;
|
||||
break;
|
||||
case SMPS_EXTENDED_EN:
|
||||
if (min_uV == 0)
|
||||
vsel = 0;
|
||||
else if ((min_uV >= 1852000) && (max_uV <= 4013600)) {
|
||||
vsel = (min_uV - 1852000) / 386;
|
||||
if (vsel % 100)
|
||||
vsel += 100;
|
||||
vsel /= 100;
|
||||
vsel++;
|
||||
}
|
||||
break;
|
||||
case SMPS_OFFSET_EN|SMPS_EXTENDED_EN:
|
||||
if (min_uV == 0)
|
||||
vsel = 0;
|
||||
else if ((min_uV >= 2161000) && (max_uV <= 4321000)) {
|
||||
vsel = (min_uV - 1852000) / 386;
|
||||
if (vsel % 100)
|
||||
vsel += 100;
|
||||
vsel /= 100;
|
||||
vsel++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
*selector = vsel;
|
||||
|
||||
return twlreg_write(info, TWL_MODULE_PM_DVS, VREG_VOLTAGE_DVS_SMPS,
|
||||
vsel);
|
||||
}
|
||||
|
||||
static int twl6030dvssmps_get_voltage_sel(struct regulator_dev *rdev)
|
||||
{
|
||||
struct twlreg_info *info = rdev_get_drvdata(rdev);
|
||||
|
||||
return twlreg_read(info, TWL_MODULE_PM_DVS, VREG_VOLTAGE_DVS_SMPS);
|
||||
}
|
||||
#endif
|
||||
static int twl6030smps_get_voltage_sel(struct regulator_dev *rdev)
|
||||
{
|
||||
struct twlreg_info *info = rdev_get_drvdata(rdev);
|
||||
|
|
@ -827,16 +1014,49 @@ static struct regulator_ops twlsmps_ops = {
|
|||
.set_mode = twl6030reg_set_mode,
|
||||
|
||||
.get_status = twl6030reg_get_status,
|
||||
|
||||
.set_suspend_enable = twl6030ldo_suspend_enable,
|
||||
.set_suspend_disable = twl6030ldo_suspend_disable,
|
||||
};
|
||||
|
||||
static struct regulator_ops twl6030_external_control_pin_ops = {
|
||||
.enable = twl6030reg_enable,
|
||||
.disable = twl6030reg_disable,
|
||||
.is_enabled = twl6030reg_is_enabled,
|
||||
|
||||
.set_mode = twl6030reg_set_mode,
|
||||
|
||||
.get_status = twl6030reg_get_status,
|
||||
|
||||
.set_suspend_enable = twl6030ldo_suspend_enable,
|
||||
.set_suspend_disable = twl6030ldo_suspend_disable,
|
||||
};
|
||||
//add
|
||||
static struct regulator_ops twldvssmps_ops = {
|
||||
.list_voltage = twl6030smps_list_voltage,
|
||||
|
||||
.set_voltage = twl6030dvssmps_set_voltage,
|
||||
.get_voltage_sel = twl6030dvssmps_get_voltage_sel,
|
||||
|
||||
.enable = twl6030reg_enable,
|
||||
.disable = twl6030reg_disable,
|
||||
.is_enabled = twl6030reg_is_enabled,
|
||||
|
||||
.set_mode = twl6030reg_set_mode,
|
||||
|
||||
.get_status = twl6030reg_get_status,
|
||||
|
||||
.set_suspend_enable = twl6030ldo_suspend_enable,
|
||||
.set_suspend_disable = twl6030ldo_suspend_disable,
|
||||
};
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
#define TWL4030_FIXED_LDO(label, offset, mVolts, num, turnon_delay, \
|
||||
remap_conf) \
|
||||
TWL_FIXED_LDO(label, offset, mVolts, num, turnon_delay, \
|
||||
remap_conf, TWL4030, twl4030fixed_ops)
|
||||
#define TWL6030_FIXED_LDO(label, offset, mVolts, num, turnon_delay) \
|
||||
TWL_FIXED_LDO(label, offset, mVolts, num, turnon_delay, \
|
||||
#define TWL6030_FIXED_LDO(label, offset, mVolts, turnon_delay) \
|
||||
TWL_FIXED_LDO(label, offset, mVolts, 0x0, turnon_delay, \
|
||||
0x0, TWL6030, twl6030fixed_ops)
|
||||
|
||||
#define TWL4030_ADJUSTABLE_LDO(label, offset, num, turnon_delay, remap_conf) { \
|
||||
|
|
@ -856,29 +1076,27 @@ static struct regulator_ops twlsmps_ops = {
|
|||
}, \
|
||||
}
|
||||
|
||||
#define TWL6030_ADJUSTABLE_LDO(label, offset, min_mVolts, max_mVolts, num) { \
|
||||
#define TWL6030_ADJUSTABLE_LDO(label, offset, min_mVolts, max_mVolts) { \
|
||||
.base = offset, \
|
||||
.id = num, \
|
||||
.min_mV = min_mVolts, \
|
||||
.max_mV = max_mVolts, \
|
||||
.desc = { \
|
||||
.name = #label, \
|
||||
.id = TWL6030_REG_##label, \
|
||||
.n_voltages = (max_mVolts - min_mVolts)/100, \
|
||||
.n_voltages = (max_mVolts - min_mVolts)/100 + 1, \
|
||||
.ops = &twl6030ldo_ops, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
.owner = THIS_MODULE, \
|
||||
}, \
|
||||
}
|
||||
|
||||
#define TWL6025_ADJUSTABLE_LDO(label, offset, min_mVolts, max_mVolts, num) { \
|
||||
#define TWL6032_ADJUSTABLE_LDO(label, offset, min_mVolts, max_mVolts) { \
|
||||
.base = offset, \
|
||||
.id = num, \
|
||||
.min_mV = min_mVolts, \
|
||||
.max_mV = max_mVolts, \
|
||||
.desc = { \
|
||||
.name = #label, \
|
||||
.id = TWL6025_REG_##label, \
|
||||
.id = TWL6032_REG_##label, \
|
||||
.n_voltages = ((max_mVolts - min_mVolts)/100) + 1, \
|
||||
.ops = &twl6030ldo_ops, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
|
|
@ -903,9 +1121,8 @@ static struct regulator_ops twlsmps_ops = {
|
|||
}, \
|
||||
}
|
||||
|
||||
#define TWL6030_FIXED_RESOURCE(label, offset, num, turnon_delay) { \
|
||||
#define TWL6030_FIXED_RESOURCE(label, offset, turnon_delay) { \
|
||||
.base = offset, \
|
||||
.id = num, \
|
||||
.delay = turnon_delay, \
|
||||
.desc = { \
|
||||
.name = #label, \
|
||||
|
|
@ -916,21 +1133,61 @@ static struct regulator_ops twlsmps_ops = {
|
|||
}, \
|
||||
}
|
||||
|
||||
#define TWL6025_ADJUSTABLE_SMPS(label, offset, num) { \
|
||||
#define TWL6030_ADJUSTABLE_SMPS(label, offset, min_mVolts, max_mVolts) { \
|
||||
.base = offset, \
|
||||
.min_mV = min_mVolts, \
|
||||
.max_mV = max_mVolts, \
|
||||
.desc = { \
|
||||
.name = #label, \
|
||||
.id = TWL6030_REG_##label, \
|
||||
.n_voltages = TWL603X_SMPS_NUMBER_VOLTAGES, \
|
||||
.ops = &twlsmps_ops, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
.owner = THIS_MODULE, \
|
||||
}, \
|
||||
}
|
||||
|
||||
#define TWL6032_ADJUSTABLE_SMPS(label, offset) { \
|
||||
.base = offset, \
|
||||
.id = num, \
|
||||
.min_mV = 600, \
|
||||
.max_mV = 2100, \
|
||||
.desc = { \
|
||||
.name = #label, \
|
||||
.id = TWL6025_REG_##label, \
|
||||
.n_voltages = 63, \
|
||||
.id = TWL6032_REG_##label, \
|
||||
.n_voltages = TWL603X_SMPS_NUMBER_VOLTAGES, \
|
||||
.ops = &twlsmps_ops, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
.owner = THIS_MODULE, \
|
||||
}, \
|
||||
}
|
||||
|
||||
#define TWL6030_EXTERNAL_CONTROL_PIN(label, offset, turnon_delay) { \
|
||||
.base = offset, \
|
||||
.delay = turnon_delay, \
|
||||
.desc = { \
|
||||
.name = #label, \
|
||||
.id = TWL6030_REG_##label, \
|
||||
.ops = &twl6030_external_control_pin_ops, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
.owner = THIS_MODULE, \
|
||||
}, \
|
||||
}
|
||||
|
||||
//add
|
||||
#define TWL6032_ADJUSTABLE_DVSSMPS(label, offset) { \
|
||||
.base = offset, \
|
||||
.min_mV = 600, \
|
||||
.max_mV = 2100, \
|
||||
.desc = { \
|
||||
.name = #label, \
|
||||
.id = TWL6032_REG_##label, \
|
||||
.n_voltages = TWL603X_SMPS_NUMBER_VOLTAGES, \
|
||||
.ops = &twldvssmps_ops, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
.owner = THIS_MODULE, \
|
||||
}, \
|
||||
}
|
||||
|
||||
/*
|
||||
* We list regulators here if systems need some level of
|
||||
* software control over them after boot.
|
||||
|
|
@ -961,32 +1218,46 @@ static struct twlreg_info twl_regs[] = {
|
|||
/* 6030 REG with base as PMC Slave Misc : 0x0030 */
|
||||
/* Turnon-delay and remap configuration values for 6030 are not
|
||||
verified since the specification is not public */
|
||||
TWL6030_ADJUSTABLE_LDO(VAUX1_6030, 0x54, 1000, 3300, 1),
|
||||
TWL6030_ADJUSTABLE_LDO(VAUX2_6030, 0x58, 1000, 3300, 2),
|
||||
TWL6030_ADJUSTABLE_LDO(VAUX3_6030, 0x5c, 1000, 3300, 3),
|
||||
TWL6030_ADJUSTABLE_LDO(VMMC, 0x68, 1000, 3300, 4),
|
||||
TWL6030_ADJUSTABLE_LDO(VPP, 0x6c, 1000, 3300, 5),
|
||||
TWL6030_ADJUSTABLE_LDO(VUSIM, 0x74, 1000, 3300, 7),
|
||||
TWL6030_FIXED_LDO(VANA, 0x50, 2100, 15, 0),
|
||||
TWL6030_FIXED_LDO(VCXIO, 0x60, 1800, 16, 0),
|
||||
TWL6030_FIXED_LDO(VDAC, 0x64, 1800, 17, 0),
|
||||
TWL6030_FIXED_LDO(VUSB, 0x70, 3300, 18, 0),
|
||||
TWL6030_FIXED_RESOURCE(CLK32KG, 0x8C, 48, 0),
|
||||
TWL6030_ADJUSTABLE_LDO(VAUX1_6030, 0x54, 1000, 3300),
|
||||
TWL6030_ADJUSTABLE_LDO(VAUX2_6030, 0x58, 1000, 3300),
|
||||
TWL6030_ADJUSTABLE_LDO(VAUX3_6030, 0x5c, 1000, 3300),
|
||||
TWL6030_ADJUSTABLE_LDO(VMMC, 0x68, 1000, 3300),
|
||||
TWL6030_ADJUSTABLE_LDO(VPP, 0x6c, 1000, 3300),
|
||||
TWL6030_ADJUSTABLE_LDO(VUSIM, 0x74, 1000, 3300),
|
||||
TWL6030_FIXED_LDO(VANA, 0x50, 2100, 0),
|
||||
TWL6030_FIXED_LDO(VCXIO, 0x60, 1800, 0),
|
||||
TWL6030_FIXED_LDO(VDAC, 0x64, 1800, 0),
|
||||
TWL6030_FIXED_LDO(VUSB, 0x70, 3300, 0),
|
||||
TWL6030_FIXED_RESOURCE(CLK32KG, 0x8C, 0),
|
||||
TWL6030_FIXED_RESOURCE(CLK32KAUDIO, 0x8F, 0),
|
||||
TWL6030_ADJUSTABLE_SMPS(VDD1, 0x22, 600, 4000),
|
||||
TWL6030_ADJUSTABLE_SMPS(VDD2, 0x28, 600, 4000),
|
||||
TWL6030_ADJUSTABLE_SMPS(VDD3, 0x2e, 600, 4000),
|
||||
TWL6030_ADJUSTABLE_SMPS(VMEM, 0x34, 600, 4000),
|
||||
TWL6030_ADJUSTABLE_SMPS(V2V1, 0x1c, 1800, 2100),
|
||||
|
||||
/* 6025 are renamed compared to 6030 versions */
|
||||
TWL6025_ADJUSTABLE_LDO(LDO2, 0x54, 1000, 3300, 1),
|
||||
TWL6025_ADJUSTABLE_LDO(LDO4, 0x58, 1000, 3300, 2),
|
||||
TWL6025_ADJUSTABLE_LDO(LDO3, 0x5c, 1000, 3300, 3),
|
||||
TWL6025_ADJUSTABLE_LDO(LDO5, 0x68, 1000, 3300, 4),
|
||||
TWL6025_ADJUSTABLE_LDO(LDO1, 0x6c, 1000, 3300, 5),
|
||||
TWL6025_ADJUSTABLE_LDO(LDO7, 0x74, 1000, 3300, 7),
|
||||
TWL6025_ADJUSTABLE_LDO(LDO6, 0x60, 1000, 3300, 16),
|
||||
TWL6025_ADJUSTABLE_LDO(LDOLN, 0x64, 1000, 3300, 17),
|
||||
TWL6025_ADJUSTABLE_LDO(LDOUSB, 0x70, 1000, 3300, 18),
|
||||
/* 6032 are renamed compared to 6030 versions */
|
||||
TWL6032_ADJUSTABLE_LDO(LDO2, 0x54, 1000, 3300),
|
||||
TWL6032_ADJUSTABLE_LDO(LDO4, 0x58, 1000, 3300),
|
||||
TWL6032_ADJUSTABLE_LDO(LDO3, 0x5c, 1000, 3300),
|
||||
TWL6032_ADJUSTABLE_LDO(LDO5, 0x68, 1000, 3300),
|
||||
TWL6032_ADJUSTABLE_LDO(LDO1, 0x6c, 1000, 3300),
|
||||
TWL6032_ADJUSTABLE_LDO(LDO7, 0x74, 1000, 3300),
|
||||
TWL6032_ADJUSTABLE_LDO(LDO6, 0x60, 1000, 3300),
|
||||
TWL6032_ADJUSTABLE_LDO(LDOLN, 0x64, 1000, 3300),
|
||||
TWL6032_ADJUSTABLE_LDO(LDOUSB, 0x70, 1000, 3300),
|
||||
|
||||
TWL6032_ADJUSTABLE_SMPS(SMPS3, 0x34),
|
||||
TWL6032_ADJUSTABLE_SMPS(SMPS4, 0x10),
|
||||
TWL6032_ADJUSTABLE_SMPS(VIO, 0x16),
|
||||
|
||||
TWL6032_ADJUSTABLE_DVSSMPS(SMPS1, 0x22),
|
||||
TWL6032_ADJUSTABLE_DVSSMPS(SMPS2, 0x28),
|
||||
TWL6032_ADJUSTABLE_DVSSMPS(SMPS5, 0x26),
|
||||
|
||||
TWL6030_EXTERNAL_CONTROL_PIN(SYSEN, 0x83, 0),
|
||||
TWL6030_EXTERNAL_CONTROL_PIN(REGEN1, 0x7d, 0),
|
||||
|
||||
TWL6025_ADJUSTABLE_SMPS(SMPS3, 0x34, 1),
|
||||
TWL6025_ADJUSTABLE_SMPS(SMPS4, 0x10, 2),
|
||||
TWL6025_ADJUSTABLE_SMPS(VIO, 0x16, 3),
|
||||
};
|
||||
|
||||
static u8 twl_get_smps_offset(void)
|
||||
|
|
@ -1014,6 +1285,7 @@ static int __devinit twlreg_probe(struct platform_device *pdev)
|
|||
struct regulator_init_data *initdata;
|
||||
struct regulation_constraints *c;
|
||||
struct regulator_dev *rdev;
|
||||
int ret;
|
||||
|
||||
for (i = 0, info = NULL; i < ARRAY_SIZE(twl_regs); i++) {
|
||||
if (twl_regs[i].desc.id != pdev->id)
|
||||
|
|
@ -1049,24 +1321,37 @@ static int __devinit twlreg_probe(struct platform_device *pdev)
|
|||
case TWL4030_REG_VINTDIG:
|
||||
c->always_on = true;
|
||||
break;
|
||||
case TWL6030_REG_VUSB:
|
||||
/* Program CFG_LDO_PD2 register and set VUSB bit */
|
||||
ret = twl_i2c_write_u8(TWL6030_MODULE_ID0, 0x1,
|
||||
TWL6030_CFG_LDO_PD2);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Program MISC2 register and set bit VUSB_IN_VBAT */
|
||||
ret = twl_i2c_write_u8(TWL6030_MODULE_ID0, 0x10, TWL6030_MISC2);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (pdev->id) {
|
||||
case TWL6025_REG_SMPS3:
|
||||
case TWL6032_REG_SMPS3:
|
||||
if (twl_get_smps_mult() & SMPS_MULTOFFSET_SMPS3)
|
||||
info->flags |= SMPS_EXTENDED_EN;
|
||||
if (twl_get_smps_offset() & SMPS_MULTOFFSET_SMPS3)
|
||||
info->flags |= SMPS_OFFSET_EN;
|
||||
break;
|
||||
case TWL6025_REG_SMPS4:
|
||||
case TWL6032_REG_SMPS4:
|
||||
if (twl_get_smps_mult() & SMPS_MULTOFFSET_SMPS4)
|
||||
info->flags |= SMPS_EXTENDED_EN;
|
||||
if (twl_get_smps_offset() & SMPS_MULTOFFSET_SMPS4)
|
||||
info->flags |= SMPS_OFFSET_EN;
|
||||
break;
|
||||
case TWL6025_REG_VIO:
|
||||
|
||||
case TWL6032_REG_VIO:
|
||||
if (twl_get_smps_mult() & SMPS_MULTOFFSET_VIO)
|
||||
info->flags |= SMPS_EXTENDED_EN;
|
||||
if (twl_get_smps_offset() & SMPS_MULTOFFSET_VIO)
|
||||
|
|
@ -1119,7 +1404,7 @@ static int __init twlreg_init(void)
|
|||
{
|
||||
return platform_driver_register(&twlreg_driver);
|
||||
}
|
||||
subsys_initcall(twlreg_init);
|
||||
subsys_initcall_sync(twlreg_init);
|
||||
|
||||
static void __exit twlreg_exit(void)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -362,14 +362,6 @@ static irqreturn_t twl_rtc_interrupt(int irq, void *rtc)
|
|||
int res;
|
||||
u8 rd_reg;
|
||||
|
||||
#ifdef CONFIG_LOCKDEP
|
||||
/* WORKAROUND for lockdep forcing IRQF_DISABLED on us, which
|
||||
* we don't want and can't tolerate. Although it might be
|
||||
* friendlier not to borrow this thread context...
|
||||
*/
|
||||
local_irq_enable();
|
||||
#endif
|
||||
|
||||
res = twl_rtc_read_u8(&rd_reg, REG_RTC_STATUS_REG);
|
||||
if (res)
|
||||
goto out;
|
||||
|
|
@ -428,24 +420,12 @@ static struct rtc_class_ops twl_rtc_ops = {
|
|||
static int __devinit twl_rtc_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct rtc_device *rtc;
|
||||
int ret = 0;
|
||||
int ret = -EINVAL;
|
||||
int irq = platform_get_irq(pdev, 0);
|
||||
u8 rd_reg;
|
||||
|
||||
if (irq <= 0)
|
||||
return -EINVAL;
|
||||
|
||||
rtc = rtc_device_register(pdev->name,
|
||||
&pdev->dev, &twl_rtc_ops, THIS_MODULE);
|
||||
if (IS_ERR(rtc)) {
|
||||
ret = PTR_ERR(rtc);
|
||||
dev_err(&pdev->dev, "can't register RTC device, err %ld\n",
|
||||
PTR_ERR(rtc));
|
||||
goto out0;
|
||||
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, rtc);
|
||||
goto out1;
|
||||
|
||||
ret = twl_rtc_read_u8(&rd_reg, REG_RTC_STATUS_REG);
|
||||
if (ret < 0)
|
||||
|
|
@ -462,14 +442,6 @@ static int __devinit twl_rtc_probe(struct platform_device *pdev)
|
|||
if (ret < 0)
|
||||
goto out1;
|
||||
|
||||
ret = request_irq(irq, twl_rtc_interrupt,
|
||||
IRQF_TRIGGER_RISING,
|
||||
dev_name(&rtc->dev), rtc);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "IRQ is not free.\n");
|
||||
goto out1;
|
||||
}
|
||||
|
||||
if (twl_class_is_6030()) {
|
||||
twl6030_interrupt_unmask(TWL6030_RTC_INT_MASK,
|
||||
REG_INT_MSK_LINE_A);
|
||||
|
|
@ -480,28 +452,48 @@ static int __devinit twl_rtc_probe(struct platform_device *pdev)
|
|||
/* Check RTC module status, Enable if it is off */
|
||||
ret = twl_rtc_read_u8(&rd_reg, REG_RTC_CTRL_REG);
|
||||
if (ret < 0)
|
||||
goto out2;
|
||||
goto out1;
|
||||
|
||||
if (!(rd_reg & BIT_RTC_CTRL_REG_STOP_RTC_M)) {
|
||||
dev_info(&pdev->dev, "Enabling TWL-RTC.\n");
|
||||
rd_reg = BIT_RTC_CTRL_REG_STOP_RTC_M;
|
||||
ret = twl_rtc_write_u8(rd_reg, REG_RTC_CTRL_REG);
|
||||
if (ret < 0)
|
||||
goto out2;
|
||||
goto out1;
|
||||
}
|
||||
|
||||
/* init cached IRQ enable bits */
|
||||
ret = twl_rtc_read_u8(&rtc_irq_bits, REG_RTC_INTERRUPTS_REG);
|
||||
if (ret < 0)
|
||||
goto out2;
|
||||
goto out1;
|
||||
|
||||
return ret;
|
||||
rtc = rtc_device_register(pdev->name,
|
||||
&pdev->dev, &twl_rtc_ops, THIS_MODULE);
|
||||
if (IS_ERR(rtc)) {
|
||||
ret = PTR_ERR(rtc);
|
||||
dev_err(&pdev->dev, "can't register RTC device, err %ld\n",
|
||||
PTR_ERR(rtc));
|
||||
goto out1;
|
||||
|
||||
}
|
||||
|
||||
ret = request_threaded_irq(irq, NULL, twl_rtc_interrupt,
|
||||
IRQF_TRIGGER_RISING,
|
||||
dev_name(&rtc->dev), rtc);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "IRQ is not free.\n");
|
||||
goto out2;
|
||||
}
|
||||
|
||||
if (enable_irq_wake(irq) < 0)
|
||||
dev_warn(&pdev->dev, "Cannot enable wakeup for IRQ %d\n", irq);
|
||||
|
||||
platform_set_drvdata(pdev, rtc);
|
||||
return 0;
|
||||
|
||||
out2:
|
||||
free_irq(irq, rtc);
|
||||
out1:
|
||||
rtc_device_unregister(rtc);
|
||||
out0:
|
||||
out1:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
|||
201
include/linux/i2c/twl.h
Normal file → Executable file
201
include/linux/i2c/twl.h
Normal file → Executable file
|
|
@ -71,6 +71,8 @@
|
|||
#define TWL4030_MODULE_PM_RECEIVER 0x15
|
||||
#define TWL4030_MODULE_RTC 0x16
|
||||
#define TWL4030_MODULE_SECURED_REG 0x17
|
||||
#define TWL6032_MODULE_CHARGER 0x18
|
||||
#define TWL6030_MODULE_SLAVE_RES 0x19
|
||||
|
||||
#define TWL_MODULE_USB TWL4030_MODULE_USB
|
||||
#define TWL_MODULE_AUDIO_VOICE TWL4030_MODULE_AUDIO_VOICE
|
||||
|
|
@ -81,7 +83,11 @@
|
|||
#define TWL_MODULE_PM_RECEIVER TWL4030_MODULE_PM_RECEIVER
|
||||
#define TWL_MODULE_RTC TWL4030_MODULE_RTC
|
||||
#define TWL_MODULE_PWM TWL4030_MODULE_PWM0
|
||||
#define TWL6030_MODULE_CHARGER TWL4030_MODULE_MAIN_CHARGE
|
||||
#define TWL_MODULE_PM_SLAVE_RES TWL6030_MODULE_SLAVE_RES
|
||||
#define TWL_MODULE_PM_DVS 0x1A //add
|
||||
|
||||
#define TWL6030_MODULE_GASGAUGE 0x0B
|
||||
#define TWL6030_MODULE_ID0 0x0D
|
||||
#define TWL6030_MODULE_ID1 0x0E
|
||||
#define TWL6030_MODULE_ID2 0x0F
|
||||
|
|
@ -100,6 +106,7 @@
|
|||
* Offset from TWL6030_IRQ_BASE / pdata->irq_base
|
||||
*/
|
||||
#define PWR_INTR_OFFSET 0
|
||||
#define TWL_VLOW_INTR_OFFSET 6
|
||||
#define HOTDIE_INTR_OFFSET 12
|
||||
#define SMPSLDO_INTR_OFFSET 13
|
||||
#define BATDETECT_INTR_OFFSET 14
|
||||
|
|
@ -108,6 +115,7 @@
|
|||
#define GASGAUGE_INTR_OFFSET 17
|
||||
#define USBOTG_INTR_OFFSET 4
|
||||
#define CHARGER_INTR_OFFSET 2
|
||||
#define GPADCSW_INTR_OFFSET 1
|
||||
#define RSV_INTR_OFFSET 0
|
||||
|
||||
/* INT register offsets */
|
||||
|
|
@ -147,10 +155,17 @@
|
|||
#define SW_FC (0x1 << 2)
|
||||
#define STS_MMC 0x1
|
||||
|
||||
#define TWL6030_MMCDEBOUNCING 0xED
|
||||
#define MMC_DEB_BYPASS (0x1 << 7)
|
||||
#define MMC_MINS_DEB_MASK (0xF << 3)
|
||||
#define MMC_MEXT_DEB_MASK (0x7 << 0)
|
||||
|
||||
#define TWL6030_CFG_INPUT_PUPD3 0xF2
|
||||
#define MMC_PU (0x1 << 3)
|
||||
#define MMC_PD (0x1 << 2)
|
||||
|
||||
#define VLOW_INT_MASK (0x1 << 2)
|
||||
|
||||
#define TWL_SIL_TYPE(rev) ((rev) & 0x00FFFFFF)
|
||||
#define TWL_SIL_REV(rev) ((rev) >> 24)
|
||||
#define TWL_SIL_5030 0x09002F
|
||||
|
|
@ -171,7 +186,7 @@ static inline int twl_class_is_ ##class(void) \
|
|||
TWL_CLASS_IS(4030, TWL4030_CLASS_ID)
|
||||
TWL_CLASS_IS(6030, TWL6030_CLASS_ID)
|
||||
|
||||
#define TWL6025_SUBCLASS BIT(4) /* TWL6025 has changed registers */
|
||||
#define TWL6032_SUBCLASS BIT(4) /* Phoenix Lite is a varient*/
|
||||
|
||||
/*
|
||||
* Read and write single 8-bit registers
|
||||
|
|
@ -230,6 +245,11 @@ static inline int twl6030_mmc_card_detect(struct device *dev, int slot)
|
|||
#define TWL4030_SIH_CTRL_PENDDIS_MASK BIT(1)
|
||||
#define TWL4030_SIH_CTRL_COR_MASK BIT(2)
|
||||
|
||||
int twl6030_register_notifier(struct notifier_block *nb,
|
||||
unsigned int events);
|
||||
int twl6030_unregister_notifier(struct notifier_block *nb,
|
||||
unsigned int events);
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
|
|
@ -450,6 +470,23 @@ static inline int twl6030_mmc_card_detect(struct device *dev, int slot)
|
|||
|
||||
#define TWL4030_PM_MASTER_GLOBAL_TST 0xb6
|
||||
|
||||
#define TWL6030_PHOENIX_DEV_ON 0x06
|
||||
|
||||
/*
|
||||
* TWL6030 PM Master module register offsets (use TWL_MODULE_PM_MASTER)
|
||||
*/
|
||||
|
||||
#define TWL6030_PM_MASTER_MSK_TRANSITION 0x01
|
||||
#define TWL6030_VBATMIN_HI_THRESHOLD 0x05
|
||||
|
||||
/*
|
||||
* PM Slave resource module register offsets (use TWL6030_MODULE_SLAVE_RES)
|
||||
*/
|
||||
|
||||
#define REG_VBATMIN_HI_CFG_STATE 0x1D
|
||||
|
||||
#define VBATMIN_VLOW_EN 0x21
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
/* Power bus message definitions */
|
||||
|
|
@ -522,6 +559,43 @@ static inline int twl6030_mmc_card_detect(struct device *dev, int slot)
|
|||
#define RES_MAIN_REF 28
|
||||
|
||||
#define TOTAL_RESOURCES 28
|
||||
/* 6030 extra resources */
|
||||
#define RES_V1V29 29
|
||||
#define RES_V1V8 30
|
||||
#define RES_V2V1 31
|
||||
#define RES_VDD3 32
|
||||
#define RES_VMEM 33
|
||||
#define RES_VANA 34
|
||||
#define RES_VUAX1 35
|
||||
#define RES_VCXIO 36
|
||||
#define RES_VPP 37
|
||||
#define RES_VRTC 38
|
||||
#define RES_REGEN2 39
|
||||
#define RES_32KCLKAO 40
|
||||
#define RES_32KCLKG 41
|
||||
#define RES_32KCLKAUDIO 42
|
||||
#define RES_BIAS 43
|
||||
#define RES_VBATMIN_HI 44
|
||||
#define RES_RC6MHZ 45
|
||||
#define RES_TEMP 46
|
||||
|
||||
/* 6032 extra resources */
|
||||
#define RES_LDOUSB 47
|
||||
#define RES_SMPS5 48
|
||||
#define RES_SMPS4 49
|
||||
#define RES_SMPS3 50
|
||||
#define RES_SMPS2 51
|
||||
#define RES_SMPS1 52
|
||||
#define RES_LDOLN 53
|
||||
#define RES_LDO7 54
|
||||
#define RES_LDO6 55
|
||||
#define RES_LDO5 56
|
||||
#define RES_LDO4 57
|
||||
#define RES_LDO3 58
|
||||
#define RES_LDO2 59
|
||||
#define RES_LDO1 60
|
||||
#define RES_VSYSMIN_HI 61
|
||||
|
||||
/*
|
||||
* Power Bus Message Format ... these can be sent individually by Linux,
|
||||
* but are usually part of downloaded scripts that are run when various
|
||||
|
|
@ -557,6 +631,20 @@ struct twl4030_clock_init_data {
|
|||
struct twl4030_bci_platform_data {
|
||||
int *battery_tmp_tbl;
|
||||
unsigned int tblsize;
|
||||
|
||||
unsigned int monitoring_interval;
|
||||
|
||||
unsigned int max_charger_currentmA;
|
||||
unsigned int max_charger_voltagemV;
|
||||
unsigned int termination_currentmA;
|
||||
|
||||
unsigned int max_bat_voltagemV;
|
||||
unsigned int low_bat_voltagemV;
|
||||
|
||||
unsigned int sense_resistor_mohm;
|
||||
|
||||
/* twl6032 */
|
||||
unsigned long features;
|
||||
};
|
||||
|
||||
/* TWL4030_GPIO_MAX (18) GPIOs, with interrupts */
|
||||
|
|
@ -589,6 +677,7 @@ struct twl4030_gpio_platform_data {
|
|||
|
||||
struct twl4030_madc_platform_data {
|
||||
int irq_line;
|
||||
int features;
|
||||
};
|
||||
|
||||
/* Boards have unique mappings of {row, col} --> keycode.
|
||||
|
|
@ -641,21 +730,41 @@ struct twl4030_script {
|
|||
struct twl4030_resconfig {
|
||||
u8 resource;
|
||||
u8 devgroup; /* Processor group that Power resource belongs to */
|
||||
/* The following are used by TWL4030 only */
|
||||
u8 type; /* Power resource addressed, 6 / broadcast message */
|
||||
u8 type2; /* Power resource addressed, 3 / broadcast message */
|
||||
u8 remap_off; /* off state remapping */
|
||||
u8 remap_sleep; /* sleep state remapping */
|
||||
};
|
||||
|
||||
struct twl4030_system_config {
|
||||
char *name;
|
||||
u8 group;
|
||||
};
|
||||
|
||||
struct twl4030_power_data {
|
||||
struct twl4030_script **scripts;
|
||||
unsigned num;
|
||||
struct twl4030_script **scripts; /* used in TWL4030 only */
|
||||
unsigned num; /* used in TWL4030 only */
|
||||
struct twl4030_resconfig *resource_config;
|
||||
struct twl4030_system_config *sys_config; /*system resources*/
|
||||
#define TWL4030_RESCONFIG_UNDEF ((u8)-1)
|
||||
};
|
||||
|
||||
#ifdef CONFIG_TWL4030_POWER
|
||||
extern void twl4030_power_init(struct twl4030_power_data *triton2_scripts);
|
||||
extern int twl4030_remove_script(u8 flags);
|
||||
#else
|
||||
static inline void twl4030_power_init(struct twl4030_power_data *triton2_scripts) { }
|
||||
static inline int twl4030_remove_script(u8 flags) { return -EINVAL; }
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_TWL6030_POWER
|
||||
extern void twl6030_power_init(struct twl4030_power_data *power_data,\
|
||||
unsigned long features);
|
||||
#else
|
||||
extern inline void twl6030_power_init(struct twl4030_power_data *power_data,\
|
||||
unsigned long features) { }
|
||||
#endif
|
||||
|
||||
struct twl4030_codec_audio_data {
|
||||
unsigned int digimic_delay; /* in ms */
|
||||
|
|
@ -664,11 +773,26 @@ struct twl4030_codec_audio_data {
|
|||
unsigned int check_defaults:1;
|
||||
unsigned int reset_registers:1;
|
||||
unsigned int hs_extmute:1;
|
||||
u16 hs_left_step;
|
||||
u16 hs_right_step;
|
||||
u16 hf_left_step;
|
||||
u16 hf_right_step;
|
||||
u16 ep_step;
|
||||
void (*set_hs_extmute)(int mute);
|
||||
|
||||
/* twl6040 */
|
||||
int vddhf_uV;
|
||||
};
|
||||
|
||||
struct twl4030_codec_vibra_data {
|
||||
unsigned int coexist;
|
||||
|
||||
/* timed-output based implementations */
|
||||
int max_timeout;
|
||||
int initial_vibrate;
|
||||
int (*init)(void);
|
||||
void (*exit)(void);
|
||||
u8 voltage_raise_speed;
|
||||
};
|
||||
|
||||
struct twl4030_codec_data {
|
||||
|
|
@ -676,13 +800,22 @@ struct twl4030_codec_data {
|
|||
struct twl4030_codec_audio_data *audio;
|
||||
struct twl4030_codec_vibra_data *vibra;
|
||||
|
||||
int (*init)(void);
|
||||
void (*exit)(void);
|
||||
|
||||
/* twl6040 */
|
||||
int audpwron_gpio; /* audio power-on gpio */
|
||||
int naudint_irq; /* audio interrupt */
|
||||
unsigned int irq_base;
|
||||
int (*get_ext_clk32k)(void);
|
||||
void (*put_ext_clk32k)(void);
|
||||
int (*set_ext_clk32k)(bool on);
|
||||
};
|
||||
|
||||
struct twl4030_platform_data {
|
||||
unsigned irq_base, irq_end;
|
||||
int(*pre_init)(void);
|
||||
int(*set_init)(void);
|
||||
struct twl4030_clock_init_data *clock;
|
||||
struct twl4030_bci_platform_data *bci;
|
||||
struct twl4030_gpio_platform_data *gpio;
|
||||
|
|
@ -710,6 +843,10 @@ struct twl4030_platform_data {
|
|||
struct regulator_init_data *vintana1;
|
||||
struct regulator_init_data *vintana2;
|
||||
struct regulator_init_data *vintdig;
|
||||
/* TWL6030 DCDC regulators */
|
||||
struct regulator_init_data *vdd3;
|
||||
struct regulator_init_data *vmem;
|
||||
struct regulator_init_data *v2v1;
|
||||
/* TWL6030 LDO regulators */
|
||||
struct regulator_init_data *vmmc;
|
||||
struct regulator_init_data *vpp;
|
||||
|
|
@ -718,7 +855,8 @@ struct twl4030_platform_data {
|
|||
struct regulator_init_data *vcxio;
|
||||
struct regulator_init_data *vusb;
|
||||
struct regulator_init_data *clk32kg;
|
||||
/* TWL6025 LDO regulators */
|
||||
struct regulator_init_data *clk32kaudio;
|
||||
/* TWL6032 LDO regulators */
|
||||
struct regulator_init_data *ldo1;
|
||||
struct regulator_init_data *ldo2;
|
||||
struct regulator_init_data *ldo3;
|
||||
|
|
@ -728,10 +866,21 @@ struct twl4030_platform_data {
|
|||
struct regulator_init_data *ldo7;
|
||||
struct regulator_init_data *ldoln;
|
||||
struct regulator_init_data *ldousb;
|
||||
/* TWL6025 DCDC regulators */
|
||||
/* TWL6032 DCDC regulators */
|
||||
struct regulator_init_data *smps3;
|
||||
struct regulator_init_data *smps4;
|
||||
struct regulator_init_data *vio6025;
|
||||
struct regulator_init_data *vio6032;
|
||||
|
||||
struct regulator_init_data *smps1; //add
|
||||
struct regulator_init_data *smps2; //add
|
||||
struct regulator_init_data *smps5; //add
|
||||
|
||||
/* External control pins */
|
||||
struct regulator_init_data *sysen;
|
||||
struct regulator_init_data *regen1;
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
|
@ -813,21 +962,33 @@ static inline int twl4030charger_usb_en(int enable) { return 0; }
|
|||
#define TWL6030_REG_VRTC 47
|
||||
#define TWL6030_REG_CLK32KG 48
|
||||
|
||||
/* LDOs on 6025 have different names */
|
||||
#define TWL6025_REG_LDO2 49
|
||||
#define TWL6025_REG_LDO4 50
|
||||
#define TWL6025_REG_LDO3 51
|
||||
#define TWL6025_REG_LDO5 52
|
||||
#define TWL6025_REG_LDO1 53
|
||||
#define TWL6025_REG_LDO7 54
|
||||
#define TWL6025_REG_LDO6 55
|
||||
#define TWL6025_REG_LDOLN 56
|
||||
#define TWL6025_REG_LDOUSB 57
|
||||
/* LDOs on 6032 have different names */
|
||||
#define TWL6032_REG_LDO2 49
|
||||
#define TWL6032_REG_LDO4 50
|
||||
#define TWL6032_REG_LDO3 51
|
||||
#define TWL6032_REG_LDO5 52
|
||||
#define TWL6032_REG_LDO1 53
|
||||
#define TWL6032_REG_LDO7 54
|
||||
#define TWL6032_REG_LDO6 55
|
||||
#define TWL6032_REG_LDOLN 56
|
||||
#define TWL6032_REG_LDOUSB 57
|
||||
|
||||
/* 6025 DCDC supplies */
|
||||
#define TWL6025_REG_SMPS3 58
|
||||
#define TWL6025_REG_SMPS4 59
|
||||
#define TWL6025_REG_VIO 60
|
||||
/* 6032 DCDC supplies */
|
||||
#define TWL6032_REG_SMPS3 58
|
||||
#define TWL6032_REG_SMPS4 59
|
||||
#define TWL6032_REG_VIO 60
|
||||
|
||||
#define TWL6030_REG_CLK32KAUDIO 61
|
||||
|
||||
/* External control pins */
|
||||
#define TWL6030_REG_SYSEN 62
|
||||
#define TWL6030_REG_REGEN1 63
|
||||
|
||||
#define TWL6032_REG_SMPS1 64 //add
|
||||
#define TWL6032_REG_SMPS2 65 //add
|
||||
#define TWL6032_REG_SMPS5 66 //add
|
||||
|
||||
#define TWL6032_PREQ1_RES_ASS_A 0xd7
|
||||
|
||||
|
||||
#endif /* End of __TWL4030_H */
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user