예제 #1
0
파일: da9052_wdt.c 프로젝트: 020gzh/linux
static int da9052_wdt_ping(struct watchdog_device *wdt_dev)
{
	struct da9052_wdt_data *driver_data = watchdog_get_drvdata(wdt_dev);
	struct da9052 *da9052 = driver_data->da9052;
	unsigned long msec, jnow = jiffies;
	int ret;

	/*
	 * We have a minimum time for watchdog window called TWDMIN. A write
	 * to the watchdog before this elapsed time should cause an error.
	 */
	msec = (jnow - driver_data->jpast) * 1000/HZ;
	if (msec < DA9052_TWDMIN)
		mdelay(msec);

	/* Reset the watchdog timer */
	ret = da9052_reg_update(da9052, DA9052_CONTROL_D_REG,
				DA9052_CONTROLD_WATCHDOG, 1 << 7);
	if (ret < 0)
		goto err_strobe;

	/*
	 * FIXME: Reset the watchdog core, in general PMIC
	 * is supposed to do this
	 */
	ret = da9052_reg_update(da9052, DA9052_CONTROL_D_REG,
				DA9052_CONTROLD_WATCHDOG, 0 << 7);
err_strobe:
	return ret;
}
예제 #2
0
static int da9052_configure_leds(struct da9052 *da9052)
{
	int error;
	unsigned char register_value = DA9052_OPENDRAIN_OUTPUT
				       | DA9052_SET_HIGH_LVL_OUTPUT;

	error = da9052_reg_update(da9052, DA9052_GPIO_14_15_REG,
				  DA9052_MASK_LOWER_NIBBLE,
				  register_value);

	if (error < 0) {
		dev_err(da9052->dev, "Failed to write GPIO 14-15 reg, %d\n",
			error);
		return error;
	}

	error = da9052_reg_update(da9052, DA9052_GPIO_14_15_REG,
				  DA9052_MASK_UPPER_NIBBLE,
				  register_value << DA9052_NIBBLE_SHIFT);
	if (error < 0)
		dev_err(da9052->dev, "Failed to write GPIO 14-15 reg, %d\n",
			error);

	return error;
}
예제 #3
0
static int da9052_set_alarm(struct da9052 *da9052, struct rtc_time *rtc_tm)
{
	int ret;
	uint8_t v[3];

	rtc_tm->tm_year -= 100;
	rtc_tm->tm_mon += 1;

	ret = da9052_reg_update(da9052, DA9052_ALARM_MI_REG,
				DA9052_RTC_MIN, rtc_tm->tm_min);
	if (ret != 0) {
		rtc_err(da9052, "Failed to write ALRM MIN: %d\n", ret);
		return ret;
	}

	v[0] = rtc_tm->tm_hour;
	v[1] = rtc_tm->tm_mday;
	v[2] = rtc_tm->tm_mon;

	ret = da9052_group_write(da9052, DA9052_ALARM_H_REG, 3, v);
	if (ret < 0)
		return ret;

	ret = da9052_reg_update(da9052, DA9052_ALARM_Y_REG,
				DA9052_RTC_YEAR, rtc_tm->tm_year);
	if (ret != 0)
		rtc_err(da9052, "Failed to write ALRM YEAR: %d\n", ret);

	return ret;
}
예제 #4
0
파일: da9052_wdt.c 프로젝트: 020gzh/linux
static int da9052_wdt_set_timeout(struct watchdog_device *wdt_dev,
				  unsigned int timeout)
{
	struct da9052_wdt_data *driver_data = watchdog_get_drvdata(wdt_dev);
	struct da9052 *da9052 = driver_data->da9052;
	int ret, i;

	/*
	 * Disable the Watchdog timer before setting
	 * new time out.
	 */
	ret = da9052_reg_update(da9052, DA9052_CONTROL_D_REG,
				DA9052_CONTROLD_TWDSCALE, 0);
	if (ret < 0) {
		dev_err(da9052->dev, "Failed to disable watchdog bit, %d\n",
			ret);
		return ret;
	}
	if (timeout) {
		/*
		 * To change the timeout, da9052 needs to
		 * be disabled for at least 150 us.
		 */
		udelay(150);

		/* Set the desired timeout */
		for (i = 0; i < ARRAY_SIZE(da9052_wdt_maps); i++)
			if (da9052_wdt_maps[i].time == timeout)
				break;

		if (i == ARRAY_SIZE(da9052_wdt_maps))
			ret = -EINVAL;
		else
			ret = da9052_reg_update(da9052, DA9052_CONTROL_D_REG,
						DA9052_CONTROLD_TWDSCALE,
						da9052_wdt_maps[i].reg_val);
		if (ret < 0) {
			dev_err(da9052->dev,
				"Failed to update timescale bit, %d\n", ret);
			return ret;
		}

		wdt_dev->timeout = timeout;
		driver_data->jpast = jiffies;
	}

	return 0;
}
예제 #5
0
static int da9052_USB_current_notifier(struct notifier_block *nb,
					unsigned long events, void *data)
{
	u8 row;
	u8 col;
	int *current_mA = data;
	int ret;
	struct da9052_battery *bat = container_of(nb, struct da9052_battery,
						  nb);

	if (bat->status == POWER_SUPPLY_STATUS_DISCHARGING)
		return -EPERM;

	ret = da9052_reg_read(bat->da9052, DA9052_CHGBUCK_REG);
	if (ret & DA9052_CHG_USB_ILIM_MASK)
		return -EPERM;

	if (bat->da9052->chip_id == DA9052)
		row = 0;
	else
		row = 1;

	if (*current_mA < da9052_chg_current_lim[row][0] ||
	    *current_mA > da9052_chg_current_lim[row][DA9052_CHG_LIM_COLS - 1])
		return -EINVAL;

	for (col = 0; col <= DA9052_CHG_LIM_COLS - 1 ; col++) {
		if (*current_mA <= da9052_chg_current_lim[row][col])
			break;
	}

	return da9052_reg_update(bat->da9052, DA9052_ISET_REG,
				 DA9052_ISET_USB_MASK, col);
}
예제 #6
0
파일: rtc-da9052.c 프로젝트: 3null/linux
static int da9052_rtc_probe(struct platform_device *pdev)
{
	struct da9052_rtc *rtc;
	int ret;

	rtc = devm_kzalloc(&pdev->dev, sizeof(struct da9052_rtc), GFP_KERNEL);
	if (!rtc)
		return -ENOMEM;

	rtc->da9052 = dev_get_drvdata(pdev->dev.parent);
	platform_set_drvdata(pdev, rtc);

	ret = da9052_reg_write(rtc->da9052, DA9052_BBAT_CONT_REG, 0xFE);
	if (ret < 0) {
		rtc_err(rtc,
			"Failed to setup RTC battery charging: %d\n", ret);
		return ret;
	}

	ret = da9052_reg_update(rtc->da9052, DA9052_ALARM_Y_REG,
				DA9052_ALARM_Y_TICK_ON, 0);
	if (ret != 0)
		rtc_err(rtc, "Failed to disable TICKS: %d\n", ret);

	ret = da9052_request_irq(rtc->da9052, DA9052_IRQ_ALARM, "ALM",
				da9052_rtc_irq, rtc);
	if (ret != 0) {
		rtc_err(rtc, "irq registration failed: %d\n", ret);
		return ret;
	}

	rtc->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
				       &da9052_rtc_ops, THIS_MODULE);
	return PTR_ERR_OR_ZERO(rtc->rtc);
}
예제 #7
0
static int da9052_rtc_enable_alarm(struct da9052 *da9052, bool enable)
{
	int ret;
	if (enable) {
		ret = da9052_reg_update(da9052, DA9052_ALARM_Y_REG,
					DA9052_ALARM_Y_ALARM_ON,
					DA9052_ALARM_Y_ALARM_ON);
		if (ret != 0)
			rtc_err(da9052, "Failed to enable ALM: %d\n", ret);
	} else {
		ret = da9052_reg_update(da9052, DA9052_ALARM_Y_REG,
					DA9052_ALARM_Y_ALARM_ON, 0);
		if (ret != 0)
			rtc_err(da9052, "Write error: %d\n", ret);
	}
	return ret;
}
예제 #8
0
파일: rtc-da9052.c 프로젝트: 3null/linux
static int da9052_set_alarm(struct da9052_rtc *rtc, struct rtc_time *rtc_tm)
{
	struct da9052 *da9052 = rtc->da9052;
	unsigned long alm_time;
	int ret;
	uint8_t v[3];

	ret = rtc_tm_to_time(rtc_tm, &alm_time);
	if (ret != 0)
		return ret;

	if (rtc_tm->tm_sec > 0) {
		alm_time += 60 - rtc_tm->tm_sec;
		rtc_time_to_tm(alm_time, rtc_tm);
	}
	BUG_ON(rtc_tm->tm_sec); /* it will cause repeated irqs if not zero */

	rtc_tm->tm_year -= 100;
	rtc_tm->tm_mon += 1;

	ret = da9052_reg_update(da9052, DA9052_ALARM_MI_REG,
				DA9052_RTC_MIN, rtc_tm->tm_min);
	if (ret != 0) {
		rtc_err(rtc, "Failed to write ALRM MIN: %d\n", ret);
		return ret;
	}

	v[0] = rtc_tm->tm_hour;
	v[1] = rtc_tm->tm_mday;
	v[2] = rtc_tm->tm_mon;

	ret = da9052_group_write(da9052, DA9052_ALARM_H_REG, 3, v);
	if (ret < 0)
		return ret;

	ret = da9052_reg_update(da9052, DA9052_ALARM_Y_REG,
				DA9052_RTC_YEAR, rtc_tm->tm_year);
	if (ret != 0)
		rtc_err(rtc, "Failed to write ALRM YEAR: %d\n", ret);

	return ret;
}
예제 #9
0
파일: da9052_wdt.c 프로젝트: 020gzh/linux
static int da9052_wdt_probe(struct platform_device *pdev)
{
	struct da9052 *da9052 = dev_get_drvdata(pdev->dev.parent);
	struct da9052_wdt_data *driver_data;
	struct watchdog_device *da9052_wdt;
	int ret;

	driver_data = devm_kzalloc(&pdev->dev, sizeof(*driver_data),
				   GFP_KERNEL);
	if (!driver_data) {
		ret = -ENOMEM;
		goto err;
	}
	driver_data->da9052 = da9052;

	da9052_wdt = &driver_data->wdt;

	da9052_wdt->timeout = DA9052_DEF_TIMEOUT;
	da9052_wdt->info = &da9052_wdt_info;
	da9052_wdt->ops = &da9052_wdt_ops;
	da9052_wdt->parent = &pdev->dev;
	watchdog_set_drvdata(da9052_wdt, driver_data);

	ret = da9052_reg_update(da9052, DA9052_CONTROL_D_REG,
				DA9052_CONTROLD_TWDSCALE, 0);
	if (ret < 0) {
		dev_err(&pdev->dev, "Failed to disable watchdog bits, %d\n",
			ret);
		goto err;
	}

	ret = watchdog_register_device(&driver_data->wdt);
	if (ret != 0) {
		dev_err(da9052->dev, "watchdog_register_device() failed: %d\n",
			ret);
		goto err;
	}

	platform_set_drvdata(pdev, driver_data);
err:
	return ret;
}