clk: rockchip: support setting ddr clock via SCPI APIs
[firefly-linux-kernel-4.4.55.git] / drivers / regulator / act8846.c
index be07922ce36c2b3e40dd70e3e52de63c5bbfb4e5..3042b0000678d118ec41b1ed8c85a80b38d512b6 100755 (executable)
@@ -20,6 +20,7 @@
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/mutex.h>
+#include <linux/mfd/core.h>
 #ifdef CONFIG_HAS_EARLYSUSPEND
 #include <linux/earlysuspend.h>
 #endif
@@ -33,6 +34,7 @@
 #include <linux/regulator/driver.h>
 #include <linux/regulator/machine.h>
 #include <linux/regmap.h>
+#include <asm/system_misc.h>
 
 #if 0
 #define DBG(x...)      printk(KERN_INFO x)
@@ -52,10 +54,13 @@ struct act8846 {
        struct i2c_client *i2c;
        int num_regulators;
        struct regulator_dev **rdev;
-//     struct early_suspend act8846_suspend;
+#ifdef CONFIG_HAS_EARLYSUSPEND
+       struct early_suspend act8846_suspend;
+#endif
        int irq_base;
        int chip_irq;
        int pmic_sleep_gpio; /* */
+       int pmic_hold_gpio; /* */
        unsigned int dcdc_slp_voltage[3]; /* buckx_voltage in uV */
        bool pmic_sleep;
        struct regmap *regmap;
@@ -382,6 +387,9 @@ static int act8846_dcdc_set_voltage(struct regulator_dev *dev,
        #else
        ret = act8846_set_bits(act8846, act8846_BUCK_SET_VOL_REG(buck) ,BUCK_VOL_MASK, val);
        #endif
+
+       if(ret < 0)
+               printk("##################:set voltage error!voltage set is %d mv\n",vol_map[val]);
        
        return ret;
 }
@@ -453,8 +461,7 @@ static int act8846_dcdc_set_mode(struct regulator_dev *dev, unsigned int mode)
 static int act8846_dcdc_set_voltage_time_sel(struct regulator_dev *dev,   unsigned int old_selector,
                                     unsigned int new_selector)
 {
-       struct act8846 *act8846 = rdev_get_drvdata(dev);
-       int ret =0,old_volt, new_volt;
+       int old_volt, new_volt;
        
        old_volt = act8846_dcdc_list_voltage(dev, old_selector);
        if (old_volt < 0)
@@ -621,7 +628,7 @@ static int act8846_i2c_read(struct i2c_client *i2c, char reg, int count,    u16 *de
 
        DBG("***run in %s %d msgs[1].buf = %d\n",__FUNCTION__,__LINE__,*(msgs[1].buf));
 
-       return 0;   
+       return ret;   
 }
 
 static int act8846_i2c_write(struct i2c_client *i2c, char reg, int count, const u16 src)
@@ -654,10 +661,15 @@ static int act8846_i2c_write(struct i2c_client *i2c, char reg, int count, const
 static u8 act8846_reg_read(struct act8846 *act8846, u8 reg)
 {
        u16 val = 0;
+       int ret;
 
        mutex_lock(&act8846->io_lock);
 
-       act8846_i2c_read(act8846->i2c, reg, 1, &val);
+       ret = act8846_i2c_read(act8846->i2c, reg, 1, &val);
+       if(ret < 0){
+               mutex_unlock(&act8846->io_lock);
+               return ret;
+       }
 
        DBG("reg read 0x%02x -> 0x%02x\n", (int)reg, (unsigned)val&0xff);
 
@@ -674,13 +686,24 @@ static int act8846_set_bits(struct act8846 *act8846, u8 reg, u16 mask, u16 val)
        mutex_lock(&act8846->io_lock);
 
        ret = act8846_i2c_read(act8846->i2c, reg, 1, &tmp);
+       if(ret < 0){
+               mutex_unlock(&act8846->io_lock);
+               return ret;
+       }
        DBG("1 reg read 0x%02x -> 0x%02x\n", (int)reg, (unsigned)tmp&0xff);
        tmp = (tmp & ~mask) | val;
-       if (ret == 0) {
-               ret = act8846_i2c_write(act8846->i2c, reg, 1, tmp);
-               DBG("reg write 0x%02x -> 0x%02x\n", (int)reg, (unsigned)val&0xff);
+       ret = act8846_i2c_write(act8846->i2c, reg, 1, tmp);
+       if(ret < 0){
+               mutex_unlock(&act8846->io_lock);
+               return ret;
+       }
+       DBG("reg write 0x%02x -> 0x%02x\n", (int)reg, (unsigned)val&0xff);
+       
+       ret = act8846_i2c_read(act8846->i2c, reg, 1, &tmp);
+       if(ret < 0){
+               mutex_unlock(&act8846->io_lock);
+               return ret;
        }
-       act8846_i2c_read(act8846->i2c, reg, 1, &tmp);
        DBG("2 reg read 0x%02x -> 0x%02x\n", (int)reg, (unsigned)tmp&0xff);
        mutex_unlock(&act8846->io_lock);
 
@@ -716,7 +739,7 @@ static struct act8846_board *act8846_parse_dt(struct act8846 *act8846)
        struct act8846_board *pdata;
        struct device_node *regs;
        struct device_node *act8846_pmic_np;
-       int i, count,sleep_voltage_nr =1;
+       int i, count;
        int gpio;
        printk("%s,line=%d\n", __func__,__LINE__);      
        
@@ -748,59 +771,21 @@ static struct act8846_board *act8846_parse_dt(struct act8846 *act8846)
        pdata->irq = act8846->chip_irq;
        pdata->irq_base = -1;
 
-       if (of_get_property(act8846_pmic_np, "act,pmic-dcdc-sleep-voltage", NULL))
-               pdata->pmic_sleep = true;
-
-       if (of_get_property(act8846_pmic_np, "act,pmic-ldo-sleep-voltage", NULL))
-               pdata->pmic_sleep = true;
-
        gpio = of_get_named_gpio(act8846_pmic_np,"gpios", 0);
                if (!gpio_is_valid(gpio)) 
                        printk("invalid gpio: %d\n",gpio);
-       pdata->pmic_sleep_gpio = gpio;
+       pdata->pmic_sleep_gpio = gpio;  
+       pdata->pmic_sleep = true;
        
-       if (of_property_read_u32_array(act8846_pmic_np,
-                               "act,pmic-dcdc-sleep-voltage",
-                               pdata->dcdc_slp_voltage, sleep_voltage_nr)) {
-               printk("dcdc sleep voltages not specified\n");
-       }\r      
+       gpio = of_get_named_gpio(act8846_pmic_np,"gpios", 1);
+               if (!gpio_is_valid(gpio)) 
+                       printk("invalid gpio: %d\n",gpio);
+       pdata->pmic_hold_gpio = gpio;   
+       pdata->pm_off = of_property_read_bool(act8846_pmic_np,"act8846,system-power-controller");
 
        return pdata;
 }
-static int act8846_dcdc_sleep_voltage_get_val(int min_uV,int buck)
-{
-       int min_vol = min_uV / 1000, max_vol = min_uV / 1000;
-       const int *vol_map = buck_voltage_map;
-       u16 val;
-
-       if (min_vol < vol_map[VOL_MIN_IDX] ||
-           min_vol > vol_map[VOL_MAX_IDX])
-               return -EINVAL;
-
-       for (val = VOL_MIN_IDX; val <= VOL_MAX_IDX; val++){
-               if (vol_map[val] >= min_vol)
-                       break;
-        }
 
-       if (vol_map[val] > max_vol)
-               printk("WARNING:this voltage is not support!voltage set is %d mv\n",vol_map[val]);
-       return val;
-}
-static int act8846_dts_dcdc_set_mode(unsigned int mode,int buck)
-{
-       struct act8846 *act8846 = g_act8846;
-       u16 mask = 0x80;
-       switch(mode)
-       {
-       case REGULATOR_MODE_STANDBY:
-               return act8846_set_bits(act8846, act8846_BUCK_CONTR_REG(buck), mask, 0);
-       case REGULATOR_MODE_NORMAL:
-               return act8846_set_bits(act8846, act8846_BUCK_CONTR_REG(buck), mask, mask);
-       default:
-               printk("error:pmu_act8846 only powersave and pwm mode\n");
-               return -EINVAL;
-       }
-}
 #else
 static struct act8846_board *act8846_parse_dt(struct i2c_client *i2c)
 {
@@ -809,14 +794,19 @@ static struct act8846_board *act8846_parse_dt(struct i2c_client *i2c)
 #endif
 
 
-int act8846_device_shutdown(void)
+void act8846_device_shutdown(void)
 {
-       int ret;
-       int err = -1;
        struct act8846 *act8846 = g_act8846;
        
        printk("%s\n",__func__);
-
+#if 1
+       if (act8846->pmic_hold_gpio) {
+                       gpio_direction_output(act8846->pmic_hold_gpio,0);
+                       mdelay(100);
+                       arm_pm_restart('h', "charge");
+       }
+       
+#else
        ret = act8846_reg_read(act8846,0xc3);
        ret = act8846_set_bits(act8846, 0xc3,(0x1<<3),(0x1<<3));
        ret = act8846_set_bits(act8846, 0xc3,(0x1<<4),(0x1<<4));
@@ -824,31 +814,31 @@ int act8846_device_shutdown(void)
                printk("act8846 set 0xc3 error!\n");
                return err;
        }
-       return 0;       
+#endif
 }
 EXPORT_SYMBOL_GPL(act8846_device_shutdown);
 
 __weak void  act8846_device_suspend(void) {}
 __weak void  act8846_device_resume(void) {}
 #ifdef CONFIG_PM
-static int act8846_suspend(struct i2c_client *i2c, pm_message_t mesg)
-{              
+static int act8846_suspend(struct device *dev)
+{      
        act8846_device_suspend();
        return 0;
 }
 
-static int act8846_resume(struct i2c_client *i2c)
+static int act8846_resume(struct device *dev)
 {
        act8846_device_resume();
        return 0;
 }
 #else
-static int act8846_suspend(struct i2c_client *i2c, pm_message_t mesg)
+static int act8846_suspend(struct device *dev)
 {              
        return 0;
 }
 
-static int act8846_resume(struct i2c_client *i2c)
+static int act8846_resume(struct device *dev)
 {
        return 0;
 }
@@ -897,7 +887,7 @@ static int act8846_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id
                }
        }
 
-       act8846 = kzalloc(sizeof(struct act8846), GFP_KERNEL);
+       act8846 = devm_kzalloc(&i2c->dev,sizeof(struct act8846), GFP_KERNEL);
        if (act8846 == NULL) {
                ret = -ENOMEM;          
                goto err;
@@ -919,7 +909,7 @@ static int act8846_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id
        ret = act8846_reg_read(act8846,0x22);
        if ((ret < 0) || (ret == 0xff)){
                printk("The device is not act8846 %x \n",ret);
-               return 0;
+               goto err;
        }
 
        ret = act8846_set_bits(act8846, 0xf4,(0x1<<7),(0x0<<7));
@@ -930,6 +920,21 @@ static int act8846_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id
 
        if (act8846->dev->of_node)
                pdev = act8846_parse_dt(act8846);
+
+       #ifdef CONFIG_OF
+       act8846->pmic_hold_gpio = pdev->pmic_hold_gpio;
+       if (act8846->pmic_hold_gpio) {
+                       ret = gpio_request(act8846->pmic_hold_gpio, "act8846_pmic_hold");
+                       if (ret < 0) {
+                               dev_err(act8846->dev,"Failed to request gpio %d with ret:""%d\n",       act8846->pmic_hold_gpio, ret);
+                               return IRQ_NONE;
+                       }
+                       gpio_direction_output(act8846->pmic_hold_gpio,1);
+                       ret = gpio_get_value(act8846->pmic_hold_gpio);
+       //              gpio_free(act8846->pmic_hold_gpio);
+                       printk("%s: act8846_pmic_hold=%x\n", __func__, ret);
+       }
+       #endif
        
        /******************************set sleep vol & dcdc mode******************/
        #ifdef CONFIG_OF
@@ -940,29 +945,19 @@ static int act8846_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id
                                dev_err(act8846->dev,"Failed to request gpio %d with ret:""%d\n",       act8846->pmic_sleep_gpio, ret);
                                return IRQ_NONE;
                        }
-                       gpio_direction_input(act8846->pmic_sleep_gpio);
+                       gpio_direction_output(act8846->pmic_sleep_gpio,1);
                        ret = gpio_get_value(act8846->pmic_sleep_gpio);
                        gpio_free(act8846->pmic_sleep_gpio);
                        printk("%s: act8846_pmic_sleep=%x\n", __func__, ret);
        }
-       for (i = 0;i <4 ; i ++){
-       act8846->dcdc_slp_voltage[i] = pdev->dcdc_slp_voltage[i];
-               if (act8846->dcdc_slp_voltage[i]){
-                       if (i ==0)
-                               continue;
-
-                       #ifdef CONFIG_ACT8846_SUPPORT_RESET
-                       ret = act8846_set_bits(act8846, act8846_BUCK_SET_VOL_REG(i) ,BUCK_VOL_MASK, act8846_dcdc_sleep_voltage_get_val(act8846->dcdc_slp_voltage[i],i));
-                       #else
-                       ret = act8846_set_bits(act8846, (act8846_BUCK_SET_VOL_REG(i) +0x01),BUCK_VOL_MASK, act8846_dcdc_sleep_voltage_get_val(act8846->dcdc_slp_voltage[i],i));
-                       #endif
-               }
-       }
        #endif
        
        if (pdev) {
                act8846->num_regulators = act8846_NUM_REGULATORS;
-               act8846->rdev = kcalloc(act8846_NUM_REGULATORS,sizeof(struct regulator_dev *), GFP_KERNEL);
+               act8846->rdev = devm_kcalloc(act8846->dev,
+                                            act8846_NUM_REGULATORS,
+                                            sizeof(struct regulator_dev *),
+                                            GFP_KERNEL);
                if (!act8846->rdev) {
                        return -ENOMEM;
                }
@@ -993,6 +988,10 @@ static int act8846_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id
                act8846->rdev[i] = act_rdev;
                }
        }
+
+       if (pdev->pm_off && !pm_power_off) {
+               pm_power_off = act8846_device_shutdown;
+       }
        
        #ifdef CONFIG_HAS_EARLYSUSPEND
        act8846->act8846_suspend.suspend = act8846_early_suspend,
@@ -1016,13 +1015,16 @@ static int  act8846_i2c_remove(struct i2c_client *i2c)
        for (i = 0; i < act8846->num_regulators; i++)
                if (act8846->rdev[i])
                        regulator_unregister(act8846->rdev[i]);
-       kfree(act8846->rdev);
        i2c_set_clientdata(i2c, NULL);
-       kfree(act8846);
 
        return 0;
 }
 
+static const struct dev_pm_ops act8846_pm_ops = {
+       .suspend = act8846_suspend,
+       .resume =  act8846_resume,
+};
+
 static const struct i2c_device_id act8846_i2c_id[] = {
        { "act8846", 0 },
        { }
@@ -1034,15 +1036,14 @@ static struct i2c_driver act8846_i2c_driver = {
        .driver = {
                .name = "act8846",
                .owner = THIS_MODULE,
+               #ifdef CONFIG_PM
+               .pm = &act8846_pm_ops,
+               #endif
                .of_match_table =of_match_ptr(act8846_of_match),
        },
        .probe    = act8846_i2c_probe,
        .remove   = act8846_i2c_remove,
        .id_table = act8846_i2c_id,
-       #ifdef CONFIG_PM
-       .suspend        = act8846_suspend,
-       .resume         = act8846_resume,
-       #endif
 };
 
 static int __init act8846_module_init(void)