static void smb136_set_charging_current(int set_current) { struct smb136_chg_data *chg = smb136_chg; u8 data = 0; if (set_current > 450) { /* HC mode */ data = 0x8c; smb136_i2c_write(chg->client, SMB_CommandA, data); udelay(10); /* Set charge current to 1500mA */ data = 0xf4; smb136_i2c_write(chg->client, SMB_ChargeCurrent, data); udelay(10); } else { /* USBIN 500mA mode */ data = 0x88; smb136_i2c_write(chg->client, SMB_CommandA, data); udelay(10); /* Set charge current to 500mA */ data = 0x14; smb136_i2c_write(chg->client, SMB_ChargeCurrent, data); udelay(10); } pr_debug("%s: Set charging current as %dmA.\n", __func__, set_current); }
static void smb136_i2c_write_array(struct i2c_client *client, u8 *buf, int size) { int i; for (i = 0; i < size; i += 3) smb136_i2c_write(client, (u8) (*(buf + i)), (buf + i) + 1); }
static ssize_t command_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { struct smb136_chg_data *chg = smb136_chg; struct i2c_client *client = chg->client; int v1, v2; u8 addr, data; printk("input data --> %s\n", buf); if(sscanf(buf, "%x %x", &v1, &v2) == 2) { addr = (u8) v1; data = (u8) v2; smb136_i2c_write(client, addr, data); } return size; }
static void smb136_allow_volatile_writes(struct i2c_client *client) { int val, reg; u8 data; reg = SMB136_COMMAND_A; val = smb136_i2c_read(client, reg, &data); if ((val >= 0) && !(data & 0x80)) { dev_dbg(&client->dev, "%s : reg(0x%02x): 0x%02x", __func__, reg, data); data |= (0x1 << 7); if (smb136_i2c_write(client, reg, &data) < 0) dev_err(&client->dev, "%s : error!\n", __func__); val = smb136_i2c_read(client, reg, &data); if (val >= 0) { data = (u8) data; dev_dbg(&client->dev, " => 0x%02x\n", data); } } }
static void smb136_set_command(struct i2c_client *client, int reg, int datum) { int val; u8 data = 0; val = smb136_i2c_read(client, reg, &data); if (val >= 0) { dev_dbg(&client->dev, "%s : reg(0x%02x): 0x%02x", __func__, reg, data); if (data != datum) { data = datum; if (smb136_i2c_write(client, reg, &data) < 0) dev_err(&client->dev, "%s : error!\n", __func__); val = smb136_i2c_read(client, reg, &data); if (val >= 0) dev_dbg(&client->dev, " => 0x%02x\n", data); } } }
ssize_t sec_hal_chg_store_attrs(struct device *dev, const ptrdiff_t offset, const char *buf, size_t count) { struct power_supply *psy = dev_get_drvdata(dev); struct sec_charger_info *chg = container_of(psy, struct sec_charger_info, psy_chg); int ret = 0; int x = 0; u8 data = 0; switch (offset) { case CHG_REG: if (sscanf(buf, "%x\n", &x) == 1) { chg->reg_addr = x; smb136_i2c_read(chg->client, chg->reg_addr, &data); chg->reg_data = data; dev_dbg(dev, "%s: (read) addr = 0x%x, data = 0x%x\n", __func__, chg->reg_addr, chg->reg_data); ret = count; } break; case CHG_DATA: if (sscanf(buf, "%x\n", &x) == 1) { data = (u8)x; dev_dbg(dev, "%s: (write) addr = 0x%x, data = 0x%x\n", __func__, chg->reg_addr, data); smb136_i2c_write(chg->client, chg->reg_addr, &data); ret = count; } break; default: ret = -EINVAL; break; } return ret; }
static void smb136_set_charging_state(int en, int cable_status) { struct smb136_chg_data *chg = smb136_chg; u8 data = 0; if (!charger_i2c_init) { pr_info("%s : smb136 charger IC i2c is not initialized!!\n" , __func__); return; } pr_info("%s : enable(%d), cable_status(%d)\n" , __func__, en, cable_status); if (en) { /* enable */ /* 2. Change USB5/1/HC Control from Pin to I2C */ smb136_i2c_write(chg->client, SMB_PinControl, 0x8); udelay(10); /* 1. USB 100mA Mode, USB5/1 Current Levels */ /* Prevent in-rush current */ data = 0x80; smb136_i2c_write(chg->client, SMB_CommandA, data); udelay(10); /* 3. Set charge current to 100mA */ /* Prevent in-rush current */ data = 0x14; smb136_i2c_write(chg->client, SMB_ChargeCurrent, data); udelay(10); /* 4. Disable Automatic Input Current Limit */ data = 0xe6; smb136_i2c_write(chg->client, SMB_InputCurrentLimit, data); udelay(10); /* 4. Automatic Recharge Disabed */ data = 0x8c; smb136_i2c_write(chg->client, SMB_ControlA, data); udelay(10); /* 5. Safty timer Disabled */ data = 0x28; smb136_i2c_write(chg->client, SMB_ControlB, data); udelay(10); /* 6. Disable USB D+/D- Detection */ data = 0x28; smb136_i2c_write(chg->client, SMB_OTGControl, data); udelay(10); /* 7. Set Output Polarity for STAT */ data = 0xCA; smb136_i2c_write(chg->client, SMB_FloatVoltage, data); udelay(10); /* 9. Re-load Enable */ data = 0x4b; smb136_i2c_write(chg->client, SMB_SafetyTimer, data); udelay(10); /* Enable charge */ gpio_set_value(chg->pdata->enable, 0); switch (cable_status) { case CABLE_TYPE_TA: /* HC mode */ data = 0x8c; smb136_i2c_write(chg->client, SMB_CommandA, data); udelay(10); /* Set charge current to 1500mA */ data = 0xf4; smb136_i2c_write(chg->client, SMB_ChargeCurrent, data); udelay(10); break; case CABLE_TYPE_STATION: /* HC mode */ data = 0x8c; smb136_i2c_write(chg->client, SMB_CommandA, data); udelay(10); /* Set charge current to 750mA */ data = 0x54; smb136_i2c_write(chg->client, SMB_ChargeCurrent, data); udelay(10); /* Disable Automatic Input Current Limit, * USBIN Current Limit to 700mA */ data = 0x06; smb136_i2c_write(chg->client, SMB_InputCurrentLimit, data); udelay(10); break; case CABLE_TYPE_USB: default: /* Prevent in-rush current */ msleep(100); /* USBIN 500mA mode */ data = 0x88; smb136_i2c_write(chg->client, SMB_CommandA, data); udelay(10); /* Set charge current to 500mA */ data = 0x14; smb136_i2c_write(chg->client, SMB_ChargeCurrent, data); udelay(10); break; } } else { gpio_set_value(chg->pdata->enable, 1); /* USB 100mA Mode, USB5/1 Current Levels */ /* Prevent in-rush current */ data = 0x80; smb136_i2c_write(chg->client, SMB_CommandA, data); udelay(10); /* Set charge current to 100mA */ /* Prevent in-rush current */ data = 0x14; smb136_i2c_write(chg->client, SMB_ChargeCurrent, data); udelay(10); } return; }
void smb136_set_otg_mode(int enable) { struct i2c_client *client = smb136_i2c_client; u8 data; printk("[SMB136] %s (enable : %d)\n", __func__, enable); if(!charger_i2c_init) { printk("%s : smb136 charger IC i2c is not initialized!!\n", __func__); return ; } if(enable) // Enable OTG Mode { // 1. Set OTG Mode (Clear Bit5 of Pin Control) smb136_i2c_read(client, SMB_PinControl, &data); data &= ~(0x1 << 5); smb136_i2c_write(client, SMB_PinControl, data); udelay(10); // 2. Enable OTG Mode (Set Bit1 of Command Register A) smb136_i2c_read(client, SMB_CommandA, &data); data |= (0x1 << 1); smb136_i2c_write(client, SMB_CommandA, data); udelay(10); } else // Re-init charger IC { // 1. Allow volatile writes to 00~09h, USB 500mA Mode, USB5/1 Mode data = 0x88; smb136_i2c_write(client, SMB_CommandA, data); udelay(10); // 2. Change USB5/1/HC Control from Pin to I2C data = 0x08; smb136_i2c_write(client, SMB_PinControl, data); udelay(10); // 3. Allow volatile writes to 00~09h, USB 500mA Mode, USB5/1 Mode data = 0x88; smb136_i2c_write(client, SMB_CommandA, data); udelay(10); // 4. Disable Automatic Input Current Limit data = 0xe6; smb136_i2c_write(client, SMB_InputCurrentLimit, data); udelay(10); //5. Fast Charge Current set 500mA #ifdef CONFIG_TARGET_LOCALE_VZW data = 0xf2; #else data = 0xf4; #endif smb136_i2c_write(client, SMB_ChargeCurrent, data); udelay(10); //6. Automatic Recharge Disabed data = 0x8c; smb136_i2c_write(client, SMB_ControlA, data); udelay(10); //7. Safty timer Disabled data = 0x28; smb136_i2c_write(client, SMB_ControlB, data); udelay(10); //8. Disable USB D+/D- Detection data = 0x28; smb136_i2c_write(client, SMB_OTGControl, data); udelay(10); //9. Set Output Polarity for STAT data = 0xca; smb136_i2c_write(client, SMB_FloatVoltage, data); udelay(10); //10. Re-load Enable data = 0x4b; smb136_i2c_write(client, SMB_SafetyTimer, data); udelay(10); } smb136_test_read(); }
void smb136_charging(int source) { u8 data; if(!charger_i2c_init) { printk("%s : smb136 charger IC i2c is not initialized!!\n", __func__); return ; } if(source ==DEVICE_TA) { //1. HC mode data= 0x8c; smb136_i2c_write(smb136_i2c_client,SMB_CommandA, data); udelay(10); // 2. Change USB5/1/HC Control from Pin to I2C smb136_i2c_write(smb136_i2c_client, SMB_PinControl,0x8); udelay(10); smb136_i2c_write(smb136_i2c_client,SMB_CommandA, 0x8c); udelay(10); //3. Set charge current to 1500mA #ifdef CONFIG_TARGET_LOCALE_VZW data = 0xf2; //terminal Current 100mA #else data = 0xf4; #endif smb136_i2c_write(smb136_i2c_client,SMB_ChargeCurrent, data); udelay(10); } else if(source ==DEVICE_USB) { // 1. USBIN 500mA mode data= 0x88; smb136_i2c_write(smb136_i2c_client,SMB_CommandA, data); udelay(10); // 2. Change USB5/1/HC Control from Pin to I2C smb136_i2c_write(smb136_i2c_client, SMB_PinControl,0x8); udelay(10); smb136_i2c_write(smb136_i2c_client,SMB_CommandA, 0x88); udelay(10); // 3. Set charge current to 500mA #ifdef CONFIG_TARGET_LOCALE_VZW data = 0x12; #else data = 0x14; #endif smb136_i2c_write(smb136_i2c_client,SMB_ChargeCurrent, data); udelay(10); } // 3. Disable Automatic Input Current Limit data= 0xe6; smb136_i2c_write(smb136_i2c_client,SMB_InputCurrentLimit, data); udelay(10); //4. Automatic Recharge Disabed data = 0x8c; smb136_i2c_write(smb136_i2c_client,SMB_ControlA, data); udelay(10); //5. Safty timer Disabled data = 0x28; smb136_i2c_write(smb136_i2c_client,SMB_ControlB, data); udelay(10); //6. Disable USB D+/D- Detection data=0x28; smb136_i2c_write(smb136_i2c_client,SMB_OTGControl, data); udelay(10); //7. Set Output Polarity for STAT data=0xCA; smb136_i2c_write(smb136_i2c_client, SMB_FloatVoltage, data); udelay(10); //8. Re-load Enable data=0x4b; smb136_i2c_write(smb136_i2c_client, SMB_SafetyTimer, data); udelay(10); }
static int smb136_charging(struct i2c_client *client) { struct smb136_chip *chg = i2c_get_clientdata(client); u8 data = 0; int gpio = 0; dev_info(&client->dev, "%s : enable(%d), cable(%d)\n", __func__, chg->is_enable, chg->cable_type); if(chg->is_enable) { switch(chg->cable_type) { case CABLE_TYPE_AC: //1. HC mode data = 0x8c; smb136_i2c_write(chg->client, SMB_CommandA, data); udelay(10); // 2. Change USB5/1/HC Control from Pin to I2C // 2. EN pin control - active low smb136_i2c_write(chg->client, SMB_PinControl, 0x8); udelay(10); smb136_i2c_write(chg->client, SMB_CommandA, 0x8c); udelay(10); //3. Set charge current to 950mA, termination current to 150mA data = 0x94; smb136_i2c_write(chg->client, SMB_ChargeCurrent, data); udelay(10); break; case CABLE_TYPE_USB: default: // 1. USBIN 500mA mode data = 0x88; smb136_i2c_write(chg->client, SMB_CommandA, data); udelay(10); // 2. Change USB5/1/HC Control from Pin to I2C // 2. EN pin control - active low smb136_i2c_write(chg->client, SMB_PinControl, 0x8); udelay(10); smb136_i2c_write(chg->client, SMB_CommandA, 0x88); udelay(10); // 3. Set charge current to 500mA, termination current to 150mA data = 0x14; smb136_i2c_write(chg->client, SMB_ChargeCurrent, data); udelay(10); break; } // 3. Enable Automatic Input Current Limit to 1000mA (threshold 4.25V) data = 0x60; smb136_i2c_write(chg->client, SMB_InputCurrentLimit, data); udelay(10); //4. Automatic Recharge Disabed data = 0x8c; smb136_i2c_write(chg->client, SMB_ControlA, data); udelay(10); //5. Safty timer Disabled data = 0x28; smb136_i2c_write(chg->client, SMB_ControlB, data); udelay(10); //6. Disable USB D+/D- Detection data = 0x28; smb136_i2c_write(chg->client, SMB_OTGControl, data); udelay(10); //7. Set Output Polarity for STAT //7. Set float voltage to 4.2V data = 0x4a; smb136_i2c_write(chg->client, SMB_FloatVoltage, data); udelay(10); //8. Re-load Enable data = 0x4b; smb136_i2c_write(chg->client, SMB_SafetyTimer, data); udelay(10); } else { // do nothing... } /* CHG_EN pin control - active low */ gpio = gpio_request(chg->pdata->gpio_chg_en, "CHG_EN"); if (!gpio) { gpio_direction_output(chg->pdata->gpio_chg_en, !(chg->is_enable)); dev_info(&client->dev, "gpio(CHG_EN)is %d\n", gpio_get_value(chg->pdata->gpio_chg_en)); gpio_free(chg->pdata->gpio_chg_en); } else dev_err(&client->dev, "faile to request gpio(CHG_EN)\n"); /* smb136_test_read(client); */ return 0; }
int smb136_charging(int en, int cable_status) { struct smb136_chg_data *chg = smb136_chg; u8 data = 0; if(!charger_i2c_init) { printk("%s : smb136 charger IC i2c is not initialized!!\n", __func__); return -1; } printk("%s : enable(%d), cable_status(%d)\n",__func__,en, cable_status); if(en) { // enable if(cable_status==CABLE_TYPE_AC) { //1. HC mode data = 0x88; // usb host plug detect only works if 0x88 fixme, we want 0x8c for HC mode smb136_i2c_write(chg->client, SMB_CommandA, data); udelay(10); // 2. Change USB5/1/HC Control from Pin to I2C smb136_i2c_write(chg->client, SMB_PinControl, 0x8); udelay(10); smb136_i2c_write(chg->client, SMB_CommandA, data); udelay(10); //3. Set charge current to 1500mA data = 0xf4; smb136_i2c_write(chg->client, SMB_ChargeCurrent, data); udelay(10); } else if(cable_status==CABLE_TYPE_USB || cable_status==CABLE_TYPE_IMPROPER_AC) { // 1. USBIN 500mA mode data = 0x88; smb136_i2c_write(chg->client, SMB_CommandA, data); udelay(10); // 2. Change USB5/1/HC Control from Pin to I2C smb136_i2c_write(chg->client, SMB_PinControl, 0x8); udelay(10); smb136_i2c_write(chg->client, SMB_CommandA, data); udelay(10); // 3. Set charge current to 500mA data = 0x14; smb136_i2c_write(chg->client, SMB_ChargeCurrent, data); udelay(10); } // 3. Disable Automatic Input Current Limit data = 0xe6; smb136_i2c_write(chg->client, SMB_InputCurrentLimit, data); udelay(10); //4. Automatic Recharge Disabed data = 0x8c; smb136_i2c_write(chg->client, SMB_ControlA, data); udelay(10); //5. Safty timer Disabled data = 0x28; smb136_i2c_write(chg->client, SMB_ControlB, data); udelay(10); //6. Disable USB D+/D- Detection data = 0x28; smb136_i2c_write(chg->client, SMB_OTGControl, data); udelay(10); //7. Set Output Polarity for STAT data = 0xCA; smb136_i2c_write(chg->client, SMB_FloatVoltage, data); udelay(10); //8. Re-load Enable data = 0x4b; smb136_i2c_write(chg->client, SMB_SafetyTimer, data); udelay(10); } else { // do nothing... } return 0; }
static void smb136_charger_function_conrol( struct i2c_client *client) { struct sec_charger_info *charger = i2c_get_clientdata(client); u8 data; u8 cur_reg; u8 chg_cur_reg; if (charger->charging_current < 0) { dev_dbg(&client->dev, "%s : OTG is activated. Ignore command!\n", __func__); return; } smb136_allow_volatile_writes(client); if (charger->cable_type == POWER_SUPPLY_TYPE_BATTERY) { /* turn off charger */ smb136_set_command(client, SMB136_COMMAND_A, 0x80); } else { /* Pre-charge curr 250mA */ dev_dbg(&client->dev, "%s : fast charging current (%dmA)\n", __func__, charger->charging_current); dev_dbg(&client->dev, "%s : termination current (%dmA)\n", __func__, charger->pdata->charging_current[ charger->cable_type].full_check_current_1st); smb136_i2c_read(client, SMB136_CHARGE_CURRENT, &chg_cur_reg); chg_cur_reg &= 0x18; data = smb136_get_fast_charging_current_data( charger->charging_current) | chg_cur_reg; data |= smb136_get_termination_current_limit_data( charger->pdata->charging_current[ charger->cable_type].full_check_current_1st); smb136_set_command(client, SMB136_CHARGE_CURRENT, data); /* Pin enable control */ /* DCIN Input Pre-bias Enable */ smb136_i2c_read(client, SMB136_PIN_ENABLE_CONTROL, &data); if (charger->pdata->chg_gpio_en) data |= 0x40; smb136_set_command(client, SMB136_PIN_ENABLE_CONTROL, data); /* Input current limit */ dev_dbg(&client->dev, "%s : input current (%dmA)\n", __func__, charger->pdata->charging_current [charger->cable_type].input_current_limit); data = 0; data = smb136_get_input_current_limit_data( charger, charger->pdata->charging_current [charger->cable_type].input_current_limit); smb136_i2c_read(client, SMB136_INPUT_CURRENTLIMIT, &cur_reg); data |= (cur_reg & 0xF); smb136_set_command(client, SMB136_INPUT_CURRENTLIMIT, data); /* Float voltage, Vprechg : 2.4V */ dev_dbg(&client->dev, "%s : float voltage (%dmV)\n", __func__, charger->pdata->chg_float_voltage); data = 0; data |= smb136_get_float_voltage_data( charger->pdata->chg_float_voltage); smb136_set_command(client, SMB136_FLOAT_VOLTAGE, data); /* 4. Automatic Recharge Disabed */ data = 0x8C; smb136_i2c_write(client, SMB136_CHARGE_CONTROL_A, &data); /* 5. Safty timer Disabled */ data = 0x28; smb136_i2c_write(client, SMB136_CHARGE_CONTROL_B, &data); /* 6. Disable USB D+/D- Detection */ data = 0x28; smb136_i2c_write(client, SMB136_OTG_CONTROL, &data); /* 9. Re-load Enable */ data = 0x4B; smb136_i2c_write(client, SMB136_SAFTY, &data); /* HC or USB5 mode */ smb136_i2c_read(client, SMB136_COMMAND_A, &data); data &= 0xF3; switch (charger->cable_type) { case POWER_SUPPLY_TYPE_MAINS: case POWER_SUPPLY_TYPE_MISC: /* High-current mode */ data |= 0x0C; break; case POWER_SUPPLY_TYPE_USB: case POWER_SUPPLY_TYPE_USB_DCP: case POWER_SUPPLY_TYPE_USB_CDP: case POWER_SUPPLY_TYPE_USB_ACA: /* USB5 */ data |= 0x08; break; default: /* USB1 */ data = 0x00; break; } smb136_set_command(client, SMB136_COMMAND_A, data); } }