Beispiel #1
0
static void max14577_muic_irq_work(struct work_struct *work)
{
	struct max14577_muic_info *info = container_of(work,
			struct max14577_muic_info, irq_work);
	int ret = 0;

	if (!info->edev)
		return;

	mutex_lock(&info->mutex);

	ret = max14577_bulk_read(info->max14577->regmap,
			MAX14577_MUIC_REG_STATUS1, info->status, 2);
	if (ret) {
		dev_err(info->dev, "failed to read MUIC register\n");
		mutex_unlock(&info->mutex);
		return;
	}

	if (info->irq_adc) {
		ret = max14577_muic_adc_handler(info);
		info->irq_adc = false;
	}
	if (info->irq_chg) {
		ret = max14577_muic_chg_handler(info);
		info->irq_chg = false;
	}

	if (ret < 0)
		dev_err(info->dev, "failed to handle MUIC interrupt\n");

	mutex_unlock(&info->mutex);
}
static ssize_t max14577_muic_show_dump_reg(struct device *dev,
						   struct device_attribute *attr, char *buf)
{
	struct max14577_muic_data *muic_data = dev_get_drvdata(dev);
	u8 stat[3] = {0};
	u8 ctrl[3] = {0};
	u8 cdet[2] = {0};

	max14577_bulk_read(muic_data->i2c, MAX14577_MUIC_REG_STATUS1, 3, stat);
	max14577_bulk_read(muic_data->i2c, MAX14577_MUIC_REG_CONTROL1, 3, ctrl);
	max14577_bulk_read(muic_data->i2c, MAX14577_REG_CDETCTRL1, 2, cdet);

	return sprintf(buf,
		"reg :   1  /   2  /   3  \n"
		"stat: 0x%02x / 0x%02x / 0x%02x\n"
		"ctrl: 0x%02x / 0x%02x / 0x%02x\n"
		"cdet: 0x%02x / 0x%02x /\n",
		stat[0], stat[1], stat[2], ctrl[0], ctrl[1], ctrl[2], cdet[0], cdet[1]);
}
static irqreturn_t max14577_irq_thread(int irq, void *data)
{
	struct max14577_dev *max14577 = data;
	struct max14577_platform_data *pdata = max14577->pdata;
	u8 irq_reg[MAX14577_IRQ_REGS_NUM] = {0};
	u8 tmp_irq_reg[MAX14577_IRQ_REGS_NUM] = {};
	int gpio_val;
	int i;

	pr_debug("%s: irq gpio pre-state(0x%02x)\n", __func__,
		gpio_get_value(pdata->irq_gpio));

	do {
		/* MAX14577 INT1 ~ INT3 */
		max14577_bulk_read(max14577->i2c, MAX14577_REG_INT1,
				MAX14577_IRQ_REGS_NUM,
				&tmp_irq_reg[MAX14577_IRQ_INT1]);

		/* Or temp irq register to irq register for if it retries */
		for (i = MAX14577_IRQ_INT1; i < MAX14577_IRQ_REGS_NUM; i++)
			irq_reg[i] |= tmp_irq_reg[i];

		pr_info("%s: interrupt[1:0x%02x, 2:0x%02x, 3:0x%02x]\n",
			__func__, irq_reg[MAX14577_IRQ_INT1],
			irq_reg[MAX14577_IRQ_INT2], irq_reg[MAX14577_IRQ_INT3]);

		gpio_val = gpio_get_value(pdata->irq_gpio);

		pr_debug("%s: irq gpio post-state(0x%02x)\n", __func__,
				gpio_val);

		if (gpio_get_value(pdata->irq_gpio) == 0)
			pr_warn("%s: irq_gpio is not High, retry read int reg\n",
					__func__);
	} while (gpio_val == 0);

	/* Apply masking */
	for (i = 0; i < MAX14577_IRQ_REGS_NUM; i++)
		irq_reg[i] &= max14577->irq_masks_cur[i];

	/* Report */
	for (i = 0; i < MAX14577_IRQ_NUM; i++) {
		if (irq_reg[max14577_irqs[i].group] & max14577_irqs[i].mask)
			handle_nested_irq(pdata->irq_base + i);
	}

	return IRQ_HANDLED;
}
Beispiel #4
0
static int max14577_muic_detect_accessory(struct max14577_muic_info *info)
{
	int ret = 0;
	int adc;
	int chg_type;
	bool attached;

	mutex_lock(&info->mutex);

	/* Read STATUSx register to detect accessory */
	ret = max14577_bulk_read(info->max14577->regmap,
			MAX14577_MUIC_REG_STATUS1, info->status, 2);
	if (ret) {
		dev_err(info->dev, "failed to read MUIC register\n");
		mutex_unlock(&info->mutex);
		return ret;
	}

	adc = max14577_muic_get_cable_type(info, MAX14577_CABLE_GROUP_ADC,
					&attached);
	if (attached && adc != MAX14577_MUIC_ADC_OPEN) {
		ret = max14577_muic_adc_handler(info);
		if (ret < 0) {
			dev_err(info->dev, "Cannot detect accessory\n");
			mutex_unlock(&info->mutex);
			return ret;
		}
	}

	chg_type = max14577_muic_get_cable_type(info, MAX14577_CABLE_GROUP_CHG,
					&attached);
	if (attached && chg_type != MAX14577_CHARGER_TYPE_NONE) {
		ret = max14577_muic_chg_handler(info);
		if (ret < 0) {
			dev_err(info->dev, "Cannot detect charger accessory\n");
			mutex_unlock(&info->mutex);
			return ret;
		}
	}

	mutex_unlock(&info->mutex);

	return 0;
}
Beispiel #5
0
static void max14577_muic_detect_dev(struct max14577_muic_data *muic_data, int irq)
{
	struct i2c_client *i2c = muic_data->i2c;
	const struct max14577_muic_vps_data *tmp_vps;
	muic_attached_dev_t new_dev = ATTACHED_DEV_UNKNOWN_MUIC;
	int intr = MUIC_INTR_DETACH;
	u8 status[2];
	u8 adcerr, adclow, adc, vbvolt, chgdetrun, chgtyp;
	int ret;
	int i;

	ret = max14577_bulk_read(i2c, MAX14577_MUIC_REG_STATUS1, 2, status);
	if (ret) {
		pr_err("%s:%s fail to read muic reg(%d)\n", MUIC_DEV_NAME,
				__func__, ret);
		return;
	}

	pr_info("%s:%s STATUS1:0x%02x, 2:0x%02x\n", MUIC_DEV_NAME, __func__,
			status[0], status[1]);

	adcerr = status[0] & STATUS1_ADCERR_MASK;
	adclow = status[0] & STATUS1_ADCLOW_MASK;
	adc = status[0] & STATUS1_ADC_MASK;
	vbvolt = status[1] & STATUS2_VBVOLT_MASK;
	chgdetrun = status[1] & STATUS2_CHGDETRUN_MASK;
	chgtyp = status[1] & STATUS2_CHGTYP_MASK;

	pr_info("%s:%s adcerr:0x%x adclow:0x%x adc:0x%x vb:0x%x chgdetrun:0x%x"
			" chgtyp:0x%x\n", MUIC_DEV_NAME, __func__, adcerr,
			adclow, adc, vbvolt, chgdetrun, chgtyp);

	/* Workaround for Factory mode.
	 * Abandon adc interrupt of approximately +-100K range
	 * if previous cable status was JIG UART BOOT OFF.
	 */
	if (muic_data->attached_dev == ATTACHED_DEV_JIG_UART_OFF_MUIC) {
		if ((adc == (ADC_JIG_UART_OFF + 1)) ||
				(adc == (ADC_JIG_UART_OFF - 1))) {
			pr_warn("%s:%s abandon ADC\n", MUIC_DEV_NAME, __func__);
			return;
		}
	}

	for (i = 0; i < ARRAY_SIZE(muic_vps_table); i++) {
		tmp_vps = &(muic_vps_table[i]);

		if (tmp_vps->adcerr != adcerr)
			continue;

		if (tmp_vps->adclow != adclow)
			continue;

		if (tmp_vps->adc != adc)
			continue;

		if (tmp_vps->vbvolt != vbvolt)
			continue;

		if (tmp_vps->chgdetrun != chgdetrun)
			continue;

		if (tmp_vps->chgtyp != chgtyp)
			continue;

		pr_info("%s:%s vps table match found at i(%d), %s\n",
				MUIC_DEV_NAME, __func__, i, tmp_vps->vps_name);

		new_dev = tmp_vps->attached_dev;

		intr = MUIC_INTR_ATTACH;
		break;
	}

	if (intr == MUIC_INTR_ATTACH) {
		pr_info("%s:%s ATTACHED\n", MUIC_DEV_NAME, __func__);
		max14577_muic_handle_attach(muic_data, new_dev);
	} else {
		pr_info("%s:%s DETACHED\n", MUIC_DEV_NAME, __func__);
		max14577_muic_handle_detach(muic_data);
	}
	return;
}