static int smb345_configure_otg(struct i2c_client *client) { int ret = 0; /*Enable volatile writes to registers and Allow fast charge */ ret = smb345_write(client, smb345_CMD_REG, 0xc0); if (ret < 0) { dev_err(&client->dev, "%s(): Failed in writing" "register 0x%02x\n", __func__, smb345_CMD_REG); goto error; } /* Change "OTG output current limit" to 250mA */ ret = smb345_write(client, smb345_OTG_TLIM_REG, 0x34); if (ret < 0) { dev_err(&client->dev, "%s(): Failed in writing" "register 0x%02x\n", __func__, smb345_OTG_TLIM_REG); goto error; } /* Enable OTG */ ret = smb345_update_reg(client, smb345_CMD_REG, 0x10); if (ret < 0) { dev_err(&client->dev, "%s: Failed in writing register" "0x%02x\n", __func__, smb345_CMD_REG); goto error; } /* Change "OTG output current limit" from 250mA to 750mA */ ret = smb345_update_reg(client, smb345_OTG_TLIM_REG, 0x08); if (ret < 0) { dev_err(&client->dev, "%s: Failed in writing register" "0x%02x\n", __func__, smb345_OTG_TLIM_REG); goto error; } /* Change OTG to Pin control */ ret = smb345_write(client, smb345_CTRL_REG, 0x65); if (ret < 0) { dev_err(&client->dev, "%s(): Failed in writing" "register 0x%02x\n", __func__, smb345_CTRL_REG); goto error; } /* Disable volatile writes to registers */ ret = smb345_volatile_writes(client, smb345_DISABLE_WRITE); if (ret < 0) { dev_err(&client->dev, "%s error in configuring OTG..\n", __func__); goto error; } return 0; error: return ret; }
int smb345_float_volt_set(unsigned int val) { struct i2c_client *client = charger->client; int ret = 0, retval; if (val > 4500 || val < 3500) { SMB_ERR("%s(): val=%d is out of range !\n",__func__, val); } printk("%s(): val=%d\n",__func__, val); ret = smb345_volatile_writes(client, smb345_ENABLE_WRITE); if (ret < 0) { dev_err(&client->dev, "%s() charger enable write error..\n", __func__); goto fault; } retval = smb345_read(client, smb345_FLOAT_VLTG); if (retval < 0) { dev_err(&client->dev, "%s(): Failed in reading 0x%02x", __func__, smb345_FLOAT_VLTG); goto fault; } retval = retval & (~FLOAT_VOLT_MASK); val = clamp_val(val, 3500, 4500) - 3500; val /= 20; retval |= val; ret = smb345_write(client, smb345_FLOAT_VLTG, retval); if (ret < 0) { dev_err(&client->dev, "%s(): Failed in writing" "register 0x%02x\n", __func__, smb345_FLOAT_VLTG); goto fault; } ret = smb345_volatile_writes(client, smb345_DISABLE_WRITE); if (ret < 0) { dev_err(&client->dev, "%s() charger disable write error..\n", __func__); } return 0; fault: return ret; }
int smb345_config_thermal_limit(void) { struct i2c_client *client = charger->client; int ret = 0, retval, setting = 0; ret = smb345_volatile_writes(client, smb345_ENABLE_WRITE); if (ret < 0) { dev_err(&client->dev, "%s() charger enable write error..\n", __func__); goto error; } retval = smb345_read(client, smb345_HRD_SFT_TEMP); if (retval < 0) { dev_err(&client->dev, "%s(): Failed in reading 0x%02x", __func__, smb345_HRD_SFT_TEMP); goto error; } setting = retval & HOT_LIMIT_MASK; if (setting != 0x33) { setting = retval & (~HOT_LIMIT_MASK); setting |= 0x33; SMB_NOTICE("Set HRD SFT limit, retval=%x setting=%x\n", retval, setting); ret = smb345_write(client, smb345_HRD_SFT_TEMP, setting); if (ret < 0) { dev_err(&client->dev, "%s(): Failed in writing 0x%02x to register" "0x%02x\n", __func__, setting, smb345_HRD_SFT_TEMP); goto error; } } else SMB_NOTICE("Bypass set HRD SFT limit=%x\n", retval); ret = smb345_volatile_writes(client, smb345_DISABLE_WRITE); if (ret < 0) { dev_err(&client->dev, "%s() charger enable write error..\n", __func__); goto error; } error: return ret; }
int smb345_vflt_setting(void) { struct i2c_client *client = charger->client; u8 ret = 0, setting; ret = smb345_volatile_writes(client, smb345_ENABLE_WRITE); if (ret < 0) { dev_err(&client->dev, "%s() error in smb345 volatile writes \n", __func__); goto error; } ret = smb345_read(client, smb345_FLOAT_VLTG); if (ret < 0) { dev_err(&client->dev, "%s() error in smb345 read \n", __func__); goto error; } setting = ret & FLOAT_VOLT_MASK; if (setting != FLOAT_VOLT_43V) { setting = ret & (~FLOAT_VOLT_MASK); setting |= FLOAT_VOLT_43V; SMB_NOTICE("Set Float Volt, retval=%x setting=%x\n", ret, setting); ret = smb345_write(client, smb345_FLOAT_VLTG, setting); if (ret < 0) { dev_err(&client->dev, "%s() error in smb345 write \n", __func__); goto error; } } else SMB_NOTICE("Bypass set Float Volt=%x\n", ret); ret = smb345_volatile_writes(client, smb345_DISABLE_WRITE); if (ret < 0) { dev_err(&client->dev, "%s() error in smb345 volatile writes \n", __func__); goto error; } error: return ret; }
int smb345_charger_enable(bool state) { struct i2c_client *client = charger->client; u8 ret = 0; ret = smb345_volatile_writes(client, smb345_ENABLE_WRITE); if (ret < 0) { dev_err(&client->dev, "%s() error in configuring charger..\n", __func__); goto error; } charge_en_flag = state; smb345_pin_control(state); ret = smb345_volatile_writes(client, smb345_DISABLE_WRITE); if (ret < 0) { dev_err(&client->dev, "%s() error in configuring charger..\n", __func__); goto error; } error: return ret; }
int smb345_set_WCInputCurrentlimit(struct i2c_client *client, u32 current_setting) { int ret = 0, retval; u8 setting; charger->wpc_curr_limit_count++; ret = smb345_volatile_writes(client, smb345_ENABLE_WRITE); if (ret < 0) { dev_err(&client->dev, "%s() error in configuring charger..\n", __func__); goto error; } if (current_setting != 0) { retval = smb345_read(client, smb345_CHRG_CRNTS); if (retval < 0) { dev_err(&client->dev, "%s(): Failed in reading 0x%02x", __func__, smb345_CHRG_CRNTS); goto error; } setting = retval & 0x0F; if (current_setting == 2000) setting |= 0x70; else if (current_setting == 1800) setting |= 0x60; else if (current_setting == 1200) setting |= 0x40; else if (current_setting == 900) setting |= 0x30; else if (current_setting == 700) setting |= 0x20; else if (current_setting == 500) setting |= 0x10; else if (current_setting == 300) setting |= 0x00; else setting |= 0x20; SMB_NOTICE("Set ICL=%u retval =%x setting=%x\n", current_setting, retval, setting); ret = smb345_write(client, smb345_CHRG_CRNTS, setting); if (ret < 0) { dev_err(&client->dev, "%s(): Failed in writing 0x%02x to register" "0x%02x\n", __func__, setting, smb345_CHRG_CRNTS); goto error; } charger->wpc_curr_limit = current_setting; } if (current_setting == 300) { retval = smb345_read(client, smb345_VRS_FUNC); if (retval < 0) { dev_err(&client->dev, "%s(): Failed in reading 0x%02x", __func__, smb345_VRS_FUNC); goto error; } setting = retval & (~(BIT(4))); SMB_NOTICE("Disable AICL, retval=%x setting=%x\n", retval, setting); ret = smb345_write(client, smb345_VRS_FUNC, setting); if (ret < 0) { dev_err(&client->dev, "%s(): Failed in writing 0x%02x to register" "0x%02x\n", __func__, setting, smb345_VRS_FUNC); goto error; } } ret = smb345_volatile_writes(client, smb345_DISABLE_WRITE); if (ret < 0) { dev_err(&client->dev, "%s() error in configuring charger..\n", __func__); goto error; } error: return ret; }
int smb345_set_InputCurrentlimit(struct i2c_client *client, u32 current_setting) { int ret = 0, retval; u8 setting = 0; wake_lock(&charger_wakelock); ret = smb345_volatile_writes(client, smb345_ENABLE_WRITE); if (ret < 0) { dev_err(&client->dev, "%s() error in configuring charger..\n", __func__); goto error; } if (charge_en_flag) smb345_pin_control(0); retval = smb345_read(client, smb345_VRS_FUNC); if (retval < 0) { dev_err(&client->dev, "%s(): Failed in reading 0x%02x", __func__, smb345_VRS_FUNC); goto error; } setting = retval & (~(BIT(4))); SMB_NOTICE("Disable AICL, retval=%x setting=%x\n", retval, setting); ret = smb345_write(client, smb345_VRS_FUNC, setting); if (ret < 0) { dev_err(&client->dev, "%s(): Failed in writing 0x%02x to register" "0x%02x\n", __func__, setting, smb345_VRS_FUNC); goto error; } retval = smb345_read(client, smb345_CHRG_CRNTS); if (retval < 0) { dev_err(&client->dev, "%s(): Failed in reading 0x%02x", __func__, smb345_CHRG_CRNTS); goto error; } setting = retval & 0xF0; if(current_setting == 2000) setting |= 0x07; else if(current_setting == 1800) setting |= 0x06; else if (current_setting == 1200) setting |= 0x04; else if(current_setting == 900) setting |= 0x03; else if(current_setting == 500) setting |= 0x01; else setting |= 0x07; SMB_NOTICE("Set ICL=%u retval =%x setting=%x\n", current_setting, retval, setting); ret = smb345_write(client, smb345_CHRG_CRNTS, setting); if (ret < 0) { dev_err(&client->dev, "%s(): Failed in writing 0x%02x to register" "0x%02x\n", __func__, setting, smb345_CHRG_CRNTS); goto error; } if(current_setting == 2000) charger->curr_limit = 2000; else if(current_setting == 1800) charger->curr_limit = 1800; else if (current_setting == 1200) charger->curr_limit = 1200; else if(current_setting == 900) charger->curr_limit = 900; else if(current_setting == 500) charger->curr_limit = 500; else charger->curr_limit = 2000; if (current_setting > 900) { charger->time_of_1800mA_limit = jiffies; } else{ charger->time_of_1800mA_limit = 0; } retval = smb345_read(client, smb345_VRS_FUNC); if (retval < 0) { dev_err(&client->dev, "%s(): Failed in reading 0x%02x", __func__, smb345_VRS_FUNC); goto error; } setting = retval | BIT(4); SMB_NOTICE("Re-enable AICL, setting=%x\n", setting); msleep(20); ret = smb345_write(client, smb345_VRS_FUNC, setting); if (ret < 0) { dev_err(&client->dev, "%s(): Failed in writing 0x%02x to register" "0x%02x\n", __func__, setting, smb345_VRS_FUNC); goto error; } if (charge_en_flag) smb345_pin_control(1); ret = smb345_volatile_writes(client, smb345_DISABLE_WRITE); if (ret < 0) { dev_err(&client->dev, "%s() error in configuring charger..\n", __func__); goto error; } error: wake_unlock(&charger_wakelock); return ret; }
int smb345_config_thermal_charging(int temp, int volt, int rule) { struct i2c_client *client = charger->client; int ret = 0, retval, setting = 0; int BAT_Mid_Temp = BAT_Mid_Temp_Wired; if (rule == THERMAL_RULE1) BAT_Mid_Temp = BAT_Mid_Temp_Wired; else if (rule == THERMAL_RULE2) BAT_Mid_Temp = BAT_Mid_Temp_Wireless; smb345_config_thermal_limit(); SMB_NOTICE("temp=%d, volt=%d\n", temp, volt); ret = smb345_volatile_writes(client, smb345_ENABLE_WRITE); if (ret < 0) { dev_err(&client->dev, "%s() charger enable write error..\n", __func__); goto error; } /*control float voltage*/ retval = smb345_read(client, smb345_FLOAT_VLTG); if (retval < 0) { dev_err(&client->dev, "%s(): Failed in reading 0x%02x", __func__, smb345_FLOAT_VLTG); goto error; } setting = retval & FLOAT_VOLT_MASK; if (temp <= BAT_Mid_Temp || (temp > BAT_Mid_Temp && volt > FLOAT_VOLT_LOW_DECIMAL) || temp > BAT_Hot_Limit) { if (setting != FLOAT_VOLT_43V) { setting = retval & (~FLOAT_VOLT_MASK); setting |= FLOAT_VOLT_43V; SMB_NOTICE("Set Float Volt, retval=%x setting=%x\n", retval, setting); ret = smb345_write(client, smb345_FLOAT_VLTG, setting); if (ret < 0) { dev_err(&client->dev, "%s(): Failed in writing 0x%02x to register" "0x%02x\n", __func__, setting, smb345_FLOAT_VLTG); goto error; } } else SMB_NOTICE("Bypass set Float Volt=%x\n", retval); } else { if (setting != FLOAT_VOLT_LOW) { setting = retval & (~FLOAT_VOLT_MASK); setting |= FLOAT_VOLT_LOW; SMB_NOTICE("Set Float Volt, retval=%x setting=%x\n", retval, setting); ret = smb345_write(client, smb345_FLOAT_VLTG, setting); if (ret < 0) { dev_err(&client->dev, "%s(): Failed in writing 0x%02x to register" "0x%02x\n", __func__, setting, smb345_FLOAT_VLTG); goto error; } } else SMB_NOTICE("Bypass set Float Volt=%x\n", retval); } /*charger enable/disable*/ retval = smb345_read(client, smb345_PIN_CTRL); if (retval < 0) { dev_err(&client->dev, "%s(): Failed in reading 0x%02x", __func__, smb345_PIN_CTRL); goto error; } setting = retval & ENABLE_PIN_CTRL_MASK; if (temp < BAT_Cold_Limit || temp > BAT_Hot_Limit || (temp > BAT_Mid_Temp && volt > FLOAT_VOLT_LOW_DECIMAL)) { if (setting != 0x40) { SMB_NOTICE("Charger disable\n"); smb345_charger_enable(false); } else SMB_NOTICE("Bypass charger disable\n"); } else { if (setting != 0x60) { SMB_NOTICE("Charger enable\n"); smb345_charger_enable(true); } else { /*interrupt status*/ retval = smb345_read(client, smb345_INTR_STS_B); if (retval < 0) { dev_err(&client->dev, "%s(): Failed in reading 0x%02x", __func__, smb345_INTR_STS_B); goto error; } if ((retval & BAT_OVER_VOLT_MASK) == 0x40) { SMB_NOTICE("disable then enable charger to recover bat over-volt\n"); smb345_charger_enable(false); smb345_charger_enable(true); } else SMB_NOTICE("Bypass charger enable\n"); } } ret = smb345_volatile_writes(client, smb345_DISABLE_WRITE); if (ret < 0) { dev_err(&client->dev, "%s() charger enable write error..\n", __func__); goto error; } error: return ret; }
int smb345_config_thermal_charging(int temp, int volt, int rule) { struct i2c_client *client = charger->client; int ret = 0, retval, setting = 0; int BAT_Mid_Temp = BAT_Mid_Temp_Wired; /*Charger float voltage for normal temperature conditions. Default 4.3V.*/ int flt_volt_43 = FLOAT_VOLT_43V; /*Charger float voltage for high temperature conditions. Default 4.1V.*/ int flt_volt_low = FLOAT_VOLT_LOW; flt_volt_43 = (float_volt_setting - 3500) / 20; if(flt_volt_43 < 0 || flt_volt_43 > FLOAT_VOLT_43V) { SMB_NOTICE("BUG: Invalid float voltage setting calculated: %d\n", flt_volt_43); flt_volt_43 = FLOAT_VOLT_43V; } if(flt_volt_low > flt_volt_43) flt_volt_low = flt_volt_43; if (rule == THERMAL_RULE1) BAT_Mid_Temp = BAT_Mid_Temp_Wired; else if (rule == THERMAL_RULE2) BAT_Mid_Temp = BAT_Mid_Temp_Wireless; mdelay(100); smb345_config_thermal_limit(); SMB_NOTICE("temp=%d, volt=%d\n", temp, volt); ret = smb345_volatile_writes(client, smb345_ENABLE_WRITE); if (ret < 0) { dev_err(&client->dev, "%s() charger enable write error..\n", __func__); goto error; } /*control float voltage*/ retval = smb345_read(client, smb345_FLOAT_VLTG); if (retval < 0) { dev_err(&client->dev, "%s(): Failed in reading 0x%02x", __func__, smb345_FLOAT_VLTG); goto error; } setting = retval & FLOAT_VOLT_MASK; if (temp <= BAT_Mid_Temp || (temp > BAT_Mid_Temp && volt > FLOAT_VOLT_LOW_DECIMAL) || temp > BAT_Hot_Limit) { if (setting != flt_volt_43) { setting = retval & (~FLOAT_VOLT_MASK); setting |= flt_volt_43; SMB_NOTICE("Set Float Volt, retval=%x setting=%x V=%dmV\n", retval, setting, float_volt_setting); ret = smb345_write(client, smb345_FLOAT_VLTG, setting); if (ret < 0) { dev_err(&client->dev, "%s(): Failed in writing 0x%02x to register" "0x%02x\n", __func__, setting, smb345_FLOAT_VLTG); goto error; } } else SMB_NOTICE("Bypass set Float Volt setting=%x V=%dmV\n", retval, float_volt_setting); } else { if (setting != flt_volt_low) { setting = retval & (~FLOAT_VOLT_MASK); setting |= flt_volt_low; SMB_NOTICE("Set Float Volt, retval=%x setting=%x\n", retval, setting); ret = smb345_write(client, smb345_FLOAT_VLTG, setting); if (ret < 0) { dev_err(&client->dev, "%s(): Failed in writing 0x%02x to register" "0x%02x\n", __func__, setting, smb345_FLOAT_VLTG); goto error; } } else SMB_NOTICE("Bypass set Float Volt=%x\n", retval); } /*charger enable/disable*/ retval = smb345_read(client, smb345_PIN_CTRL); if (retval < 0) { dev_err(&client->dev, "%s(): Failed in reading 0x%02x", __func__, smb345_PIN_CTRL); goto error; } setting = retval & ENABLE_PIN_CTRL_MASK; if (temp < BAT_Cold_Limit || temp > BAT_Hot_Limit || (temp > BAT_Mid_Temp && volt > FLOAT_VOLT_LOW_DECIMAL)) { if (setting != 0x40) { SMB_NOTICE("Charger disable\n"); smb345_charger_enable(false); } else SMB_NOTICE("Bypass charger disable\n"); } else { if (setting != 0x60) { SMB_NOTICE("Charger enable\n"); smb345_charger_enable(true); } else { /*interrupt status*/ retval = smb345_read(client, smb345_INTR_STS_B); if (retval < 0) { dev_err(&client->dev, "%s(): Failed in reading 0x%02x", __func__, smb345_INTR_STS_B); goto error; } if ((retval & BAT_OVER_VOLT_MASK) == 0x40) { SMB_NOTICE("disable then enable charger to recover bat over-volt\n"); smb345_charger_enable(false); smb345_charger_enable(true); } else SMB_NOTICE("Bypass charger enable\n"); } } ret = smb345_volatile_writes(client, smb345_DISABLE_WRITE); if (ret < 0) { dev_err(&client->dev, "%s() charger enable write error..\n", __func__); goto error; } error: return ret; }