X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=drivers%2Fmfd%2Frk808.c;h=2eadd2c10e6994f8366af01221675f355b1361de;hb=2ae05321496aa27767bc33a5cc19451b3db67919;hp=eaf83c93cee58b028ccce758de68e86ef37c3c71;hpb=3ca9efa2f84503d67046ce2583470618b0faba24;p=firefly-linux-kernel-4.4.55.git diff --git a/drivers/mfd/rk808.c b/drivers/mfd/rk808.c old mode 100755 new mode 100644 index eaf83c93cee5..2eadd2c10e69 --- a/drivers/mfd/rk808.c +++ b/drivers/mfd/rk808.c @@ -1,1570 +1,941 @@ /* - * Regulator driver for rk808 PMIC chip for rk31xx + * MFD core driver for Rockchip RK808 * - * Based on rk808.c that is work by zhangqing + * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd * - * 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. + * Author: Chris Zhong + * Author: Zhang Qing * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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. */ -#include -#include #include +#include #include -#include #include #include -#include -#include -#include -#ifdef CONFIG_HAS_EARLYSUSPEND -#include -#endif -#include #include -#include -#include -#include #include -#include -#include -#include #include -#include - -#if 0 -#define DBG(x...) printk(KERN_INFO x) -#else -#define DBG(x...) -#endif -#if 1 -#define DBG_INFO(x...) printk(KERN_INFO x) -#else -#define DBG_INFO(x...) -#endif -#define PM_CONTROL - -struct rk808 *g_rk808; -#define DCDC_RAISE_VOL_BYSTEP 1 -#define DCDC_VOL_STEP 25000 //25mv - -static struct mfd_cell rk808s[] = { - { - .name = "rk808-rtc", - }, -}; - -#define BUCK_VOL_MASK 0x3f -#define LDO_VOL_MASK 0x3f - -#define VOL_MIN_IDX 0x00 -#define VOL_MAX_IDX 0x3f - -const static int buck_set_vol_base_addr[] = { - RK808_BUCK1_ON_REG, - RK808_BUCK2_ON_REG, - RK808_BUCK3_CONFIG_REG, - RK808_BUCK4_ON_REG, -}; -const static int buck_contr_base_addr[] = { - RK808_BUCK1_CONFIG_REG, - RK808_BUCK2_CONFIG_REG, - RK808_BUCK3_CONFIG_REG, - RK808_BUCK4_CONFIG_REG, -}; -#define rk808_BUCK_SET_VOL_REG(x) (buck_set_vol_base_addr[x]) -#define rk808_BUCK_CONTR_REG(x) (buck_contr_base_addr[x]) - - -const static int ldo_set_vol_base_addr[] = { - RK808_LDO1_ON_VSEL_REG, - RK808_LDO2_ON_VSEL_REG, - RK808_LDO3_ON_VSEL_REG, - RK808_LDO4_ON_VSEL_REG, - RK808_LDO5_ON_VSEL_REG, - RK808_LDO6_ON_VSEL_REG, - RK808_LDO7_ON_VSEL_REG, - RK808_LDO8_ON_VSEL_REG, -// RK808_LDO1_ON_VSEL_REG, -}; -/* -const static int ldo_contr_base_addr[] = { - rk808_LDO1_CONTR_BASE, - rk808_LDO2_CONTR_BASE, - rk808_LDO3_CONTR_BASE, - rk808_LDO4_CONTR_BASE, - rk808_LDO5_CONTR_BASE, - rk808_LDO6_CONTR_BASE, - rk808_LDO7_CONTR_BASE, - rk808_LDO8_CONTR_BASE, -// rk808_LDO9_CONTR_BASE, -}; -*/ -#define rk808_LDO_SET_VOL_REG(x) (ldo_set_vol_base_addr[x]) -//#define rk808_LDO_CONTR_REG(x) (ldo_contr_base_addr[x]) - -const static int buck_voltage_map[] = { - 700, 712, 725, 737, 750, 762, 775, 787, 800, - 812, 825, 837, 850,862, 875, 887, 900, 912, - 925, 937, 950, 962, 975, 987, 1000, 1012, 1025, - 1037, 1050,1062, 1075, 1087, 1100, 1112, 1125, 1137, - 1150,1162, 1175, 1187, 1200, 1212, 1225, 1237, 1250, - 1262, 1275, 1287, 1300, 1312, 1325, 1337, 1350,1362, - 1375, 1387, 1400, 1412, 1425, 1437, 1450,1462, 1475, - 1487, 1500, -}; - -const static int buck4_voltage_map[] = { - 1800, 1900, 2000, 2100, 2200, 2300, 2400, 2500, 2600, - 2700, 2800, 2900, 3000, 3100, 3200,3300, -}; +#include +#include +#include -const static int ldo_voltage_map[] = { - 1800, 1900, 2000, 2100, 2200, 2300, 2400, 2500, 2600, - 2700, 2800, 2900, 3000, 3100, 3200,3300, 3400, -}; -const static int ldo3_voltage_map[] = { - 800, 900, 1000, 1100, 1200, 1300, 1400, 1500, 1600, - 1700, 1800, 1900, 2000,2100, 2200, 2500, -}; -const static int ldo6_voltage_map[] = { - 800, 900, 1000, 1100, 1200, 1300, 1400, 1500, 1600, - 1700, 1800, 1900, 2000,2100, 2200, 2300,2400,2500, +struct rk808_reg_data { + int addr; + int mask; + int value; }; -static int rk808_ldo_list_voltage(struct regulator_dev *dev, unsigned index) -{ - int ldo= rdev_get_id(dev) - RK808_LDO1; - if (ldo == 2){ - if (index >= ARRAY_SIZE(ldo3_voltage_map)) - return -EINVAL; - return 1000 * ldo3_voltage_map[index]; - } - else if (ldo == 5 || ldo ==6){ - if (index >= ARRAY_SIZE(ldo6_voltage_map)) - return -EINVAL; - return 1000 * ldo6_voltage_map[index]; - } - else{ - if (index >= ARRAY_SIZE(ldo_voltage_map)) - return -EINVAL; - return 1000 * ldo_voltage_map[index]; +static bool rk808_is_volatile_reg(struct device *dev, unsigned int reg) +{ + /* + * Notes: + * - Technically the ROUND_30s bit makes RTC_CTRL_REG volatile, but + * we don't use that feature. It's better to cache. + * - It's unlikely we care that RK808_DEVCTRL_REG is volatile since + * bits are cleared in case when we shutoff anyway, but better safe. + */ + + switch (reg) { + case RK808_SECONDS_REG ... RK808_WEEKS_REG: + case RK808_RTC_STATUS_REG: + case RK808_VB_MON_REG: + case RK808_THERMAL_REG: + case RK808_DCDC_UV_STS_REG: + case RK808_LDO_UV_STS_REG: + case RK808_DCDC_PG_REG: + case RK808_LDO_PG_REG: + case RK808_DEVCTRL_REG: + case RK808_INT_STS_REG1: + case RK808_INT_STS_REG2: + return true; } -} -static int rk808_ldo_is_enabled(struct regulator_dev *dev) -{ - struct rk808 *rk808 = rdev_get_drvdata(dev); - int ldo= rdev_get_id(dev) - RK808_LDO1; - u16 val; - - if ((ldo ==8) ||(ldo ==9)){ - val = rk808_reg_read(rk808, RK808_DCDC_EN_REG); - if (val < 0) - return val; - if (val & (1 <<( ldo -3))) - return 1; - else - return 0; - } - else{ - val = rk808_reg_read(rk808, RK808_LDO_EN_REG); - if (val < 0) - return val; - if (val & (1 << ldo)) - return 1; - else - return 0; - } -} -static int rk808_ldo_enable(struct regulator_dev *dev) -{ - struct rk808 *rk808 = rdev_get_drvdata(dev); - int ldo= rdev_get_id(dev) - RK808_LDO1; - - if(ldo == 8) - return rk808_set_bits(rk808, RK808_DCDC_EN_REG, 1 << 5, 1 << 5); - else if(ldo ==9) - return rk808_set_bits(rk808, RK808_DCDC_EN_REG, 1 << 6, 1 << 6); - else - return rk808_set_bits(rk808, RK808_LDO_EN_REG, 1 << ldo, 1 << ldo); - -} -static int rk808_ldo_disable(struct regulator_dev *dev) -{ - struct rk808 *rk808 = rdev_get_drvdata(dev); - int ldo= rdev_get_id(dev) - RK808_LDO1; - - if(ldo == 8) - return rk808_set_bits(rk808, RK808_DCDC_EN_REG, 1 << 5, 0); - else if(ldo ==9) - return rk808_set_bits(rk808, RK808_DCDC_EN_REG, 1 << 6, 0); - else - return rk808_set_bits(rk808, RK808_LDO_EN_REG, 1 << ldo, 0); + return false; } -static int rk808_ldo_suspend_enable(struct regulator_dev *dev) -{ - struct rk808 *rk808 = rdev_get_drvdata(dev); - int ldo= rdev_get_id(dev) - RK808_LDO1; - - if(ldo == 8) - return rk808_set_bits(rk808, RK808_SLEEP_SET_OFF_REG1, 1 << 5, 0); - else if(ldo ==9) - return rk808_set_bits(rk808, RK808_SLEEP_SET_OFF_REG1, 1 << 6, 0); - else - return rk808_set_bits(rk808, RK808_SLEEP_SET_OFF_REG2, 1 << ldo, 0); - -} -static int rk808_ldo_suspend_disable(struct regulator_dev *dev) -{ - struct rk808 *rk808 = rdev_get_drvdata(dev); - int ldo= rdev_get_id(dev) - RK808_LDO1; - - if(ldo == 8) - return rk808_set_bits(rk808, RK808_SLEEP_SET_OFF_REG1, 1 << 5, 1 << 5); - else if(ldo ==9) - return rk808_set_bits(rk808, RK808_SLEEP_SET_OFF_REG1, 1 << 6, 1 << 6); - else - return rk808_set_bits(rk808, RK808_SLEEP_SET_OFF_REG2, 1 << ldo, 1 << ldo); -} -static int rk808_ldo_get_voltage(struct regulator_dev *dev) +static int rk808_shutdown(struct regmap *regmap) { - struct rk808 *rk808 = rdev_get_drvdata(dev); - int ldo= rdev_get_id(dev) - RK808_LDO1; - u16 reg = 0; - int val; - - if ((ldo ==8 ) || (ldo ==9)){ - reg = rk808_reg_read(rk808,rk808_BUCK_SET_VOL_REG(3)); - reg &= BUCK_VOL_MASK; - val = 1000 * buck4_voltage_map[reg]; - } - else{ - reg = rk808_reg_read(rk808,rk808_LDO_SET_VOL_REG(ldo)); - reg &= LDO_VOL_MASK; - if (ldo ==2){ - val = 1000 * ldo3_voltage_map[reg]; - } - else if (ldo == 5 || ldo ==6){ - val = 1000 * ldo6_voltage_map[reg]; - } - else{ - val = 1000 * ldo_voltage_map[reg]; - } - } - return val; -} -static int rk808_ldo_set_sleep_voltage(struct regulator_dev *dev, - int uV) -{ - struct rk808 *rk808 = rdev_get_drvdata(dev); - int ldo= rdev_get_id(dev) - RK808_LDO1; - const int *vol_map = ldo_voltage_map; - int min_vol = uV / 1000; - u16 val; - int ret = 0,num =0; - - if (ldo ==2){ - vol_map = ldo3_voltage_map; - num = 15; - } - else if (ldo == 5 || ldo ==6){ - vol_map = ldo6_voltage_map; - num = 17; - } - else { - num = 16; - } - - if (min_vol < vol_map[0] || - min_vol > vol_map[num]) - return -EINVAL; + int ret; - for (val = 0; val <= num; val++){ - if (vol_map[val] >= min_vol) - break; - } + ret = regmap_update_bits(regmap, + RK808_DEVCTRL_REG, + DEV_OFF, DEV_OFF); + if (ret) + printk("DEV_OFF error!\n"); + + mdelay(2); + ret = regmap_update_bits(regmap, + RK808_DCDC_EN_REG, + BUCK1_EN_MASK | BUCK2_EN_MASK | BUCK3_EN_MASK | BUCK4_EN_MASK, 0xf); + if (ret) + printk("RK808_DCDC_EN_REG error!\n"); + ret = regmap_update_bits(regmap, + RK808_LDO_EN_REG, + 0xff, 0xff); + if (ret) + printk("RK808_LDO_EN_REG error!\n"); - ret = rk808_set_bits(rk808, rk808_LDO_SET_VOL_REG(ldo) +0x01, - LDO_VOL_MASK, val); return ret; } -static int rk808_ldo_set_voltage(struct regulator_dev *dev, - int min_uV, int max_uV,unsigned *selector) +static int rk816_shutdown(struct regmap *regmap) { - struct rk808 *rk808 = rdev_get_drvdata(dev); - int ldo= rdev_get_id(dev) - RK808_LDO1; - const int *vol_map; - int min_vol = min_uV / 1000; - u16 val; - int ret = 0,num =0; - - if (ldo ==2){ - vol_map = ldo3_voltage_map; - num = 15; - } - else if (ldo == 5 || ldo ==6){ - vol_map = ldo6_voltage_map; - num = 17; - } - else { - vol_map = ldo_voltage_map; - num = 16; - } - - if (min_vol < vol_map[0] || - min_vol > vol_map[num]) - return -EINVAL; + int ret; - for (val = 0; val <= num; val++){ - if (vol_map[val] >= min_vol) - break; - } - - ret = rk808_set_bits(rk808, rk808_LDO_SET_VOL_REG(ldo), - LDO_VOL_MASK, val); + ret = regmap_update_bits(regmap, + RK816_DEV_CTRL_REG, + DEV_OFF, DEV_OFF); return ret; - -} -static unsigned int rk808_ldo_get_mode(struct regulator_dev *dev) -{ - struct rk808 *rk808 = rdev_get_drvdata(dev); - int ldo = rdev_get_id(dev) - RK808_LDO1; - u16 mask = 0x80; - u16 val; - val = rk808_reg_read(rk808, rk808_LDO_SET_VOL_REG(ldo)); - if (val < 0) { - return val; - } - val=val & mask; - if (val== mask) - return REGULATOR_MODE_NORMAL; - else - return REGULATOR_MODE_STANDBY; - -} -static int rk808_ldo_set_mode(struct regulator_dev *dev, unsigned int mode) -{ - struct rk808 *rk808 = rdev_get_drvdata(dev); - int ldo = rdev_get_id(dev) - RK808_LDO1; - u16 mask = 0x80; - switch(mode) - { - case REGULATOR_MODE_FAST: - return rk808_set_bits(rk808, rk808_LDO_SET_VOL_REG(ldo), mask, mask); - case REGULATOR_MODE_NORMAL: - return rk808_set_bits(rk808, rk808_LDO_SET_VOL_REG(ldo), mask, 0); - default: - printk("error:pmu_rk808 only lowpower and nomal mode\n"); - return -EINVAL; - } - - } -static struct regulator_ops rk808_ldo_ops = { - .set_voltage = rk808_ldo_set_voltage, - .get_voltage = rk808_ldo_get_voltage, - .list_voltage = rk808_ldo_list_voltage, - .is_enabled = rk808_ldo_is_enabled, - .enable = rk808_ldo_enable, - .disable = rk808_ldo_disable, - .set_suspend_enable =rk808_ldo_suspend_enable, - .set_suspend_disable =rk808_ldo_suspend_disable, - .get_mode = rk808_ldo_get_mode, - .set_mode = rk808_ldo_set_mode, - .set_suspend_voltage = rk808_ldo_set_sleep_voltage, - -}; - -static int rk808_dcdc_list_voltage(struct regulator_dev *dev, unsigned selector) -{ - int volt; - int buck = rdev_get_id(dev) - RK808_DCDC1; - - if (selector < 0x0 ||selector > BUCK_VOL_MASK ) - return -EINVAL; - - switch (buck) { - case 0: - case 1: - volt = 700000 + selector * 12500; - break; - case 3: - volt = 1800000 + selector * 100000; - break; - case 2: - volt = 1200000; - break; - default: - BUG(); - return -EINVAL; - } - return volt ; -} -static int rk808_dcdc_is_enabled(struct regulator_dev *dev) -{ - struct rk808 *rk808 = rdev_get_drvdata(dev); - int buck = rdev_get_id(dev) - RK808_DCDC1; - u16 val; - - val = rk808_reg_read(rk808, RK808_DCDC_EN_REG); - if (val < 0) - return val; - if (val & (1 << buck)) - return 1; - else - return 0; -} -static int rk808_dcdc_enable(struct regulator_dev *dev) +static int rk818_shutdown(struct regmap *regmap) { - struct rk808 *rk808 = rdev_get_drvdata(dev); - int buck = rdev_get_id(dev) - RK808_DCDC1; - - return rk808_set_bits(rk808, RK808_DCDC_EN_REG, 1 << buck, 1 << buck); + int ret; -} -static int rk808_dcdc_disable(struct regulator_dev *dev) -{ - struct rk808 *rk808 = rdev_get_drvdata(dev); - int buck = rdev_get_id(dev) - RK808_DCDC1; - - return rk808_set_bits(rk808, RK808_DCDC_EN_REG, 1 << buck , 0); + ret = regmap_update_bits(regmap, + RK818_DEVCTRL_REG, + DEV_OFF, DEV_OFF); + return ret; } -static int rk808_dcdc_suspend_enable(struct regulator_dev *dev) +static int rk805_shutdown_prepare(struct regmap *regmap) { - struct rk808 *rk808 = rdev_get_drvdata(dev); - int buck = rdev_get_id(dev) - RK808_DCDC1; - - return rk808_set_bits(rk808, RK808_SLEEP_SET_OFF_REG1, 1 << buck, 0); + int ret; -} -static int rk808_dcdc_suspend_disable(struct regulator_dev *dev) -{ - struct rk808 *rk808 = rdev_get_drvdata(dev); - int buck = rdev_get_id(dev) - RK808_DCDC1; - - return rk808_set_bits(rk808, RK808_SLEEP_SET_OFF_REG1, 1 << buck , 1 << buck); -} -static int rk808_dcdc_get_voltage(struct regulator_dev *dev) -{ - struct rk808 *rk808 = rdev_get_drvdata(dev); - int buck = rdev_get_id(dev) - RK808_DCDC1; - u16 reg = 0; - int val; - - reg = rk808_reg_read(rk808,rk808_BUCK_SET_VOL_REG(buck)); - - reg &= BUCK_VOL_MASK; - val = rk808_dcdc_list_voltage(dev,reg); - return val; -} -static int rk808_dcdc_select_min_voltage(struct regulator_dev *dev, - int min_uV, int max_uV ,int buck) -{ - u16 vsel =0; - - if (buck == 0 || buck == 1){ - if (min_uV < 700000) - vsel = 0; - else if (min_uV <= 1500000) - vsel = ((min_uV - 700000) / 12500) ; - else - return -EINVAL; - } - else if (buck ==3){ - if (min_uV < 1800000) - vsel = 0; - else if (min_uV <= 3300000) - vsel = ((min_uV - 1800000) / 100000) ; - else - return -EINVAL; - } - if (rk808_dcdc_list_voltage(dev, vsel) > max_uV) - return -EINVAL; - return vsel; + /* close rtc int when power off */ + regmap_update_bits(regmap, + RK808_INT_STS_MSK_REG1, + (0x3 << 5), (0x3 << 5)); + regmap_update_bits(regmap, + RK808_RTC_INT_REG, + (0x3 << 2), (0x0 << 2)); + + /* pmic sleep shutdown function */ + ret = regmap_update_bits(regmap, + RK805_GPIO_IO_POL_REG, + SLP_SD_MSK, SHUTDOWN_FUN); + return ret; } -static int rk808_dcdc_set_voltage(struct regulator_dev *dev, - int min_uV, int max_uV,unsigned *selector) -{ - struct rk808 *rk808 = rdev_get_drvdata(dev); - int buck = rdev_get_id(dev) - RK808_DCDC1; - u16 val; - int ret = 0,old_voltage =0,vol_temp =0; - - if (buck ==2){ - return 0; - }else if (buck==3){ - val = rk808_dcdc_select_min_voltage(dev,min_uV,max_uV,buck); - ret = rk808_set_bits(rk808, rk808_BUCK_SET_VOL_REG(buck), BUCK_VOL_MASK, val); - } - else { -#if defined(DCDC_RAISE_VOL_BYSTEP) - old_voltage = rk808_dcdc_get_voltage(dev); - if (max_uV >old_voltage){ - vol_temp = old_voltage; - do{ - vol_temp += DCDC_VOL_STEP; - val = rk808_dcdc_select_min_voltage(dev,vol_temp,vol_temp,buck); - // printk("rk808_dcdc_set_voltage buck = %d vol_temp= %d old_voltage= %d min_uV =%d \n",buck,vol_temp,old_voltage,min_uV); - ret = rk808_set_bits(rk808, rk808_BUCK_SET_VOL_REG(buck), BUCK_VOL_MASK, val); - }while(vol_temp != max_uV); - } - else{ - val = rk808_dcdc_select_min_voltage(dev,min_uV,max_uV,buck); - ret = rk808_set_bits(rk808, rk808_BUCK_SET_VOL_REG(buck), BUCK_VOL_MASK, val); - } -#else - val = rk808_dcdc_select_min_voltage(dev,min_uV,max_uV,buck); - ret = rk808_set_bits(rk808, rk808_BUCK_SET_VOL_REG(buck), BUCK_VOL_MASK, val); -#endif +static bool rk818_is_volatile_reg(struct device *dev, unsigned int reg) +{ + /* + * Notes: + * - Technically the ROUND_30s bit makes RTC_CTRL_REG volatile, but + * we don't use that feature. It's better to cache. + * - It's unlikely we care that RK808_DEVCTRL_REG is volatile since + * bits are cleared in case when we shutoff anyway, but better safe. + */ + + switch (reg) { + case RK808_SECONDS_REG ... RK808_WEEKS_REG: + case RK808_RTC_STATUS_REG: + case RK808_VB_MON_REG: + case RK808_THERMAL_REG: + case RK808_DCDC_EN_REG: + case RK808_DCDC_UV_STS_REG: + case RK808_LDO_UV_STS_REG: + case RK808_DCDC_PG_REG: + case RK808_LDO_PG_REG: + case RK808_DEVCTRL_REG: + case RK808_INT_STS_REG1: + case RK808_INT_STS_REG2: + case RK808_INT_STS_MSK_REG1: + case RK808_INT_STS_MSK_REG2: + case RK818_SUP_STS_REG ... RK818_SAVE_DATA19: + return true; } - if(ret<0) - printk("################WARNING:set voltage is error!voltage set is %d mv %d\n",min_uV,ret); - return ret; + return false; } -static int rk808_dcdc_set_sleep_voltage(struct regulator_dev *dev, - int uV) -{ - struct rk808 *rk808 = rdev_get_drvdata(dev); - int buck = rdev_get_id(dev) - RK808_DCDC1; - u16 val; - int ret = 0; - if (buck ==2){ - return 0; - }else{ - val = rk808_dcdc_select_min_voltage(dev,uV,uV,buck); - ret = rk808_set_bits(rk808, (rk808_BUCK_SET_VOL_REG(buck) + 0x01), BUCK_VOL_MASK, val); - } - return ret; -} -static unsigned int rk808_dcdc_get_mode(struct regulator_dev *dev) -{ - struct rk808 *rk808 = rdev_get_drvdata(dev); - int buck = rdev_get_id(dev) - RK808_DCDC1; - u16 mask = 0x80; - u16 val; - val = rk808_reg_read(rk808, rk808_BUCK_SET_VOL_REG(buck)); - if (val < 0) { - return val; - } - val=val & mask; - if (val== mask) - return REGULATOR_MODE_FAST; - else - return REGULATOR_MODE_NORMAL; +static const struct regmap_config rk808_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = RK808_IO_POL_REG, + .cache_type = REGCACHE_RBTREE, + .volatile_reg = rk808_is_volatile_reg, +}; -} -static int rk808_dcdc_set_mode(struct regulator_dev *dev, unsigned int mode) -{ - struct rk808 *rk808 = rdev_get_drvdata(dev); - int buck = rdev_get_id(dev) - RK808_DCDC1; - u16 mask = 0x80; +static const struct regmap_config rk805_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = RK805_OFF_SOURCE_REG, + .cache_type = REGCACHE_RBTREE, + .volatile_reg = rk808_is_volatile_reg, +}; - switch(mode) - { - case REGULATOR_MODE_FAST: - return rk808_set_bits(rk808, rk808_BUCK_SET_VOL_REG(buck), mask, mask); - case REGULATOR_MODE_NORMAL: - return rk808_set_bits(rk808, rk808_BUCK_SET_VOL_REG(buck), mask, 0); - default: - printk("error:pmu_rk808 only powersave and pwm mode\n"); - return -EINVAL; - } +static const struct regmap_config rk816_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = RK816_DATA18_REG, + .cache_type = REGCACHE_RBTREE, + .volatile_reg = rk818_is_volatile_reg, +}; -} -static int rk808_dcdc_set_suspend_mode(struct regulator_dev *dev, unsigned int mode) -{ - struct rk808 *rk808 = rdev_get_drvdata(dev); - int buck = rdev_get_id(dev) - RK808_DCDC1; - u16 mask = 0x80; +static const struct regmap_config rk818_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = RK818_SAVE_DATA19, + .cache_type = REGCACHE_RBTREE, + .volatile_reg = rk818_is_volatile_reg, +}; - switch(mode) +static struct resource rtc_resources[] = { { - case REGULATOR_MODE_FAST: - return rk808_set_bits(rk808, (rk808_BUCK_SET_VOL_REG(buck) + 0x01), mask, mask); - case REGULATOR_MODE_NORMAL: - return rk808_set_bits(rk808, (rk808_BUCK_SET_VOL_REG(buck) + 0x01), mask, 0); - default: - printk("error:pmu_rk808 only powersave and pwm mode\n"); - return -EINVAL; + .start = RK808_IRQ_RTC_ALARM, + .end = RK808_IRQ_RTC_ALARM, + .flags = IORESOURCE_IRQ, } - -} -static int rk808_dcdc_set_voltage_time_sel(struct regulator_dev *dev, unsigned int old_selector, - unsigned int new_selector) -{ - int old_volt, new_volt; - - old_volt = rk808_dcdc_list_voltage(dev, old_selector); - if (old_volt < 0) - return old_volt; - - new_volt = rk808_dcdc_list_voltage(dev, new_selector); - if (new_volt < 0) - return new_volt; - - return DIV_ROUND_UP(abs(old_volt - new_volt)*2, 2500); -} - -static struct regulator_ops rk808_dcdc_ops = { - .set_voltage = rk808_dcdc_set_voltage, - .get_voltage = rk808_dcdc_get_voltage, - .list_voltage= rk808_dcdc_list_voltage, - .is_enabled = rk808_dcdc_is_enabled, - .enable = rk808_dcdc_enable, - .disable = rk808_dcdc_disable, - .set_suspend_enable =rk808_dcdc_suspend_enable, - .set_suspend_disable =rk808_dcdc_suspend_disable, - .get_mode = rk808_dcdc_get_mode, - .set_mode = rk808_dcdc_set_mode, - .set_suspend_mode = rk808_dcdc_set_suspend_mode, - .set_suspend_voltage = rk808_dcdc_set_sleep_voltage, - .set_voltage_time_sel = rk808_dcdc_set_voltage_time_sel, }; -static struct regulator_desc regulators[] = { - - { - .name = "RK_DCDC1", - .id = 0, - .ops = &rk808_dcdc_ops, - .n_voltages = ARRAY_SIZE(buck_voltage_map), - .type = REGULATOR_VOLTAGE, - .owner = THIS_MODULE, + +static struct resource pwrkey_resources[] = { + { + .start = RK805_IRQ_PWRON_RISE, + .end = RK805_IRQ_PWRON_RISE, + .flags = IORESOURCE_IRQ, }, { - .name = "RK_DCDC2", - .id = 1, - .ops = &rk808_dcdc_ops, - .n_voltages = ARRAY_SIZE(buck_voltage_map), - .type = REGULATOR_VOLTAGE, - .owner = THIS_MODULE, + .start = RK805_IRQ_PWRON_FALL, + .end = RK805_IRQ_PWRON_FALL, + .flags = IORESOURCE_IRQ, }, +}; + +static struct resource rk816_pwrkey_resources[] = { { - .name = "RK_DCDC3", - .id = 2, - .ops = &rk808_dcdc_ops, - .n_voltages = ARRAY_SIZE(buck4_voltage_map), - .type = REGULATOR_VOLTAGE, - .owner = THIS_MODULE, + .start = RK816_IRQ_PWRON_RISE, + .end = RK816_IRQ_PWRON_RISE, + .flags = IORESOURCE_IRQ, }, { - .name = "RK_DCDC4", - .id = 3, - .ops = &rk808_dcdc_ops, - .n_voltages = ARRAY_SIZE(buck4_voltage_map), - .type = REGULATOR_VOLTAGE, - .owner = THIS_MODULE, + .start = RK816_IRQ_PWRON_FALL, + .end = RK816_IRQ_PWRON_FALL, + .flags = IORESOURCE_IRQ, }, +}; +static const struct mfd_cell rk808s[] = { + { .name = "rk808-clkout", }, + { .name = "rk808-regulator", }, { - .name = "RK_LDO1", - .id =4, - .ops = &rk808_ldo_ops, - .n_voltages = ARRAY_SIZE(ldo_voltage_map), - .type = REGULATOR_VOLTAGE, - .owner = THIS_MODULE, + .name = "rk808-rtc", + .num_resources = ARRAY_SIZE(rtc_resources), + .resources = &rtc_resources[0], }, - { - .name = "RK_LDO2", - .id = 5, - .ops = &rk808_ldo_ops, - .n_voltages = ARRAY_SIZE(ldo_voltage_map), - .type = REGULATOR_VOLTAGE, - .owner = THIS_MODULE, +}; + +static const struct rk808_reg_data rk808_pre_init_reg[] = { + { RK808_BUCK3_CONFIG_REG, BUCK_ILMIN_MASK, BUCK_ILMIN_150MA }, + { RK808_BUCK4_CONFIG_REG, BUCK_ILMIN_MASK, BUCK_ILMIN_200MA }, + { RK808_BOOST_CONFIG_REG, BOOST_ILMIN_MASK, BOOST_ILMIN_100MA }, + { RK808_BUCK1_CONFIG_REG, BUCK1_RATE_MASK, BUCK_ILMIN_200MA }, + { RK808_BUCK2_CONFIG_REG, BUCK2_RATE_MASK, BUCK_ILMIN_200MA }, + { RK808_DCDC_UV_ACT_REG, BUCK_UV_ACT_MASK, BUCK_UV_ACT_DISABLE}, + { RK808_RTC_CTRL_REG, RTC_STOP, RTC_STOP}, + { RK808_VB_MON_REG, MASK_ALL, VB_LO_ACT | + VB_LO_SEL_3500MV }, +}; + +static const struct regmap_irq rk808_irqs[] = { + /* INT_STS */ + [RK808_IRQ_VOUT_LO] = { + .mask = RK808_IRQ_VOUT_LO_MSK, + .reg_offset = 0, }, - { - .name = "RK_LDO3", - .id = 6, - .ops = &rk808_ldo_ops, - .n_voltages = ARRAY_SIZE(ldo3_voltage_map), - .type = REGULATOR_VOLTAGE, - .owner = THIS_MODULE, + [RK808_IRQ_VB_LO] = { + .mask = RK808_IRQ_VB_LO_MSK, + .reg_offset = 0, }, - { - .name = "RK_LDO4", - .id = 7, - .ops = &rk808_ldo_ops, - .n_voltages = ARRAY_SIZE(ldo_voltage_map), - .type = REGULATOR_VOLTAGE, - .owner = THIS_MODULE, + [RK808_IRQ_PWRON] = { + .mask = RK808_IRQ_PWRON_MSK, + .reg_offset = 0, }, - - { - .name = "RK_LDO5", - .id =8, - .ops = &rk808_ldo_ops, - .n_voltages = ARRAY_SIZE(ldo_voltage_map), - .type = REGULATOR_VOLTAGE, - .owner = THIS_MODULE, + [RK808_IRQ_PWRON_LP] = { + .mask = RK808_IRQ_PWRON_LP_MSK, + .reg_offset = 0, }, - { - .name = "RK_LDO6", - .id = 9, - .ops = &rk808_ldo_ops, - .n_voltages = ARRAY_SIZE(ldo6_voltage_map), - .type = REGULATOR_VOLTAGE, - .owner = THIS_MODULE, + [RK808_IRQ_HOTDIE] = { + .mask = RK808_IRQ_HOTDIE_MSK, + .reg_offset = 0, }, - { - .name = "RK_LDO7", - .id = 10, - .ops = &rk808_ldo_ops, - .n_voltages = ARRAY_SIZE(ldo6_voltage_map), - .type = REGULATOR_VOLTAGE, - .owner = THIS_MODULE, + [RK808_IRQ_RTC_ALARM] = { + .mask = RK808_IRQ_RTC_ALARM_MSK, + .reg_offset = 0, }, - { - .name = "RK_LDO8", - .id = 11, - .ops = &rk808_ldo_ops, - .n_voltages = ARRAY_SIZE(ldo_voltage_map), - .type = REGULATOR_VOLTAGE, - .owner = THIS_MODULE, + [RK808_IRQ_RTC_PERIOD] = { + .mask = RK808_IRQ_RTC_PERIOD_MSK, + .reg_offset = 0, + }, + + /* INT_STS2 */ + [RK808_IRQ_PLUG_IN_INT] = { + .mask = RK808_IRQ_PLUG_IN_INT_MSK, + .reg_offset = 1, + }, + [RK808_IRQ_PLUG_OUT_INT] = { + .mask = RK808_IRQ_PLUG_OUT_INT_MSK, + .reg_offset = 1, }, +}; + +static struct regmap_irq_chip rk808_irq_chip = { + .name = "rk808", + .irqs = rk808_irqs, + .num_irqs = ARRAY_SIZE(rk808_irqs), + .num_regs = 2, + .irq_reg_stride = 2, + .status_base = RK808_INT_STS_REG1, + .mask_base = RK808_INT_STS_MSK_REG1, + .ack_base = RK808_INT_STS_REG1, + .init_ack_masked = true, +}; + +static const struct mfd_cell rk816s[] = { + { .name = "rk808-clkout", }, + { .name = "rk808-regulator", }, + { .name = "rk8xx-gpio", }, { - .name = "RK_LDO9", - .id = 12, - .ops = &rk808_ldo_ops, - .n_voltages = ARRAY_SIZE(buck4_voltage_map), - .type = REGULATOR_VOLTAGE, - .owner = THIS_MODULE, + .name = "rk8xx-pwrkey", + .num_resources = ARRAY_SIZE(rk816_pwrkey_resources), + .resources = &rk816_pwrkey_resources[0], }, { - .name = "RK_LDO10", - .id = 13, - .ops = &rk808_ldo_ops, - .n_voltages = ARRAY_SIZE(buck4_voltage_map), - .type = REGULATOR_VOLTAGE, - .owner = THIS_MODULE, + .name = "rk808-rtc", + .num_resources = ARRAY_SIZE(rtc_resources), + .resources = &rtc_resources[0], }, - }; -/* - * - */ - int rk808_i2c_read(struct rk808 *rk808, char reg, int count,u8 *dest) -{ - struct i2c_client *i2c = rk808->i2c; - int ret; - struct i2c_adapter *adap; - struct i2c_msg msgs[2]; - - if(!i2c) - return ret; +static const struct rk808_reg_data rk816_pre_init_reg[] = { + /* buck4 Max ILMIT*/ + {RK816_BUCK4_CONFIG_REG, BUCK4_MAX_ILIMIT, REG_WRITE_MSK}, + /* hotdie temperature: 105c*/ + {RK816_THERMAL_REG, TEMP105C, REG_WRITE_MSK}, + /* set buck 12.5mv/us */ + {RK816_BUCK1_CONFIG_REG, BUCK_RATE_12_5MV_US, BUCK_RATE_MSK}, + {RK816_BUCK2_CONFIG_REG, BUCK_RATE_12_5MV_US, BUCK_RATE_MSK}, + /* enable RTC_PERIOD & RTC_ALARM int */ + {RK816_INT_STS_MSK_REG2, RTC_PERIOD_ALARM_INT_EN, REG_WRITE_MSK}, + /* set bat 3.0 low and act shutdown */ + {RK816_VB_MON_REG, RK816_VBAT_LOW_3V0 | EN_VABT_LOW_SHUT_DOWN, + VBAT_LOW_VOL_MASK | VBAT_LOW_ACT_MASK}, + /* enable PWRON rising/faling int */ + {RK816_INT_STS_MSK_REG1, RK816_PWRON_FALL_RISE_INT_EN, REG_WRITE_MSK}, + /* enable PLUG IN/OUT int */ + {RK816_INT_STS_MSK_REG3, PLUGIN_OUT_INT_EN, REG_WRITE_MSK}, + /* clear int flags */ + {RK816_INT_STS_REG1, ALL_INT_FLAGS_ST, REG_WRITE_MSK}, + {RK816_INT_STS_REG2, ALL_INT_FLAGS_ST, REG_WRITE_MSK}, + {RK816_INT_STS_REG3, ALL_INT_FLAGS_ST, REG_WRITE_MSK}, + {RK816_DCDC_EN_REG2, BOOST_DISABLE, BOOST_EN_MASK}, +}; - if (count != 1) - return -EIO; - - adap = i2c->adapter; - - msgs[0].addr = i2c->addr; - msgs[0].buf = ® - msgs[0].flags = i2c->flags; - msgs[0].len = 1; - msgs[0].scl_rate = 100*1000; - - msgs[1].buf = (u8 *)dest; - msgs[1].addr = i2c->addr; - msgs[1].flags = i2c->flags |I2C_M_RD; - msgs[1].len = 1; - msgs[1].scl_rate = 100*1000; - - ret = i2c_transfer(adap, msgs, 2); - - DBG("***run in %s %x % x\n",__FUNCTION__,i2c->addr,*(msgs[1].buf)); - return ret; -} +static const struct regmap_irq rk816_irqs[] = { + /* INT_STS */ + [RK816_IRQ_PWRON_FALL] = { + .mask = RK816_IRQ_PWRON_FALL_MSK, + .reg_offset = 0, + }, + [RK816_IRQ_PWRON_RISE] = { + .mask = RK816_IRQ_PWRON_RISE_MSK, + .reg_offset = 0, + }, + [RK816_IRQ_VB_LOW] = { + .mask = RK816_IRQ_VB_LOW_MSK, + .reg_offset = 1, + }, + [RK816_IRQ_PWRON] = { + .mask = RK816_IRQ_PWRON_MSK, + .reg_offset = 1, + }, + [RK816_IRQ_PWRON_LP] = { + .mask = RK816_IRQ_PWRON_LP_MSK, + .reg_offset = 1, + }, + [RK816_IRQ_HOTDIE] = { + .mask = RK816_IRQ_HOTDIE_MSK, + .reg_offset = 1, + }, + [RK816_IRQ_RTC_ALARM] = { + .mask = RK816_IRQ_RTC_ALARM_MSK, + .reg_offset = 1, + }, + [RK816_IRQ_RTC_PERIOD] = { + .mask = RK816_IRQ_RTC_PERIOD_MSK, + .reg_offset = 1, + }, + [RK816_IRQ_USB_OV] = { + .mask = RK816_IRQ_USB_OV_MSK, + .reg_offset = 1, + }, +}; -int rk808_i2c_write(struct rk808 *rk808, char reg, int count, const u8 src) -{ - int ret=-1; - struct i2c_client *i2c = rk808->i2c; - struct i2c_adapter *adap; - struct i2c_msg msg; - char tx_buf[2]; +static struct regmap_irq_chip rk816_irq_chip = { + .name = "rk816", + .irqs = rk816_irqs, + .num_irqs = ARRAY_SIZE(rk816_irqs), + .num_regs = 2, + .irq_reg_stride = 3, + .status_base = RK816_INT_STS_REG1, + .mask_base = RK816_INT_STS_MSK_REG1, + .ack_base = RK816_INT_STS_REG1, + .init_ack_masked = true, +}; - if(!i2c) - return ret; - if (count != 1) - return -EIO; - - adap = i2c->adapter; - tx_buf[0] = reg; - tx_buf[1] = src; - - msg.addr = i2c->addr; - msg.buf = &tx_buf[0]; - msg.len = 1 +1; - msg.flags = i2c->flags; - msg.scl_rate = 100*1000; - - ret = i2c_transfer(adap, &msg, 1); - return ret; -} +static const struct mfd_cell rk818s[] = { + { .name = "rk808-clkout", }, + { .name = "rk808-regulator", }, + { .name = "rk818-battery", .of_compatible = "rk818-battery", }, + { .name = "rk818-charger", }, + { + .name = "rk808-rtc", + .num_resources = ARRAY_SIZE(rtc_resources), + .resources = &rtc_resources[0], + }, +}; -int rk808_reg_read(struct rk808 *rk808, u8 reg) -{ - u8 val = 0; - int ret; +static const struct rk808_reg_data rk818_pre_init_reg[] = { + { RK818_H5V_EN_REG, REF_RDY_CTRL_ENABLE | H5V_EN_MASK, + REF_RDY_CTRL_ENABLE | H5V_EN_ENABLE }, + { RK818_DCDC_EN_REG, BOOST_EN_MASK | SWITCH_EN_MASK, + BOOST_EN_ENABLE | SWITCH_EN_ENABLE }, + { RK818_SLEEP_SET_OFF_REG1, OTG_SLP_SET_MASK, OTG_SLP_SET_OFF }, + { RK818_BUCK4_CONFIG_REG, BUCK_ILMIN_MASK, BUCK_ILMIN_250MA }, + { RK808_RTC_CTRL_REG, RTC_STOP, RTC_STOP}, +}; - mutex_lock(&rk808->io_lock); +static const struct regmap_irq rk818_irqs[] = { + /* INT_STS */ + [RK818_IRQ_VOUT_LO] = { + .mask = VOUT_LO_MASK, + .reg_offset = 0, + }, + [RK818_IRQ_VB_LO] = { + .mask = VB_LO_MASK, + .reg_offset = 0, + }, + [RK818_IRQ_PWRON] = { + .mask = PWRON_MASK, + .reg_offset = 0, + }, + [RK818_IRQ_PWRON_LP] = { + .mask = PWRON_LP_MASK, + .reg_offset = 0, + }, + [RK818_IRQ_HOTDIE] = { + .mask = HOTDIE_MASK, + .reg_offset = 0, + }, + [RK818_IRQ_RTC_ALARM] = { + .mask = RTC_ALARM_MASK, + .reg_offset = 0, + }, + [RK818_IRQ_RTC_PERIOD] = { + .mask = RTC_PERIOD_MASK, + .reg_offset = 0, + }, + [RK818_IRQ_USB_OV] = { + .mask = USB_OV_MASK, + .reg_offset = 0, + }, + /* INT_STS2 */ + [RK818_IRQ_PLUG_IN] = { + .mask = PLUG_IN_MASK, + .reg_offset = 1, + }, + [RK818_IRQ_PLUG_OUT] = { + .mask = PLUG_OUT_MASK, + .reg_offset = 1, + }, + [RK818_IRQ_CHG_OK] = { + .mask = CHGOK_MASK, + .reg_offset = 1, + }, + [RK818_IRQ_CHG_TE] = { + .mask = CHGTE_MASK, + .reg_offset = 1, + }, + [RK818_IRQ_CHG_TS1] = { + .mask = CHGTS1_MASK, + .reg_offset = 1, + }, + [RK818_IRQ_TS2] = { + .mask = TS2_MASK, + .reg_offset = 1, + }, + [RK818_IRQ_CHG_CVTLIM] = { + .mask = CHG_CVTLIM_MASK, + .reg_offset = 1, + }, + [RK818_IRQ_DISCHG_ILIM] = { + .mask = DISCHG_ILIM_MASK, + .reg_offset = 1, + }, +}; - ret = rk808_i2c_read(rk808, reg, 1, &val); - DBG("reg read 0x%02x -> 0x%02x\n", (int)reg, (unsigned)val&0xff); - if (ret < 0){ - mutex_unlock(&rk808->io_lock); - return ret; - } - mutex_unlock(&rk808->io_lock); +static struct regmap_irq_chip rk818_irq_chip = { + .name = "rk818", + .irqs = rk818_irqs, + .num_irqs = ARRAY_SIZE(rk818_irqs), + .num_regs = 2, + .irq_reg_stride = 2, + .status_base = RK808_INT_STS_REG1, + .mask_base = RK808_INT_STS_MSK_REG1, + .ack_base = RK808_INT_STS_REG1, + .init_ack_masked = true, +}; - return val & 0xff; -} -EXPORT_SYMBOL_GPL(rk808_reg_read); +static const struct regmap_irq rk805_irqs[] = { + [RK805_IRQ_PWRON_RISE] = { + .mask = RK805_IRQ_PWRON_RISE_MSK, + .reg_offset = 0, + }, + [RK805_IRQ_VB_LOW] = { + .mask = RK805_IRQ_VB_LOW_MSK, + .reg_offset = 0, + }, + [RK805_IRQ_PWRON] = { + .mask = RK805_IRQ_PWRON_MSK, + .reg_offset = 0, + }, + [RK805_IRQ_PWRON_LP] = { + .mask = RK805_IRQ_PWRON_LP_MSK, + .reg_offset = 0, + }, + [RK805_IRQ_HOTDIE] = { + .mask = RK805_IRQ_HOTDIE_MSK, + .reg_offset = 0, + }, + [RK805_IRQ_RTC_ALARM] = { + .mask = RK805_IRQ_RTC_ALARM_MSK, + .reg_offset = 0, + }, + [RK805_IRQ_RTC_PERIOD] = { + .mask = RK805_IRQ_RTC_PERIOD_MSK, + .reg_offset = 0, + }, + [RK805_IRQ_PWRON_FALL] = { + .mask = RK805_IRQ_PWRON_FALL_MSK, + .reg_offset = 0, + }, +}; -int rk808_reg_write(struct rk808 *rk808, u8 reg, u8 val) -{ - int err =0; +static struct regmap_irq_chip rk805_irq_chip = { + .name = "rk805", + .irqs = rk805_irqs, + .num_irqs = ARRAY_SIZE(rk805_irqs), + .num_regs = 1, + .status_base = RK805_INT_STS_REG, + .mask_base = RK805_INT_STS_MSK_REG, + .ack_base = RK805_INT_STS_REG, + .init_ack_masked = true, +}; - mutex_lock(&rk808->io_lock); +static const struct mfd_cell rk805s[] = { + { .name = "rk808-clkout", }, + { .name = "rk818-regulator", }, + { .name = "rk8xx-gpio", }, + { + .name = "rk8xx-pwrkey", + .num_resources = ARRAY_SIZE(pwrkey_resources), + .resources = &pwrkey_resources[0], + }, + { + .name = "rk808-rtc", + .num_resources = ARRAY_SIZE(rtc_resources), + .resources = &rtc_resources[0], + }, +}; - err = rk808_i2c_write(rk808, reg, 1,val); - if (err < 0) - dev_err(rk808->dev, "Write for reg 0x%x failed\n", reg); +static const struct rk808_reg_data rk805_pre_init_reg[] = { + {RK805_BUCK4_CONFIG_REG, BUCK_ILMIN_MASK, BUCK_ILMIN_400MA}, + {RK805_GPIO_IO_POL_REG, SLP_SD_MSK, SLEEP_FUN}, + {RK808_RTC_CTRL_REG, RTC_STOP, RTC_STOP}, + {RK805_THERMAL_REG, TEMP_HOTDIE_MSK, TEMP115C}, +}; - mutex_unlock(&rk808->io_lock); - return err; -} -EXPORT_SYMBOL_GPL(rk808_reg_write); +static int (*pm_shutdown)(struct regmap *regmap); +static int (*pm_shutdown_prepare)(struct regmap *regmap); +static struct i2c_client *rk808_i2c_client; - int rk808_set_bits(struct rk808 *rk808, u8 reg, u8 mask, u8 val) +static void rk808_device_shutdown_prepare(void) { - u8 tmp; int ret; + struct rk808 *rk808 = i2c_get_clientdata(rk808_i2c_client); - mutex_lock(&rk808->io_lock); - - ret = rk808_i2c_read(rk808, reg, 1, &tmp); - DBG("1 reg read 0x%02x -> 0x%02x\n", (int)reg, (unsigned)tmp&0xff); - if (ret < 0){ - mutex_unlock(&rk808->io_lock); - return ret; + if (gpio_is_valid(rk808->stby_gpio)) { + printk("rk808->stby_gpio(%d)=low\n", rk808->stby_gpio); + gpio_direction_output(rk808->stby_gpio, 0); + } + if (gpio_is_valid(rk808->hold_gpio)) { + printk("rk808->hold_gpio(%d)=low\n", rk808->hold_gpio); + gpio_direction_output(rk808->hold_gpio, 0); + mdelay(200); + } + if (!rk808) { + dev_warn(&rk808_i2c_client->dev, + "have no rk808, so do nothing here\n"); + return; } - tmp = (tmp & ~mask) | val; - ret = rk808_i2c_write(rk808, reg, 1, tmp); - DBG("reg write 0x%02x -> 0x%02x\n", (int)reg, (unsigned)val&0xff); - if (ret < 0){ - mutex_unlock(&rk808->io_lock); - return ret; - } - ret = rk808_i2c_read(rk808, reg, 1, &tmp); - if (ret < 0){ - mutex_unlock(&rk808->io_lock); - return ret; - } - DBG("2 reg read 0x%02x -> 0x%02x\n", (int)reg, (unsigned)tmp&0xff); - mutex_unlock(&rk808->io_lock); - - return 0;//ret; -} -EXPORT_SYMBOL_GPL(rk808_set_bits); -int rk808_clear_bits(struct rk808 *rk808, u8 reg, u8 mask) -{ - u8 data; - int err; - - mutex_lock(&rk808->io_lock); - err = rk808_i2c_read(rk808, reg, 1, &data); - if (err <0) { - dev_err(rk808->dev, "read from reg %x failed\n", reg); - goto out; + if (pm_shutdown_prepare) { + ret = pm_shutdown_prepare(rk808->regmap); + if (ret) + dev_err(&rk808_i2c_client->dev, + "power off prepare error!\n"); } - - data &= ~mask; - err = rk808_i2c_write(rk808, reg, 1, data); - if (err <0) - dev_err(rk808->dev, "write to reg %x failed\n", reg); - -out: - mutex_unlock(&rk808->io_lock); - return err; } -EXPORT_SYMBOL_GPL(rk808_clear_bits); -#if 0 -int rk808_bulk_read(struct rk808 *rk808, u8 reg, - int count, u8 *buf) + +static void rk808_device_shutdown(void) { int ret; - -#if defined(CONFIG_MFD_RK610) - int i; //Solve communication conflict when rk610 and rk808 on the same i2c + struct rk808 *rk808 = i2c_get_clientdata(rk808_i2c_client); - mutex_lock(&rk808->io_lock); - for(i=0; iio_lock); - return ret; - }else{ - buf[i] = ret & 0x000000FF; - } + if (!rk808) { + dev_warn(&rk808_i2c_client->dev, + "have no rk808, so do nothing here\n"); + return; } - mutex_unlock(&rk808->io_lock); -#else - mutex_lock(&rk808->io_lock); - - ret = rk808->read(rk808, reg, count, buf); - mutex_unlock(&rk808->io_lock); + /* close rtc int when power off */ +#if 0 + regmap_update_bits(rk808->regmap, + RK808_INT_STS_MSK_REG1, + (0x3 << 5), (0x3 << 5)); + regmap_update_bits(rk808->regmap, + RK808_RTC_INT_REG, + (0x3 << 2), (0x0 << 2)); #endif - return 0; + if (gpio_is_valid(rk808->stby_gpio)) { + printk("rk808->stby_gpio(%d)=low\n", rk808->stby_gpio); + gpio_direction_output(rk808->stby_gpio, 0); + } + if (gpio_is_valid(rk808->hold_gpio)) { + printk("rk808->hold_gpio(%d)=low\n", rk808->hold_gpio); + gpio_direction_output(rk808->hold_gpio, 0); + mdelay(200); + } + if (pm_shutdown) { + ret = pm_shutdown(rk808->regmap); + if (ret) + dev_err(&rk808_i2c_client->dev, "power off error!\n"); + } + printk("%s-%d: pm_shutdown\n", __FUNCTION__, __LINE__); } -EXPORT_SYMBOL_GPL(rk808_bulk_read); -int rk808_bulk_write(struct rk808 *rk808, u8 reg, - int count, u8 *buf) +static ssize_t rk8xx_dbg_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) { int ret; - -#if defined(CONFIG_MFD_RK610) - int i; // //Solve communication conflict when rk610 and 808 on the same i2c - - mutex_lock(&rk808->io_lock); - for(i=0; iio_lock); - return ret; - } - } - mutex_unlock(&rk808->io_lock); -#else - mutex_lock(&rk808->io_lock); - - ret = rk808->write(rk808, reg, count, buf); - - mutex_unlock(&rk808->io_lock); -#endif - return 0; + char cmd; + u32 input[2], addr, data; + struct rk808 *rk808 = i2c_get_clientdata(rk808_i2c_client); -} -EXPORT_SYMBOL_GPL(rk808_bulk_write); -#endif - -#if 1 -static ssize_t rk808_test_store(struct kobject *kobj, struct kobj_attribute *attr, - const char *buf, size_t n) -{ - u32 getdata[8]; - u8 regAddr; - u8 data; - char cmd; - const char *buftmp = buf; - struct rk808 *rk808 = g_rk808; - /** - * W Addr(8Bit) regAddr(8Bit) data0(8Bit) data1(8Bit) data2(8Bit) data3(8Bit) - * :data can be less than 4 byte - * R regAddr(8Bit) - * C gpio_name(poweron/powerhold/sleep/boot0/boot1) value(H/L) - */ - sscanf(buftmp, "%c ", &cmd); - printk("------zhangqing: get cmd = %c\n", cmd); + ret = sscanf(buf, "%c ", &cmd); switch (cmd) { case 'w': - sscanf(buftmp, "%c %x %x ", &cmd, &getdata[0], &getdata[1]); - regAddr = (u8)(getdata[0] & 0xff); - data = (u8)(getdata[1] & 0xff); - printk("get value = %x\n", data); - - rk808_i2c_write(rk808, regAddr, 1, data); - rk808_i2c_read(rk808, regAddr, 1, &data); - printk("%x %x\n", getdata[1], data); + ret = sscanf(buf, "%c %x %x ", &cmd, &input[0], &input[1]); + if (ret != 3) { + pr_err("erro! cmd format: echo w [addr] [value]\n"); + goto out; + }; + addr = input[0] & 0xff; + data = input[1] & 0xff; + pr_info("cmd : %c %x %x\n\n", cmd, input[0], input[1]); + regmap_write(rk808->regmap, addr, data); + regmap_read(rk808->regmap, addr, &data); + pr_info("new: %x %x\n", addr, data); break; case 'r': - sscanf(buftmp, "%c %x ", &cmd, &getdata[0]); - printk("CMD : %c %x\n", cmd, getdata[0]); - - regAddr = (u8)(getdata[0] & 0xff); - rk808_i2c_read(rk808, regAddr, 1, &data); - printk("%x %x\n", getdata[0], data); + ret = sscanf(buf, "%c %x ", &cmd, &input[0]); + if (ret != 2) { + pr_err("erro! cmd format: echo r [addr]\n"); + goto out; + }; + pr_info("cmd : %c %x\n\n", cmd, input[0]); + addr = input[0] & 0xff; + regmap_read(rk808->regmap, addr, &data); + pr_info("%x %x\n", input[0], data); break; default: - printk("Unknown command\n"); + pr_err("Unknown command\n"); break; } - return n; - -} -static ssize_t rk808_test_show(struct kobject *kobj, struct kobj_attribute *attr, - char *buf) -{ - char *s = buf; - buf = "hello"; - return sprintf(s, "%s\n", buf); +out: + return count; } -static struct kobject *rk808_kobj; -struct rk808_attribute { - struct attribute attr; - ssize_t (*show)(struct kobject *kobj, struct kobj_attribute *attr, - char *buf); - ssize_t (*store)(struct kobject *kobj, struct kobj_attribute *attr, - const char *buf, size_t n); -}; +static struct kobject *rk8xx_kobj; +static struct device_attribute rk8xx_attrs = + __ATTR(rk8xx_dbg, 0200, NULL, rk8xx_dbg_store); -static struct rk808_attribute rk808_attrs[] = { - /* node_name permision show_func store_func */ - __ATTR(rk808_test, S_IRUGO | S_IWUSR, rk808_test_show, rk808_test_store), -}; -#endif -#if 0 -extern void rk_send_wakeup_key(void); -static irqreturn_t rk808_vbat_lo_irq(int irq, void *data) -{ - printk("rk808 vbat low %s:irq=%d\n",__func__,irq); - rk808_set_bits(g_rk808,0x4c,(0x1 << 1),(0x1 <<1)); -// rk_send_wakeup_key(); - return IRQ_HANDLED; -} -#endif -#ifdef CONFIG_OF -static struct of_device_id rk808_of_match[] = { - { .compatible = "rockchip,rk808"}, +static const struct of_device_id rk808_of_match[] = { + { .compatible = "rockchip,rk805" }, + { .compatible = "rockchip,rk808" }, + { .compatible = "rockchip,rk816" }, + { .compatible = "rockchip,rk818" }, { }, }; -MODULE_DEVICE_TABLE(of, rk808_of_match); -#endif -#ifdef CONFIG_OF -static struct of_regulator_match rk808_reg_matches[] = { - { .name = "rk_dcdc1", .driver_data = (void *)0 }, - { .name = "rk_dcdc2", .driver_data = (void *)1 }, - { .name = "rk_dcdc3", .driver_data = (void *)2 }, - { .name = "rk_dcdc4", .driver_data = (void *)3 }, - { .name = "rk_ldo1", .driver_data = (void *)4 }, - { .name = "rk_ldo2", .driver_data = (void *)5 }, - { .name = "rk_ldo3", .driver_data = (void *)6 }, - { .name = "rk_ldo4", .driver_data = (void *)7 }, - { .name = "rk_ldo5", .driver_data = (void *)8 }, - { .name = "rk_ldo6", .driver_data = (void *)9 }, - { .name = "rk_ldo7", .driver_data = (void *)10 }, - { .name = "rk_ldo8", .driver_data = (void *)11 }, - { .name = "rk_ldo9", .driver_data = (void *)12 }, - { .name = "rk_ldo10", .driver_data = (void *)13 }, -}; +MODULE_DEVICE_TABLE(of, rk808_of_match); -static struct rk808_board *rk808_parse_dt(struct rk808 *rk808) -{ - struct rk808_board *pdata; - struct device_node *regs,*rk808_pmic_np; - int i, count; - - rk808_pmic_np = of_node_get(rk808->dev->of_node); - if (!rk808_pmic_np) { - printk("could not find pmic sub-node\n"); - return NULL; +static int rk808_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct device_node *np = client->dev.of_node; + struct rk808 *rk808; + int (*pm_shutdown_fn)(struct regmap *regmap) = NULL; + int (*pm_shutdown_prepare_fn)(struct regmap *regmap) = NULL; + const struct rk808_reg_data *pre_init_reg; + const struct regmap_config *regmap_config; + const struct regmap_irq_chip *irq_chip; + const struct mfd_cell *cell; + u8 on_source = 0, off_source = 0; + int msb, lsb, reg_num, cell_num; + int ret, i, pm_off = 0; + unsigned int on, off; + + if (!client->irq) { + dev_err(&client->dev, "No interrupt support, no core IRQ\n"); + return -EINVAL; } - regs = of_find_node_by_name(rk808_pmic_np, "regulators"); - if (!regs) - return NULL; - - count = of_regulator_match(rk808->dev, regs, rk808_reg_matches, - rk808_NUM_REGULATORS); - of_node_put(regs); - if ((count < 0) || (count > rk808_NUM_REGULATORS)) - return NULL; - - pdata = devm_kzalloc(rk808->dev, sizeof(*pdata), GFP_KERNEL); - if (!pdata) - return NULL; - - for (i = 0; i < count; i++) { - if (!rk808_reg_matches[i].init_data || !rk808_reg_matches[i].of_node) - continue; + rk808 = devm_kzalloc(&client->dev, sizeof(*rk808), GFP_KERNEL); + if (!rk808) + return -ENOMEM; - pdata->rk808_init_data[i] = rk808_reg_matches[i].init_data; - pdata->of_node[i] = rk808_reg_matches[i].of_node; + /* read Chip variant */ + msb = i2c_smbus_read_byte_data(client, RK808_ID_MSB); + if (msb < 0) { + dev_err(&client->dev, "failed to read the chip id at 0x%x\n", + RK808_ID_MSB); + return msb; + } + + lsb = i2c_smbus_read_byte_data(client, RK808_ID_LSB); + if (lsb < 0) { + dev_err(&client->dev, "failed to read the chip id at 0x%x\n", + RK808_ID_LSB); + return lsb; + } + + rk808->variant = ((msb << 8) | lsb) & RK8XX_ID_MSK; + dev_info(&client->dev, "Pmic Chip id: 0x%lx\n", rk808->variant); + + /* set Chip platform init data*/ + switch (rk808->variant) { + case RK818_ID: + cell = rk818s; + cell_num = ARRAY_SIZE(rk818s); + pre_init_reg = rk818_pre_init_reg; + reg_num = ARRAY_SIZE(rk818_pre_init_reg); + regmap_config = &rk818_regmap_config; + irq_chip = &rk818_irq_chip; + pm_shutdown_fn = rk818_shutdown; + on_source = RK818_ON_SOURCE_REG; + off_source = RK818_OFF_SOURCE_REG; + break; + case RK816_ID: + cell = rk816s; + cell_num = ARRAY_SIZE(rk816s); + pre_init_reg = rk816_pre_init_reg; + reg_num = ARRAY_SIZE(rk816_pre_init_reg); + regmap_config = &rk816_regmap_config; + irq_chip = &rk816_irq_chip; + pm_shutdown_fn = rk816_shutdown; + on_source = RK816_ON_SOURCE_REG; + off_source = RK816_OFF_SOURCE_REG; + break; + case RK808_ID: + cell = rk808s; + cell_num = ARRAY_SIZE(rk808s); + pre_init_reg = rk808_pre_init_reg; + reg_num = ARRAY_SIZE(rk808_pre_init_reg); + regmap_config = &rk808_regmap_config; + irq_chip = &rk808_irq_chip; + pm_shutdown_fn = rk808_shutdown; + break; + case RK805_ID: + cell = rk805s; + cell_num = ARRAY_SIZE(rk805s); + pre_init_reg = rk805_pre_init_reg; + reg_num = ARRAY_SIZE(rk805_pre_init_reg); + regmap_config = &rk805_regmap_config; + irq_chip = &rk805_irq_chip; + pm_shutdown_prepare_fn = rk805_shutdown_prepare; + on_source = RK805_ON_SOURCE_REG; + off_source = RK805_OFF_SOURCE_REG; + break; + default: + dev_err(&client->dev, "unsupported RK8XX ID 0x%lx\n", + rk808->variant); + return -EINVAL; } - pdata->irq = rk808->chip_irq; - pdata->irq_base = -1; - - pdata->irq_gpio = of_get_named_gpio(rk808_pmic_np,"gpios",0); - if (!gpio_is_valid(pdata->irq_gpio)) { - printk("invalid gpio: %d\n", pdata->irq_gpio); - return NULL; - } - - pdata->pmic_sleep_gpio = of_get_named_gpio(rk808_pmic_np,"gpios",1); - if (!gpio_is_valid(pdata->pmic_sleep_gpio)) { - printk("invalid gpio: %d\n", pdata->pmic_sleep_gpio); - } - pdata->pmic_sleep = true; - - pdata->pm_off = of_property_read_bool(rk808_pmic_np,"rk808,system-power-controller"); - - return pdata; -} -#else -static struct rk808_board *rk808_parse_dt(struct i2c_client *i2c) -{ - return NULL; -} -#endif -static void rk808_shutdown(void) -{ - int ret,i,val; - u16 reg = 0; - struct rk808 *rk808 = g_rk808; - - printk("%s\n",__func__); - /***************get dc1\dc2 voltage *********************/ - for(i=0;i<2;i++){ - reg = rk808_reg_read(rk808,rk808_BUCK_SET_VOL_REG(i)); - reg &= BUCK_VOL_MASK; - val = 700000 + reg * 12500; - printk("%s,line=%d dc[%d]= %d\n", __func__,__LINE__,(i+1),val); + rk808->regmap = devm_regmap_init_i2c(client, regmap_config); + if (IS_ERR(rk808->regmap)) { + dev_err(&client->dev, "regmap initialization failed\n"); + return PTR_ERR(rk808->regmap); } - /*****************************************************/ - ret = rk808_set_bits(rk808, RK808_INT_STS_MSK_REG1,(0x3<<5),(0x3<<5)); //close rtc int when power off - ret = rk808_clear_bits(rk808, RK808_RTC_INT_REG,(0x3<<2)); //close rtc int when power off - mutex_lock(&rk808->io_lock); - mdelay(100); -} -static struct syscore_ops rk808_syscore_ops = { - .shutdown = rk808_shutdown, -}; - -static void rk808_device_shutdown(void) -{ - int ret,i; - u8 reg = 0; - struct rk808 *rk808 = g_rk808; - for(i=0;i < 10;i++){ - printk("%s\n",__func__); - ret = rk808_i2c_read(rk808,RK808_DEVCTRL_REG,1,®); - if(ret < 0) - continue; - ret = rk808_i2c_write(rk808, RK808_DEVCTRL_REG, 1,(reg |(0x1 <<3))); - if (ret < 0) { - printk("rk808 power off error!\n"); - continue; + /* on & off source */ + if (on_source && off_source) { + ret = regmap_read(rk808->regmap, on_source, &on); + if (ret) { + dev_err(&client->dev, "read 0x%x failed\n", on_source); + return ret; } - } - while(1)wfi(); -} -EXPORT_SYMBOL_GPL(rk808_device_shutdown); - -__weak void rk808_device_suspend(void) {} -__weak void rk808_device_resume(void) {} -#ifdef CONFIG_PM -static int rk808_suspend(struct device *dev) -{ - rk808_device_suspend(); - return 0; -} - -static int rk808_resume(struct device *dev) -{ - rk808_device_resume(); - return 0; -} -#else -static int rk808_suspend(struct device *dev) -{ - return 0; -} - -static int rk808_resume(struct device *dev) -{ - return 0; -} -#endif - -static bool is_volatile_reg(struct device *dev, unsigned int reg) -{ - if ((reg >= RK808_DCDC_EN_REG) && (reg <= RK808_LDO8_SLP_VSEL_REG)) { - return true; - } - return true; -} - -static const struct regmap_config rk808_regmap_config = { - .reg_bits = 8, - .val_bits = 8, - .volatile_reg = is_volatile_reg, - .max_register = rk808_NUM_REGULATORS - 1, - .cache_type = REGCACHE_RBTREE, -}; -#ifdef CONFIG_HAS_EARLYSUSPEND -__weak void rk808_early_suspend(struct early_suspend *h) {} -__weak void rk808_late_resume(struct early_suspend *h) {} -#endif + ret = regmap_read(rk808->regmap, off_source, &off); + if (ret) { + dev_err(&client->dev, "read 0x%x failed\n", off_source); + return ret; + } -static int rk808_pre_init(struct rk808 *rk808) -{ - int ret,val; - printk("%s,line=%d\n", __func__,__LINE__); - /**********disable dcdc uv func****************/ - ret = rk808_reg_write(rk808,RK808_DCDC_UV_ACT_REG,0x10); - if (ret <0) { - printk(KERN_ERR "Unable to write RK808_DCDC_UV_ACT_REG reg\n"); - return ret; - } - /**********************************/ - /***********set ILIM ************/ - val = rk808_reg_read(rk808,RK808_BUCK3_CONFIG_REG); - val &= (~(0x7 <<0)); - val |= (0x2 <<0); - ret = rk808_reg_write(rk808,RK808_BUCK3_CONFIG_REG,val); - if (ret < 0) { - printk(KERN_ERR "Unable to write RK808_BUCK3_CONFIG_REG reg\n"); - return ret; - } - - val = rk808_reg_read(rk808,RK808_BUCK4_CONFIG_REG); - val &= (~(0x7 <<0)); - val |= (0x3 <<0); - ret = rk808_reg_write(rk808,RK808_BUCK4_CONFIG_REG,val); - if (ret < 0) { - printk(KERN_ERR "Unable to write RK808_BUCK4_CONFIG_REG reg\n"); - return ret; - } - - val = rk808_reg_read(rk808,RK808_BOOST_CONFIG_REG); - val &= (~(0x7 <<0)); - val |= (0x1 <<0); - ret = rk808_reg_write(rk808,RK808_BOOST_CONFIG_REG,val); - if (ret < 0) { - printk(KERN_ERR "Unable to write RK808_BOOST_CONFIG_REG reg\n"); - return ret; - } - /*****************************************/ - /***********set buck OTP function************/ - ret = rk808_reg_write(rk808,0x6f,0x5a); - if (ret < 0) { - printk(KERN_ERR "Unable to write 0x6f reg\n"); - return ret; - } - - ret = rk808_reg_write(rk808,0x91,0x80); - if (ret < 0) { - printk(KERN_ERR "Unable to write 0x91 reg\n"); - return ret; - } - - ret = rk808_reg_write(rk808,0x92,0x55); - if (ret <0) { - printk(KERN_ERR "Unable to write 0x92 reg\n"); - return ret; - } - /*****************************************/ - /***********set buck 12.5mv/us ************/ - val = rk808_reg_read(rk808,RK808_BUCK1_CONFIG_REG); - val &= (~(0x3 <<3)); - val |= (0x3 <<0); - ret = rk808_reg_write(rk808,RK808_BUCK1_CONFIG_REG,val); - if (ret < 0) { - printk(KERN_ERR "Unable to write RK808_BUCK1_CONFIG_REG reg\n"); - return ret; - } - - val = rk808_reg_read(rk808,RK808_BUCK2_CONFIG_REG); - val &= (~(0x3 <<3)); - val |= (0x3 <<0); - ret = rk808_reg_write(rk808,RK808_BUCK2_CONFIG_REG,val); - if (ret <0) { - printk(KERN_ERR "Unable to write RK808_BUCK2_CONFIG_REG reg\n"); - return ret; - } - /*****************************************/ - - /*******enable switch and boost***********/ - val = rk808_reg_read(rk808,RK808_DCDC_EN_REG); - val |= (0x3 << 5); //enable switch1/2 - val |= (0x1 << 4); //enable boost - ret = rk808_reg_write(rk808,RK808_DCDC_EN_REG,val); - if (ret <0) { - printk(KERN_ERR "Unable to write RK808_DCDC_EN_REG reg\n"); - return ret; + dev_info(&client->dev, "source: on=0x%02x, off=0x%02x\n", + on, off); } - /****************************************/ - - /****************set vbat low **********/ - val = rk808_reg_read(rk808,RK808_VB_MON_REG); - val &=(~(VBAT_LOW_VOL_MASK | VBAT_LOW_ACT_MASK)); - val |= (RK808_VBAT_LOW_3V5 | EN_VBAT_LOW_IRQ); - ret = rk808_reg_write(rk808,RK808_VB_MON_REG,val); - if (ret <0) { - printk(KERN_ERR "Unable to write RK818_VB_MON_REG reg\n"); - return ret; - } - /**************************************/ - - /**********mask int****************/ - val = rk808_reg_read(rk808,RK808_INT_STS_MSK_REG1); - val |= (0x1<<0); //mask vout_lo_int - ret = rk808_reg_write(rk808,RK808_INT_STS_MSK_REG1,val); - if (ret <0) { - printk(KERN_ERR "Unable to write RK808_INT_STS_MSK_REG1 reg\n"); - return ret; - } - /**********************************/ - /**********enable clkout2****************/ - ret = rk808_reg_write(rk808,RK808_CLK32OUT_REG,0x01); - if (ret <0) { - printk(KERN_ERR "Unable to write RK808_CLK32OUT_REG reg\n"); - return ret; - } - /**********************************/ - ret = rk808_clear_bits(rk808, RK808_INT_STS_MSK_REG1,(0x3<<5)); //open rtc int when power on - ret = rk808_set_bits(rk808, RK808_RTC_INT_REG,(0x1<<3),(0x1<<3)); //open rtc int when power on - - return 0; -} -static int rk808_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) -{ - struct rk808 *rk808; - struct rk808_board *pdev; - const struct of_device_id *match; - struct regulator_config config = { }; - struct regulator_dev *rk808_rdev; - struct regulator_init_data *reg_data; - const char *rail_name = NULL; - int ret,i=0; -// int vlow_irq; - - printk("%s,line=%d\n", __func__,__LINE__); - - if (i2c->dev.of_node) { - match = of_match_device(rk808_of_match, &i2c->dev); - if (!match) { - dev_err(&i2c->dev,"Failed to find matching dt id\n"); - return -EINVAL; + for (i = 0; i < reg_num; i++) { + ret = regmap_update_bits(rk808->regmap, + pre_init_reg[i].addr, + pre_init_reg[i].mask, + pre_init_reg[i].value); + if (ret) { + dev_err(&client->dev, + "0x%x write err\n", + pre_init_reg[i].addr); + return ret; } } - rk808 = devm_kzalloc(&i2c->dev,sizeof(struct rk808), GFP_KERNEL); - if (rk808 == NULL) { - ret = -ENOMEM; - goto err; - } - rk808->i2c = i2c; - rk808->dev = &i2c->dev; - i2c_set_clientdata(i2c, rk808); -// rk808->read = rk808_i2c_read; -// rk808->write = rk808_i2c_write; - - rk808->regmap = devm_regmap_init_i2c(i2c, &rk808_regmap_config); - if (IS_ERR(rk808->regmap)) { - printk("regmap initialization failed\n"); + ret = regmap_add_irq_chip(rk808->regmap, client->irq, + IRQF_ONESHOT, -1, + irq_chip, &rk808->irq_data); + if (ret) { + dev_err(&client->dev, "Failed to add irq_chip %d\n", ret); return ret; } - - mutex_init(&rk808->io_lock); - ret = rk808_reg_read(rk808,0x2f); - if ((ret < 0) || (ret == 0xff)){ - printk("The device is not rk808 %d\n",ret); - goto err; - } + rk808->i2c = client; + i2c_set_clientdata(client, rk808); - ret = rk808_pre_init(rk808); - if (ret < 0){ - printk("The rk808_pre_init failed %d\n",ret); - goto err; + ret = mfd_add_devices(&client->dev, -1, + cell, cell_num, + NULL, 0, regmap_irq_get_domain(rk808->irq_data)); + if (ret) { + dev_err(&client->dev, "failed to add MFD devices %d\n", ret); + goto err_irq; } - if (rk808->dev->of_node) - pdev = rk808_parse_dt(rk808); - - /******************************set sleep vol & dcdc mode******************/ - #ifdef CONFIG_OF - rk808->pmic_sleep_gpio = pdev->pmic_sleep_gpio; - if (rk808->pmic_sleep_gpio) { - ret = gpio_request(rk808->pmic_sleep_gpio, "rk808_pmic_sleep"); - if (ret < 0) { - dev_err(rk808->dev,"Failed to request gpio %d with ret:""%d\n", rk808->pmic_sleep_gpio, ret); - return IRQ_NONE; - } - gpio_direction_output(rk808->pmic_sleep_gpio,0); - ret = gpio_get_value(rk808->pmic_sleep_gpio); - gpio_free(rk808->pmic_sleep_gpio); - pr_info("%s: rk808_pmic_sleep=%x\n", __func__, ret); - } - #endif - /**********************************************************/ - - if (pdev) { - rk808->num_regulators = rk808_NUM_REGULATORS; - rk808->rdev = kcalloc(rk808_NUM_REGULATORS,sizeof(struct regulator_dev *), GFP_KERNEL); - if (!rk808->rdev) { - return -ENOMEM; - } - /* Instantiate the regulators */ - for (i = 0; i < rk808_NUM_REGULATORS; i++) { - reg_data = pdev->rk808_init_data[i]; - if (!reg_data) - continue; - config.dev = rk808->dev; - config.driver_data = rk808; - config.regmap = rk808->regmap; - if (rk808->dev->of_node) - config.of_node = pdev->of_node[i]; - if (reg_data && reg_data->constraints.name) - rail_name = reg_data->constraints.name; - else - rail_name = regulators[i].name; - reg_data->supply_regulator = rail_name; - - config.init_data =reg_data; - - rk808_rdev = regulator_register(®ulators[i],&config); - if (IS_ERR(rk808_rdev)) { - printk("failed to register %d regulator\n",i); - goto err; + pm_off = of_property_read_bool(np, + "rockchip,system-power-controller"); + if (pm_off) { + rk808_i2c_client = client; + if (pm_shutdown_prepare_fn) { + pm_shutdown_prepare = pm_shutdown_prepare_fn; + pm_power_off_prepare = rk808_device_shutdown_prepare; } - rk808->rdev[i] = rk808_rdev; + if (pm_shutdown_fn) { + pm_shutdown = pm_shutdown_fn; + pm_power_off = rk808_device_shutdown; } } -// rk808->wakeup = pdev->wakeup; - rk808->irq_gpio = pdev->irq_gpio; - ret = rk808_irq_init(rk808, rk808->irq_gpio, pdev); - if (ret < 0) - goto err; - - ret = mfd_add_devices(rk808->dev, -1, - rk808s, ARRAY_SIZE(rk808s), - NULL, 0,NULL); - #if 0 - /********************vbat low int**************/ - vlow_irq = irq_create_mapping(rk808->irq_domain, RK808_IRQ_VB_LO); - ret = request_threaded_irq(vlow_irq, NULL, rk808_vbat_lo_irq, - IRQF_TRIGGER_RISING, "rk808_vbatlow", - rk808); - if (ret != 0) { - dev_err(rk808->dev, "Failed to request periodic IRQ %d: %d\n", - vlow_irq+ RK808_IRQ_VB_LO, ret); - - } - #endif - /*********************************************/ - - g_rk808 = rk808; - if (pdev->pm_off && !pm_power_off) { - pm_power_off = rk808_device_shutdown; + rk8xx_kobj = kobject_create_and_add("rk8xx", NULL); + if (rk8xx_kobj) { + ret = sysfs_create_file(rk8xx_kobj, &rk8xx_attrs.attr); + if (ret) + dev_err(&client->dev, "create rk8xx sysfs error\n"); } - - #ifdef CONFIG_HAS_EARLYSUSPEND - rk808->rk808_suspend.suspend = rk808_early_suspend, - rk808->rk808_suspend.resume = rk808_late_resume, - rk808->rk808_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB + 1, - register_early_suspend(&rk808->rk808_suspend); - #endif - - #if 1 - rk808_kobj = kobject_create_and_add("rk808", NULL); - if (!rk808_kobj) - return -ENOMEM; - for (i = 0; i < ARRAY_SIZE(rk808_attrs); i++) { - ret = sysfs_create_file(rk808_kobj, &rk808_attrs[i].attr); - if (ret != 0) { - printk("create index %d error\n", i); - return ret; + //pmic,hold-gpio + rk808->hold_gpio = of_get_named_gpio(np, "pmic,hold-gpio", 0); + if (gpio_is_valid(rk808->hold_gpio)) { + ret = devm_gpio_request(&client->dev, rk808->hold_gpio, "pmic-hold-gpio"); + if(ret < 0){ + dev_err(&client->dev, "pmic-hold-gpio request ERROR\n"); + goto err_irq; + } + dev_dbg(&client->dev, "hold_gpio(%d)=high\n", rk808->hold_gpio); + gpio_direction_output(rk808->hold_gpio, 1); + } + else { + dev_err(&client->dev, "Can not read property pmic,hold-gpio\n"); + //goto err_irq; + } + + //pmic,stby-gpio + rk808->stby_gpio = of_get_named_gpio(np, "pmic,stby-gpio", 0); + if (gpio_is_valid(rk808->stby_gpio)) { + ret = devm_gpio_request(&client->dev, rk808->stby_gpio, "pmic-stby-gpio"); + if(ret < 0){ + dev_err(&client->dev, "devm_gpio_request pmic-stby-gpio request ERROR\n"); + goto err_irq; } + dev_dbg(&client->dev, "stby_gpio(%d)=low\n", rk808->stby_gpio); + gpio_direction_output(rk808->stby_gpio, 1); + } else { + dev_err(&client->dev, "Can not read property pmic,stby-gpio\n"); + //goto err_irq; } - #endif - register_syscore_ops(&rk808_syscore_ops); - return 0; -err: - mfd_remove_devices(rk808->dev); - return ret; - +err_irq: + regmap_del_irq_chip(client->irq, rk808->irq_data); + return ret; } -static int rk808_i2c_remove(struct i2c_client *i2c) +static int rk808_remove(struct i2c_client *client) { - struct rk808 *rk808 = i2c_get_clientdata(i2c); - int i; + struct rk808 *rk808 = i2c_get_clientdata(client); - unregister_syscore_ops(&rk808_syscore_ops); - for (i = 0; i < rk808->num_regulators; i++) - if (rk808->rdev[i]) - regulator_unregister(rk808->rdev[i]); - kfree(rk808->rdev); - i2c_set_clientdata(i2c, NULL); + regmap_del_irq_chip(client->irq, rk808->irq_data); + mfd_remove_devices(&client->dev); + if (pm_power_off == rk808_device_shutdown) + pm_power_off = NULL; + if (pm_power_off_prepare == rk808_device_shutdown_prepare) + pm_power_off_prepare = NULL; return 0; } -static const struct dev_pm_ops rk808_pm_ops = { - .suspend = rk808_suspend, - .resume = rk808_resume, -}; - -static const struct i2c_device_id rk808_i2c_id[] = { - { "rk808", 0 }, - { } +static const struct i2c_device_id rk808_ids[] = { + { "rk805" }, + { "rk808" }, + { "rk816" }, + { "rk818" }, + { }, }; - -MODULE_DEVICE_TABLE(i2c, rk808_i2c_id); +MODULE_DEVICE_TABLE(i2c, rk808_ids); static struct i2c_driver rk808_i2c_driver = { .driver = { .name = "rk808", - .owner = THIS_MODULE, - #ifdef CONFIG_PM - .pm = &rk808_pm_ops, - #endif - .of_match_table =of_match_ptr(rk808_of_match), + .of_match_table = rk808_of_match, }, - .probe = rk808_i2c_probe, - .remove = rk808_i2c_remove, - .id_table = rk808_i2c_id, + .probe = rk808_probe, + .remove = rk808_remove, + .id_table = rk808_ids, }; -static int __init rk808_module_init(void) -{ - int ret; - ret = i2c_add_driver(&rk808_i2c_driver); - if (ret != 0) - pr_err("Failed to register I2C driver: %d\n", ret); - return ret; -} -//module_init(rk808_module_init); -//subsys_initcall(rk808_module_init); -//rootfs_initcall(rk808_module_init); -subsys_initcall_sync(rk808_module_init); - -static void __exit rk808_module_exit(void) -{ - i2c_del_driver(&rk808_i2c_driver); -} -module_exit(rk808_module_exit); +module_i2c_driver(rk808_i2c_driver); MODULE_LICENSE("GPL"); -MODULE_AUTHOR("zhangqing "); -MODULE_DESCRIPTION("rk808 PMIC driver"); - +MODULE_AUTHOR("Chris Zhong "); +MODULE_AUTHOR("Zhang Qing "); +MODULE_AUTHOR("Chen jianhong "); +MODULE_DESCRIPTION("RK808 PMIC driver");