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);
}
예제 #3
0
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;
}
예제 #8
0
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();
}
예제 #9
0
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);

}
예제 #10
0
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;
}
예제 #11
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);
	}
}