#include <linux/kernel.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/rk2818_lp8725.h>
+#include <mach/gpio.h>
+#include <linux/delay.h>
+#include <mach/iomux.h>
+
+//add by robert for reboot notifier
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+
+//end add
+
#if 0
#define DBG_INFO(x...)
#endif
-
+#define PM_CONTROL
struct lp8725 {
{
struct lp8725 *lp8725 = rdev_get_drvdata(dev);
int lilo = rdev_get_id(dev) - LP8725_LILO1;
- u16 mask = 1 << (lilo+4);
+ u16 mask = 1 << (lilo+5);
u16 val;
val = lp8725_reg_read(lp8725, LP8725_LILO_ENABLE_REG);
{
struct lp8725 *lp8725 = rdev_get_drvdata(dev);
int lilo = rdev_get_id(dev) - LP8725_LILO1;
- u16 mask = 1 << (lilo+4);
+ u16 mask = 1 << (lilo+5);
return lp8725_set_bits(lp8725, LP8725_LILO_ENABLE_REG, mask, mask);
}
{
struct lp8725 *lp8725 = rdev_get_drvdata(dev);
int lilo = rdev_get_id(dev) - LP8725_LILO1;
- u16 mask = 1 << (lilo+4);
+ u16 mask = 1 << (lilo+5);
return lp8725_set_bits(lp8725, LP8725_LILO_ENABLE_REG, mask, 0);
}
static int lp8725_dcdc_is_enabled(struct regulator_dev *dev)
{
struct lp8725 *lp8725 = rdev_get_drvdata(dev);
- int buck = rdev_get_id(dev) - LP8725_DCDC1;
- u16 mask = 1 << (buck * 2);
+ int buck = rdev_get_id(dev);
u16 val;
+ u16 mask,mask2;
- val = lp8725_reg_read(lp8725, LP8725_BUCK_VOL_ENABLE_REG);
- return (val & mask) != 0;
+ switch(buck)
+ {
+ case LP8725_DCDC1:
+ mask = 1 << 0;
+ mask2 = 1 << 2;
+ val = lp8725_reg_read(lp8725, LP8725_BUCK_VOL_ENABLE_REG);
+ return ((val & mask) && (val & mask2)) != 0;
+ case LP8725_DCDC2:
+ mask = 1 << 4;
+ mask2 = 1 << 3;
+ val = lp8725_reg_read(lp8725, LP8725_BUCK_VOL_ENABLE_REG);
+ return ((val & mask) && (val & mask2)) != 0;
+ case LP8725_DCDC1_V2:
+ mask = 1 << 0;
+ mask2 = 1<< 2;
+ val = lp8725_reg_read(lp8725, LP8725_BUCK_VOL_ENABLE_REG);
+ return ((val & mask) && (!(val & mask2))) !=0;
+ case LP8725_DCDC2_V2:
+ mask = 1 << 4;
+ mask2 = 1 << 3;
+ val = lp8725_reg_read(lp8725, LP8725_BUCK_VOL_ENABLE_REG);
+ return ((val & mask) && (!(val & mask2))) !=0;
+ }
}
static int lp8725_dcdc_enable(struct regulator_dev *dev)
{
struct lp8725 *lp8725 = rdev_get_drvdata(dev);
- int buck = rdev_get_id(dev) - LP8725_DCDC1;
- u16 mask = 1 << (buck * 2);
-
- return lp8725_set_bits(lp8725, LP8725_BUCK_VOL_ENABLE_REG, mask, mask);
+ int buck = rdev_get_id(dev);
+ u16 mask;
+ int ret = 0;
+ switch(buck)
+ {
+ case LP8725_DCDC1:
+ mask = 1 << 0;
+ ret = lp8725_set_bits(lp8725, LP8725_BUCK_VOL_ENABLE_REG, mask, mask);
+ mask = 1 << 2;
+ ret = lp8725_set_bits(lp8725, LP8725_BUCK_VOL_ENABLE_REG, mask, mask);
+ break;
+ case LP8725_DCDC1_V2:
+ mask = 1 << 0;
+ ret = lp8725_set_bits(lp8725, LP8725_BUCK_VOL_ENABLE_REG, mask, mask);
+ mask = 1 << 2;
+ ret = lp8725_set_bits(lp8725, LP8725_BUCK_VOL_ENABLE_REG, mask, 0);
+ break;
+ case LP8725_DCDC2:
+ mask = 1 << 4;
+ ret = lp8725_set_bits(lp8725, LP8725_BUCK_VOL_ENABLE_REG, mask, mask);
+ mask = 1 << 3;
+ ret = lp8725_set_bits(lp8725, LP8725_BUCK_VOL_ENABLE_REG, mask, mask);
+ break;
+ case LP8725_DCDC2_V2:
+ mask = 1 << 4;
+ ret = lp8725_set_bits(lp8725, LP8725_BUCK_VOL_ENABLE_REG, mask, mask);
+ mask = 1 << 3;
+ ret = lp8725_set_bits(lp8725, LP8725_BUCK_VOL_ENABLE_REG, mask, 0);
+ break;
+ }
+ dev->use_count--;
+ return ret;
}
static int lp8725_dcdc_disable(struct regulator_dev *dev)
{
struct lp8725 *lp8725 = rdev_get_drvdata(dev);
- int buck = rdev_get_id(dev) - LP8725_DCDC1;
- u16 mask = 1 << (buck * 2);
+ int buck = rdev_get_id(dev) ;
+ u16 mask;
- return lp8725_set_bits(lp8725, LP8725_BUCK_VOL_ENABLE_REG, mask, 0);
+ switch(buck)
+ {
+ case LP8725_DCDC1:
+ case LP8725_DCDC1_V2:
+ mask = 1 << 0;
+ return lp8725_set_bits(lp8725, LP8725_BUCK_VOL_ENABLE_REG, mask, 0);
+ case LP8725_DCDC2:
+ case LP8725_DCDC2_V2:
+ mask = 1 << 4;
+ return lp8725_set_bits(lp8725, LP8725_BUCK_VOL_ENABLE_REG, mask,0);
+ }
}
static int lp8725_dcdc_get_voltage(struct regulator_dev *dev)
{
struct lp8725 *lp8725 = rdev_get_drvdata(dev);
- int buck = rdev_get_id(dev) - LP8725_DCDC1;
- u16 reg;
+ int buck = rdev_get_id(dev) ;
+ u16 reg = 0;
int val;
- reg = lp8725_reg_read(lp8725, LP8725_BUCK_TARGET_VOL1_REG(buck));
- reg &= BUCK_TARGET_VOL_MASK;
+ switch(buck)
+ {
+ case LP8725_DCDC1:
+ case LP8725_DCDC2:
+ buck -= LP8725_DCDC1;
+ reg = lp8725_reg_read(lp8725, LP8725_BUCK_TARGET_VOL1_REG(buck));
+ break;
+ case LP8725_DCDC1_V2:
+ case LP8725_DCDC2_V2:
+ buck -= LP8725_DCDC1_V2;
+ reg = lp8725_reg_read(lp8725, LP8725_BUCK_TARGET_VOL2_REG(buck));
+ break;
+ }
+ reg &= BUCK_TARGET_VOL_MASK;
val = 1000 * buck_voltage_map[reg];
return val;
int min_uV, int max_uV)
{
struct lp8725 *lp8725 = rdev_get_drvdata(dev);
- int buck = rdev_get_id(dev) - LP8725_DCDC1;
+ int buck = rdev_get_id(dev);
int min_vol = min_uV / 1000, max_vol = max_uV / 1000;
const int *vol_map = buck_voltage_map;
u16 val;
- int ret;
+ int ret = 0;
if (min_vol < vol_map[BUCK_TARGET_VOL_MIN_IDX] ||
min_vol > vol_map[BUCK_TARGET_VOL_MAX_IDX])
if (vol_map[val] > max_vol)
return -EINVAL;
- ret = lp8725_set_bits(lp8725, LP8725_BUCK_TARGET_VOL1_REG(buck),
- BUCK_TARGET_VOL_MASK, val);
- if (ret)
- return ret;
+ switch(buck)
+ {
+ case LP8725_DCDC1:
+ case LP8725_DCDC2:
+ buck -= LP8725_DCDC1;
+ ret = lp8725_set_bits(lp8725, LP8725_BUCK_TARGET_VOL1_REG(buck),
+ BUCK_TARGET_VOL_MASK, val);
+ if (ret)
+ return ret;
+ break;
+ case LP8725_DCDC1_V2:
+ case LP8725_DCDC2_V2:
+ buck -= LP8725_DCDC1_V2;
+ ret = lp8725_set_bits(lp8725, LP8725_BUCK_TARGET_VOL2_REG(buck),
+ BUCK_TARGET_VOL_MASK, val);
+ if (ret)
+ return ret;
+ break;
+ }
- ret = lp8725_set_bits(lp8725, LP8725_BUCK_TARGET_VOL2_REG(buck),
- BUCK_TARGET_VOL_MASK, val);
- if (ret)
- return ret;
+ return ret;
+}
- return ret;
+static unsigned int lp8725_dcdc_get_mode(struct regulator_dev *dev)
+{
+ struct lp8725 *lp8725 = rdev_get_drvdata(dev);
+ u16 mask = 1 << 1;
+ u16 val;
+ val = lp8725_reg_read(lp8725, LP8725_BUCK_VOL_ENABLE_REG);
+ if ((val & mask) == 0)
+ return REGULATOR_MODE_NORMAL;
+ else
+ return REGULATOR_MODE_IDLE;
+}
+
+static int lp8725_dcdc_set_mode(struct regulator_dev *dev, unsigned int mode)
+{
+ struct lp8725 *lp8725 = rdev_get_drvdata(dev);
+ u16 mask = 1 << 1;
+ switch(mode)
+ {
+ case REGULATOR_MODE_NORMAL:
+ return lp8725_set_bits(lp8725, LP8725_BUCK_VOL_ENABLE_REG, mask, 0);
+ case REGULATOR_MODE_IDLE:
+ return lp8725_set_bits(lp8725, LP8725_BUCK_VOL_ENABLE_REG, mask, mask);
+ default:
+ printk("error:pmu_lp8725 only normal and idle mode\n");
+ return -EINVAL;
+ }
}
static struct regulator_ops lp8725_dcdc_ops = {
.disable = lp8725_dcdc_disable,
.get_voltage = lp8725_dcdc_get_voltage,
.set_voltage = lp8725_dcdc_set_voltage,
+ .get_mode = lp8725_dcdc_get_mode,
+ .set_mode = lp8725_dcdc_set_mode,
};
static struct regulator_desc regulators[] = {
.type = REGULATOR_VOLTAGE,
.owner = THIS_MODULE,
},
+ {
+ .name = "DCDC1_V2",
+ .id = LP8725_DCDC1_V2,
+ .ops = &lp8725_dcdc_ops,
+ .n_voltages = ARRAY_SIZE(buck_voltage_map),
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+ },
+ {
+ .name = "DCDC2_V2",
+ .id = LP8725_DCDC2_V2,
+ .ops = &lp8725_dcdc_ops,
+ .n_voltages = ARRAY_SIZE(buck_voltage_map),
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+ },
};
static int lp8725_i2c_read(struct i2c_client *i2c, char reg, int count, u16 *dest)
}
+//add by robert for power on bp
+#define AP_TD_UNDEFINED_GBIN5 FPGA_PIO2_02
+#define AP_RESET_TD FPGA_PIO2_04
+#define AP_SHUTDOWN_TD_PMU FPGA_PIO2_05
+#define AP_PW_EN_TD FPGA_PIO2_03
+
+static int bp_power_on(void)
+{
+ int ret=0;
+
+ ret = gpio_request(AP_TD_UNDEFINED_GBIN5, NULL);
+ if (ret) {
+ printk("%s:failed to request fpga s %d\n",__FUNCTION__,__LINE__);
+ goto err;
+ }
+ ret = gpio_request(AP_RESET_TD, NULL);
+ if (ret) {
+ printk("%s:failed to request fpga s %d\n",__FUNCTION__,__LINE__);
+ goto err0;
+ }
+
+
+ ret = gpio_request(AP_SHUTDOWN_TD_PMU, NULL);
+ if (ret) {
+ printk("%s:failed to request fpga %d\n",__FUNCTION__,__LINE__);
+ goto err1;
+ }
+
+ ret = gpio_request(AP_PW_EN_TD, NULL);
+ if (ret) {
+ printk("%s:failed to request fpga %d\n",__FUNCTION__,__LINE__);
+ goto err2;
+ }
+
+ gpio_set_value(AP_TD_UNDEFINED_GBIN5, 1);
+ gpio_direction_output(AP_TD_UNDEFINED_GBIN5, 1);
+ gpio_direction_input(AP_RESET_TD);
+
+ gpio_set_value(AP_SHUTDOWN_TD_PMU, 0);
+ gpio_direction_output(AP_SHUTDOWN_TD_PMU, 0);
+
+ gpio_set_value(AP_PW_EN_TD, 0);
+ gpio_direction_output(AP_PW_EN_TD, 0);
+ mdelay(1);
+ gpio_set_value(AP_PW_EN_TD, 1);
+ mdelay(1200);
+ gpio_set_value(AP_PW_EN_TD, 0);
+
+ return true;
+err2:
+ gpio_free(AP_SHUTDOWN_TD_PMU);
+err1:
+ gpio_free(AP_RESET_TD);
+err0:
+ gpio_free(AP_TD_UNDEFINED_GBIN5);
+err:
+ return false;
+}
+
+
+
+static int bp_power_off(struct notifier_block *this,
+ unsigned long code, void *unused)
+{
+ printk("+++--++++++%s_________%d \r\n",__FUNCTION__,code);
+
+ gpio_set_value(AP_TD_UNDEFINED_GBIN5, 0);
+
+ gpio_set_value(AP_PW_EN_TD, 0);
+ //gpio_direction_output(AP_PW_EN_TD, 0);
+ mdelay(1);
+ gpio_set_value(AP_PW_EN_TD, 1);
+ mdelay(1200);
+ gpio_set_value(AP_PW_EN_TD, 0);
+
+ mdelay(5000);
+ gpio_set_value(AP_SHUTDOWN_TD_PMU, 1);
+ mdelay(1200);
+ // gpio_free(AP_PW_EN_TD);
+printk("++++--+++++%s ok_________\r\n",__FUNCTION__);
+ return NOTIFY_DONE;
+}
+//add end
+
static int lp8725_set_init(void)
{
- int ret;
int tmp = 0;
struct regulator *ldo1,*ldo2,*ldo3,*ldo4,*ldo5;
struct regulator *lilo1,*lilo2;
- struct regulator *buck1,*buck2;
+ struct regulator *buck1,*buck1_v2,*buck2;
DBG_INFO("***run in %s %d ",__FUNCTION__,__LINE__);
/*init buck1*/
DBG_INFO("***buck1 vcc init\n");
buck1 = regulator_get(NULL, "vdd12");
- regulator_set_voltage(buck1,1200000,1200000);
+// regulator_set_voltage(buck1,1200000,1200000);
tmp = regulator_get_voltage(buck1);
DBG_INFO("***regulator_set_init: buck1 vcc =%d\n",tmp);
+ #ifdef PM_CONTROL
+ DBG_INFO("***buck1 v2 init\n");
+ buck1_v2 = regulator_get(NULL, "vdd12_v2");// dvs 0
+ regulator_enable(buck1_v2);
+ regulator_set_voltage(buck1_v2,1000000,1000000);//1300000
+ tmp = regulator_get_voltage(buck1_v2);
+ DBG_INFO("***regulator_set_init: buck1 v2 =%d\n",tmp);
+ #endif
+
/*init buck2*/
DBG_INFO("***buck2 vcc init\n");
buck2 = regulator_get(NULL, "vccdr");
tmp = regulator_get_voltage(buck2);
DBG_INFO("***regulator_set_init: buck2 vcc =%d\n",tmp);
+
+//add by robert for power on bp
+ bp_power_on();
+//end add
+
return(0);
}
-static int setup_regulators(struct lp8725 *lp8725, struct lp8725_platform_data *pdata)
+static int __devinit setup_regulators(struct lp8725 *lp8725, struct lp8725_platform_data *pdata)
{
int i, err;
- int num_regulators = pdata->num_regulators;
- lp8725->num_regulators = num_regulators;
- lp8725->rdev = kzalloc(sizeof(struct regulator_dev *) * num_regulators,
- GFP_KERNEL);
+
+ lp8725->num_regulators = pdata->num_regulators;
+ lp8725->rdev = kcalloc(pdata->num_regulators,
+ sizeof(struct regulator_dev *), GFP_KERNEL);
+ if (!lp8725->rdev) {
+ return -ENOMEM;
+ }
/* Instantiate the regulators */
- for (i = 0; i < num_regulators; i++) {
+ for (i = 0; i < pdata->num_regulators; i++) {
int id = pdata->regulators[i].id;
lp8725->rdev[i] = regulator_register(®ulators[id],
lp8725->dev, pdata->regulators[i].initdata, lp8725);
- err = IS_ERR(lp8725->rdev[i]);
- if (err) {
+ if (IS_ERR(lp8725->rdev[i])) {
+ err = PTR_ERR(lp8725->rdev[i]);
dev_err(lp8725->dev, "regulator init failed: %d\n",
err);
goto error;
return 0;
error:
- for (i = 0; i < num_regulators; i++)
- if (lp8725->rdev[i])
- regulator_unregister(lp8725->rdev[i]);
+ while (--i >= 0)
+ regulator_unregister(lp8725->rdev[i]);
kfree(lp8725->rdev);
lp8725->rdev = NULL;
return err;
} else
dev_warn(lp8725->dev, "No platform init data supplied\n");
+ //DVS pin control, make sure it is high level at start.
+ #ifdef PM_CONTROL
+ rk2818_lp8725_pm_control();
+ #endif
lp8725_set_init();
return 0;
{
struct lp8725 *lp8725 = i2c_get_clientdata(i2c);
int i;
+
for (i = 0; i < lp8725->num_regulators; i++)
if (lp8725->rdev[i])
regulator_unregister(lp8725->rdev[i]);
.id_table = lp8725_i2c_id,
};
+
+//add by robert for bp powerdown register
+static struct notifier_block BP_powerdown_notifier = {
+ .notifier_call = bp_power_off,
+};
+//end add
+
+
+
static int __init lp8725_module_init(void)
{
int ret;
if (ret != 0)
pr_err("Failed to register I2C driver: %d\n", ret);
+ //add by robert for bp powerdown register
+ ret = register_reboot_notifier(&BP_powerdown_notifier);
+ if (ret != 0)
+ {
+ printk("cannot register reboot notifier (err=%d), %s\n", ret,__FUNCTION__);
+ }
+ //end add
+
+
return ret;
}
module_init(lp8725_module_init);
static void __exit lp8725_module_exit(void)
{
+//add by robert for bp power down
+ unregister_reboot_notifier(&BP_powerdown_notifier);
+//end add
+
i2c_del_driver(&lp8725_i2c_driver);
}
module_exit(lp8725_module_exit);