clk: rockchip: rk3366: modify the parent's name of usbphy480m
[firefly-linux-kernel-4.4.55.git] / drivers / regulator / rk2818_lp8725.c
old mode 100644 (file)
new mode 100755 (executable)
index cb4db7d..3a99ff1
@@ -31,6 +31,16 @@ REVISION 0.01
 #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
@@ -44,7 +54,7 @@ REVISION 0.01
 #define DBG_INFO(x...)
 #endif
 
-
+#define PM_CONTROL
 
 
 struct lp8725 {
@@ -210,7 +220,7 @@ static int lp8725_lilo_is_enabled(struct regulator_dev *dev)
 {
        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);
@@ -221,7 +231,7 @@ static int lp8725_lilo_enable(struct regulator_dev *dev)
 {
        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);
 }
@@ -230,7 +240,7 @@ static int lp8725_lilo_disable(struct regulator_dev *dev)
 {
        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);
 }
@@ -290,42 +300,113 @@ static int lp8725_dcdc_list_voltage(struct regulator_dev *dev, unsigned index)
 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;
@@ -335,11 +416,11 @@ static int lp8725_dcdc_set_voltage(struct regulator_dev *dev,
                                  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])
@@ -353,17 +434,55 @@ static int lp8725_dcdc_set_voltage(struct regulator_dev *dev,
        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 = {
@@ -373,6 +492,8 @@ 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[] = {
@@ -448,6 +569,22 @@ 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)
@@ -543,13 +680,96 @@ static int lp8725_set_bits(struct lp8725 *lp8725, u8 reg, u16 mask, u16 val)
 }
 
 
+//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__);
 
@@ -612,10 +832,19 @@ static int lp8725_set_init(void)
        /*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");
@@ -623,26 +852,34 @@ static int lp8725_set_init(void)
        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(&regulators[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;
@@ -651,9 +888,8 @@ static int setup_regulators(struct lp8725 *lp8725, struct lp8725_platform_data *
 
        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;
@@ -684,6 +920,10 @@ static int __devinit lp8725_i2c_probe(struct i2c_client *i2c, const struct i2c_d
        } 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;
@@ -696,6 +936,7 @@ static int __devexit lp8725_i2c_remove(struct i2c_client *i2c)
 {
        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]);
@@ -723,6 +964,15 @@ static struct i2c_driver lp8725_i2c_driver = {
        .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;
@@ -731,12 +981,25 @@ static int __init lp8725_module_init(void)
        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);