From: Huang, Tao Date: Wed, 11 Nov 2015 07:02:36 +0000 (+0800) Subject: rk: rename rk808 to rk-rk808 X-Git-Tag: firefly_0821_release~3614 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=9e01585d365ab9241c548711c339b1db5098b430;p=firefly-linux-kernel-4.4.55.git rk: rename rk808 to rk-rk808 Signed-off-by: Huang, Tao --- diff --git a/drivers/mfd/rk-rk808.c b/drivers/mfd/rk-rk808.c new file mode 100644 index 000000000000..c42c3af07fe9 --- /dev/null +++ b/drivers/mfd/rk-rk808.c @@ -0,0 +1,1570 @@ +/* + * Regulator driver for rk808 PMIC chip for rk31xx + * + * Based on rk808.c that is work by zhangqing + * + * 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. + * + */ + +#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 12500 /*12.5mv*/ + +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[] = { + 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, +}; + +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, +}; + +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 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); + +} +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) +{ + 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; + + for (val = 0; val <= num; val++){ + if (vol_map[val] >= min_vol) + break; + } + + 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) +{ + 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; + + 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); + 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 = 712500 + 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) +{ + 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); + +} +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); +} + +static int rk808_dcdc_suspend_enable(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, 0); + +} +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 < 712500) + vsel = 0; + else if (min_uV <= 1500000) + vsel = ((min_uV - 712500) / 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; +} + +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 + } + if(ret<0) + printk("################WARNING:set voltage is error!voltage set is %d mv %d\n",min_uV,ret); + + return ret; +} +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 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; + + 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 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; + + switch(mode) + { + 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; + } + +} +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, + }, + { + .name = "RK_DCDC2", + .id = 1, + .ops = &rk808_dcdc_ops, + .n_voltages = ARRAY_SIZE(buck_voltage_map), + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + }, + { + .name = "RK_DCDC3", + .id = 2, + .ops = &rk808_dcdc_ops, + .n_voltages = ARRAY_SIZE(buck4_voltage_map), + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + }, + { + .name = "RK_DCDC4", + .id = 3, + .ops = &rk808_dcdc_ops, + .n_voltages = ARRAY_SIZE(buck4_voltage_map), + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + }, + + { + .name = "RK_LDO1", + .id =4, + .ops = &rk808_ldo_ops, + .n_voltages = ARRAY_SIZE(ldo_voltage_map), + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + }, + { + .name = "RK_LDO2", + .id = 5, + .ops = &rk808_ldo_ops, + .n_voltages = ARRAY_SIZE(ldo_voltage_map), + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + }, + { + .name = "RK_LDO3", + .id = 6, + .ops = &rk808_ldo_ops, + .n_voltages = ARRAY_SIZE(ldo3_voltage_map), + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + }, + { + .name = "RK_LDO4", + .id = 7, + .ops = &rk808_ldo_ops, + .n_voltages = ARRAY_SIZE(ldo_voltage_map), + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + }, + + { + .name = "RK_LDO5", + .id =8, + .ops = &rk808_ldo_ops, + .n_voltages = ARRAY_SIZE(ldo_voltage_map), + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + }, + { + .name = "RK_LDO6", + .id = 9, + .ops = &rk808_ldo_ops, + .n_voltages = ARRAY_SIZE(ldo6_voltage_map), + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + }, + { + .name = "RK_LDO7", + .id = 10, + .ops = &rk808_ldo_ops, + .n_voltages = ARRAY_SIZE(ldo6_voltage_map), + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + }, + { + .name = "RK_LDO8", + .id = 11, + .ops = &rk808_ldo_ops, + .n_voltages = ARRAY_SIZE(ldo_voltage_map), + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + }, + { + .name = "RK_LDO9", + .id = 12, + .ops = &rk808_ldo_ops, + .n_voltages = ARRAY_SIZE(buck4_voltage_map), + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + }, + { + .name = "RK_LDO10", + .id = 13, + .ops = &rk808_ldo_ops, + .n_voltages = ARRAY_SIZE(buck4_voltage_map), + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + }, + +}; + +/* + * + */ + 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; + + 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; +} + +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]; + + 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; +} + +int rk808_reg_read(struct rk808 *rk808, u8 reg) +{ + u8 val = 0; + int ret; + + mutex_lock(&rk808->io_lock); + + 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); + + return val & 0xff; +} +EXPORT_SYMBOL_GPL(rk808_reg_read); + +int rk808_reg_write(struct rk808 *rk808, u8 reg, u8 val) +{ + int err =0; + + mutex_lock(&rk808->io_lock); + + err = rk808_i2c_write(rk808, reg, 1,val); + if (err < 0) + dev_err(rk808->dev, "Write for reg 0x%x failed\n", reg); + + mutex_unlock(&rk808->io_lock); + return err; +} +EXPORT_SYMBOL_GPL(rk808_reg_write); + + int rk808_set_bits(struct rk808 *rk808, u8 reg, u8 mask, u8 val) +{ + u8 tmp; + int ret; + + 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; + } + 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; + } + + 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) +{ + int ret; + +#if defined(CONFIG_MFD_RK610) + int i; //Solve communication conflict when rk610 and rk808 on the same i2c + + mutex_lock(&rk808->io_lock); + for(i=0; iio_lock); + return ret; + }else{ + buf[i] = ret & 0x000000FF; + } + } + mutex_unlock(&rk808->io_lock); +#else + mutex_lock(&rk808->io_lock); + + ret = rk808->read(rk808, reg, count, buf); + + mutex_unlock(&rk808->io_lock); +#endif + return 0; + +} +EXPORT_SYMBOL_GPL(rk808_bulk_read); + +int rk808_bulk_write(struct rk808 *rk808, u8 reg, + int count, u8 *buf) +{ + 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; + +} +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); + 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); + 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); + break; + default: + printk("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); + +} + +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 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"}, + { }, +}; +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 }, +}; + +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; + } + + 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; + + pdata->rk808_init_data[i] = rk808_reg_matches[i].init_data; + pdata->of_node[i] = rk808_reg_matches[i].of_node; + } + 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 = 712500 + reg * 12500; + printk("%s,line=%d dc[%d]= %d\n", __func__,__LINE__,(i+1),val); + } + /*****************************************************/ + 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; + } + } + 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 + +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; + } + /****************************************/ + + /****************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; + } + } + + 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"); + 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; + } + + ret = rk808_pre_init(rk808); + if (ret < 0){ + printk("The rk808_pre_init failed %d\n",ret); + goto err; + } + + 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 (gpio_is_valid(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; + } + rk808->rdev[i] = rk808_rdev; + } + } + +// 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; + } + + #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; + } + } + #endif + + register_syscore_ops(&rk808_syscore_ops); + + return 0; + +err: + mfd_remove_devices(rk808->dev); + return ret; + +} + +static int rk808_i2c_remove(struct i2c_client *i2c) +{ + struct rk808 *rk808 = i2c_get_clientdata(i2c); + int i; + + 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); + + 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 }, + { } +}; + +MODULE_DEVICE_TABLE(i2c, rk808_i2c_id); + +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), + }, + .probe = rk808_i2c_probe, + .remove = rk808_i2c_remove, + .id_table = rk808_i2c_id, +}; + +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_LICENSE("GPL"); +MODULE_AUTHOR("zhangqing "); +MODULE_DESCRIPTION("rk808 PMIC driver"); + diff --git a/drivers/mfd/rk808.c b/drivers/mfd/rk808.c deleted file mode 100644 index c42c3af07fe9..000000000000 --- a/drivers/mfd/rk808.c +++ /dev/null @@ -1,1570 +0,0 @@ -/* - * Regulator driver for rk808 PMIC chip for rk31xx - * - * Based on rk808.c that is work by zhangqing - * - * 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. - * - */ - -#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 12500 /*12.5mv*/ - -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[] = { - 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, -}; - -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, -}; - -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 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); - -} -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) -{ - 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; - - for (val = 0; val <= num; val++){ - if (vol_map[val] >= min_vol) - break; - } - - 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) -{ - 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; - - 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); - 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 = 712500 + 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) -{ - 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); - -} -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); -} - -static int rk808_dcdc_suspend_enable(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, 0); - -} -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 < 712500) - vsel = 0; - else if (min_uV <= 1500000) - vsel = ((min_uV - 712500) / 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; -} - -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 - } - if(ret<0) - printk("################WARNING:set voltage is error!voltage set is %d mv %d\n",min_uV,ret); - - return ret; -} -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 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; - - 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 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; - - switch(mode) - { - 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; - } - -} -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, - }, - { - .name = "RK_DCDC2", - .id = 1, - .ops = &rk808_dcdc_ops, - .n_voltages = ARRAY_SIZE(buck_voltage_map), - .type = REGULATOR_VOLTAGE, - .owner = THIS_MODULE, - }, - { - .name = "RK_DCDC3", - .id = 2, - .ops = &rk808_dcdc_ops, - .n_voltages = ARRAY_SIZE(buck4_voltage_map), - .type = REGULATOR_VOLTAGE, - .owner = THIS_MODULE, - }, - { - .name = "RK_DCDC4", - .id = 3, - .ops = &rk808_dcdc_ops, - .n_voltages = ARRAY_SIZE(buck4_voltage_map), - .type = REGULATOR_VOLTAGE, - .owner = THIS_MODULE, - }, - - { - .name = "RK_LDO1", - .id =4, - .ops = &rk808_ldo_ops, - .n_voltages = ARRAY_SIZE(ldo_voltage_map), - .type = REGULATOR_VOLTAGE, - .owner = THIS_MODULE, - }, - { - .name = "RK_LDO2", - .id = 5, - .ops = &rk808_ldo_ops, - .n_voltages = ARRAY_SIZE(ldo_voltage_map), - .type = REGULATOR_VOLTAGE, - .owner = THIS_MODULE, - }, - { - .name = "RK_LDO3", - .id = 6, - .ops = &rk808_ldo_ops, - .n_voltages = ARRAY_SIZE(ldo3_voltage_map), - .type = REGULATOR_VOLTAGE, - .owner = THIS_MODULE, - }, - { - .name = "RK_LDO4", - .id = 7, - .ops = &rk808_ldo_ops, - .n_voltages = ARRAY_SIZE(ldo_voltage_map), - .type = REGULATOR_VOLTAGE, - .owner = THIS_MODULE, - }, - - { - .name = "RK_LDO5", - .id =8, - .ops = &rk808_ldo_ops, - .n_voltages = ARRAY_SIZE(ldo_voltage_map), - .type = REGULATOR_VOLTAGE, - .owner = THIS_MODULE, - }, - { - .name = "RK_LDO6", - .id = 9, - .ops = &rk808_ldo_ops, - .n_voltages = ARRAY_SIZE(ldo6_voltage_map), - .type = REGULATOR_VOLTAGE, - .owner = THIS_MODULE, - }, - { - .name = "RK_LDO7", - .id = 10, - .ops = &rk808_ldo_ops, - .n_voltages = ARRAY_SIZE(ldo6_voltage_map), - .type = REGULATOR_VOLTAGE, - .owner = THIS_MODULE, - }, - { - .name = "RK_LDO8", - .id = 11, - .ops = &rk808_ldo_ops, - .n_voltages = ARRAY_SIZE(ldo_voltage_map), - .type = REGULATOR_VOLTAGE, - .owner = THIS_MODULE, - }, - { - .name = "RK_LDO9", - .id = 12, - .ops = &rk808_ldo_ops, - .n_voltages = ARRAY_SIZE(buck4_voltage_map), - .type = REGULATOR_VOLTAGE, - .owner = THIS_MODULE, - }, - { - .name = "RK_LDO10", - .id = 13, - .ops = &rk808_ldo_ops, - .n_voltages = ARRAY_SIZE(buck4_voltage_map), - .type = REGULATOR_VOLTAGE, - .owner = THIS_MODULE, - }, - -}; - -/* - * - */ - 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; - - 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; -} - -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]; - - 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; -} - -int rk808_reg_read(struct rk808 *rk808, u8 reg) -{ - u8 val = 0; - int ret; - - mutex_lock(&rk808->io_lock); - - 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); - - return val & 0xff; -} -EXPORT_SYMBOL_GPL(rk808_reg_read); - -int rk808_reg_write(struct rk808 *rk808, u8 reg, u8 val) -{ - int err =0; - - mutex_lock(&rk808->io_lock); - - err = rk808_i2c_write(rk808, reg, 1,val); - if (err < 0) - dev_err(rk808->dev, "Write for reg 0x%x failed\n", reg); - - mutex_unlock(&rk808->io_lock); - return err; -} -EXPORT_SYMBOL_GPL(rk808_reg_write); - - int rk808_set_bits(struct rk808 *rk808, u8 reg, u8 mask, u8 val) -{ - u8 tmp; - int ret; - - 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; - } - 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; - } - - 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) -{ - int ret; - -#if defined(CONFIG_MFD_RK610) - int i; //Solve communication conflict when rk610 and rk808 on the same i2c - - mutex_lock(&rk808->io_lock); - for(i=0; iio_lock); - return ret; - }else{ - buf[i] = ret & 0x000000FF; - } - } - mutex_unlock(&rk808->io_lock); -#else - mutex_lock(&rk808->io_lock); - - ret = rk808->read(rk808, reg, count, buf); - - mutex_unlock(&rk808->io_lock); -#endif - return 0; - -} -EXPORT_SYMBOL_GPL(rk808_bulk_read); - -int rk808_bulk_write(struct rk808 *rk808, u8 reg, - int count, u8 *buf) -{ - 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; - -} -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); - 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); - 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); - break; - default: - printk("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); - -} - -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 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"}, - { }, -}; -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 }, -}; - -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; - } - - 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; - - pdata->rk808_init_data[i] = rk808_reg_matches[i].init_data; - pdata->of_node[i] = rk808_reg_matches[i].of_node; - } - 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 = 712500 + reg * 12500; - printk("%s,line=%d dc[%d]= %d\n", __func__,__LINE__,(i+1),val); - } - /*****************************************************/ - 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; - } - } - 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 - -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; - } - /****************************************/ - - /****************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; - } - } - - 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"); - 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; - } - - ret = rk808_pre_init(rk808); - if (ret < 0){ - printk("The rk808_pre_init failed %d\n",ret); - goto err; - } - - 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 (gpio_is_valid(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; - } - rk808->rdev[i] = rk808_rdev; - } - } - -// 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; - } - - #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; - } - } - #endif - - register_syscore_ops(&rk808_syscore_ops); - - return 0; - -err: - mfd_remove_devices(rk808->dev); - return ret; - -} - -static int rk808_i2c_remove(struct i2c_client *i2c) -{ - struct rk808 *rk808 = i2c_get_clientdata(i2c); - int i; - - 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); - - 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 }, - { } -}; - -MODULE_DEVICE_TABLE(i2c, rk808_i2c_id); - -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), - }, - .probe = rk808_i2c_probe, - .remove = rk808_i2c_remove, - .id_table = rk808_i2c_id, -}; - -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_LICENSE("GPL"); -MODULE_AUTHOR("zhangqing "); -MODULE_DESCRIPTION("rk808 PMIC driver"); - diff --git a/drivers/rtc/rtc-rk-rk808.c b/drivers/rtc/rtc-rk-rk808.c new file mode 100644 index 000000000000..c396f36b4728 --- /dev/null +++ b/drivers/rtc/rtc-rk-rk808.c @@ -0,0 +1,833 @@ +/* + * Real Time Clock driver for rk808 + * + * Author: zhangqing + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/* RTC Definitions */ +/* RTC_CTRL_REG bitfields */ +#define BIT_RTC_CTRL_REG_STOP_RTC_M 0x01 +#define BIT_RTC_CTRL_REG_ROUND_30S_M 0x02 +#define BIT_RTC_CTRL_REG_AUTO_COMP_M 0x04 +#define BIT_RTC_CTRL_REG_MODE_12_24_M 0x08 +#define BIT_RTC_CTRL_REG_TEST_MODE_M 0x10 +#define BIT_RTC_CTRL_REG_SET_32_COUNTER_M 0x20 +#define BIT_RTC_CTRL_REG_GET_TIME_M 0x40 +#define BIT_RTC_CTRL_REG_RTC_V_OPT_M 0x80 + +/* RTC_STATUS_REG bitfields */ +#define BIT_RTC_STATUS_REG_RUN_M 0x02 +#define BIT_RTC_STATUS_REG_1S_EVENT_M 0x04 +#define BIT_RTC_STATUS_REG_1M_EVENT_M 0x08 +#define BIT_RTC_STATUS_REG_1H_EVENT_M 0x10 +#define BIT_RTC_STATUS_REG_1D_EVENT_M 0x20 +#define BIT_RTC_STATUS_REG_ALARM_M 0x40 +#define BIT_RTC_STATUS_REG_POWER_UP_M 0x80 + +/* RTC_INTERRUPTS_REG bitfields */ +#define BIT_RTC_INTERRUPTS_REG_EVERY_M 0x03 +#define BIT_RTC_INTERRUPTS_REG_IT_TIMER_M 0x04 +#define BIT_RTC_INTERRUPTS_REG_IT_ALARM_M 0x08 + +/* DEVCTRL bitfields */ +#define BIT_RTC_PWDN 0x40 + +/* REG_SECONDS_REG through REG_YEARS_REG is how many registers? */ +#define ALL_TIME_REGS 7 +#define ALL_ALM_REGS 6 + + +#define RTC_SET_TIME_RETRIES 5 +#define RTC_GET_TIME_RETRIES 5 + + +struct rk808_rtc { + struct rk808 *rk808; + struct rtc_device *rtc; + unsigned int alarm_enabled:1; +}; + +/* + * Read current time and date in RTC + */ +static int rk808_rtc_readtime(struct device *dev, struct rtc_time *tm) +{ + struct rk808_rtc *rk808_rtc = dev_get_drvdata(dev); + struct rk808 *rk808 = rk808_rtc->rk808; + int ret; + unsigned char rtc_data[ALL_TIME_REGS + 1]; + u8 rtc_ctl; + + /*Dummy read*/ + ret = rk808_reg_read(rk808, RK808_RTC_CTRL_REG); + + /* Has the RTC been programmed? */ + ret = rk808_reg_read(rk808, RK808_RTC_CTRL_REG); + if (ret < 0) { + dev_err(dev, "Failed to read RTC control: %d\n", ret); + return ret; + } + + rtc_ctl = ret & (~BIT_RTC_CTRL_REG_RTC_V_OPT_M); + + ret = rk808_reg_write(rk808, RK808_RTC_CTRL_REG, rtc_ctl); + if (ret < 0) { + dev_err(dev, "Failed to write RTC control: %d\n", ret); + return ret; + } + +#if 0 + /* Read twice to make sure we don't read a corrupt, partially + * incremented, value. + */ + do { + ret = rk808_bulk_read(rk808, RK808_SECONDS_REG, + ALL_TIME_REGS, rtc_data); + if (ret != 0) + continue; + + tm->tm_sec = bcd2bin(rtc_data[0]); + tm->tm_min = bcd2bin(rtc_data[1]); + tm->tm_hour = bcd2bin(rtc_data[2]) ; + tm->tm_mday = bcd2bin(rtc_data[3]); + tm->tm_mon = bcd2bin(rtc_data[4]) - 1; + tm->tm_year = bcd2bin(rtc_data[5]) + 100; + tm->tm_wday = bcd2bin(rtc_data[6]); + + printk( "RTC date/time %4d-%02d-%02d(%d) %02d:%02d:%02d\n", + 1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday, tm->tm_wday, + tm->tm_hour, tm->tm_min, tm->tm_sec); + + return ret; + + } while (++count < RTC_GET_TIME_RETRIES); + dev_err(dev, "Timed out reading current time\n"); +#else + rtc_data[0] = rk808_reg_read(rk808,0x00); + rtc_data[1] = rk808_reg_read(rk808,0x01); + rtc_data[2] = rk808_reg_read(rk808,0x02); + rtc_data[3] = rk808_reg_read(rk808,0x03); + rtc_data[4] = rk808_reg_read(rk808,0x04); + rtc_data[5] = rk808_reg_read(rk808,0x05); + rtc_data[6] = rk808_reg_read(rk808,0x06); + + tm->tm_sec = bcd2bin(rtc_data[0]); + tm->tm_min = bcd2bin(rtc_data[1]); + tm->tm_hour = bcd2bin(rtc_data[2]) ; + tm->tm_mday = bcd2bin(rtc_data[3]); + tm->tm_mon = bcd2bin(rtc_data[4]) - 1; + tm->tm_year = bcd2bin(rtc_data[5]) + 100; + tm->tm_wday = bcd2bin(rtc_data[6]); + + dev_dbg(dev, "RTC date/time %4d-%02d-%02d(%d) %02d:%02d:%02d\n", + 1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday, tm->tm_wday,tm->tm_hour , tm->tm_min, tm->tm_sec); + +#endif + return 0; + +} + +/* + * Set current time and date in RTC + */ +static int rk808_rtc_set_time(struct device *dev, struct rtc_time *tm) +{ + struct rk808_rtc *rk808_rtc = dev_get_drvdata(dev); + struct rk808 *rk808 = rk808_rtc->rk808; + int ret; + u8 rtc_ctl; + unsigned char rtc_data[ALL_TIME_REGS + 1]; + + rtc_data[0] = bin2bcd(tm->tm_sec); + rtc_data[1] = bin2bcd(tm->tm_min); + rtc_data[2] = bin2bcd(tm->tm_hour ); + rtc_data[3] = bin2bcd(tm->tm_mday); + rtc_data[4] = bin2bcd(tm->tm_mon + 1); + rtc_data[5] = bin2bcd(tm->tm_year - 100); + rtc_data[6] = bin2bcd(tm->tm_wday); + + dev_dbg(dev, "set RTC date/time %4d-%02d-%02d(%d) %02d:%02d:%02d\n", + 1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday, tm->tm_wday,tm->tm_hour , tm->tm_min, tm->tm_sec); + + /*Dummy read*/ + ret = rk808_reg_read(rk808, RK808_RTC_CTRL_REG); + + /* Stop RTC while updating the TC registers */ + ret = rk808_reg_read(rk808, RK808_RTC_CTRL_REG); + if (ret < 0) { + dev_err(dev, "Failed to read RTC control: %d\n", ret); + return ret; + } + + rtc_ctl = ret | (BIT_RTC_CTRL_REG_STOP_RTC_M); + + ret = rk808_reg_write(rk808, RK808_RTC_CTRL_REG, rtc_ctl); + if (ret < 0) { + dev_err(dev, "Failed to write RTC control: %d\n", ret); + return ret; + } +#if 0 + /* update all the time registers in one shot */ + ret = rk808_bulk_write(rk808, RK808_SECONDS_REG, + ALL_TIME_REGS, rtc_data); + if (ret < 0) { + dev_err(dev, "Failed to read RTC times: %d\n", ret); + return ret; + } +#else + rk808_reg_write(rk808,0x00,rtc_data[0]); + rk808_reg_write(rk808,0x01,rtc_data[1]); + rk808_reg_write(rk808,0x02,rtc_data[2]); + rk808_reg_write(rk808,0x03,rtc_data[3]); + rk808_reg_write(rk808,0x04,rtc_data[4]); + rk808_reg_write(rk808,0x05,rtc_data[5]); + rk808_reg_write(rk808,0x06,rtc_data[6]); + +#endif + /*Dummy read*/ + ret = rk808_reg_read(rk808, RK808_RTC_CTRL_REG); + + /* Start RTC again */ + ret = rk808_reg_read(rk808, RK808_RTC_CTRL_REG); + if (ret < 0) { + dev_err(dev, "Failed to read RTC control: %d\n", ret); + return ret; + } + + rtc_ctl = ret &(~ BIT_RTC_CTRL_REG_STOP_RTC_M); + + ret = rk808_reg_write(rk808, RK808_RTC_CTRL_REG, rtc_ctl); + if (ret < 0) { + dev_err(dev, "Failed to write RTC control: %d\n", ret); + return ret; + } + + return 0; +} + +/* + * Read alarm time and date in RTC + */ +static int rk808_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm) +{ + struct rk808_rtc *rk808_rtc = dev_get_drvdata(dev); + int ret; + unsigned char alrm_data[ALL_ALM_REGS + 1]; +#if 0 + ret = rk808_bulk_read(rk808_rtc->rk808, RK808_ALARM_SECONDS_REG, + ALL_ALM_REGS, alrm_data); + if (ret != 0) { + dev_err(dev, "Failed to read alarm time: %d\n", ret); + return ret; + } +#else + alrm_data[0] = rk808_reg_read(rk808_rtc->rk808,0x08); + alrm_data[1] = rk808_reg_read(rk808_rtc->rk808,0x09); + alrm_data[2] = rk808_reg_read(rk808_rtc->rk808,0x0a); + alrm_data[3] = rk808_reg_read(rk808_rtc->rk808,0x0b); + alrm_data[4] = rk808_reg_read(rk808_rtc->rk808,0x0c); + alrm_data[5] = rk808_reg_read(rk808_rtc->rk808,0x0d); + + +#endif + /* some of these fields may be wildcard/"match all" */ + alrm->time.tm_sec = bcd2bin(alrm_data[0]); + alrm->time.tm_min = bcd2bin(alrm_data[1]); + alrm->time.tm_hour = bcd2bin(alrm_data[2]); + alrm->time.tm_mday = bcd2bin(alrm_data[3]); + alrm->time.tm_mon = bcd2bin(alrm_data[4]) - 1; + alrm->time.tm_year = bcd2bin(alrm_data[5]) + 100; + + ret = rk808_reg_read(rk808_rtc->rk808, RK808_RTC_INT_REG); + if (ret < 0) { + dev_err(dev, "Failed to read RTC control: %d\n", ret); + return ret; + } + dev_dbg(dev,"alrm read RTC date/time %4d-%02d-%02d(%d) %02d:%02d:%02d\n", + 1900 + alrm->time.tm_year, alrm->time.tm_mon + 1, alrm->time.tm_mday, alrm->time.tm_wday, alrm->time.tm_hour, alrm->time.tm_min, alrm->time.tm_sec); + + + + if (ret & BIT_RTC_INTERRUPTS_REG_IT_ALARM_M) + alrm->enabled = 1; + else + alrm->enabled = 0; + + return 0; +} + +static int rk808_rtc_stop_alarm(struct rk808_rtc *rk808_rtc) +{ + rk808_rtc->alarm_enabled = 0; + + return rk808_clear_bits(rk808_rtc->rk808, RK808_RTC_INT_REG, + BIT_RTC_INTERRUPTS_REG_IT_ALARM_M); + +} + +static int rk808_rtc_start_alarm(struct rk808_rtc *rk808_rtc) +{ + rk808_rtc->alarm_enabled = 1; + + return rk808_set_bits(rk808_rtc->rk808, RK808_RTC_INT_REG, + BIT_RTC_INTERRUPTS_REG_IT_ALARM_M,BIT_RTC_INTERRUPTS_REG_IT_ALARM_M); + +} + +static int rk808_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) +{ + struct rk808_rtc *rk808_rtc = dev_get_drvdata(dev); + int ret; + unsigned char alrm_data[ALL_TIME_REGS + 1]; + + ret = rk808_rtc_stop_alarm(rk808_rtc); + if (ret < 0) { + dev_err(dev, "Failed to stop alarm: %d\n", ret); + return ret; + } + + dev_dbg(dev,"alrm set RTC date/time %4d-%02d-%02d(%d) %02d:%02d:%02d\n", + 1900 + alrm->time.tm_year, alrm->time.tm_mon + 1, alrm->time.tm_mday, alrm->time.tm_wday, alrm->time.tm_hour, alrm->time.tm_min, alrm->time.tm_sec); + + alrm_data[0] = bin2bcd(alrm->time.tm_sec); + alrm_data[1] = bin2bcd(alrm->time.tm_min); + alrm_data[2] = bin2bcd(alrm->time.tm_hour ); + alrm_data[3] = bin2bcd(alrm->time.tm_mday); + alrm_data[4] = bin2bcd(alrm->time.tm_mon + 1); + alrm_data[5] = bin2bcd(alrm->time.tm_year - 100); +#if 0 + ret = rk808_bulk_write(rk808_rtc->rk808, RK808_ALARM_SECONDS_REG, + ALL_ALM_REGS, alrm_data); + if (ret != 0) { + dev_err(dev, "Failed to read alarm time: %d\n", ret); + return ret; + } +#else + rk808_reg_write(rk808_rtc->rk808,0x08,alrm_data[0]); + rk808_reg_write(rk808_rtc->rk808,0x09,alrm_data[1]); + rk808_reg_write(rk808_rtc->rk808,0x0a,alrm_data[2]); + rk808_reg_write(rk808_rtc->rk808,0x0b,alrm_data[3]); + rk808_reg_write(rk808_rtc->rk808,0x0c,alrm_data[4]); + rk808_reg_write(rk808_rtc->rk808,0x0d,alrm_data[5]); + +#endif + if (alrm->enabled) { + ret = rk808_rtc_start_alarm(rk808_rtc); + if (ret < 0) { + dev_err(dev, "Failed to start alarm: %d\n", ret); + return ret; + } + } + + return 0; +} + +static int rk808_rtc_alarm_irq_enable(struct device *dev, + unsigned int enabled) +{ + struct rk808_rtc *rk808_rtc = dev_get_drvdata(dev); + + if (enabled) + return rk808_rtc_start_alarm(rk808_rtc); + else + return rk808_rtc_stop_alarm(rk808_rtc); +} + +static int rk808_rtc_update_irq_enable(struct device *dev, + unsigned int enabled) +{ + struct rk808_rtc *rk808_rtc = dev_get_drvdata(dev); + + if (enabled) + return rk808_set_bits(rk808_rtc->rk808, RK808_RTC_INT_REG, + BIT_RTC_INTERRUPTS_REG_IT_TIMER_M,BIT_RTC_INTERRUPTS_REG_IT_TIMER_M); + else + return rk808_clear_bits(rk808_rtc->rk808, RK808_RTC_INT_REG, + BIT_RTC_INTERRUPTS_REG_IT_TIMER_M); +} + +/* + * We will just handle setting the frequency and make use the framework for + * reading the periodic interupts. + * + * @freq: Current periodic IRQ freq: + * bit 0: every second + * bit 1: every minute + * bit 2: every hour + * bit 3: every day + */ +#if 0 +static int rk808_rtc_irq_set_freq(struct device *dev, int freq) +{ + struct rk808_rtc *rk808_rtc = dev_get_drvdata(dev); + int ret; + u8 rtc_ctl; + + if (freq < 0 || freq > 3) + return -EINVAL; + + ret = rk808_reg_read(rk808_rtc->rk808, RK808_RTC_INT_REG); + if (ret < 0) { + dev_err(dev, "Failed to read RTC interrupt: %d\n", ret); + return ret; + } + + rtc_ctl = ret | freq; + + ret = rk808_reg_write(rk808_rtc->rk808, RK808_RTC_INT_REG, rtc_ctl); + if (ret < 0) { + dev_err(dev, "Failed to write RTC control: %d\n", ret); + return ret; + } + + return ret; +} +#endif +static irqreturn_t rk808_alm_irq(int irq, void *data) +{ + struct rk808_rtc *rk808_rtc = data; + int ret; + u8 rtc_ctl; + + /*Dummy read -- mandatory for status register*/ + ret = rk808_reg_read(rk808_rtc->rk808, RK808_RTC_STATUS_REG); + if (ret < 0) { + printk("%s:Failed to read RTC status: %d\n", __func__, ret); + return ret; + } + + ret = rk808_reg_read(rk808_rtc->rk808, RK808_RTC_STATUS_REG); + if (ret < 0) { + printk("%s:Failed to read RTC status: %d\n", __func__, ret); + return ret; + } + rtc_ctl = ret&0xff; + + //The alarm interrupt keeps its low level, until the micro-controller write 1 in the ALARM bit of the RTC_STATUS_REG register. + ret = rk808_reg_write(rk808_rtc->rk808, RK808_RTC_STATUS_REG,rtc_ctl); + if (ret < 0) { + printk("%s:Failed to read RTC status: %d\n", __func__, ret); + return ret; + } + + rtc_update_irq(rk808_rtc->rtc, 1, RTC_IRQF | RTC_AF); + + printk("%s:irq=%d,rtc_ctl=0x%x\n",__func__,irq,rtc_ctl); + return IRQ_HANDLED; +} + +static irqreturn_t rk808_per_irq(int irq, void *data) +{ + struct rk808_rtc *rk808_rtc = data; + + rtc_update_irq(rk808_rtc->rtc, 1, RTC_IRQF | RTC_UF); + + //printk("%s:irq=%d\n",__func__,irq); + return IRQ_HANDLED; +} + +static const struct rtc_class_ops rk808_rtc_ops = { + .read_time = rk808_rtc_readtime, + //.set_mmss = rk808_rtc_set_mmss, + .set_time = rk808_rtc_set_time, + .read_alarm = rk808_rtc_readalarm, + .set_alarm = rk808_rtc_setalarm, + .alarm_irq_enable = rk808_rtc_alarm_irq_enable, + //.update_irq_enable = rk808_rtc_update_irq_enable, + //.irq_set_freq = rk808_rtc_irq_set_freq, +}; + +#ifdef CONFIG_PM +/* Turn off the alarm if it should not be a wake source. */ +static int rk808_rtc_suspend(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct rk808_rtc *rk808_rtc = dev_get_drvdata(&pdev->dev); + int ret; + + if (rk808_rtc->alarm_enabled && device_may_wakeup(&pdev->dev)) + ret = rk808_rtc_start_alarm(rk808_rtc); + else + ret = rk808_rtc_stop_alarm(rk808_rtc); + + if (ret < 0) + dev_err(&pdev->dev, "Failed to update RTC alarm: %d\n", ret); + + return 0; +} + +/* Enable the alarm if it should be enabled (in case it was disabled to + * prevent use as a wake source). + */ +static int rk808_rtc_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct rk808_rtc *rk808_rtc = dev_get_drvdata(&pdev->dev); + int ret; + + if (rk808_rtc->alarm_enabled) { + ret = rk808_rtc_start_alarm(rk808_rtc); + if (ret <0) + dev_err(&pdev->dev, + "Failed to restart RTC alarm: %d\n", ret); + } + + return 0; +} + +/* Unconditionally disable the alarm */ +static int rk808_rtc_freeze(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct rk808_rtc *rk808_rtc = dev_get_drvdata(&pdev->dev); + int ret; + + ret = rk808_rtc_stop_alarm(rk808_rtc); + if (ret < 0) + dev_err(&pdev->dev, "Failed to stop RTC alarm: %d\n", ret); + + return 0; +} +#else +#define rk808_rtc_suspend NULL +#define rk808_rtc_resume NULL +#define rk808_rtc_freeze NULL +#endif +extern struct rk808 *g_rk808; +struct platform_device *rk808_pdev; +struct rtc_time tm_def = { // 2012.1.1 12:00:00 Saturday + .tm_wday = 6, + .tm_year = 112, + .tm_mon = 0, + .tm_mday = 1, + .tm_hour = 12, + .tm_min = 0, + .tm_sec = 0, +}; + +static int rk808_rtc_probe(struct platform_device *pdev) +{ + struct rk808 *rk808 = dev_get_drvdata(pdev->dev.parent); + struct rk808_rtc *rk808_rtc; + struct rtc_time tm; + int per_irq; + int alm_irq; + int ret = 0; + u8 rtc_ctl; + + printk("%s,line=%d\n", __func__,__LINE__); + + rk808_rtc = kzalloc(sizeof(*rk808_rtc), GFP_KERNEL); + if (rk808_rtc == NULL) + return -ENOMEM; + + platform_set_drvdata(pdev, rk808_rtc); + rk808_rtc->rk808 = rk808; + + /* Take rtc out of reset */ + /* + ret = rk808_reg_read(rk808, RK808_DEVCTRL); + if (ret < 0) { + dev_err(&pdev->dev, "Failed to read RK808_DEVCTRL: %d\n", ret); + return ret; + } + + if(ret & BIT_RTC_PWDN) + { + rtc_ctl = ret & (~BIT_RTC_PWDN); + + ret = rk808_reg_write(rk808, RK808_DEVCTRL, rtc_ctl); + if (ret < 0) { + dev_err(&pdev->dev, "Failed to write RTC control: %d\n", ret); + return ret; + } + } + */ + /*start rtc default*/ + ret = rk808_reg_read(rk808, RK808_RTC_CTRL_REG); + if (ret < 0) { + dev_err(&pdev->dev, "Failed to read RTC control: %d\n", ret); + return ret; + } + rtc_ctl = ret & (~BIT_RTC_CTRL_REG_STOP_RTC_M); + + ret = rk808_reg_write(rk808, RK808_RTC_CTRL_REG, rtc_ctl); + if (ret < 0) { + dev_err(&pdev->dev, "Failed to write RTC control: %d\n", ret); + return ret; + } + + ret = rk808_reg_read(rk808, RK808_RTC_STATUS_REG); + if (ret < 0) { + dev_err(&pdev->dev, "Failed to read RTC status: %d\n", ret); + return ret; + } + rk808_reg_write(rk808,RK808_RTC_STATUS_REG,0xfe); + /*set init time*/ + + ret = rk808_rtc_readtime(&pdev->dev, &tm); + if (ret<0) + { + dev_err(&pdev->dev, "Failed to read RTC time\n"); + return ret; + } + + ret = rtc_valid_tm(&tm); + if (ret) { + dev_err(&pdev->dev,"invalid date/time and init time\n"); + rk808_rtc_set_time(&pdev->dev, &tm_def); // 2012-01-01 12:00:00 +// DBG( "set RTC date/time %4d-%02d-%02d(%d) %02d:%02d:%02d\n",1900 + tm_def.tm_year, tm_def.tm_mon + 1, tm_def.tm_mday, tm_def.tm_wday,tm_def.tm_hour, tm_def.tm_min, tm_def.tm_sec); + } + + device_init_wakeup(&pdev->dev, 1); + + rk808_rtc->rtc = rtc_device_register("rk808", &pdev->dev, + &rk808_rtc_ops, THIS_MODULE); + if (IS_ERR(rk808_rtc->rtc)) { + ret = PTR_ERR(rk808_rtc->rtc); + goto err; + } + + per_irq = irq_create_mapping(rk808->irq_domain, RK808_IRQ_RTC_PERIOD); + alm_irq = irq_create_mapping(rk808->irq_domain, RK808_IRQ_RTC_ALARM); + + /*request rtc and alarm irq of rk808*/ + ret = devm_request_threaded_irq(rk808->dev,per_irq, NULL, rk808_per_irq, + IRQF_TRIGGER_RISING, "RTC period", + rk808_rtc); + if (ret != 0) { + dev_err(&pdev->dev, "Failed to request periodic IRQ %d: %d\n", + per_irq, ret); + } + + ret = devm_request_threaded_irq(rk808->dev,alm_irq, NULL, rk808_alm_irq, + IRQF_TRIGGER_RISING, "RTC alarm", + rk808_rtc); + if (ret != 0) { + dev_err(&pdev->dev, "Failed to request alarm IRQ %d: %d\n", + alm_irq, ret); + } + + //for rtc irq test + /* + rk808_set_bits(rk808_rtc->rk808, RK808_RTC_STATUS_REG,(0x1<< 6),(0x1 <<6)); + rk808_set_bits(rk808_rtc->rk808, RK808_RTC_INT_REG,0x0c,0x0c); + rk808_set_bits(rk808_rtc->rk808,RK808_INT_STS_REG1,(0x3 << 5),(0x3 <<5)); + rk808_set_bits(rk808_rtc->rk808, RK808_INT_STS_MSK_REG1,(0x3 <<5),0); +*/ + +// enable_irq_wake(alm_irq); // so rk808 alarm irq can wake up system + rk808_pdev = pdev; + + printk("%s:ok\n",__func__); + + return 0; + +err: + kfree(rk808_rtc); + return ret; +} + +static int rk808_rtc_remove(struct platform_device *pdev) +{ + struct rk808_rtc *rk808_rtc = platform_get_drvdata(pdev); + int per_irq = rk808_rtc->rk808->irq_base + RK808_IRQ_RTC_PERIOD; + int alm_irq = rk808_rtc->rk808->irq_base + RK808_IRQ_RTC_ALARM; + + free_irq(alm_irq, rk808_rtc); + free_irq(per_irq, rk808_rtc); + rtc_device_unregister(rk808_rtc->rtc); + kfree(rk808_rtc); + + return 0; +} + +static const struct dev_pm_ops rk808_rtc_pm_ops = { + .suspend = rk808_rtc_suspend, + .resume = rk808_rtc_resume, + + .freeze = rk808_rtc_freeze, + .thaw = rk808_rtc_resume, + .restore = rk808_rtc_resume, + + .poweroff = rk808_rtc_suspend, +}; + +static struct platform_driver rk808_rtc_driver = { + .probe = rk808_rtc_probe, + .remove = rk808_rtc_remove, + .driver = { + .name = "rk808-rtc", + .pm = &rk808_rtc_pm_ops, + }, +}; + +static ssize_t rtc_rk808_test_write(struct file *file, + const char __user *buf, size_t count, loff_t *offset) +{ + char nr_buf[8]; + int nr = 0, ret; + struct platform_device *pdev; + struct rtc_time tm; + struct rtc_wkalrm alrm; + struct rk808_rtc *rk808_rtc; + + if(count > 3) + return -EFAULT; + ret = copy_from_user(nr_buf, buf, count); + if(ret < 0) + return -EFAULT; + + sscanf(nr_buf, "%d", &nr); + if(nr > 5 || nr < 0) + { + printk("%s:data is error\n",__func__); + return -EFAULT; + } + + if(!rk808_pdev) + return -EFAULT; + else + pdev = rk808_pdev; + + + rk808_rtc = dev_get_drvdata(&pdev->dev); + + //test rtc time + if(nr == 0) + { + tm.tm_wday = 6; + tm.tm_year = 111; + tm.tm_mon = 0; + tm.tm_mday = 1; + tm.tm_hour = 12; + tm.tm_min = 0; + tm.tm_sec = 0; + + ret = rk808_rtc_set_time(&pdev->dev, &tm); // 2011-01-01 12:00:00 + if (ret) + { + dev_err(&pdev->dev, "Failed to set RTC time\n"); + return -EFAULT; + } + + } + + /*set init time*/ + ret = rk808_rtc_readtime(&pdev->dev, &tm); + if (ret) + dev_err(&pdev->dev, "Failed to read RTC time\n"); + else + dev_info(&pdev->dev, "RTC date/time %4d-%02d-%02d(%d) %02d:%02d:%02d\n", + 1900 + tm.tm_year, tm.tm_mon + 1, tm.tm_mday, tm.tm_wday, + tm.tm_hour, tm.tm_min, tm.tm_sec); + + if(!ret) + printk("%s:ok\n",__func__); + else + printk("%s:error\n",__func__); + + + //test rtc alarm + if(nr == 2) + { + //2000-01-01 00:00:30 + if(tm.tm_sec < 30) + { + alrm.time.tm_sec = tm.tm_sec+30; + alrm.time.tm_min = tm.tm_min; + } + else + { + alrm.time.tm_sec = tm.tm_sec-30; + alrm.time.tm_min = tm.tm_min+1; + } + alrm.time.tm_hour = tm.tm_hour; + alrm.time.tm_mday = tm.tm_mday; + alrm.time.tm_mon = tm.tm_mon; + alrm.time.tm_year = tm.tm_year; + rk808_rtc_alarm_irq_enable(&pdev->dev, 1); + rk808_rtc_setalarm(&pdev->dev, &alrm); + + dev_info(&pdev->dev, "Set alarm %4d-%02d-%02d(%d) %02d:%02d:%02d\n", + 1900 + alrm.time.tm_year, alrm.time.tm_mon + 1, alrm.time.tm_mday, alrm.time.tm_wday, + alrm.time.tm_hour, alrm.time.tm_min, alrm.time.tm_sec); + } + + + if(nr == 3) + { + ret = rk808_reg_read(rk808_rtc->rk808, RK808_RTC_STATUS_REG); + if (ret < 0) { + printk("%s:Failed to read RTC status: %d\n", __func__, ret); + return ret; + } + printk("%s:ret=0x%x\n",__func__,ret&0xff); + + ret = rk808_reg_write(rk808_rtc->rk808, RK808_RTC_STATUS_REG, ret&0xff); + if (ret < 0) { + printk("%s:Failed to read RTC status: %d\n", __func__, ret); + return ret; + } + } + + if(nr == 4) + rk808_rtc_update_irq_enable(&pdev->dev, 1); + + if(nr == 5) + rk808_rtc_update_irq_enable(&pdev->dev, 0); + + return count; +} + +static const struct file_operations rtc_rk808_test_fops = { + .write = rtc_rk808_test_write, +}; + +static struct miscdevice rtc_rk808_test_misc = { + .minor = MISC_DYNAMIC_MINOR, + .name = "rtc_rk808_test", + .fops = &rtc_rk808_test_fops, +}; + + +static int __init rk808_rtc_init(void) +{ + misc_register(&rtc_rk808_test_misc); + return platform_driver_register(&rk808_rtc_driver); +} +subsys_initcall_sync(rk808_rtc_init); + +static void __exit rk808_rtc_exit(void) +{ + misc_deregister(&rtc_rk808_test_misc); + platform_driver_unregister(&rk808_rtc_driver); +} +module_exit(rk808_rtc_exit); + +MODULE_DESCRIPTION("RTC driver for the rk808 series PMICs"); +MODULE_AUTHOR("ZHANGQING "); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:rk808-rtc"); diff --git a/drivers/rtc/rtc-rk808.c b/drivers/rtc/rtc-rk808.c deleted file mode 100644 index c396f36b4728..000000000000 --- a/drivers/rtc/rtc-rk808.c +++ /dev/null @@ -1,833 +0,0 @@ -/* - * Real Time Clock driver for rk808 - * - * Author: zhangqing - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -/* RTC Definitions */ -/* RTC_CTRL_REG bitfields */ -#define BIT_RTC_CTRL_REG_STOP_RTC_M 0x01 -#define BIT_RTC_CTRL_REG_ROUND_30S_M 0x02 -#define BIT_RTC_CTRL_REG_AUTO_COMP_M 0x04 -#define BIT_RTC_CTRL_REG_MODE_12_24_M 0x08 -#define BIT_RTC_CTRL_REG_TEST_MODE_M 0x10 -#define BIT_RTC_CTRL_REG_SET_32_COUNTER_M 0x20 -#define BIT_RTC_CTRL_REG_GET_TIME_M 0x40 -#define BIT_RTC_CTRL_REG_RTC_V_OPT_M 0x80 - -/* RTC_STATUS_REG bitfields */ -#define BIT_RTC_STATUS_REG_RUN_M 0x02 -#define BIT_RTC_STATUS_REG_1S_EVENT_M 0x04 -#define BIT_RTC_STATUS_REG_1M_EVENT_M 0x08 -#define BIT_RTC_STATUS_REG_1H_EVENT_M 0x10 -#define BIT_RTC_STATUS_REG_1D_EVENT_M 0x20 -#define BIT_RTC_STATUS_REG_ALARM_M 0x40 -#define BIT_RTC_STATUS_REG_POWER_UP_M 0x80 - -/* RTC_INTERRUPTS_REG bitfields */ -#define BIT_RTC_INTERRUPTS_REG_EVERY_M 0x03 -#define BIT_RTC_INTERRUPTS_REG_IT_TIMER_M 0x04 -#define BIT_RTC_INTERRUPTS_REG_IT_ALARM_M 0x08 - -/* DEVCTRL bitfields */ -#define BIT_RTC_PWDN 0x40 - -/* REG_SECONDS_REG through REG_YEARS_REG is how many registers? */ -#define ALL_TIME_REGS 7 -#define ALL_ALM_REGS 6 - - -#define RTC_SET_TIME_RETRIES 5 -#define RTC_GET_TIME_RETRIES 5 - - -struct rk808_rtc { - struct rk808 *rk808; - struct rtc_device *rtc; - unsigned int alarm_enabled:1; -}; - -/* - * Read current time and date in RTC - */ -static int rk808_rtc_readtime(struct device *dev, struct rtc_time *tm) -{ - struct rk808_rtc *rk808_rtc = dev_get_drvdata(dev); - struct rk808 *rk808 = rk808_rtc->rk808; - int ret; - unsigned char rtc_data[ALL_TIME_REGS + 1]; - u8 rtc_ctl; - - /*Dummy read*/ - ret = rk808_reg_read(rk808, RK808_RTC_CTRL_REG); - - /* Has the RTC been programmed? */ - ret = rk808_reg_read(rk808, RK808_RTC_CTRL_REG); - if (ret < 0) { - dev_err(dev, "Failed to read RTC control: %d\n", ret); - return ret; - } - - rtc_ctl = ret & (~BIT_RTC_CTRL_REG_RTC_V_OPT_M); - - ret = rk808_reg_write(rk808, RK808_RTC_CTRL_REG, rtc_ctl); - if (ret < 0) { - dev_err(dev, "Failed to write RTC control: %d\n", ret); - return ret; - } - -#if 0 - /* Read twice to make sure we don't read a corrupt, partially - * incremented, value. - */ - do { - ret = rk808_bulk_read(rk808, RK808_SECONDS_REG, - ALL_TIME_REGS, rtc_data); - if (ret != 0) - continue; - - tm->tm_sec = bcd2bin(rtc_data[0]); - tm->tm_min = bcd2bin(rtc_data[1]); - tm->tm_hour = bcd2bin(rtc_data[2]) ; - tm->tm_mday = bcd2bin(rtc_data[3]); - tm->tm_mon = bcd2bin(rtc_data[4]) - 1; - tm->tm_year = bcd2bin(rtc_data[5]) + 100; - tm->tm_wday = bcd2bin(rtc_data[6]); - - printk( "RTC date/time %4d-%02d-%02d(%d) %02d:%02d:%02d\n", - 1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday, tm->tm_wday, - tm->tm_hour, tm->tm_min, tm->tm_sec); - - return ret; - - } while (++count < RTC_GET_TIME_RETRIES); - dev_err(dev, "Timed out reading current time\n"); -#else - rtc_data[0] = rk808_reg_read(rk808,0x00); - rtc_data[1] = rk808_reg_read(rk808,0x01); - rtc_data[2] = rk808_reg_read(rk808,0x02); - rtc_data[3] = rk808_reg_read(rk808,0x03); - rtc_data[4] = rk808_reg_read(rk808,0x04); - rtc_data[5] = rk808_reg_read(rk808,0x05); - rtc_data[6] = rk808_reg_read(rk808,0x06); - - tm->tm_sec = bcd2bin(rtc_data[0]); - tm->tm_min = bcd2bin(rtc_data[1]); - tm->tm_hour = bcd2bin(rtc_data[2]) ; - tm->tm_mday = bcd2bin(rtc_data[3]); - tm->tm_mon = bcd2bin(rtc_data[4]) - 1; - tm->tm_year = bcd2bin(rtc_data[5]) + 100; - tm->tm_wday = bcd2bin(rtc_data[6]); - - dev_dbg(dev, "RTC date/time %4d-%02d-%02d(%d) %02d:%02d:%02d\n", - 1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday, tm->tm_wday,tm->tm_hour , tm->tm_min, tm->tm_sec); - -#endif - return 0; - -} - -/* - * Set current time and date in RTC - */ -static int rk808_rtc_set_time(struct device *dev, struct rtc_time *tm) -{ - struct rk808_rtc *rk808_rtc = dev_get_drvdata(dev); - struct rk808 *rk808 = rk808_rtc->rk808; - int ret; - u8 rtc_ctl; - unsigned char rtc_data[ALL_TIME_REGS + 1]; - - rtc_data[0] = bin2bcd(tm->tm_sec); - rtc_data[1] = bin2bcd(tm->tm_min); - rtc_data[2] = bin2bcd(tm->tm_hour ); - rtc_data[3] = bin2bcd(tm->tm_mday); - rtc_data[4] = bin2bcd(tm->tm_mon + 1); - rtc_data[5] = bin2bcd(tm->tm_year - 100); - rtc_data[6] = bin2bcd(tm->tm_wday); - - dev_dbg(dev, "set RTC date/time %4d-%02d-%02d(%d) %02d:%02d:%02d\n", - 1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday, tm->tm_wday,tm->tm_hour , tm->tm_min, tm->tm_sec); - - /*Dummy read*/ - ret = rk808_reg_read(rk808, RK808_RTC_CTRL_REG); - - /* Stop RTC while updating the TC registers */ - ret = rk808_reg_read(rk808, RK808_RTC_CTRL_REG); - if (ret < 0) { - dev_err(dev, "Failed to read RTC control: %d\n", ret); - return ret; - } - - rtc_ctl = ret | (BIT_RTC_CTRL_REG_STOP_RTC_M); - - ret = rk808_reg_write(rk808, RK808_RTC_CTRL_REG, rtc_ctl); - if (ret < 0) { - dev_err(dev, "Failed to write RTC control: %d\n", ret); - return ret; - } -#if 0 - /* update all the time registers in one shot */ - ret = rk808_bulk_write(rk808, RK808_SECONDS_REG, - ALL_TIME_REGS, rtc_data); - if (ret < 0) { - dev_err(dev, "Failed to read RTC times: %d\n", ret); - return ret; - } -#else - rk808_reg_write(rk808,0x00,rtc_data[0]); - rk808_reg_write(rk808,0x01,rtc_data[1]); - rk808_reg_write(rk808,0x02,rtc_data[2]); - rk808_reg_write(rk808,0x03,rtc_data[3]); - rk808_reg_write(rk808,0x04,rtc_data[4]); - rk808_reg_write(rk808,0x05,rtc_data[5]); - rk808_reg_write(rk808,0x06,rtc_data[6]); - -#endif - /*Dummy read*/ - ret = rk808_reg_read(rk808, RK808_RTC_CTRL_REG); - - /* Start RTC again */ - ret = rk808_reg_read(rk808, RK808_RTC_CTRL_REG); - if (ret < 0) { - dev_err(dev, "Failed to read RTC control: %d\n", ret); - return ret; - } - - rtc_ctl = ret &(~ BIT_RTC_CTRL_REG_STOP_RTC_M); - - ret = rk808_reg_write(rk808, RK808_RTC_CTRL_REG, rtc_ctl); - if (ret < 0) { - dev_err(dev, "Failed to write RTC control: %d\n", ret); - return ret; - } - - return 0; -} - -/* - * Read alarm time and date in RTC - */ -static int rk808_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm) -{ - struct rk808_rtc *rk808_rtc = dev_get_drvdata(dev); - int ret; - unsigned char alrm_data[ALL_ALM_REGS + 1]; -#if 0 - ret = rk808_bulk_read(rk808_rtc->rk808, RK808_ALARM_SECONDS_REG, - ALL_ALM_REGS, alrm_data); - if (ret != 0) { - dev_err(dev, "Failed to read alarm time: %d\n", ret); - return ret; - } -#else - alrm_data[0] = rk808_reg_read(rk808_rtc->rk808,0x08); - alrm_data[1] = rk808_reg_read(rk808_rtc->rk808,0x09); - alrm_data[2] = rk808_reg_read(rk808_rtc->rk808,0x0a); - alrm_data[3] = rk808_reg_read(rk808_rtc->rk808,0x0b); - alrm_data[4] = rk808_reg_read(rk808_rtc->rk808,0x0c); - alrm_data[5] = rk808_reg_read(rk808_rtc->rk808,0x0d); - - -#endif - /* some of these fields may be wildcard/"match all" */ - alrm->time.tm_sec = bcd2bin(alrm_data[0]); - alrm->time.tm_min = bcd2bin(alrm_data[1]); - alrm->time.tm_hour = bcd2bin(alrm_data[2]); - alrm->time.tm_mday = bcd2bin(alrm_data[3]); - alrm->time.tm_mon = bcd2bin(alrm_data[4]) - 1; - alrm->time.tm_year = bcd2bin(alrm_data[5]) + 100; - - ret = rk808_reg_read(rk808_rtc->rk808, RK808_RTC_INT_REG); - if (ret < 0) { - dev_err(dev, "Failed to read RTC control: %d\n", ret); - return ret; - } - dev_dbg(dev,"alrm read RTC date/time %4d-%02d-%02d(%d) %02d:%02d:%02d\n", - 1900 + alrm->time.tm_year, alrm->time.tm_mon + 1, alrm->time.tm_mday, alrm->time.tm_wday, alrm->time.tm_hour, alrm->time.tm_min, alrm->time.tm_sec); - - - - if (ret & BIT_RTC_INTERRUPTS_REG_IT_ALARM_M) - alrm->enabled = 1; - else - alrm->enabled = 0; - - return 0; -} - -static int rk808_rtc_stop_alarm(struct rk808_rtc *rk808_rtc) -{ - rk808_rtc->alarm_enabled = 0; - - return rk808_clear_bits(rk808_rtc->rk808, RK808_RTC_INT_REG, - BIT_RTC_INTERRUPTS_REG_IT_ALARM_M); - -} - -static int rk808_rtc_start_alarm(struct rk808_rtc *rk808_rtc) -{ - rk808_rtc->alarm_enabled = 1; - - return rk808_set_bits(rk808_rtc->rk808, RK808_RTC_INT_REG, - BIT_RTC_INTERRUPTS_REG_IT_ALARM_M,BIT_RTC_INTERRUPTS_REG_IT_ALARM_M); - -} - -static int rk808_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) -{ - struct rk808_rtc *rk808_rtc = dev_get_drvdata(dev); - int ret; - unsigned char alrm_data[ALL_TIME_REGS + 1]; - - ret = rk808_rtc_stop_alarm(rk808_rtc); - if (ret < 0) { - dev_err(dev, "Failed to stop alarm: %d\n", ret); - return ret; - } - - dev_dbg(dev,"alrm set RTC date/time %4d-%02d-%02d(%d) %02d:%02d:%02d\n", - 1900 + alrm->time.tm_year, alrm->time.tm_mon + 1, alrm->time.tm_mday, alrm->time.tm_wday, alrm->time.tm_hour, alrm->time.tm_min, alrm->time.tm_sec); - - alrm_data[0] = bin2bcd(alrm->time.tm_sec); - alrm_data[1] = bin2bcd(alrm->time.tm_min); - alrm_data[2] = bin2bcd(alrm->time.tm_hour ); - alrm_data[3] = bin2bcd(alrm->time.tm_mday); - alrm_data[4] = bin2bcd(alrm->time.tm_mon + 1); - alrm_data[5] = bin2bcd(alrm->time.tm_year - 100); -#if 0 - ret = rk808_bulk_write(rk808_rtc->rk808, RK808_ALARM_SECONDS_REG, - ALL_ALM_REGS, alrm_data); - if (ret != 0) { - dev_err(dev, "Failed to read alarm time: %d\n", ret); - return ret; - } -#else - rk808_reg_write(rk808_rtc->rk808,0x08,alrm_data[0]); - rk808_reg_write(rk808_rtc->rk808,0x09,alrm_data[1]); - rk808_reg_write(rk808_rtc->rk808,0x0a,alrm_data[2]); - rk808_reg_write(rk808_rtc->rk808,0x0b,alrm_data[3]); - rk808_reg_write(rk808_rtc->rk808,0x0c,alrm_data[4]); - rk808_reg_write(rk808_rtc->rk808,0x0d,alrm_data[5]); - -#endif - if (alrm->enabled) { - ret = rk808_rtc_start_alarm(rk808_rtc); - if (ret < 0) { - dev_err(dev, "Failed to start alarm: %d\n", ret); - return ret; - } - } - - return 0; -} - -static int rk808_rtc_alarm_irq_enable(struct device *dev, - unsigned int enabled) -{ - struct rk808_rtc *rk808_rtc = dev_get_drvdata(dev); - - if (enabled) - return rk808_rtc_start_alarm(rk808_rtc); - else - return rk808_rtc_stop_alarm(rk808_rtc); -} - -static int rk808_rtc_update_irq_enable(struct device *dev, - unsigned int enabled) -{ - struct rk808_rtc *rk808_rtc = dev_get_drvdata(dev); - - if (enabled) - return rk808_set_bits(rk808_rtc->rk808, RK808_RTC_INT_REG, - BIT_RTC_INTERRUPTS_REG_IT_TIMER_M,BIT_RTC_INTERRUPTS_REG_IT_TIMER_M); - else - return rk808_clear_bits(rk808_rtc->rk808, RK808_RTC_INT_REG, - BIT_RTC_INTERRUPTS_REG_IT_TIMER_M); -} - -/* - * We will just handle setting the frequency and make use the framework for - * reading the periodic interupts. - * - * @freq: Current periodic IRQ freq: - * bit 0: every second - * bit 1: every minute - * bit 2: every hour - * bit 3: every day - */ -#if 0 -static int rk808_rtc_irq_set_freq(struct device *dev, int freq) -{ - struct rk808_rtc *rk808_rtc = dev_get_drvdata(dev); - int ret; - u8 rtc_ctl; - - if (freq < 0 || freq > 3) - return -EINVAL; - - ret = rk808_reg_read(rk808_rtc->rk808, RK808_RTC_INT_REG); - if (ret < 0) { - dev_err(dev, "Failed to read RTC interrupt: %d\n", ret); - return ret; - } - - rtc_ctl = ret | freq; - - ret = rk808_reg_write(rk808_rtc->rk808, RK808_RTC_INT_REG, rtc_ctl); - if (ret < 0) { - dev_err(dev, "Failed to write RTC control: %d\n", ret); - return ret; - } - - return ret; -} -#endif -static irqreturn_t rk808_alm_irq(int irq, void *data) -{ - struct rk808_rtc *rk808_rtc = data; - int ret; - u8 rtc_ctl; - - /*Dummy read -- mandatory for status register*/ - ret = rk808_reg_read(rk808_rtc->rk808, RK808_RTC_STATUS_REG); - if (ret < 0) { - printk("%s:Failed to read RTC status: %d\n", __func__, ret); - return ret; - } - - ret = rk808_reg_read(rk808_rtc->rk808, RK808_RTC_STATUS_REG); - if (ret < 0) { - printk("%s:Failed to read RTC status: %d\n", __func__, ret); - return ret; - } - rtc_ctl = ret&0xff; - - //The alarm interrupt keeps its low level, until the micro-controller write 1 in the ALARM bit of the RTC_STATUS_REG register. - ret = rk808_reg_write(rk808_rtc->rk808, RK808_RTC_STATUS_REG,rtc_ctl); - if (ret < 0) { - printk("%s:Failed to read RTC status: %d\n", __func__, ret); - return ret; - } - - rtc_update_irq(rk808_rtc->rtc, 1, RTC_IRQF | RTC_AF); - - printk("%s:irq=%d,rtc_ctl=0x%x\n",__func__,irq,rtc_ctl); - return IRQ_HANDLED; -} - -static irqreturn_t rk808_per_irq(int irq, void *data) -{ - struct rk808_rtc *rk808_rtc = data; - - rtc_update_irq(rk808_rtc->rtc, 1, RTC_IRQF | RTC_UF); - - //printk("%s:irq=%d\n",__func__,irq); - return IRQ_HANDLED; -} - -static const struct rtc_class_ops rk808_rtc_ops = { - .read_time = rk808_rtc_readtime, - //.set_mmss = rk808_rtc_set_mmss, - .set_time = rk808_rtc_set_time, - .read_alarm = rk808_rtc_readalarm, - .set_alarm = rk808_rtc_setalarm, - .alarm_irq_enable = rk808_rtc_alarm_irq_enable, - //.update_irq_enable = rk808_rtc_update_irq_enable, - //.irq_set_freq = rk808_rtc_irq_set_freq, -}; - -#ifdef CONFIG_PM -/* Turn off the alarm if it should not be a wake source. */ -static int rk808_rtc_suspend(struct device *dev) -{ - struct platform_device *pdev = to_platform_device(dev); - struct rk808_rtc *rk808_rtc = dev_get_drvdata(&pdev->dev); - int ret; - - if (rk808_rtc->alarm_enabled && device_may_wakeup(&pdev->dev)) - ret = rk808_rtc_start_alarm(rk808_rtc); - else - ret = rk808_rtc_stop_alarm(rk808_rtc); - - if (ret < 0) - dev_err(&pdev->dev, "Failed to update RTC alarm: %d\n", ret); - - return 0; -} - -/* Enable the alarm if it should be enabled (in case it was disabled to - * prevent use as a wake source). - */ -static int rk808_rtc_resume(struct device *dev) -{ - struct platform_device *pdev = to_platform_device(dev); - struct rk808_rtc *rk808_rtc = dev_get_drvdata(&pdev->dev); - int ret; - - if (rk808_rtc->alarm_enabled) { - ret = rk808_rtc_start_alarm(rk808_rtc); - if (ret <0) - dev_err(&pdev->dev, - "Failed to restart RTC alarm: %d\n", ret); - } - - return 0; -} - -/* Unconditionally disable the alarm */ -static int rk808_rtc_freeze(struct device *dev) -{ - struct platform_device *pdev = to_platform_device(dev); - struct rk808_rtc *rk808_rtc = dev_get_drvdata(&pdev->dev); - int ret; - - ret = rk808_rtc_stop_alarm(rk808_rtc); - if (ret < 0) - dev_err(&pdev->dev, "Failed to stop RTC alarm: %d\n", ret); - - return 0; -} -#else -#define rk808_rtc_suspend NULL -#define rk808_rtc_resume NULL -#define rk808_rtc_freeze NULL -#endif -extern struct rk808 *g_rk808; -struct platform_device *rk808_pdev; -struct rtc_time tm_def = { // 2012.1.1 12:00:00 Saturday - .tm_wday = 6, - .tm_year = 112, - .tm_mon = 0, - .tm_mday = 1, - .tm_hour = 12, - .tm_min = 0, - .tm_sec = 0, -}; - -static int rk808_rtc_probe(struct platform_device *pdev) -{ - struct rk808 *rk808 = dev_get_drvdata(pdev->dev.parent); - struct rk808_rtc *rk808_rtc; - struct rtc_time tm; - int per_irq; - int alm_irq; - int ret = 0; - u8 rtc_ctl; - - printk("%s,line=%d\n", __func__,__LINE__); - - rk808_rtc = kzalloc(sizeof(*rk808_rtc), GFP_KERNEL); - if (rk808_rtc == NULL) - return -ENOMEM; - - platform_set_drvdata(pdev, rk808_rtc); - rk808_rtc->rk808 = rk808; - - /* Take rtc out of reset */ - /* - ret = rk808_reg_read(rk808, RK808_DEVCTRL); - if (ret < 0) { - dev_err(&pdev->dev, "Failed to read RK808_DEVCTRL: %d\n", ret); - return ret; - } - - if(ret & BIT_RTC_PWDN) - { - rtc_ctl = ret & (~BIT_RTC_PWDN); - - ret = rk808_reg_write(rk808, RK808_DEVCTRL, rtc_ctl); - if (ret < 0) { - dev_err(&pdev->dev, "Failed to write RTC control: %d\n", ret); - return ret; - } - } - */ - /*start rtc default*/ - ret = rk808_reg_read(rk808, RK808_RTC_CTRL_REG); - if (ret < 0) { - dev_err(&pdev->dev, "Failed to read RTC control: %d\n", ret); - return ret; - } - rtc_ctl = ret & (~BIT_RTC_CTRL_REG_STOP_RTC_M); - - ret = rk808_reg_write(rk808, RK808_RTC_CTRL_REG, rtc_ctl); - if (ret < 0) { - dev_err(&pdev->dev, "Failed to write RTC control: %d\n", ret); - return ret; - } - - ret = rk808_reg_read(rk808, RK808_RTC_STATUS_REG); - if (ret < 0) { - dev_err(&pdev->dev, "Failed to read RTC status: %d\n", ret); - return ret; - } - rk808_reg_write(rk808,RK808_RTC_STATUS_REG,0xfe); - /*set init time*/ - - ret = rk808_rtc_readtime(&pdev->dev, &tm); - if (ret<0) - { - dev_err(&pdev->dev, "Failed to read RTC time\n"); - return ret; - } - - ret = rtc_valid_tm(&tm); - if (ret) { - dev_err(&pdev->dev,"invalid date/time and init time\n"); - rk808_rtc_set_time(&pdev->dev, &tm_def); // 2012-01-01 12:00:00 -// DBG( "set RTC date/time %4d-%02d-%02d(%d) %02d:%02d:%02d\n",1900 + tm_def.tm_year, tm_def.tm_mon + 1, tm_def.tm_mday, tm_def.tm_wday,tm_def.tm_hour, tm_def.tm_min, tm_def.tm_sec); - } - - device_init_wakeup(&pdev->dev, 1); - - rk808_rtc->rtc = rtc_device_register("rk808", &pdev->dev, - &rk808_rtc_ops, THIS_MODULE); - if (IS_ERR(rk808_rtc->rtc)) { - ret = PTR_ERR(rk808_rtc->rtc); - goto err; - } - - per_irq = irq_create_mapping(rk808->irq_domain, RK808_IRQ_RTC_PERIOD); - alm_irq = irq_create_mapping(rk808->irq_domain, RK808_IRQ_RTC_ALARM); - - /*request rtc and alarm irq of rk808*/ - ret = devm_request_threaded_irq(rk808->dev,per_irq, NULL, rk808_per_irq, - IRQF_TRIGGER_RISING, "RTC period", - rk808_rtc); - if (ret != 0) { - dev_err(&pdev->dev, "Failed to request periodic IRQ %d: %d\n", - per_irq, ret); - } - - ret = devm_request_threaded_irq(rk808->dev,alm_irq, NULL, rk808_alm_irq, - IRQF_TRIGGER_RISING, "RTC alarm", - rk808_rtc); - if (ret != 0) { - dev_err(&pdev->dev, "Failed to request alarm IRQ %d: %d\n", - alm_irq, ret); - } - - //for rtc irq test - /* - rk808_set_bits(rk808_rtc->rk808, RK808_RTC_STATUS_REG,(0x1<< 6),(0x1 <<6)); - rk808_set_bits(rk808_rtc->rk808, RK808_RTC_INT_REG,0x0c,0x0c); - rk808_set_bits(rk808_rtc->rk808,RK808_INT_STS_REG1,(0x3 << 5),(0x3 <<5)); - rk808_set_bits(rk808_rtc->rk808, RK808_INT_STS_MSK_REG1,(0x3 <<5),0); -*/ - -// enable_irq_wake(alm_irq); // so rk808 alarm irq can wake up system - rk808_pdev = pdev; - - printk("%s:ok\n",__func__); - - return 0; - -err: - kfree(rk808_rtc); - return ret; -} - -static int rk808_rtc_remove(struct platform_device *pdev) -{ - struct rk808_rtc *rk808_rtc = platform_get_drvdata(pdev); - int per_irq = rk808_rtc->rk808->irq_base + RK808_IRQ_RTC_PERIOD; - int alm_irq = rk808_rtc->rk808->irq_base + RK808_IRQ_RTC_ALARM; - - free_irq(alm_irq, rk808_rtc); - free_irq(per_irq, rk808_rtc); - rtc_device_unregister(rk808_rtc->rtc); - kfree(rk808_rtc); - - return 0; -} - -static const struct dev_pm_ops rk808_rtc_pm_ops = { - .suspend = rk808_rtc_suspend, - .resume = rk808_rtc_resume, - - .freeze = rk808_rtc_freeze, - .thaw = rk808_rtc_resume, - .restore = rk808_rtc_resume, - - .poweroff = rk808_rtc_suspend, -}; - -static struct platform_driver rk808_rtc_driver = { - .probe = rk808_rtc_probe, - .remove = rk808_rtc_remove, - .driver = { - .name = "rk808-rtc", - .pm = &rk808_rtc_pm_ops, - }, -}; - -static ssize_t rtc_rk808_test_write(struct file *file, - const char __user *buf, size_t count, loff_t *offset) -{ - char nr_buf[8]; - int nr = 0, ret; - struct platform_device *pdev; - struct rtc_time tm; - struct rtc_wkalrm alrm; - struct rk808_rtc *rk808_rtc; - - if(count > 3) - return -EFAULT; - ret = copy_from_user(nr_buf, buf, count); - if(ret < 0) - return -EFAULT; - - sscanf(nr_buf, "%d", &nr); - if(nr > 5 || nr < 0) - { - printk("%s:data is error\n",__func__); - return -EFAULT; - } - - if(!rk808_pdev) - return -EFAULT; - else - pdev = rk808_pdev; - - - rk808_rtc = dev_get_drvdata(&pdev->dev); - - //test rtc time - if(nr == 0) - { - tm.tm_wday = 6; - tm.tm_year = 111; - tm.tm_mon = 0; - tm.tm_mday = 1; - tm.tm_hour = 12; - tm.tm_min = 0; - tm.tm_sec = 0; - - ret = rk808_rtc_set_time(&pdev->dev, &tm); // 2011-01-01 12:00:00 - if (ret) - { - dev_err(&pdev->dev, "Failed to set RTC time\n"); - return -EFAULT; - } - - } - - /*set init time*/ - ret = rk808_rtc_readtime(&pdev->dev, &tm); - if (ret) - dev_err(&pdev->dev, "Failed to read RTC time\n"); - else - dev_info(&pdev->dev, "RTC date/time %4d-%02d-%02d(%d) %02d:%02d:%02d\n", - 1900 + tm.tm_year, tm.tm_mon + 1, tm.tm_mday, tm.tm_wday, - tm.tm_hour, tm.tm_min, tm.tm_sec); - - if(!ret) - printk("%s:ok\n",__func__); - else - printk("%s:error\n",__func__); - - - //test rtc alarm - if(nr == 2) - { - //2000-01-01 00:00:30 - if(tm.tm_sec < 30) - { - alrm.time.tm_sec = tm.tm_sec+30; - alrm.time.tm_min = tm.tm_min; - } - else - { - alrm.time.tm_sec = tm.tm_sec-30; - alrm.time.tm_min = tm.tm_min+1; - } - alrm.time.tm_hour = tm.tm_hour; - alrm.time.tm_mday = tm.tm_mday; - alrm.time.tm_mon = tm.tm_mon; - alrm.time.tm_year = tm.tm_year; - rk808_rtc_alarm_irq_enable(&pdev->dev, 1); - rk808_rtc_setalarm(&pdev->dev, &alrm); - - dev_info(&pdev->dev, "Set alarm %4d-%02d-%02d(%d) %02d:%02d:%02d\n", - 1900 + alrm.time.tm_year, alrm.time.tm_mon + 1, alrm.time.tm_mday, alrm.time.tm_wday, - alrm.time.tm_hour, alrm.time.tm_min, alrm.time.tm_sec); - } - - - if(nr == 3) - { - ret = rk808_reg_read(rk808_rtc->rk808, RK808_RTC_STATUS_REG); - if (ret < 0) { - printk("%s:Failed to read RTC status: %d\n", __func__, ret); - return ret; - } - printk("%s:ret=0x%x\n",__func__,ret&0xff); - - ret = rk808_reg_write(rk808_rtc->rk808, RK808_RTC_STATUS_REG, ret&0xff); - if (ret < 0) { - printk("%s:Failed to read RTC status: %d\n", __func__, ret); - return ret; - } - } - - if(nr == 4) - rk808_rtc_update_irq_enable(&pdev->dev, 1); - - if(nr == 5) - rk808_rtc_update_irq_enable(&pdev->dev, 0); - - return count; -} - -static const struct file_operations rtc_rk808_test_fops = { - .write = rtc_rk808_test_write, -}; - -static struct miscdevice rtc_rk808_test_misc = { - .minor = MISC_DYNAMIC_MINOR, - .name = "rtc_rk808_test", - .fops = &rtc_rk808_test_fops, -}; - - -static int __init rk808_rtc_init(void) -{ - misc_register(&rtc_rk808_test_misc); - return platform_driver_register(&rk808_rtc_driver); -} -subsys_initcall_sync(rk808_rtc_init); - -static void __exit rk808_rtc_exit(void) -{ - misc_deregister(&rtc_rk808_test_misc); - platform_driver_unregister(&rk808_rtc_driver); -} -module_exit(rk808_rtc_exit); - -MODULE_DESCRIPTION("RTC driver for the rk808 series PMICs"); -MODULE_AUTHOR("ZHANGQING "); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:rk808-rtc"); diff --git a/include/linux/mfd/rk-rk808.h b/include/linux/mfd/rk-rk808.h new file mode 100644 index 000000000000..f59f327ca80b --- /dev/null +++ b/include/linux/mfd/rk-rk808.h @@ -0,0 +1,191 @@ +/* include/linux/regulator/rk808.h + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ +#ifndef __LINUX_REGULATOR_rk808_H +#define __LINUX_REGULATOR_rk808_H + +#include +#include +#include +#ifdef CONFIG_HAS_EARLYSUSPEND +#include +#endif +//#define RK808_START 30 + +#define RK808_DCDC1 0 //(0+RK808_START) + +#define RK808_LDO1 4 //(4+RK808_START) + +#define RK808_SECONDS_REG 0x00 +#define RK808_MINUTES_REG 0x01 +#define RK808_HOURS_REG 0x02 +#define RK808_DAYS_REG 0x03 +#define RK808_MONTHS_REG 0x04 +#define RK808_YEARS_REG 0x05 +#define RK808_WEEKS_REG 0x06 +#define RK808_ALARM_SECONDS_REG 0x07 +#define RK808_ALARM_MINUTES_REG 0x08 +#define RK808_ALARM_HOURS_REG 0x09 +#define RK808_ALARM_DAYS_REG 0x0a +#define RK808_ALARM_MONTHS_REG 0x0b +#define RK808_ALARM_YEARS_REG 0x0c +#define RK808_RTC_CTRL_REG 0x10 +#define RK808_RTC_STATUS_REG 0x11 +#define RK808_RTC_INT_REG 0x12 +#define RK808_RTC_COMP_LSB_REG 0x13 +#define RK808_RTC_COMP_MSB_REG 0x14 +#define RK808_CLK32OUT_REG 0x20 +#define RK808_VB_MON_REG 0x21 +#define RK808_THERMAL_REG 0x22 +#define RK808_DCDC_EN_REG 0x23 +#define RK808_LDO_EN_REG 0x24 +#define RK808_SLEEP_SET_OFF_REG1 0x25 +#define RK808_SLEEP_SET_OFF_REG2 0x26 +#define RK808_DCDC_UV_STS_REG 0x27 +#define RK808_DCDC_UV_ACT_REG 0x28 +#define RK808_LDO_UV_STS_REG 0x29 +#define RK808_LDO_UV_ACT_REG 0x2a +#define RK808_DCDC_PG_REG 0x2b +#define RK808_LDO_PG_REG 0x2c +#define RK808_VOUT_MON_TDB_REG 0x2d +#define RK808_BUCK1_CONFIG_REG 0x2e +#define RK808_BUCK1_ON_REG 0x2f +#define RK808_BUCK1_SLP_REG 0x30 +#define RK808_BUCK1_DVS_REG 0x31 +#define RK808_BUCK2_CONFIG_REG 0x32 +#define RK808_BUCK2_ON_REG 0x33 +#define RK808_BUCK2_SLP_REG 0x34 +#define RK808_BUCK2_DVS_REG 0x35 +#define RK808_BUCK3_CONFIG_REG 0x36 +#define RK808_BUCK4_CONFIG_REG 0x37 +#define RK808_BUCK4_ON_REG 0x38 +#define RK808_BUCK4_SLP_VSEL_REG 0x39 +#define RK808_BOOST_CONFIG_REG 0x3a +#define RK808_LDO1_ON_VSEL_REG 0x3b +#define RK808_LDO1_SLP_VSEL_REG 0x3c +#define RK808_LDO2_ON_VSEL_REG 0x3d +#define RK808_LDO2_SLP_VSEL_REG 0x3e +#define RK808_LDO3_ON_VSEL_REG 0x3f +#define RK808_LDO3_SLP_VSEL_REG 0x40 +#define RK808_LDO4_ON_VSEL_REG 0x41 +#define RK808_LDO4_SLP_VSEL_REG 0x42 +#define RK808_LDO5_ON_VSEL_REG 0x43 +#define RK808_LDO5_SLP_VSEL_REG 0x44 +#define RK808_LDO6_ON_VSEL_REG 0x45 +#define RK808_LDO6_SLP_VSEL_REG 0x46 +#define RK808_LDO7_ON_VSEL_REG 0x47 +#define RK808_LDO7_SLP_VSEL_REG 0x48 +#define RK808_LDO8_ON_VSEL_REG 0x49 +#define RK808_LDO8_SLP_VSEL_REG 0x4a +#define RK808_DEVCTRL_REG 0x4b +#define RK808_INT_STS_REG1 0X4c +#define RK808_INT_STS_MSK_REG1 0X4d +#define RK808_INT_STS_REG2 0X4e +#define RK808_INT_STS_MSK_REG2 0X4f +#define RK808_IO_POL_REG 0X50 + +/* IRQ Definitions */ +#define RK808_IRQ_VOUT_LO 0 +#define RK808_IRQ_VB_LO 1 +#define RK808_IRQ_PWRON 2 +#define RK808_IRQ_PWRON_LP 3 +#define RK808_IRQ_HOTDIE 4 +#define RK808_IRQ_RTC_ALARM 5 +#define RK808_IRQ_RTC_PERIOD 6 + +#define RK808_NUM_IRQ 9 + +#define rk808_NUM_REGULATORS 14 + +#define RK808_VBAT_LOW_2V8 0x00 +#define RK808_VBAT_LOW_2V9 0x01 +#define RK808_VBAT_LOW_3V0 0x02 +#define RK808_VBAT_LOW_3V1 0x03 +#define RK808_VBAT_LOW_3V2 0x04 +#define RK808_VBAT_LOW_3V3 0x05 +#define RK808_VBAT_LOW_3V4 0x06 +#define RK808_VBAT_LOW_3V5 0x07 +#define VBAT_LOW_VOL_MASK (0x07 << 0) +#define EN_VABT_LOW_SHUT_DOWN (0x00 << 4) +#define EN_VBAT_LOW_IRQ (0x1 <<4 ) +#define VBAT_LOW_ACT_MASK (0x1 << 4) + +struct rk808; + +struct rk808_board { + int irq; + int irq_base; + int irq_gpio; + int wakeup; + struct regulator_init_data *rk808_init_data[rk808_NUM_REGULATORS]; + struct device_node *of_node[rk808_NUM_REGULATORS]; + int pmic_sleep_gpio; /* */ + unsigned int dcdc_slp_voltage[3]; /* buckx_voltage in uV */ + bool pmic_sleep; + unsigned int ldo_slp_voltage[7]; + bool pm_off; +}; + +struct rk808_regulator_subdev { + int id; + struct regulator_init_data *initdata; +}; + +struct rk808 { + struct device *dev; + struct mutex io_lock; + struct i2c_client *i2c; + int num_regulators; + struct regulator_dev **rdev; + struct wake_lock irq_wake; +// struct early_suspend rk808_suspend; + struct mutex irq_lock; + int irq_base; + int irq_num; + int chip_irq; + int irq_gpio; + int wakeup; + u32 irq_mask; + struct regmap *regmap; + struct irq_domain *irq_domain; + int (*read)(struct rk808 *rk808, u8 reg, int size, void *dest); + int (*write)(struct rk808 *rk808, u8 reg, int size, void *src); + int pmic_sleep_gpio; /* */ + unsigned int dcdc_slp_voltage[3]; /* buckx_voltage in uV */ + bool pmic_sleep; + unsigned int ldo_slp_voltage[7]; +}; + +struct rk808_platform_data { + int num_regulators; + struct rk808_regulator_subdev *regulators; + int irq; + int irq_base; + struct irq_domain *irq_domain; +}; + +int rk808_irq_init(struct rk808 *rk808, int irq,struct rk808_board *pdata); + int rk808_i2c_read(struct rk808 *rk808, char reg, int count,u8 *dest); +//int rk808_i2c_read(struct i2c_client *i2c, char reg, int count,u16 *dest); +// int rk808_i2c_read(struct rk808 *rk808 , u8 reg, int bytes,void *dest); +int rk808_i2c_write(struct rk808 *rk808, char reg, int count, const u8 src); +int rk808_set_bits(struct rk808 *rk808, u8 reg, u8 mask, u8 val); +int rk808_clear_bits(struct rk808 *rk808, u8 reg, u8 mask); +int rk808_reg_read(struct rk808 *rk808, u8 reg); +int rk808_reg_write(struct rk808 *rk808, u8 reg, u8 val); +int rk808_bulk_read(struct rk808 *rk808, u8 reg, + int count, u8 *buf); +int rk808_bulk_write(struct rk808 *rk808, u8 reg, + int count, u8 *buf); + +#endif + diff --git a/include/linux/mfd/rk808.h b/include/linux/mfd/rk808.h deleted file mode 100644 index f59f327ca80b..000000000000 --- a/include/linux/mfd/rk808.h +++ /dev/null @@ -1,191 +0,0 @@ -/* include/linux/regulator/rk808.h - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ -#ifndef __LINUX_REGULATOR_rk808_H -#define __LINUX_REGULATOR_rk808_H - -#include -#include -#include -#ifdef CONFIG_HAS_EARLYSUSPEND -#include -#endif -//#define RK808_START 30 - -#define RK808_DCDC1 0 //(0+RK808_START) - -#define RK808_LDO1 4 //(4+RK808_START) - -#define RK808_SECONDS_REG 0x00 -#define RK808_MINUTES_REG 0x01 -#define RK808_HOURS_REG 0x02 -#define RK808_DAYS_REG 0x03 -#define RK808_MONTHS_REG 0x04 -#define RK808_YEARS_REG 0x05 -#define RK808_WEEKS_REG 0x06 -#define RK808_ALARM_SECONDS_REG 0x07 -#define RK808_ALARM_MINUTES_REG 0x08 -#define RK808_ALARM_HOURS_REG 0x09 -#define RK808_ALARM_DAYS_REG 0x0a -#define RK808_ALARM_MONTHS_REG 0x0b -#define RK808_ALARM_YEARS_REG 0x0c -#define RK808_RTC_CTRL_REG 0x10 -#define RK808_RTC_STATUS_REG 0x11 -#define RK808_RTC_INT_REG 0x12 -#define RK808_RTC_COMP_LSB_REG 0x13 -#define RK808_RTC_COMP_MSB_REG 0x14 -#define RK808_CLK32OUT_REG 0x20 -#define RK808_VB_MON_REG 0x21 -#define RK808_THERMAL_REG 0x22 -#define RK808_DCDC_EN_REG 0x23 -#define RK808_LDO_EN_REG 0x24 -#define RK808_SLEEP_SET_OFF_REG1 0x25 -#define RK808_SLEEP_SET_OFF_REG2 0x26 -#define RK808_DCDC_UV_STS_REG 0x27 -#define RK808_DCDC_UV_ACT_REG 0x28 -#define RK808_LDO_UV_STS_REG 0x29 -#define RK808_LDO_UV_ACT_REG 0x2a -#define RK808_DCDC_PG_REG 0x2b -#define RK808_LDO_PG_REG 0x2c -#define RK808_VOUT_MON_TDB_REG 0x2d -#define RK808_BUCK1_CONFIG_REG 0x2e -#define RK808_BUCK1_ON_REG 0x2f -#define RK808_BUCK1_SLP_REG 0x30 -#define RK808_BUCK1_DVS_REG 0x31 -#define RK808_BUCK2_CONFIG_REG 0x32 -#define RK808_BUCK2_ON_REG 0x33 -#define RK808_BUCK2_SLP_REG 0x34 -#define RK808_BUCK2_DVS_REG 0x35 -#define RK808_BUCK3_CONFIG_REG 0x36 -#define RK808_BUCK4_CONFIG_REG 0x37 -#define RK808_BUCK4_ON_REG 0x38 -#define RK808_BUCK4_SLP_VSEL_REG 0x39 -#define RK808_BOOST_CONFIG_REG 0x3a -#define RK808_LDO1_ON_VSEL_REG 0x3b -#define RK808_LDO1_SLP_VSEL_REG 0x3c -#define RK808_LDO2_ON_VSEL_REG 0x3d -#define RK808_LDO2_SLP_VSEL_REG 0x3e -#define RK808_LDO3_ON_VSEL_REG 0x3f -#define RK808_LDO3_SLP_VSEL_REG 0x40 -#define RK808_LDO4_ON_VSEL_REG 0x41 -#define RK808_LDO4_SLP_VSEL_REG 0x42 -#define RK808_LDO5_ON_VSEL_REG 0x43 -#define RK808_LDO5_SLP_VSEL_REG 0x44 -#define RK808_LDO6_ON_VSEL_REG 0x45 -#define RK808_LDO6_SLP_VSEL_REG 0x46 -#define RK808_LDO7_ON_VSEL_REG 0x47 -#define RK808_LDO7_SLP_VSEL_REG 0x48 -#define RK808_LDO8_ON_VSEL_REG 0x49 -#define RK808_LDO8_SLP_VSEL_REG 0x4a -#define RK808_DEVCTRL_REG 0x4b -#define RK808_INT_STS_REG1 0X4c -#define RK808_INT_STS_MSK_REG1 0X4d -#define RK808_INT_STS_REG2 0X4e -#define RK808_INT_STS_MSK_REG2 0X4f -#define RK808_IO_POL_REG 0X50 - -/* IRQ Definitions */ -#define RK808_IRQ_VOUT_LO 0 -#define RK808_IRQ_VB_LO 1 -#define RK808_IRQ_PWRON 2 -#define RK808_IRQ_PWRON_LP 3 -#define RK808_IRQ_HOTDIE 4 -#define RK808_IRQ_RTC_ALARM 5 -#define RK808_IRQ_RTC_PERIOD 6 - -#define RK808_NUM_IRQ 9 - -#define rk808_NUM_REGULATORS 14 - -#define RK808_VBAT_LOW_2V8 0x00 -#define RK808_VBAT_LOW_2V9 0x01 -#define RK808_VBAT_LOW_3V0 0x02 -#define RK808_VBAT_LOW_3V1 0x03 -#define RK808_VBAT_LOW_3V2 0x04 -#define RK808_VBAT_LOW_3V3 0x05 -#define RK808_VBAT_LOW_3V4 0x06 -#define RK808_VBAT_LOW_3V5 0x07 -#define VBAT_LOW_VOL_MASK (0x07 << 0) -#define EN_VABT_LOW_SHUT_DOWN (0x00 << 4) -#define EN_VBAT_LOW_IRQ (0x1 <<4 ) -#define VBAT_LOW_ACT_MASK (0x1 << 4) - -struct rk808; - -struct rk808_board { - int irq; - int irq_base; - int irq_gpio; - int wakeup; - struct regulator_init_data *rk808_init_data[rk808_NUM_REGULATORS]; - struct device_node *of_node[rk808_NUM_REGULATORS]; - int pmic_sleep_gpio; /* */ - unsigned int dcdc_slp_voltage[3]; /* buckx_voltage in uV */ - bool pmic_sleep; - unsigned int ldo_slp_voltage[7]; - bool pm_off; -}; - -struct rk808_regulator_subdev { - int id; - struct regulator_init_data *initdata; -}; - -struct rk808 { - struct device *dev; - struct mutex io_lock; - struct i2c_client *i2c; - int num_regulators; - struct regulator_dev **rdev; - struct wake_lock irq_wake; -// struct early_suspend rk808_suspend; - struct mutex irq_lock; - int irq_base; - int irq_num; - int chip_irq; - int irq_gpio; - int wakeup; - u32 irq_mask; - struct regmap *regmap; - struct irq_domain *irq_domain; - int (*read)(struct rk808 *rk808, u8 reg, int size, void *dest); - int (*write)(struct rk808 *rk808, u8 reg, int size, void *src); - int pmic_sleep_gpio; /* */ - unsigned int dcdc_slp_voltage[3]; /* buckx_voltage in uV */ - bool pmic_sleep; - unsigned int ldo_slp_voltage[7]; -}; - -struct rk808_platform_data { - int num_regulators; - struct rk808_regulator_subdev *regulators; - int irq; - int irq_base; - struct irq_domain *irq_domain; -}; - -int rk808_irq_init(struct rk808 *rk808, int irq,struct rk808_board *pdata); - int rk808_i2c_read(struct rk808 *rk808, char reg, int count,u8 *dest); -//int rk808_i2c_read(struct i2c_client *i2c, char reg, int count,u16 *dest); -// int rk808_i2c_read(struct rk808 *rk808 , u8 reg, int bytes,void *dest); -int rk808_i2c_write(struct rk808 *rk808, char reg, int count, const u8 src); -int rk808_set_bits(struct rk808 *rk808, u8 reg, u8 mask, u8 val); -int rk808_clear_bits(struct rk808 *rk808, u8 reg, u8 mask); -int rk808_reg_read(struct rk808 *rk808, u8 reg); -int rk808_reg_write(struct rk808 *rk808, u8 reg, u8 val); -int rk808_bulk_read(struct rk808 *rk808, u8 reg, - int count, u8 *buf); -int rk808_bulk_write(struct rk808 *rk808, u8 reg, - int count, u8 *buf); - -#endif -