static int d2041_regulator_disable(struct regulator_dev *rdev) { struct d2041 *d2041 = rdev_get_drvdata(rdev); unsigned int regulator_id = rdev_get_id(rdev); unsigned int reg_num = 0; int ret = 0; u8 reg_val; if (regulator_id >= D2041_NUMBER_OF_REGULATORS) return -EINVAL; if(!is_mode_control_enabled()){ reg_num = get_regulator_reg(regulator_id); d2041_reg_read(d2041, reg_num, ®_val); reg_val &= ~(1<<6); d2041_reg_write(d2041, reg_num, reg_val); }else{ reg_num = get_regulator_mctl_reg(regulator_id); /* 0x00 == D2041_REGULATOR_MCTL0_OFF | D2041_REGULATOR_MCTL1_OFF * | D2041_REGULATOR_MCTL2_OFF | D2041_REGULATOR_MCTL3_OFF */ ret = d2041_reg_write(d2041, reg_num, 0x00); } return ret; }
static unsigned int get_regulator_mctl_mode(struct d2041 *d2041, int regulator_id) { //TODO: Make sure we can assume we have always current value in the buffer and do this: u8 reg_val, regulator_mctl_reg = get_regulator_mctl_reg(regulator_id); int ret = 0; ret = d2041_reg_read(d2041, regulator_mctl_reg, ®_val); reg_val &= D2041_REGULATOR_MCTL0; reg_val >>= MCTL0_SHIFT; return reg_val; }
int __init d2041_platform_regulator_init(struct d2041 *d2041) { int i; u8 reg_val=0; for(i = D2041_BUCK_1; i < D2041_NUMBER_OF_REGULATORS; i++) { if (d2041->pdata != NULL && d2041->pdata->regulator_data != NULL && d2041->pdata->regulator_data[i].supply != NULL) { d2041_regulators_init_data[i].consumer_supplies = &d2041->pdata->regulator_data[i]; d2041_regulators_init_data[i].num_consumer_supplies = 1; dev_info(d2041->dev, "No consumers for regulator %s\n", d2041_regulators_init_data[i].constraints.name); } d2041_register_regulator(d2041, i, &(d2041_regulators_init_data[i])); regulator_register_map[i].dsm_opmode = d2041->pdata->regl_map[i].default_pm_mode; if(i >= D2041_BUCK_1) { d2041_reg_write(d2041, get_regulator_mctl_reg(i), d2041->pdata->regl_map[i].dsm_opmode); } } // set MISC_MCTL /* reg_val = (D2041_MISC_MCTL3_DIGICLK | D2041_MISC_MCTL2_DIGICLK | D2041_MISC_MCTL1_DIGICLK | D2041_MISC_MCTL0_DIGICLK | D2041_MISC_MCTL3_BBAT | D2041_MISC_MCTL2_BBAT | D2041_MISC_MCTL1_BBAT | D2041_MISC_MCTL0_BBAT); */ reg_val = 0x0F; d2041_reg_write(d2041_regl_info, D2041_MISC_MCTL_REG, reg_val); d2041_reg_write(d2041_regl_info, D2041_BUCK1_TURBO_REG, D2041_BUCK1_NM_VOLT); d2041_reg_write(d2041_regl_info, D2041_BUCK1_RETENTION_REG, D2041_BUCK1_RETENTION_VOLT); // set AUD_LDO to 2.5v d2041_reg_write(d2041_regl_info, D2041_LDO_AUD_REG, 0x5A); // sim_vcc(LDO11) -> default 1.8v d2041_reg_write(d2041_regl_info, D2041_LDO11_REG, 0xC); // LDO_AUD pull-down disable d2041_reg_write(d2041_regl_info, D2041_PULLDOWN_REG_D, (1<<0)); return 0; }
static int d2041_regulator_enable(struct regulator_dev *rdev) { struct d2041 *d2041 = rdev_get_drvdata(rdev); u8 reg_val; int ret = 0; unsigned int regulator_id = rdev_get_id(rdev); unsigned int reg_num; if (regulator_id >= D2041_NUMBER_OF_REGULATORS) return -EINVAL; if(!is_mode_control_enabled()){ reg_num = get_regulator_reg(regulator_id); d2041_reg_read(d2041, reg_num, ®_val); reg_val |= (1<<6); ret = d2041_reg_write(d2041, reg_num,reg_val); }else { reg_num = get_regulator_mctl_reg(regulator_id); ret = d2041_reg_read(d2041, reg_num, ®_val); if(ret < 0) { dlg_err("I2C read error\n"); return ret; } reg_val &= ~(D2041_REGULATOR_MCTL1 | D2041_REGULATOR_MCTL3); // Clear MCTL11 and MCTL01 reg_val |= (D2041_REGULATOR_MCTL1_ON | D2041_REGULATOR_MCTL3_ON); switch(get_regulator_dsm_opmode(regulator_id)) { case D2041_REGULATOR_LPM_IN_DSM : reg_val &= ~(D2041_REGULATOR_MCTL0 | D2041_REGULATOR_MCTL2); reg_val |= (D2041_REGULATOR_MCTL0_SLEEP | D2041_REGULATOR_MCTL2_SLEEP); break; case D2041_REGULATOR_OFF_IN_DSM : reg_val &= ~(D2041_REGULATOR_MCTL0 | D2041_REGULATOR_MCTL2); break; case D2041_REGULATOR_ON_IN_DSM : reg_val &= ~(D2041_REGULATOR_MCTL0 | D2041_REGULATOR_MCTL2); reg_val |= (D2041_REGULATOR_MCTL0_ON | D2041_REGULATOR_MCTL2_ON); break; } ret |= d2041_reg_write(d2041, reg_num, reg_val); } return ret; }
static int set_regulator_mctl_mode(struct d2041 *d2041, int regulator_id, u8 mode) { u8 reg_val, mctl_reg; int ret = 0; if(regulator_id < 0 || regulator_id >= D2041_NUMBER_OF_REGULATORS) return -EINVAL; if(mode > REGULATOR_MCTL_TURBO) return -EINVAL; mctl_reg = get_regulator_mctl_reg(regulator_id); ret = d2041_reg_read(d2041, mctl_reg, ®_val); if(ret < 0) return ret; reg_val &= ~(D2041_REGULATOR_MCTL0 | D2041_REGULATOR_MCTL2); reg_val |= ((mode << MCTL0_SHIFT) | ( mode << MCTL2_SHIFT)); ret = d2041_reg_write(d2041, mctl_reg, reg_val); dlg_info("[REGULATOR] %s. reg_val = 0x%X\n", __func__, reg_val); return ret; }
// TODO MW: consider use of kernel parameters to override defaults/boot loader settings //TBD static void d2041_configure_mctl(struct d2041 *d2041, struct regulator_dev *rdev) { //TODO MW check and test this code ! Find out this is the bahaviour we want. int mV_val = 0; u8 misc_mctlv = 0; int i; /* WARNING: we assume here that once configured, MCTL registers content doesn't change ! * If there is any change to MCTL registers during kernel runtime, * the regulator_mctl[] table MUST also be updated ! */ if (is_mctl_preconfigured() == true) { /* MCTL configured before (preasumably by BL code) */ for (i = D2041_BUCK_1; i < D2041_NUMBER_OF_REGULATORS; i++) { /* Just copy all mctl registers to the buffer */ d2041_reg_read((d2041, get_regulator_mctl_reg(i), ®ulator_mctl[i]); } } else { /* MCTL NOT preconfigured */ /* Use predefined defaults * TODO MW: Those settings should be customized for specific platform */ for (i = D2041_BUCK_1; i < D2041_NUMBER_OF_REGULATORS; i++) {
static int d2041_regulator_is_enabled(struct regulator_dev *rdev) { struct d2041 *d2041 = rdev_get_drvdata(rdev); unsigned int reg_num, regulator_id = rdev_get_id(rdev); int ret = -EINVAL; u8 reg_val = 0; if(!is_mode_control_enabled()){ reg_num = get_regulator_reg(regulator_id); ret = d2041_reg_read(d2041, reg_num, ®_val); if(ret < 0) { dlg_err("I2C read error. \n"); return ret; } /* 0x0 : off, 0x1 : on */ ret = reg_val & (1<<6); }else{ if (regulator_id >= D2041_NUMBER_OF_REGULATORS) return -EINVAL; reg_num = get_regulator_mctl_reg(regulator_id); ret = d2041_reg_read(d2041, reg_num, ®_val); if(ret < 0) { dlg_err("I2C read error. \n"); return ret; } /* 0x0 : Off * 0x1 : On * 0x2 : Sleep * 0x3 : n/a */ ret = ((reg_val & (D2041_REGULATOR_MCTL1|D2041_REGULATOR_MCTL3)) >= 1) ? 1 : 0; } return ret; }
int __init d2083_platform_regulator_init(struct d2083 *d2083) { int i; u8 reg_val=0; #if 1 //todo struct d2083_regl_init_data *regl_data = d2083->pdata->regulator_data; if(regl_data == NULL) return -1; for(i = D2083_BUCK_1; i < D2083_NUMBER_OF_REGULATORS; i++) { d2083_register_regulator(d2083, i, (regl_data + i)->initdata); regulator_register_map[i].dsm_opmode = d2083->pdata->regl_map[i].default_pm_mode; if(i >= D2083_BUCK_1) { d2083_reg_write(d2083, get_regulator_mctl_reg(i), d2083->pdata->regl_map[i].dsm_opmode); } } #else for(i = D2083_BUCK_1; i < D2083_NUMBER_OF_REGULATORS; i++) { if (d2083->pdata != NULL && d2083->pdata->regulator_data != NULL && d2083->pdata->regulator_data[i].supply != NULL) { d2083_regulators_init_data[i].consumer_supplies = &d2083->pdata->regulator_data[i]; d2083_regulators_init_data[i].num_consumer_supplies = 1; dev_info(d2083->dev, "No consumers for regulator %s\n", d2083_regulators_init_data[i].constraints.name); } d2083_register_regulator(d2083, i, &(d2083_regulators_init_data[i])); regulator_register_map[i].dsm_opmode = d2083->pdata->regl_map[i].default_pm_mode; if(i >= D2083_BUCK_1) { d2083_reg_write(d2083, get_regulator_mctl_reg(i), d2083->pdata->regl_map[i].dsm_opmode); } } #endif // ****************************************************************************** // set MISC_MCTL /* reg_val = (D2083_MISC_MCTL3_DIGICLK | D2083_MISC_MCTL2_DIGICLK | D2083_MISC_MCTL1_DIGICLK | D2083_MISC_MCTL0_DIGICLK | D2083_MISC_MCTL3_BBAT | D2083_MISC_MCTL2_BBAT | D2083_MISC_MCTL1_BBAT | D2083_MISC_MCTL0_BBAT); */ reg_val = 0x0F; d2083_reg_write(d2083_regl_info, D2083_MISC_MCTL_REG, reg_val); // GPADC MTCL default reg_val = 0x55; // 0x55 -> 01 | 01 | 01 | 01 (01 -> On if already enabled) d2083_reg_write(d2083_regl_info, D2083_GPADC_MCTL_REG, reg_val); d2083_reg_write(d2083_regl_info, D2083_BUCK1_TURBO_REG, D2083_BUCK1_NM_VOLT); d2083_reg_write(d2083_regl_info, D2083_BUCK1_RETENTION_REG, D2083_BUCK1_RETENTION_VOLT); d2083_reg_write(d2083_regl_info, D2083_BUCK3_REG, 0x4C); // BUCK3 : 1.23v -> 1.225v // set AUD_LDO to 2.5v d2083_reg_write(d2083_regl_info, D2083_LDO_AUD_REG, 0x5A); // set LDO to 1.8v d2083_reg_write(d2083_regl_info, D2083_LDO1_REG, 0x4C); // sim_vcc(LDO11) -> default 1.8v //d2083_reg_write(d2083_regl_info, D2083_LDO11_REG, 0xC); // LDO_AUD pull-down disable d2083_reg_write(d2083_regl_info, D2083_PULLDOWN_REG_D, (1<<0)); // ****************************************************************************** return 0; }