/* TODO: remove this function later */
static int max8997_enable_charging_x(struct chg_data *chg, int charge_type)
{
	struct i2c_client *i2c = chg->max8997->i2c;
	int ret;
	u8 val, mask;

	/* enable charging */
	if (charge_type == POWER_SUPPLY_CHARGE_TYPE_FAST) {
		/* ac */
		dev_info(chg->dev, "%s: TA charging", __func__);
		/* set fast charging current : 650mA */
		ret = max8997_update_reg(i2c, MAX8997_REG_MBCCTRL4,
			(9 << MBCICHFC_SHIFT), MBCICHFC_MASK);
		if (ret)
			goto err;

	} else if (charge_type == POWER_SUPPLY_CHARGE_TYPE_TRICKLE) {
		/* usb */
		dev_info(chg->dev, "%s: USB charging", __func__);
		/* set fast charging current : 450mA */
		ret = max8997_update_reg(i2c, MAX8997_REG_MBCCTRL4,
				(5 << MBCICHFC_SHIFT), MBCICHFC_MASK);
		if (ret)
			goto err;
	} else {
		dev_err(chg->dev, "%s: invalid arg\n", __func__);
		ret = -EINVAL;
		goto err;
	}

	/* set auto stop disable */
	ret = max8997_update_reg(i2c, MAX8997_REG_MBCCTRL6,
			(0 << AUTOSTOP_SHIFT), AUTOSTOP_MASK);
	if (ret)
		goto err;

	/* set fast charging enable and main battery charging enable */
	val = (1 << MBCHOSTEN_SHIFT) | (1 << VCHGR_FC_SHIFT);
	mask = MBCHOSTEN_MASK | VCHGR_FC_MASK;
	ret = max8997_update_reg(i2c, MAX8997_REG_MBCCTRL2, val, mask);
	if (ret)
		goto err;

	return 0;
err:
	dev_err(chg->dev, "%s: max8997 update reg error!(%d)\n", __func__, ret);
	return ret;
}
static int max8997_muic_handle_dock(struct max8997_muic_info *info,
			int adc, bool attached)
{
	struct max8997_muic_platform_data *mdata = info->muic_pdata;
	int ret = 0;

	
	ret = max8997_update_reg(info->muic, MAX8997_MUIC_REG_CONTROL1,
				attached ? MAX8997_SW_AUDIO : MAX8997_SW_OPEN,
				SW_MASK);
	if (ret) {
		dev_err(info->dev, "failed to update muic register\n");
		goto out;
	}

	switch (adc) {
	case MAX8997_ADC_DESKDOCK:
		if (mdata->deskdock_callback)
			mdata->deskdock_callback(attached);
		break;
	case MAX8997_ADC_CARDOCK:
		if (mdata->cardock_callback)
			mdata->cardock_callback(attached);
		break;
	default:
		break;
	}
out:
	return ret;
}
Ejemplo n.º 3
0
/*
 * max8997_muic_set_debounce_time - Set the debounce time of ADC
 * @info: the instance including private data of max8997 MUIC
 * @time: the debounce time of ADC
 */
static int max8997_muic_set_debounce_time(struct max8997_muic_info *info,
		enum max8997_muic_adc_debounce_time time)
{
	int ret;

	switch (time) {
	case ADC_DEBOUNCE_TIME_0_5MS:
	case ADC_DEBOUNCE_TIME_10MS:
	case ADC_DEBOUNCE_TIME_25MS:
	case ADC_DEBOUNCE_TIME_38_62MS:
		ret = max8997_update_reg(info->muic,
					  MAX8997_MUIC_REG_CONTROL3,
					  time << CONTROL3_ADCDBSET_SHIFT,
					  CONTROL3_ADCDBSET_MASK);
		if (ret) {
			dev_err(info->dev, "failed to set ADC debounce time\n");
			return ret;
		}
		break;
	default:
		dev_err(info->dev, "invalid ADC debounce time\n");
		return -EINVAL;
	}

	return 0;
};
Ejemplo n.º 4
0
static ssize_t max8997_muic_set_audio_path(struct device *dev,
				    struct device_attribute *attr,
				    const char *buf, size_t count)
{
	struct max8997_muic_info *info = dev_get_drvdata(dev);
	struct i2c_client *client = info->muic;
	u8 cntl1_val, cntl1_msk;
	u8 val;

	if (!strncmp(buf, "0", 1))
		val = 0;
	else if (!strncmp(buf, "1", 1))
		val = 2;
	else {
		dev_warn(info->dev, "%s: Wrong command\n", __func__);
		return count;
	}

	cntl1_val = (val << COMN1SW_SHIFT) | (val << COMP2SW_SHIFT) |
			    (0 << MICEN_SHIFT);
	cntl1_msk = COMN1SW_MASK | COMP2SW_MASK | MICEN_MASK;

	max8997_update_reg(client, MAX8997_MUIC_REG_CTRL1, cntl1_val,
				   cntl1_msk);

	cntl1_val = 0;
	max8997_read_reg(client, MAX8997_MUIC_REG_CTRL1, &cntl1_val);
	dev_info(info->dev, "%s: CNTL1(0x%02x)\n", __func__, cntl1_val);

	return count;
}
Ejemplo n.º 5
0
static void max8997_rtc_enable_smpl(struct max8997_rtc_info *info, bool enable)
{
	int ret;
	u8 val, mask;

	if (!smpl_en)
		return;

	if (enable)
		val = (1 << SMPL_EN_SHIFT) | (0 << SMPLT_SHIFT);
	else
		val = 0;

	mask = SMPL_EN_MASK | SMPLT_MASK;

	dev_info(info->dev, "%s: %s SMPL\n", __func__,
			enable ? "enable" : "disable");

	ret = max8997_update_reg(info->rtc, MAX8997_RTC_WTSR_SMPL, val, mask);
	if (ret < 0) {
		dev_err(info->dev, "%s: fail to update SMPL reg(%d)\n",
				__func__, ret);
		return;
	}

	max8997_rtc_set_update_reg(info);

	val = 0;
	max8997_read_reg(info->rtc, MAX8997_RTC_WTSR_SMPL, &val);
	pr_info("%s: WTSR_SMPL(0x%02x)\n", __func__, val);
}
Ejemplo n.º 6
0
static void max8997_rtc_enable_wtsr(struct max8997_rtc_info *info, bool enable)
{
	int ret;
	u8 val, mask;

	if (!wtsr_en)
		return;

	if (enable)
		val = (1 << WTSR_EN_SHIFT) | (3 << WTSRT_SHIFT);
	else
		val = 0;

	mask = WTSR_EN_MASK | WTSRT_MASK;

	dev_info(info->dev, "%s: %s WTSR\n", __func__,
			enable ? "enable" : "disable");

	ret = max8997_update_reg(info->rtc, MAX8997_RTC_WTSR_SMPL, val, mask);
	if (ret < 0) {
		dev_err(info->dev, "%s: fail to update WTSR reg(%d)\n",
				__func__, ret);
		return;
	}

	max8997_rtc_set_update_reg(info);
}
Ejemplo n.º 7
0
static void max8997_led_set_current(struct max8997_led *led,
				enum led_brightness value)
{
	int ret;
	struct i2c_client *client = led->iodev->i2c;
	u8 val = 0, mask = 0, reg = 0;

	switch (led->led_mode) {
	case MAX8997_FLASH_MODE:
	case MAX8997_FLASH_PIN_CONTROL_MODE:
		val = value << MAX8997_LED_FLASH_SHIFT;
		mask = MAX8997_LED_FLASH_CUR_MASK;
		reg = led->id ? MAX8997_REG_FLASH2_CUR : MAX8997_REG_FLASH1_CUR;
		break;
	case MAX8997_MOVIE_MODE:
	case MAX8997_MOVIE_PIN_CONTROL_MODE:
		val = value << MAX8997_LED_MOVIE_SHIFT;
		mask = MAX8997_LED_MOVIE_CUR_MASK;
		reg = MAX8997_REG_MOVIE_CUR;
		break;
	default:
		break;
	}

	if (mask) {
		ret = max8997_update_reg(client, reg, val, mask);
		if (ret)
			dev_err(led->iodev->dev,
				"failed to update register(%d)\n", ret);
	}
}
Ejemplo n.º 8
0
static ssize_t max8997_muic_set_otg_test(struct device *dev,
				    struct device_attribute *attr,
				    const char *buf, size_t count)
{
	struct max8997_muic_info *info = dev_get_drvdata(dev);
	struct i2c_client *client = info->muic;
	u8 val;

	if (!strncmp(buf, "0", 1))
		val = 0;
	else if (!strncmp(buf, "1", 1))
		val = 1;
	else {
		dev_warn(info->dev, "%s: Wrong command\n", __func__);
		return count;
	}

	max8997_update_reg(client, MAX8997_MUIC_REG_CDETCTRL,
			val << CHGDETEN_SHIFT, CHGDETEN_MASK);

	val = 0;
	max8997_read_reg(client, MAX8997_MUIC_REG_CDETCTRL, &val);
	dev_info(info->dev, "%s: CDETCTRL(0x%02x)\n", __func__, val);

	return count;
}
static int max8997_disable_charging(struct chg_data *chg)
{
	struct i2c_client *i2c = chg->max8997->i2c;
	int ret;
	u8 mask;

	dev_info(chg->dev, "%s: disable charging\n", __func__);
	mask = MBCHOSTEN_MASK | VCHGR_FC_MASK;
	ret = max8997_update_reg(i2c, MAX8997_REG_MBCCTRL2, 0, mask);
	if (ret < 0)
		dev_err(chg->dev, "%s: fail update reg!!!\n", __func__);

	return ret;
}
static int max8997_enable_charging(struct chg_data *chg)
{
	struct i2c_client *i2c = chg->max8997->i2c;
	int ret;
	u8 val, mask;

	/* set auto stop disable */
	ret = max8997_update_reg(i2c, MAX8997_REG_MBCCTRL6,
			(0 << AUTOSTOP_SHIFT), AUTOSTOP_MASK);
	if (ret)
		dev_err(chg->dev, "%s: failt to disable autostop(%d)\n",
				__func__, ret);

	/* set fast charging enable and main battery charging enable */
	val = (1 << MBCHOSTEN_SHIFT) | (1 << VCHGR_FC_SHIFT);
	mask = MBCHOSTEN_MASK | VCHGR_FC_MASK;
	ret = max8997_update_reg(i2c, MAX8997_REG_MBCCTRL2, val, mask);
	if (ret)
		dev_err(chg->dev, "%s: failt to enable charging(%d)\n",
				__func__, ret);

	return ret;
}
Ejemplo n.º 11
0
/*
 * max8997_muic_set_path - Set hardware line according to attached cable
 * @info: the instance including private data of max8997 MUIC
 * @value: the path according to attached cable
 * @attached: the state of cable (true:attached, false:detached)
 *
 * The max8997 MUIC device share outside H/W line among a varity of cables,
 * so this function set internal path of H/W line according to the type of
 * attached cable.
 */
static int max8997_muic_set_path(struct max8997_muic_info *info,
		u8 val, bool attached)
{
	int ret = 0;
	u8 ctrl1, ctrl2 = 0;

	if (attached)
		ctrl1 = val;
	else
		ctrl1 = CONTROL1_SW_OPEN;

	ret = max8997_update_reg(info->muic,
			MAX8997_MUIC_REG_CONTROL1, ctrl1, COMP_SW_MASK);
	if (ret < 0) {
		dev_err(info->dev, "failed to update MUIC register\n");
		return ret;
	}

	if (attached)
		ctrl2 |= CONTROL2_CPEN_MASK;	/* LowPwr=0, CPEn=1 */
	else
		ctrl2 |= CONTROL2_LOWPWR_MASK;	/* LowPwr=1, CPEn=0 */

	ret = max8997_update_reg(info->muic,
			MAX8997_MUIC_REG_CONTROL2, ctrl2,
			CONTROL2_LOWPWR_MASK | CONTROL2_CPEN_MASK);
	if (ret < 0) {
		dev_err(info->dev, "failed to update MUIC register\n");
		return ret;
	}

	dev_info(info->dev,
		"CONTROL1 : 0x%02x, CONTROL2 : 0x%02x, state : %s\n",
		ctrl1, ctrl2, attached ? "attached" : "detached");

	return 0;
}
Ejemplo n.º 12
0
static void max8997_led_set_mode(struct max8997_led *led,
			enum max8997_led_mode mode)
{
	int ret;
	struct i2c_client *client = led->iodev->i2c;
	u8 mask = 0, val;

	switch (mode) {
	case MAX8997_FLASH_MODE:
		mask = MAX8997_LED1_FLASH_MASK | MAX8997_LED0_FLASH_MASK;
		val = led->id ?
		      MAX8997_LED1_FLASH_MASK : MAX8997_LED0_FLASH_MASK;
		led->cdev.max_brightness = MAX8997_LED_FLASH_MAX_BRIGHTNESS;
		break;
	case MAX8997_MOVIE_MODE:
		mask = MAX8997_LED1_MOVIE_MASK | MAX8997_LED0_MOVIE_MASK;
		val = led->id ?
		      MAX8997_LED1_MOVIE_MASK : MAX8997_LED0_MOVIE_MASK;
		led->cdev.max_brightness = MAX8997_LED_MOVIE_MAX_BRIGHTNESS;
		break;
	case MAX8997_FLASH_PIN_CONTROL_MODE:
		mask = MAX8997_LED1_FLASH_PIN_MASK |
		       MAX8997_LED0_FLASH_PIN_MASK;
		val = led->id ?
		      MAX8997_LED1_FLASH_PIN_MASK : MAX8997_LED0_FLASH_PIN_MASK;
		led->cdev.max_brightness = MAX8997_LED_FLASH_MAX_BRIGHTNESS;
		break;
	case MAX8997_MOVIE_PIN_CONTROL_MODE:
		mask = MAX8997_LED1_MOVIE_PIN_MASK |
		       MAX8997_LED0_MOVIE_PIN_MASK;
		val = led->id ?
		      MAX8997_LED1_MOVIE_PIN_MASK : MAX8997_LED0_MOVIE_PIN_MASK;
		led->cdev.max_brightness = MAX8997_LED_MOVIE_MAX_BRIGHTNESS;
		break;
	default:
		led->cdev.max_brightness = MAX8997_LED_NONE_MAX_BRIGHTNESS;
		break;
	}

	if (mask) {
		ret = max8997_update_reg(client, MAX8997_REG_LEN_CNTL, val,
					 mask);
		if (ret)
			dev_err(led->iodev->dev,
				"failed to update register(%d)\n", ret);
	}

	led->led_mode = mode;
}
static int max8997_chg_set_property(struct power_supply *psy,
			    enum power_supply_property psp,
			    const union power_supply_propval *val)
{
	int ret, reg_val;
	struct chg_data *chg = container_of(psy, struct chg_data, psy_bat);
	struct i2c_client *i2c = chg->max8997->i2c;

	switch (psp) {
	case POWER_SUPPLY_PROP_CHARGE_TYPE: /* TODO: remove this */
		if (val->intval == POWER_SUPPLY_CHARGE_TYPE_NONE)
			ret = max8997_disable_charging(chg);
		else
			ret = max8997_enable_charging_x(chg, val->intval);
		break;
	case POWER_SUPPLY_PROP_CURRENT_NOW: /* Set charging current */
		ret = max8997_set_charging_current(chg, val->intval);
		break;
	case POWER_SUPPLY_PROP_STATUS:	/* Enable/Disable charging */
		if (val->intval == POWER_SUPPLY_STATUS_CHARGING)
			ret = max8997_enable_charging(chg);
		else
			ret = max8997_disable_charging(chg);
		break;
	case POWER_SUPPLY_PROP_CHARGE_FULL: /* Set recharging current */
		if (val->intval < 50 || val->intval > 200) {
			dev_err(chg->dev, "%s: invalid topoff current(%d)\n",
					__func__, val->intval);
			return -EINVAL;
		}
		reg_val = (val->intval - 50) / 10;

		dev_info(chg->dev, "%s: Set toppoff current to 0x%x\n",
				__func__, reg_val);
		ret = max8997_update_reg(i2c, MAX8997_REG_MBCCTRL5,
				(reg_val << ITOPOFF_SHIFT), ITOPOFF_MASK);
		if (ret) {
			dev_err(chg->dev, "%s: max8997 update reg error(%d)\n",
					__func__, ret);
			return ret;
		}
		break;
	default:
		return -EINVAL;
	}
	return ret;
}
Ejemplo n.º 14
0
static void max8997_muic_handle_jig_uart(struct max8997_muic_info *info,
					 u8 vbvolt)
{
	struct max8997_muic_data *mdata = info->muic_data;
	enum cable_type prev_ct = info->cable_type;
	bool is_otgtest = false;
	u8 cntl1_val, cntl1_msk;

	dev_info(info->dev, "%s: JIG UART/BOOTOFF(0x%x)\n", __func__, vbvolt);

#if defined(CONFIG_SEC_MODEM_M0_TD)
	gpio_set_value(GPIO_AP_CP_INT1, 1);
#endif

	/* UT1, UR2 */
	cntl1_val = (3 << COMN1SW_SHIFT) | (3 << COMP2SW_SHIFT);
	cntl1_msk = COMN1SW_MASK | COMP2SW_MASK;
	max8997_update_reg(info->muic, MAX8997_MUIC_REG_CTRL1, cntl1_val,
			   cntl1_msk);

	if (vbvolt & STATUS2_VBVOLT_MASK) {
		if (mdata->host_notify_cb) {
			if (mdata->host_notify_cb(1) == NOTIFY_TEST_MODE) {
				is_otgtest = true;
				dev_info(info->dev, "%s: OTG TEST\n", __func__);
			}
		}

		info->cable_type = CABLE_TYPE_JIG_UART_OFF_VB;
		max8997_muic_set_charging_type(info, is_otgtest);

	} else {
		info->cable_type = CABLE_TYPE_JIG_UART_OFF;
#if 0
		if (mdata->uart_path == UART_PATH_CP &&
				mdata->jig_uart_cb)
			mdata->jig_uart_cb(UART_PATH_CP);
#endif
		if (prev_ct == CABLE_TYPE_JIG_UART_OFF_VB) {
			max8997_muic_set_charging_type(info, false);

			if (mdata->host_notify_cb)
				mdata->host_notify_cb(0);
		}
	}
}
Ejemplo n.º 15
0
static void max8997_led_enable(struct max8997_led *led, bool enable)
{
	int ret;
	struct i2c_client *client = led->iodev->i2c;
	u8 val = 0, mask = MAX8997_LED_BOOST_ENABLE_MASK;

	if (led->enabled == enable)
		return;

	val = enable ? MAX8997_LED_BOOST_ENABLE_MASK : 0;

	ret = max8997_update_reg(client, MAX8997_REG_BOOST_CNTL, val, mask);
	if (ret)
		dev_err(led->iodev->dev,
			"failed to update register(%d)\n", ret);

	led->enabled = enable;
}
static int max8997_muic_handle_jig_uart(struct max8997_muic_info *info,
			bool attached)
{
	struct max8997_muic_platform_data *mdata = info->muic_pdata;
	int ret = 0;

	
	ret = max8997_update_reg(info->muic, MAX8997_MUIC_REG_CONTROL1,
				attached ? MAX8997_SW_UART : MAX8997_SW_OPEN,
				SW_MASK);
	if (ret) {
		dev_err(info->dev, "failed to update muic register\n");
		goto out;
	}

	if (mdata->uart_callback)
		mdata->uart_callback(attached);
out:
	return ret;
}
static int max8997_set_charging_current(struct chg_data *chg, int chg_current)
{
	struct i2c_client *i2c = chg->max8997->i2c;
	int ret;
	u8 val;

	if (chg_current < 200 || chg_current > 950)
		return -EINVAL;

	val = ((chg_current - 200) / 50) & 0xf;

	dev_info(chg->dev, "%s: charging current=%d", __func__, chg_current);
	ret = max8997_update_reg(i2c, MAX8997_REG_MBCCTRL4,
		(val << MBCICHFC_SHIFT), MBCICHFC_MASK);
	if (ret)
		dev_err(chg->dev, "%s: fail to write chg current(%d)\n",
				__func__, ret);

	return ret;
}
Ejemplo n.º 18
0
void max8997_muic_shutdown(struct device *dev)
{
	struct max8997_muic_info *info = dev_get_drvdata(dev);
	int ret;
	u8 val;

	if (!info->muic) {
		dev_err(info->dev, "%s: no muic i2c client\n", __func__);
		return;
	}

	dev_info(info->dev, "%s: JIGSet: auto detection\n", __func__);
	val = (0 << CTRL3_JIGSET_SHIFT) | (0 << CTRL3_BOOTSET_SHIFT);

	ret = max8997_update_reg(info->muic, MAX8997_MUIC_REG_CTRL3, val,
			CTRL3_JIGSET_MASK | CTRL3_BOOTSET_MASK);
	if (ret < 0) {
		dev_err(info->dev, "%s: fail to update reg\n", __func__);
		return;
	}
}
static int max8997_muic_handle_usb(struct max8997_muic_info *info,
			enum max8997_muic_usb_type usb_type, bool attached)
{
	struct max8997_muic_platform_data *mdata = info->muic_pdata;
	int ret = 0;

	if (usb_type == MAX8997_USB_HOST) {
		
		ret = max8997_update_reg(info->muic, MAX8997_MUIC_REG_CONTROL1,
				attached ? MAX8997_SW_USB : MAX8997_SW_OPEN,
				SW_MASK);
		if (ret) {
			dev_err(info->dev, "failed to update muic register\n");
			goto out;
		}
	}

	if (mdata->usb_callback)
		mdata->usb_callback(usb_type, attached);
out:
	return ret;
}
static void max8997_led_clear_mode(struct max8997_led *led,
			enum max8997_led_mode mode)
{
	struct i2c_client *client = led->iodev->i2c;
	u8 val = 0, mask = 0;
	int ret;

	switch (mode) {
	case MAX8997_FLASH_MODE:
		mask = led->id ?
		      MAX8997_LED1_FLASH_MASK : MAX8997_LED0_FLASH_MASK;
		break;
	case MAX8997_MOVIE_MODE:
		mask = led->id ?
		      MAX8997_LED1_MOVIE_MASK : MAX8997_LED0_MOVIE_MASK;
		break;
	case MAX8997_FLASH_PIN_CONTROL_MODE:
		mask = led->id ?
		      MAX8997_LED1_FLASH_PIN_MASK : MAX8997_LED0_FLASH_PIN_MASK;
		break;
	case MAX8997_MOVIE_PIN_CONTROL_MODE:
		mask = led->id ?
		      MAX8997_LED1_MOVIE_PIN_MASK : MAX8997_LED0_MOVIE_PIN_MASK;
		break;
	default:
		break;
	}

	if (mask) {
		ret = max8997_update_reg(client,
				MAX8997_REG_LEN_CNTL, val, mask);
		if (ret)
			dev_err(led->iodev->dev,
				"failed to update register(%d)\n", ret);
	}
}
Ejemplo n.º 21
0
static void max8997_muic_set_adcdbset(struct max8997_muic_info *info,
					int value)
{
	int ret;
	u8 val;

	if (value > 3) {
		dev_err(info->dev, "%s: invalid value(%d)\n", __func__, value);
		return;
	}

	if (!info->muic) {
		dev_err(info->dev, "%s: no muic i2c client\n", __func__);
		return;
	}

	val = value << CTRL3_ADCDBSET_SHIFT;
	dev_info(info->dev, "%s: ADCDBSET(0x%02x)\n", __func__, val);

	ret = max8997_update_reg(info->muic, MAX8997_MUIC_REG_CTRL3, val,
			CTRL3_ADCDBSET_MASK);
	if (ret < 0)
		dev_err(info->dev, "%s: fail to update reg\n", __func__);
}
Ejemplo n.º 22
0
static int max8997_muic_set_usb_path(struct max8997_muic_info *info, int path)
{
	struct i2c_client *client = info->muic;
	struct max8997_muic_data *mdata = info->muic_data;
	int ret;
	int gpio_val;
	u8 accdet, cntl1_val, cntl1_msk = 0, cntl2_val;

	if (mdata->set_safeout) {
		ret = mdata->set_safeout(path);
		if (ret) {
			dev_err(info->dev, "%s: fail to set safout!\n",
					__func__);
			return ret;
		}
	}

	switch (path) {
	case AP_USB_MODE:
		dev_info(info->dev, "%s: AP_USB_MODE\n", __func__);
		gpio_val = 0;
		accdet = 1;

		if (info->cable_type == CABLE_TYPE_OTG) {
			accdet = 0;
			/* DN1, DP2 */
			cntl1_val = (1 << COMN1SW_SHIFT) | (1 << COMP2SW_SHIFT);
			cntl1_msk = COMN1SW_MASK | COMP2SW_MASK;
		}
		break;
	case CP_USB_MODE:
		dev_info(info->dev, "%s: CP_USB_MODE\n", __func__);
		gpio_val = 1;
		accdet = 0;
		/* UT1, UR2 */
		cntl1_val = (3 << COMN1SW_SHIFT) | (3 << COMP2SW_SHIFT);
		cntl1_msk = COMN1SW_MASK | COMP2SW_MASK;
		break;
	case AUDIO_MODE:
		dev_info(info->dev, "%s: AUDIO_MODE\n", __func__);
		gpio_val = 0;
		accdet = 0;
		/* SL1, SR2 */
		cntl1_val = (2 << COMN1SW_SHIFT) | (2 << COMP2SW_SHIFT) |
			    (0 << MICEN_SHIFT);
		cntl1_msk = COMN1SW_MASK | COMP2SW_MASK | MICEN_MASK;
		break;
	default:
		dev_warn(info->dev, "%s: invalid path(%d)\n", __func__, path);
		return -EINVAL;
	}

#if !defined(CONFIG_TARGET_LOCALE_NA) && !defined(CONFIG_MACH_U1CAMERA_BD)
	if (gpio_is_valid(info->muic_data->gpio_usb_sel))
		gpio_direction_output(mdata->gpio_usb_sel, gpio_val);
#endif /* !CONFIG_TARGET_LOCALE_NA && !CONFIG_MACH_U1CAMERA_BD */
	/* Enable/Disable Factory Accessory Detection State Machine */
	cntl2_val = accdet << CTRL2_ACCDET_SHIFT;
	max8997_update_reg(client, MAX8997_MUIC_REG_CTRL2, cntl2_val,
			CTRL2_ACCDET_MASK);

	if (!accdet) {
		dev_info(info->dev, "%s: Set manual path\n", __func__);
		max8997_update_reg(client, MAX8997_MUIC_REG_CTRL1, cntl1_val,
				   cntl1_msk);

		cntl1_val = 0;
		max8997_read_reg(client, MAX8997_MUIC_REG_CTRL1, &cntl1_val);
		dev_info(info->dev, "%s: CNTL1(0x%02x)\n", __func__, cntl1_val);
	}

	return 0;
}
static int max8997_muic_handle_detach(struct max8997_muic_info *info)
{
	struct i2c_client *client = info->muic;
	struct max8997_muic_data *mdata = info->muic_data;
	cable_type_t prev_ct = CABLE_TYPE_NONE;
	int ret = 0;

	/* Workaround: irq doesn't occur after detaching mHL cable */
	max8997_write_reg(client, MAX8997_MUIC_REG_CTRL1, 0x00);

	/* Enable Factory Accessory Detection State Machine */
	max8997_update_reg(client, MAX8997_MUIC_REG_CTRL2,
			(1 << CTRL2_ACCDET_SHIFT), CTRL2_ACCDET_MASK);

	info->previous_key = DOCK_KEY_NONE;

	if (info->cable_type == CABLE_TYPE_NONE) {
		dev_info(info->dev, "%s: duplicated(NONE)\n", __func__);
		return 0;
	}
#if 0
	if (mdata->jig_uart_cb)
		mdata->jig_uart_cb(UART_PATH_AP);
#endif
	if (mdata->is_mhl_attached && mdata->is_mhl_attached()
			&& info->cable_type == CABLE_TYPE_MHL) {
		dev_info(info->dev, "%s: MHL attached. Do Nothing\n",
				__func__);
		return 0;
	}

	switch (info->cable_type) {
	case CABLE_TYPE_OTG:
		dev_info(info->dev, "%s: OTG\n", __func__);
		info->cable_type = CABLE_TYPE_NONE;

		if (mdata->usb_cb && info->is_usb_ready)
			mdata->usb_cb(USB_OTGHOST_DETACHED);
		break;
	case CABLE_TYPE_USB:
	case CABLE_TYPE_JIG_USB_OFF:
	case CABLE_TYPE_JIG_USB_ON:
		dev_info(info->dev, "%s: USB(0x%x)\n", __func__,
				info->cable_type);
		prev_ct = info->cable_type;
		info->cable_type = CABLE_TYPE_NONE;

		ret = max8997_muic_set_charging_type(info, false);
		if (ret) {
			info->cable_type = prev_ct;
			break;
		}

		if (mdata->sw_path == CP_USB_MODE)
			return 0;

		if (mdata->usb_cb && info->is_usb_ready)
			mdata->usb_cb(USB_CABLE_DETACHED);
		break;
	case CABLE_TYPE_DESKDOCK:
		dev_info(info->dev, "%s: DESKDOCK\n", __func__);
		info->cable_type = CABLE_TYPE_NONE;

		ret = max8997_muic_set_charging_type(info, false);
		if (ret) {
			info->cable_type = CABLE_TYPE_DESKDOCK;
			break;
		}

		if (mdata->deskdock_cb)
			mdata->deskdock_cb(MAX8997_MUIC_DETACHED);
		break;
	case CABLE_TYPE_CARDOCK:
		dev_info(info->dev, "%s: CARDOCK\n", __func__);
		info->cable_type = CABLE_TYPE_NONE;

		ret = max8997_muic_set_charging_type(info, false);
		if (ret) {
			info->cable_type = CABLE_TYPE_CARDOCK;
			break;
		}

		if (mdata->cardock_cb)
			mdata->cardock_cb(MAX8997_MUIC_DETACHED);
		break;
	case CABLE_TYPE_TA:
		dev_info(info->dev, "%s: TA\n", __func__);
		info->cable_type = CABLE_TYPE_NONE;
		ret = max8997_muic_set_charging_type(info, false);
		if (ret)
			info->cable_type = CABLE_TYPE_TA;
		break;
	case CABLE_TYPE_JIG_UART_ON:
		dev_info(info->dev, "%s: JIG UART/BOOTON\n", __func__);
		info->cable_type = CABLE_TYPE_NONE;
		break;
	case CABLE_TYPE_JIG_UART_OFF:
		dev_info(info->dev, "%s: JIG UART/BOOTOFF\n", __func__);
		info->cable_type = CABLE_TYPE_NONE;
		break;
	case CABLE_TYPE_JIG_UART_OFF_VB:
		dev_info(info->dev, "%s: JIG UART/OFF/VB\n", __func__);
		info->cable_type = CABLE_TYPE_NONE;
		ret = max8997_muic_set_charging_type(info, false);
		if (ret)
			info->cable_type = CABLE_TYPE_JIG_UART_OFF_VB;
		break;
	case CABLE_TYPE_MHL:
		dev_info(info->dev, "%s: MHL\n", __func__);
		info->cable_type = CABLE_TYPE_NONE;
		break;
	case CABLE_TYPE_MHL_VB:
		dev_info(info->dev, "%s: MHL VBUS\n", __func__);
		info->cable_type = CABLE_TYPE_NONE;
		max8997_muic_set_charging_type(info, false);

		if (mdata->is_mhl_attached && mdata->is_mhl_attached()) {
			if (mdata->mhl_cb && info->is_mhl_ready)
				mdata->mhl_cb(MAX8997_MUIC_DETACHED);
		}
		break;
	case CABLE_TYPE_UNKNOWN:
		dev_info(info->dev, "%s: UNKNOWN\n", __func__);
		info->cable_type = CABLE_TYPE_NONE;

		ret = max8997_muic_set_charging_type(info, false);
		if (ret)
			info->cable_type = CABLE_TYPE_UNKNOWN;
		break;
	default:
		dev_info(info->dev, "%s:invalid cable type %d\n",
				__func__, info->cable_type);
		break;
	}
	return ret;
}
Ejemplo n.º 24
0
static int max8997_muic_handle_detach(struct max8997_muic_info *info)
{
	struct i2c_client *client = info->muic;
	struct max8997_muic_data *mdata = info->muic_data;
	enum cable_type prev_ct = CABLE_TYPE_NONE;
	int ret = 0;

#if defined(CONFIG_SEC_MODEM_M0_TD)
	gpio_set_value(GPIO_AP_CP_INT1, 0);
#endif

	/*
	 * MAX8996/8997-MUIC bug:
	 *
	 * Auto-switching COMN/P is not restored automatically when detached and
	 * remains undetermined state. UART(UT1, UR2) will be short (because TA
	 * D+/D- is short) if charger(TA) insertion is followed right after the
	 * JIG off. Reset CONTROL1 is needed when detaching cable.
	 */
	max8997_write_reg(client, MAX8997_MUIC_REG_CTRL1, 0x00);

	if (info->cable_type == CABLE_TYPE_MHL) {

		/* Enable Factory Accessory Detection State Machine */
		max8997_update_reg(client, MAX8997_MUIC_REG_CTRL2,
				(1 << CTRL2_ACCDET_SHIFT), CTRL2_ACCDET_MASK);
	}

#ifdef CONFIG_USBHUB_USB3803
	/* setting usb hub in default mode (standby) */
	usb3803_set_mode(USB_3803_MODE_STANDBY);
#endif  /* CONFIG_USBHUB_USB3803 */
	info->previous_key = DOCK_KEY_NONE;

	if (info->cable_type == CABLE_TYPE_NONE) {
		dev_info(info->dev, "%s: duplicated(NONE)\n", __func__);
		return 0;
	}
#if 0
	if (mdata->jig_uart_cb)
		mdata->jig_uart_cb(UART_PATH_AP);
#endif
	if (mdata->is_mhl_attached && mdata->is_mhl_attached()
			&& info->cable_type == CABLE_TYPE_MHL) {
		dev_info(info->dev, "%s: MHL attached. Do Nothing\n",
				__func__);
		return 0;
	}

	switch (info->cable_type) {
	case CABLE_TYPE_OTG:
		dev_info(info->dev, "%s: OTG\n", __func__);
		info->cable_type = CABLE_TYPE_NONE;

		if (mdata->usb_cb && info->is_usb_ready)
			mdata->usb_cb(USB_OTGHOST_DETACHED);
		break;
	case CABLE_TYPE_USB:
	case CABLE_TYPE_JIG_USB_OFF:
	case CABLE_TYPE_JIG_USB_ON:
		dev_info(info->dev, "%s: USB(0x%x)\n", __func__,
				info->cable_type);
		prev_ct = info->cable_type;
		info->cable_type = CABLE_TYPE_NONE;

		ret = max8997_muic_set_charging_type(info, false);
		if (ret) {
			info->cable_type = prev_ct;
			break;
		}

		if (mdata->sw_path == CP_USB_MODE)
			return 0;

		if (mdata->usb_cb && info->is_usb_ready)
			mdata->usb_cb(USB_CABLE_DETACHED);
		break;
	case CABLE_TYPE_DESKDOCK:
		dev_info(info->dev, "%s: DESKDOCK\n", __func__);
		info->cable_type = CABLE_TYPE_NONE;

		ret = max8997_muic_set_charging_type(info, false);
		if (ret) {
			info->cable_type = CABLE_TYPE_DESKDOCK;
			break;
		}

		if (mdata->deskdock_cb)
			mdata->deskdock_cb(MAX8997_MUIC_DETACHED);
		break;
	case CABLE_TYPE_CARDOCK:
		dev_info(info->dev, "%s: CARDOCK\n", __func__);
		info->cable_type = CABLE_TYPE_NONE;

		ret = max8997_muic_set_charging_type(info, false);
		if (ret) {
			info->cable_type = CABLE_TYPE_CARDOCK;
			break;
		}

		if (mdata->cardock_cb)
			mdata->cardock_cb(MAX8997_MUIC_DETACHED);
		break;
	case CABLE_TYPE_TA:
		dev_info(info->dev, "%s: TA\n", __func__);
		info->cable_type = CABLE_TYPE_NONE;
		ret = max8997_muic_set_charging_type(info, false);
		if (ret)
			info->cable_type = CABLE_TYPE_TA;
		break;
	case CABLE_TYPE_JIG_UART_ON:
		dev_info(info->dev, "%s: JIG UART/BOOTON\n", __func__);
		info->cable_type = CABLE_TYPE_NONE;
		break;
	case CABLE_TYPE_JIG_UART_OFF:
		dev_info(info->dev, "%s: JIG UART/BOOTOFF\n", __func__);
		info->cable_type = CABLE_TYPE_NONE;
		break;
	case CABLE_TYPE_JIG_UART_OFF_VB:
		dev_info(info->dev, "%s: JIG UART/OFF/VB\n", __func__);
		info->cable_type = CABLE_TYPE_NONE;
		ret = max8997_muic_set_charging_type(info, false);
		if (ret)
			info->cable_type = CABLE_TYPE_JIG_UART_OFF_VB;
		break;
	case CABLE_TYPE_MHL:
		dev_info(info->dev, "%s: MHL\n", __func__);
		info->cable_type = CABLE_TYPE_NONE;
		break;
	case CABLE_TYPE_MHL_VB:
		dev_info(info->dev, "%s: MHL VBUS\n", __func__);
		info->cable_type = CABLE_TYPE_NONE;
		max8997_muic_set_charging_type(info, false);

		if (mdata->is_mhl_attached && mdata->is_mhl_attached()) {
			if (mdata->mhl_cb && info->is_mhl_ready)
				mdata->mhl_cb(MAX8997_MUIC_DETACHED);
		}
		break;
	case CABLE_TYPE_UNKNOWN:
		dev_info(info->dev, "%s: UNKNOWN\n", __func__);
		info->cable_type = CABLE_TYPE_NONE;

		ret = max8997_muic_set_charging_type(info, false);
		if (ret)
			info->cable_type = CABLE_TYPE_UNKNOWN;
		break;
	default:
		dev_info(info->dev, "%s:invalid cable type %d\n",
				__func__, info->cable_type);
		break;
	}
	return ret;
}
static __devinit int max8997_charger_probe(struct platform_device *pdev)
{
	struct max8997_dev *max8997 = dev_get_drvdata(pdev->dev.parent);
	struct max8997_platform_data *pdata = dev_get_platdata(max8997->dev);
	struct i2c_client *i2c = max8997->i2c;
	struct chg_data *chg;
	int ret = 0;

	dev_info(&pdev->dev, "%s : MAX8997 Charger Driver Loading\n", __func__);

	chg = kzalloc(sizeof(*chg), GFP_KERNEL);
	if (!chg)
		return -ENOMEM;

	chg->dev = &pdev->dev;
	chg->max8997 = max8997;
	chg->power = pdata->power;
	chg->irq_topoff = max8997->irq_base + MAX8997_IRQ_TOPOFF;

	chg->irq_chgins = max8997->irq_base + MAX8997_IRQ_CHGINS;
	chg->irq_chgrm = max8997->irq_base + MAX8997_IRQ_CHGRM;

	chg->psy_bat.name = "max8997-charger",
	chg->psy_bat.type = POWER_SUPPLY_TYPE_BATTERY,
	chg->psy_bat.properties = max8997_battery_props,
	chg->psy_bat.num_properties = ARRAY_SIZE(max8997_battery_props),
	chg->psy_bat.get_property = max8997_chg_get_property,
	chg->psy_bat.set_property = max8997_chg_set_property,

	platform_set_drvdata(pdev, chg);

	/* TODO: configure by platform data*/
	ret = max8997_update_reg(i2c, MAX8997_REG_MBCCTRL1, /* Disable */
		(0x7 << TFCH_SHIFT), TFCH_MASK);
	if (ret < 0)
		goto err_kfree;

	/* TODO: configure by platform data*/
	ret = max8997_update_reg(i2c, MAX8997_REG_MBCCTRL3, /* 4.2V */
		(0x0 << MBCCV_SHIFT), MBCCV_MASK);
	if (ret < 0)
		goto err_kfree;

	/* init power supplier framework */
	ret = power_supply_register(&pdev->dev, &chg->psy_bat);
	if (ret) {
		pr_err("Failed to register power supply psy_bat\n");
		goto err_kfree;
	}

	ret = request_threaded_irq(chg->irq_topoff, NULL,
			max8997_chg_topoff_irq, 0, "chg-topoff", chg);
	if (ret < 0)
		dev_err(&pdev->dev, "%s: fail to request topoff IRQ: %d: %d\n",
				__func__, chg->irq_topoff, ret);

	ret = request_threaded_irq(chg->irq_chgins, NULL,
			max8997_chg_charger_irq, 0, "chg-insert", chg);
	if (ret < 0)
		dev_err(&pdev->dev, "%s: fail to request chgins IRQ: %d: %d\n",
				__func__, chg->irq_chgins, ret);

	ret = request_threaded_irq(chg->irq_chgrm, NULL,
			max8997_chg_charger_irq, 0, "chg-remove", chg);
	if (ret < 0)
		dev_err(&pdev->dev, "%s: fail to request chgrm IRQ: %d: %d\n",
				__func__, chg->irq_chgrm, ret);

	return 0;

err_kfree:
	kfree(chg);
	return ret;
}
Ejemplo n.º 26
0
static int max8997_battery_probe(struct platform_device *pdev)
{
	int ret = 0;
	struct charger_data *charger;
	struct max8997_dev *iodev = dev_get_drvdata(pdev->dev.parent);
	struct max8997_platform_data *pdata = dev_get_platdata(iodev->dev);
	struct power_supply_config psy_cfg = {};

	if (!pdata)
		return -EINVAL;

	if (pdata->eoc_mA) {
		int val = (pdata->eoc_mA - 50) / 10;
		if (val < 0)
			val = 0;
		if (val > 0xf)
			val = 0xf;

		ret = max8997_update_reg(iodev->i2c,
				MAX8997_REG_MBCCTRL5, val, 0xf);
		if (ret < 0) {
			dev_err(&pdev->dev, "Cannot use i2c bus.\n");
			return ret;
		}
	}

	switch (pdata->timeout) {
	case 5:
		ret = max8997_update_reg(iodev->i2c, MAX8997_REG_MBCCTRL1,
				0x2 << 4, 0x7 << 4);
		break;
	case 6:
		ret = max8997_update_reg(iodev->i2c, MAX8997_REG_MBCCTRL1,
				0x3 << 4, 0x7 << 4);
		break;
	case 7:
		ret = max8997_update_reg(iodev->i2c, MAX8997_REG_MBCCTRL1,
				0x4 << 4, 0x7 << 4);
		break;
	case 0:
		ret = max8997_update_reg(iodev->i2c, MAX8997_REG_MBCCTRL1,
				0x7 << 4, 0x7 << 4);
		break;
	default:
		dev_err(&pdev->dev, "incorrect timeout value (%d)\n",
				pdata->timeout);
		return -EINVAL;
	}
	if (ret < 0) {
		dev_err(&pdev->dev, "Cannot use i2c bus.\n");
		return ret;
	}

	charger = devm_kzalloc(&pdev->dev, sizeof(struct charger_data),
				GFP_KERNEL);
	if (charger == NULL) {
		dev_err(&pdev->dev, "Cannot allocate memory.\n");
		return -ENOMEM;
	}

	platform_set_drvdata(pdev, charger);


	charger->dev = &pdev->dev;
	charger->iodev = iodev;

	psy_cfg.drv_data = charger;

	charger->battery = power_supply_register(&pdev->dev,
						 &max8997_battery_desc,
						 &psy_cfg);
	if (IS_ERR(charger->battery)) {
		dev_err(&pdev->dev, "failed: power supply register\n");
		return PTR_ERR(charger->battery);
	}

	return 0;
}