static ssize_t max8997_muic_show_status(struct device *dev,
					struct device_attribute *attr,
					char *buf)
{
	struct max8997_muic_info *info = dev_get_drvdata(dev);
	u8 devid, int_value[3], status[3], intmask[3], ctrl[3], cdetctrl;

	max8997_read_reg(info->muic, MAX8997_MUIC_REG_ID, &devid);
	max8997_bulk_read(info->muic, MAX8997_MUIC_REG_INT1, 3, int_value);
	max8997_bulk_read(info->muic, MAX8997_MUIC_REG_STATUS1, 3, status);
	max8997_bulk_read(info->muic, MAX8997_MUIC_REG_INTMASK1, 3, intmask);
	max8997_bulk_read(info->muic, MAX8997_MUIC_REG_CTRL1, 3, ctrl);
	max8997_read_reg(info->muic, MAX8997_MUIC_REG_CDETCTRL, &cdetctrl);

	return sprintf(buf,
		       "Device ID(0x%02x)\n"
			   "INT1(0x%02x), INT2(0x%02x), INT3(0x%02x)\n"
		       "STATUS1(0x%02x), STATUS2(0x%02x), STATUS3(0x%02x)\n"
		       "INTMASK1(0x%02x), INTMASK2(0x%02x), INTMASK3(0x%02x)\n"
		       "CTRL1(0x%02x), CTRL2(0x%02x), CTRL3(0x%02x)\n"
		       "CDETCTRL(0x%02x)\n",
		       devid, int_value[0], int_value[1], int_value[2],
		       status[0], status[1], status[2],
		       intmask[0], intmask[1], intmask[2],
		       ctrl[0], ctrl[1], ctrl[2],
		       cdetctrl);
}
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;
}
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;
}
Пример #4
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);
}
Пример #5
0
/* Note that the charger control is done by a current regulator "CHARGER" */
static int max8997_battery_get_property(struct power_supply *psy,
		enum power_supply_property psp,
		union power_supply_propval *val)
{
	struct charger_data *charger = power_supply_get_drvdata(psy);
	struct i2c_client *i2c = charger->iodev->i2c;
	int ret;
	u8 reg;

	switch (psp) {
	case POWER_SUPPLY_PROP_STATUS:
		val->intval = 0;
		ret = max8997_read_reg(i2c, MAX8997_REG_STATUS4, &reg);
		if (ret)
			return ret;
		if ((reg & (1 << 0)) == 0x1)
			val->intval = POWER_SUPPLY_STATUS_FULL;

		break;
	case POWER_SUPPLY_PROP_PRESENT:
		val->intval = 0;
		ret = max8997_read_reg(i2c, MAX8997_REG_STATUS4, &reg);
		if (ret)
			return ret;
		if ((reg & (1 << 2)) == 0x0)
			val->intval = 1;

		break;
	case POWER_SUPPLY_PROP_ONLINE:
		val->intval = 0;
		ret = max8997_read_reg(i2c, MAX8997_REG_STATUS4, &reg);
		if (ret)
			return ret;
		/* DCINOK */
		if (reg & (1 << 1))
			val->intval = 1;

		break;
	default:
		return -EINVAL;
	}

	return 0;
}
Пример #6
0
static int max8997_freeze(struct device *dev)
{
	struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
	struct max8997_dev *max8997 = i2c_get_clientdata(i2c);
	int i;

	for (i = 0; i < ARRAY_SIZE(max8997_dumpaddr_pmic); i++)
		max8997_read_reg(i2c, max8997_dumpaddr_pmic[i],
				&max8997->reg_dump[i]);

	for (i = 0; i < ARRAY_SIZE(max8997_dumpaddr_muic); i++)
		max8997_read_reg(i2c, max8997_dumpaddr_muic[i],
				&max8997->reg_dump[i + MAX8997_REG_PMIC_END]);

	for (i = 0; i < ARRAY_SIZE(max8997_dumpaddr_haptic); i++)
		max8997_read_reg(i2c, max8997_dumpaddr_haptic[i],
				&max8997->reg_dump[i + MAX8997_REG_PMIC_END +
				MAX8997_MUIC_REG_END]);

	return 0;
}
static ssize_t max8997_muic_show_audio_path(struct device *dev,
		struct device_attribute *attr, char *buf)
{
	struct max8997_muic_info *info = dev_get_drvdata(dev);
	int ret;
	u8 val;

	ret = max8997_read_reg(info->muic, MAX8997_MUIC_REG_CTRL1, &val);
	if (ret) {
		dev_err(info->dev, "%s: fail to read muic reg\n", __func__);
		return sprintf(buf, "UNKNOWN\n");
	}

	return sprintf(buf, "%x\n", val);
}
/* whether charging enabled or not */
static bool max8997_check_vdcin(struct chg_data *chg)
{
	struct i2c_client *i2c = chg->max8997->i2c;
	u8 data = 0;
	int ret;

	ret = max8997_read_reg(i2c, MAX8997_REG_STATUS4, &data);

	if (ret < 0) {
		dev_err(chg->dev, "%s: max8997_read_reg error(%d)\n", __func__,
				ret);
		return ret;
	}

	return data & DCINOK_MASK;
}
static void max8997_muic_dump_regs(struct max8997_muic_info *info)
{
	int i, ret;
	u8 val;

	for (i = 0; i < MAX8997_MUIC_REG_END; i++) {
		ret = max8997_read_reg(info->muic, i, &val);
		if (ret) {
			dev_err(info->dev, "%s: fail to read reg(0x%x)\n",
					__func__, i);
			continue;
		}
		dev_info(info->dev, "%s: ADDR : 0x%02x, DATA : 0x%02x\n",
				__func__, i, val);
	}
}
static int max8997_muic_handle_charger_type(struct max8997_muic_info *info,
				enum max8997_muic_charger_type charger_type)
{
	struct max8997_muic_platform_data *mdata = info->muic_pdata;
	u8 adc;
	int ret;

	ret = max8997_read_reg(info->muic, MAX8997_MUIC_REG_STATUS1, &adc);
	if (ret) {
		dev_err(info->dev, "failed to read muic register\n");
		goto out;
	}

	switch (charger_type) {
	case MAX8997_CHARGER_TYPE_NONE:
		if (mdata->charger_callback)
			mdata->charger_callback(false, charger_type);
		if (info->pre_charger_type == MAX8997_CHARGER_TYPE_USB) {
			max8997_muic_handle_usb(info,
					MAX8997_USB_DEVICE, false);
		}
		break;
	case MAX8997_CHARGER_TYPE_USB:
		if ((adc & STATUS1_ADC_MASK) == MAX8997_ADC_OPEN) {
			max8997_muic_handle_usb(info,
					MAX8997_USB_DEVICE, true);
		}
		if (mdata->charger_callback)
			mdata->charger_callback(true, charger_type);
		break;
	case MAX8997_CHARGER_TYPE_DOWNSTREAM_PORT:
	case MAX8997_CHARGER_TYPE_DEDICATED_CHG:
	case MAX8997_CHARGER_TYPE_500MA:
	case MAX8997_CHARGER_TYPE_1A:
		if (mdata->charger_callback)
			mdata->charger_callback(true, charger_type);
		break;
	default:
		break;
	}

	info->pre_charger_type = charger_type;
out:
	return ret;
}
/* vf check */
static bool max8997_check_detbat(struct chg_data *chg)
{
	struct i2c_client *i2c = chg->max8997->i2c;
	u8 data = 0;
	int ret;

	ret = max8997_read_reg(i2c, MAX8997_REG_STATUS4, &data);

	if (ret < 0) {
		dev_err(chg->dev, "%s: max8997_read_reg error(%d)\n", __func__,
				ret);
		return ret;
	}

	if (data & DETBAT_MASK)
		printk("%s: batt not detected(0x%x)\n", __func__, data);

	return data & DETBAT_MASK;
}
Пример #12
0
static int max8997_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
	struct max8997_rtc_info *info = dev_get_drvdata(dev);
	u8 data[RTC_NR_TIME];
	u8 val;
	int i, ret;

	mutex_lock(&info->lock);

	ret = max8997_bulk_read(info->rtc, MAX8997_RTC_ALARM1_SEC, RTC_NR_TIME,
			data);
	if (ret < 0) {
		dev_err(info->dev, "%s:%d fail to read alarm reg(%d)\n",
				__func__, __LINE__, ret);
		goto out;
	}

	max8997_rtc_data_to_tm(data, &alrm->time, info->rtc_24hr_mode);

	alrm->enabled = 0;
	for (i = 0; i < RTC_NR_TIME; i++) {
		if (data[i] & ALARM_ENABLE_MASK) {
			alrm->enabled = 1;
			break;
		}
	}

	alrm->pending = 0;
	ret = max8997_read_reg(info->max8997->i2c, MAX8997_REG_STATUS1, &val);
	if (ret < 0) {
		dev_err(info->dev, "%s:%d fail to read status1 reg(%d)\n",
				__func__, __LINE__, ret);
		goto out;
	}

	if (val & (1 << 4)) /* RTCA1 */
		alrm->pending = 1;

out:
	mutex_unlock(&info->lock);
	return 0;
}
Пример #13
0
static ssize_t max8997_muic_show_adc_debounce_time(struct device *dev,
				struct device_attribute *attr, char *buf)
{
	struct max8997_muic_info *info = dev_get_drvdata(dev);
	int ret;
	u8 val;

	if (!info->muic)
		return sprintf(buf, "No I2C client\n");

	ret = max8997_read_reg(info->muic, MAX8997_MUIC_REG_CTRL3, &val);
	if (ret) {
		dev_err(info->dev, "%s: fail to read muic reg\n", __func__);
		return sprintf(buf, "UNKNOWN\n");
	}
	val &= CTRL3_ADCDBSET_MASK;
	val = val >> CTRL3_ADCDBSET_SHIFT;

	return sprintf(buf, "%x\n", val);
}
Пример #14
0
static int max8997_muic_freeze(struct device *dev)
{
	struct platform_device *pdev = to_platform_device(dev);
	struct max8997_muic_info *info;
	int i;
	info = platform_get_drvdata(pdev);

	for (i = 0; i < ARRAY_SIZE(max8997_dumpaddr_muic); i++)
		max8997_read_reg(info->max8997->muic, max8997_dumpaddr_muic[i],
			&info->max8997->reg_dump[i + MAX8997_REG_PMIC_END]);

	cancel_delayed_work(&info->init_work);
	cancel_delayed_work(&info->usb_work);
	cancel_delayed_work(&info->mhl_work);

	/* hibernation state, disconnect usb state*/
	dev_info(info->dev, "%s: DETACHED\n", __func__);
	mutex_lock(&info->mutex);
	max8997_muic_handle_detach(info);
	mutex_unlock(&info->mutex);

	return 0;
}
Пример #15
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;
}
Пример #16
0
static irqreturn_t max8997_irq_thread(int irq, void *data)
{
	struct max8997_dev *max8997 = data;
	u8 irq_reg[MAX8997_IRQ_GROUP_NR] = {};
	u8 irq_src;
	int ret;
	int i, cur_irq;

	ret = max8997_read_reg(max8997->i2c, MAX8997_REG_INTSRC, &irq_src);
	if (ret < 0) {
		dev_err(max8997->dev, "Failed to read interrupt source: %d\n",
				ret);
		return IRQ_NONE;
	}

	if (irq_src & MAX8997_IRQSRC_PMIC) {
		/* PMIC INT1 ~ INT4 */
		max8997_bulk_read(max8997->i2c, MAX8997_REG_INT1, 4,
				&irq_reg[PMIC_INT1]);
	}
	if (irq_src & MAX8997_IRQSRC_FUELGAUGE) {
		/*
		 * TODO: FUEL GAUGE
		 *
		 * This is to be supported by Max17042 driver. When
		 * an interrupt incurs here, it should be relayed to a
		 * Max17042 device that is connected (probably by
		 * platform-data). However, we do not have interrupt
		 * handling in Max17042 driver currently. The Max17042 IRQ
		 * driver should be ready to be used as a stand-alone device and
		 * a Max8997-dependent device. Because it is not ready in
		 * Max17042-side and it is not too critical in operating
		 * Max8997, we do not implement this in initial releases.
		 */
		irq_reg[FUEL_GAUGE] = 0;
	}
	if (irq_src & MAX8997_IRQSRC_MUIC) {
		/* MUIC INT1 ~ INT3 */
		max8997_bulk_read(max8997->muic, MAX8997_MUIC_REG_INT1, 3,
				&irq_reg[MUIC_INT1]);
	}
	if (irq_src & MAX8997_IRQSRC_GPIO) {
		/* GPIO Interrupt */
		u8 gpio_info[MAX8997_NUM_GPIO];

		irq_reg[GPIO_LOW] = 0;
		irq_reg[GPIO_HI] = 0;

		max8997_bulk_read(max8997->i2c, MAX8997_REG_GPIOCNTL1,
				MAX8997_NUM_GPIO, gpio_info);
		for (i = 0; i < MAX8997_NUM_GPIO; i++) {
			bool interrupt = false;

			switch (gpio_info[i] & MAX8997_GPIO_INT_MASK) {
			case MAX8997_GPIO_INT_BOTH:
				if (max8997->gpio_status[i] != gpio_info[i])
					interrupt = true;
				break;
			case MAX8997_GPIO_INT_RISE:
				if ((max8997->gpio_status[i] != gpio_info[i]) &&
				    (gpio_info[i] & MAX8997_GPIO_DATA_MASK))
					interrupt = true;
				break;
			case MAX8997_GPIO_INT_FALL:
				if ((max8997->gpio_status[i] != gpio_info[i]) &&
				    !(gpio_info[i] & MAX8997_GPIO_DATA_MASK))
					interrupt = true;
				break;
			default:
				break;
			}

			if (interrupt) {
				if (i < 8)
					irq_reg[GPIO_LOW] |= (1 << i);
				else
					irq_reg[GPIO_HI] |= (1 << (i - 8));
			}

		}
	}
	if (irq_src & MAX8997_IRQSRC_FLASH) {
		/* Flash Status Interrupt */
		ret = max8997_read_reg(max8997->i2c, MAX8997_REG_FLASHSTATUS,
				&irq_reg[FLASH_STATUS]);
	}

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

	/* Report */
	for (i = 0; i < MAX8997_IRQ_NR; i++) {
		if (irq_reg[max8997_irqs[i].group] & max8997_irqs[i].mask) {
			cur_irq = irq_find_mapping(max8997->irq_domain, i);
			if (cur_irq)
				handle_nested_irq(cur_irq);
		}
	}

	return IRQ_HANDLED;
}
Пример #17
0
int max8997_irq_init(struct max8997_dev *max8997)
{
	struct irq_domain *domain;
	int i;
	int ret;
	u8 val;

	if (!max8997->irq) {
		dev_warn(max8997->dev, "No interrupt specified.\n");
		return 0;
	}

	mutex_init(&max8997->irqlock);

	/* Mask individual interrupt sources */
	for (i = 0; i < MAX8997_IRQ_GROUP_NR; i++) {
		struct i2c_client *i2c;

		max8997->irq_masks_cur[i] = 0xff;
		max8997->irq_masks_cache[i] = 0xff;
		i2c = get_i2c(max8997, i);

		if (IS_ERR_OR_NULL(i2c))
			continue;
		if (max8997_mask_reg[i] == MAX8997_REG_INVALID)
			continue;

		max8997_write_reg(i2c, max8997_mask_reg[i], 0xff);
	}

	for (i = 0; i < MAX8997_NUM_GPIO; i++) {
		max8997->gpio_status[i] = (max8997_read_reg(max8997->i2c,
						MAX8997_REG_GPIOCNTL1 + i,
						&val)
					& MAX8997_GPIO_DATA_MASK) ?
					true : false;
	}

	domain = irq_domain_add_linear(NULL, MAX8997_IRQ_NR,
					&max8997_irq_domain_ops, max8997);
	if (!domain) {
		dev_err(max8997->dev, "could not create irq domain\n");
		return -ENODEV;
	}
	max8997->irq_domain = domain;

	ret = request_threaded_irq(max8997->irq, NULL, max8997_irq_thread,
			IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
			"max8997-irq", max8997);

	if (ret) {
		dev_err(max8997->dev, "Failed to request IRQ %d: %d\n",
				max8997->irq, ret);
		return ret;
	}

	if (!max8997->ono)
		return 0;

	ret = request_threaded_irq(max8997->ono, NULL, max8997_irq_thread,
			IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING |
			IRQF_ONESHOT, "max8997-ono", max8997);

	if (ret)
		dev_err(max8997->dev, "Failed to request ono-IRQ %d: %d\n",
				max8997->ono, ret);

	return 0;
}