Ejemplo n.º 1
0
static int alarm_set_rtc(struct timespec *ts)
{
	struct rtc_time new_rtc_tm;
	struct rtc_device *rtc_dev;
	unsigned long flags;
	int rv = 0;

	if (rtc_local_time)
		rtc_time_to_tm((ts->tv_sec - sys_tz.tz_minuteswest * 60), &new_rtc_tm);
	else
		rtc_time_to_tm(ts->tv_sec, &new_rtc_tm);
	rtc_dev = alarmtimer_get_rtcdev();
	rv = do_settimeofday(ts);
	if (rv < 0)
		return rv;
	if (rtc_dev)
		rv = rtc_set_time(rtc_dev, &new_rtc_tm);

	spin_lock_irqsave(&alarm_slock, flags);
	alarm_pending |= ANDROID_ALARM_TIME_CHANGE_MASK;
	wake_up(&alarm_wait_queue);
	spin_unlock_irqrestore(&alarm_slock, flags);

	return rv;
}
Ejemplo n.º 2
0
void alarm_set_power_on(struct timespec new_pwron_time, bool logo)
{
	unsigned long pwron_time;
	struct rtc_wkalrm alm;
	struct rtc_device *alarm_rtc_dev;
	
	pr_alarm(INFO, "alarm set power on\n");
	
#ifdef RTC_PWRON_SEC
	/* round down the second */
	new_pwron_time.tv_sec = (new_pwron_time.tv_sec / 60) * 60;
#endif
	if (new_pwron_time.tv_sec > 0) {
		pwron_time = new_pwron_time.tv_sec;
#ifdef RTC_PWRON_SEC
		pwron_time += RTC_PWRON_SEC;
#endif
		alm.enabled = (logo ? 3 : 2);
	} else {
		pwron_time = 0;
		alm.enabled = 4;
	}
	alarm_rtc_dev = alarmtimer_get_rtcdev();
	rtc_time_to_tm(pwron_time, &alm.time);
	
	rtc_set_alarm_poweron(alarm_rtc_dev, &alm);
}
static int alarm_set_rtc(struct timespec *ts)
{
	struct rtc_time new_rtc_tm;
	struct rtc_device *rtc_dev;
	unsigned long flags;
	int rv = 0;

	rtc_time_to_tm(ts->tv_sec, &new_rtc_tm);
#ifdef CONFIG_RTC_AUTO_PWRON
	pr_info("%s : set rtc %ld %ld - rtc %02d:%02d:%02d %02d/%02d/%04d\n", __func__,
		ts->tv_sec, ts->tv_nsec,
		new_rtc_tm.tm_hour, new_rtc_tm.tm_min,
		new_rtc_tm.tm_sec, new_rtc_tm.tm_mon + 1,
		new_rtc_tm.tm_mday,
		new_rtc_tm.tm_year + 1900);
#endif
	rtc_dev = alarmtimer_get_rtcdev();
	rv = do_settimeofday(ts);
	if (rv < 0)
		return rv;
	if (rtc_dev)
		rv = rtc_set_time(rtc_dev, &new_rtc_tm);

	spin_lock_irqsave(&alarm_slock, flags);
	alarm_pending |= ANDROID_ALARM_TIME_CHANGE_MASK;
	wake_up(&alarm_wait_queue);
	spin_unlock_irqrestore(&alarm_slock, flags);

	return rv;
}
Ejemplo n.º 4
0
static int alarm_set_rtc(struct timespec *ts)
{
	struct rtc_time new_rtc_tm;
	struct timespec old_rtc_time;
	struct rtc_device *rtc_dev;
	unsigned long flags;
	int rv = 0;

/* get original rct time */
		getnstimeofday(&old_rtc_time);

	rtc_time_to_tm(ts->tv_sec, &new_rtc_tm);
	rtc_dev = alarmtimer_get_rtcdev();
	rv = do_settimeofday(ts);
	if (rv < 0)
		return rv;
	if (rtc_dev)
		rv = rtc_set_time(rtc_dev, &new_rtc_tm);

	spin_lock_irqsave(&alarm_slock, flags);
	alarm_pending |= ANDROID_ALARM_TIME_CHANGE_MASK;
	delta += ts->tv_sec - old_rtc_time.tv_sec;
	wake_up(&alarm_wait_queue);
	wake_up(&alarm_wait_change_queue);
	spin_unlock_irqrestore(&alarm_slock, flags);

	return rv;
}
Ejemplo n.º 5
0
/**
 * alarm_clock_getres - posix getres interface
 * @which_clock: clockid
 * @tp: timespec to fill
 *
 * Returns the granularity of underlying alarm base clock
 */
static int alarm_clock_getres(const clockid_t which_clock, struct timespec *tp)
{
	clockid_t baseid = alarm_bases[clock2alarm(which_clock)].base_clockid;

	if (!alarmtimer_get_rtcdev())
		return -ENOTSUPP;

	return hrtimer_get_res(baseid, tp);
}
Ejemplo n.º 6
0
/**
 * alarm_clock_get - posix clock_get interface
 * @which_clock: clockid
 * @tp: timespec to fill.
 *
 * Provides the underlying alarm base time.
 */
static int alarm_clock_get(clockid_t which_clock, struct timespec *tp)
{
	struct alarm_base *base = &alarm_bases[clock2alarm(which_clock)];

	if (!alarmtimer_get_rtcdev())
		return -ENOTSUPP;

	*tp = ktime_to_timespec(base->gettime());
	return 0;
}
Ejemplo n.º 7
0
/**
 * alarm_timer_nsleep - alarmtimer nanosleep
 * @which_clock: clockid
 * @flags: determins abstime or relative
 * @tsreq: requested sleep time (abs or rel)
 * @rmtp: remaining sleep time saved
 *
 * Handles clock_nanosleep calls against _ALARM clockids
 */
static int alarm_timer_nsleep(const clockid_t which_clock, int flags,
		     struct timespec *tsreq, struct timespec __user *rmtp)
{
	enum  alarmtimer_type type = clock2alarm(which_clock);
	struct alarm alarm;
	ktime_t exp;
	int ret = 0;
	struct restart_block *restart;

	if (!alarmtimer_get_rtcdev())
		return -ENOTSUPP;

	if (!capable(CAP_WAKE_ALARM))
		return -EPERM;

	alarm_init(&alarm, type, alarmtimer_nsleep_wakeup);

	exp = timespec_to_ktime(*tsreq);
	/* Convert (if necessary) to absolute time */
	if (flags != TIMER_ABSTIME) {
		ktime_t now = alarm_bases[type].gettime();
		exp = ktime_add(now, exp);
	}

	if (alarmtimer_do_nsleep(&alarm, exp))
		goto out;

	if (freezing(current))
		alarmtimer_freezerset(exp, type);

	/* abs timers don't set remaining time or restart */
	if (flags == TIMER_ABSTIME) {
		ret = -ERESTARTNOHAND;
		goto out;
	}

	if (rmtp) {
		ret = update_rmtp(exp, type, rmtp);
		if (ret <= 0)
			goto out;
	}

	restart = &current_thread_info()->restart_block;
	restart->fn = alarm_timer_nsleep_restart;
	restart->nanosleep.clockid = type;
	restart->nanosleep.expires = exp.tv64;
	restart->nanosleep.rmtp = rmtp;
	ret = -ERESTART_RESTARTBLOCK;

out:
	return ret;
}
Ejemplo n.º 8
0
/**
 * alarm_timer_create - posix timer_create interface
 * @new_timer: k_itimer pointer to manage
 *
 * Initializes the k_itimer structure.
 */
static int alarm_timer_create(struct k_itimer *new_timer)
{
	enum  alarmtimer_type type;
	struct alarm_base *base;

	if (!alarmtimer_get_rtcdev())
		return -ENOTSUPP;

	if (!capable(CAP_WAKE_ALARM))
		return -EPERM;

	type = clock2alarm(new_timer->it_clock);
	base = &alarm_bases[type];
	alarm_init(&new_timer->it.alarmtimer, type, alarm_handle_timer);
	return 0;
}
static void bq2419x_shutdown(struct i2c_client *client)
{
	int ret = 0;
	struct bq2419x_chip *bq2419x = i2c_get_clientdata(client);
	int alarm_time = bq2419x->rtc_alarm_time;

	if (bq2419x->irq)
		disable_irq(bq2419x->irq);

	if (!bq2419x->rtc)
		bq2419x->rtc = alarmtimer_get_rtcdev();

	if (bq2419x->in_current_limit > 500) {
		dev_info(bq2419x->dev, "HighCurrent %dmA charger is connectd\n",
			bq2419x->in_current_limit);
		ret = bq2419x_reset_wdt(bq2419x, "shutdown");
		if (ret < 0)
			dev_err(bq2419x->dev,
				"bq2419x_reset_wdt failed: %d\n", ret);
		alarm_time = 20;
	}

	mutex_lock(&bq2419x->mutex);
	bq2419x->suspended = 1;
	mutex_unlock(&bq2419x->mutex);

	ret = bq2419x_charger_enable(bq2419x);
	if (ret < 0)
		dev_err(bq2419x->dev, "Charger enable failed %d", ret);

	if (bq2419x->in_current_limit <= 500) {
		/* Configure charging current to 500mA */
		ret = regmap_write(bq2419x->regmap,
				BQ2419X_INPUT_SRC_REG, 0x32);
		if (ret < 0)
			dev_err(bq2419x->dev,
				"INPUT_SRC_REG write failed %d\n", ret);
	}

	ret = bq2419x_wakealarm(bq2419x, alarm_time);
	if (ret < 0)
		dev_err(bq2419x->dev, "RTC wake alarm config failed %d\n", ret);
	cancel_delayed_work_sync(&bq2419x->otg_reset_work);
}
Ejemplo n.º 10
0
void power_on_alarm_init(void)
{
	struct rtc_wkalrm rtc_alarm;
	struct rtc_time rt;
	unsigned long alarm_time;
	struct rtc_device *rtc;

	rtc = alarmtimer_get_rtcdev();

	/* If we have no rtcdev, just return */
	if (!rtc)
		return;

	rtc_read_alarm(rtc, &rtc_alarm);
	rt = rtc_alarm.time;

	rtc_tm_to_time(&rt, &alarm_time);

	if (alarm_time)
		power_on_alarm = alarm_time;
	else
		power_on_alarm = 0;
}
Ejemplo n.º 11
0
int alarm_set_alarm(char* alarm_data)
{
	struct rtc_wkalrm alm;
	int ret;
	char buf_ptr[BOOTALM_BIT_TOTAL+1];
	struct rtc_time rtc_tm;
	unsigned long rtc_sec;
	unsigned long rtc_alarm_time;
	struct timespec rtc_delta;
	struct timespec wall_time;
	ktime_t wall_ktm;
	struct rtc_time wall_tm;
	struct rtc_device *rtc_dev = alarmtimer_get_rtcdev();

	if (!rtc_dev) {
		pr_err("%s: no RTC, time will be lost on reboot\n", __func__);
		return -ENXIO;
	}

	strlcpy(buf_ptr, alarm_data, BOOTALM_BIT_TOTAL+1);

	alm.time.tm_sec = 0;
	alm.time.tm_min = (buf_ptr[BOOTALM_BIT_MIN] - '0') * 10
				+ (buf_ptr[BOOTALM_BIT_MIN+1]  - '0');
	alm.time.tm_hour = (buf_ptr[BOOTALM_BIT_HOUR] - '0') * 10
				+ (buf_ptr[BOOTALM_BIT_HOUR+1] - '0');
	alm.time.tm_mday = (buf_ptr[BOOTALM_BIT_DAY] - '0') * 10
				+ (buf_ptr[BOOTALM_BIT_DAY+1] - '0');
	alm.time.tm_mon = (buf_ptr[BOOTALM_BIT_MONTH] - '0') * 10
				+ (buf_ptr[BOOTALM_BIT_MONTH+1] - '0');
	alm.time.tm_year = (buf_ptr[BOOTALM_BIT_YEAR] - '0') * 1000
				+ (buf_ptr[BOOTALM_BIT_YEAR+1] - '0') * 100
				+ (buf_ptr[BOOTALM_BIT_YEAR+2] - '0') * 10
				+ (buf_ptr[BOOTALM_BIT_YEAR+3] - '0');

	alm.enabled = (*buf_ptr == '1');

	pr_info("[SAPA] %s : %s => tm(%d %04d-%02d-%02d %02d:%02d:%02d)\n",
			__func__, buf_ptr, alm.enabled,
			alm.time.tm_year, alm.time.tm_mon, alm.time.tm_mday,
			alm.time.tm_hour, alm.time.tm_min, alm.time.tm_sec);

	if (alm.enabled) {
		/* If time daemon is exist */

		alm.time.tm_mon -= 1;
		alm.time.tm_year -= 1900;

		/* read current time */
		rtc_read_time(rtc_dev, &rtc_tm);
		rtc_tm_to_time(&rtc_tm, &rtc_sec);
		pr_info("[SAPA] rtc  %4d-%02d-%02d %02d:%02d:%02d -> %lu\n",
			rtc_tm.tm_year, rtc_tm.tm_mon, rtc_tm.tm_mday,
			rtc_tm.tm_hour, rtc_tm.tm_min, rtc_tm.tm_sec, rtc_sec);

		/* read kernel time */
		getnstimeofday(&wall_time);
		wall_ktm = timespec_to_ktime(wall_time);
		wall_tm = rtc_ktime_to_tm(wall_ktm);
		pr_info("[SAPA] wall %4d-%02d-%02d %02d:%02d:%02d -> %lu\n",
			wall_tm.tm_year, wall_tm.tm_mon, wall_tm.tm_mday,
			wall_tm.tm_hour, wall_tm.tm_min, wall_tm.tm_sec, wall_time.tv_sec);

		/* calculate offset */
		set_normalized_timespec(&rtc_delta,
					wall_time.tv_sec - rtc_sec,
					wall_time.tv_nsec);

		/* convert user requested SAPA time to second type */
		rtc_tm_to_time(&alm.time, &rtc_alarm_time);

		/* convert to RTC time with user requested SAPA time and offset */
		rtc_alarm_time -= rtc_delta.tv_sec;
		rtc_time_to_tm(rtc_alarm_time, &alm.time);
		pr_info("[SAPA] arlm %4d-%02d-%02d %02d:%02d:%02d -> %lu\n",
			alm.time.tm_year, alm.time.tm_mon, alm.time.tm_mday,
			alm.time.tm_hour, alm.time.tm_min, alm.time.tm_sec, rtc_alarm_time);

	}
	ret = rtc_set_bootalarm(rtc_dev, &alm);
	if (ret < 0) {
		pr_err("%s: Failed to set ALARM, time will be lost on reboot\n", __func__);
		return ret;
	}

	return 0;
}
Ejemplo n.º 12
0
static int __devinit bq2419x_probe(struct i2c_client *client,
				const struct i2c_device_id *id)
{
	struct bq2419x_chip *bq2419x;
	struct bq2419x_platform_data *pdata;
	int ret = 0;

	pdata = client->dev.platform_data;
	if (!pdata) {
		dev_err(&client->dev, "No Platform data");
		return -EINVAL;
	}

	bq2419x = devm_kzalloc(&client->dev, sizeof(*bq2419x), GFP_KERNEL);
	if (!bq2419x) {
		dev_err(&client->dev, "Memory allocation failed\n");
		return -ENOMEM;
	}

	bq2419x->regmap = devm_regmap_init_i2c(client, &bq2419x_regmap_config);
	if (IS_ERR(bq2419x->regmap)) {
		ret = PTR_ERR(bq2419x->regmap);
		dev_err(&client->dev, "regmap init failed with err %d\n", ret);
		return ret;
	}

	bq2419x->dev = &client->dev;

	if (pdata->bcharger_pdata) {
		bq2419x->update_status	= pdata->bcharger_pdata->update_status;
		bq2419x->rtc_alarm_time	= pdata->bcharger_pdata->rtc_alarm_time;
		bq2419x->wdt_time_sec	= pdata->bcharger_pdata->wdt_timeout;
		bq2419x->chg_restart_time =
					pdata->bcharger_pdata->chg_restart_time;
		bq2419x->chg_enable	= true;
	}

	bq2419x->wdt_refresh_timeout = 25;
	i2c_set_clientdata(client, bq2419x);
	bq2419x->irq = client->irq;

	if (bq2419x->rtc_alarm_time)
		bq2419x->rtc = alarmtimer_get_rtcdev();

	mutex_init(&bq2419x->mutex);
	bq2419x->suspended = 0;
	bq2419x->chg_restart_timeout = 0;

	ret = bq2419x_show_chip_version(bq2419x);
	if (ret < 0) {
		dev_err(&client->dev, "version read failed %d\n", ret);
		return ret;
	}

	ret = bq2419x_charger_init(bq2419x);
	if (ret < 0) {
		dev_err(bq2419x->dev, "Charger init failed: %d\n", ret);
		return ret;
	}

	ret = bq2419x_init_charger_regulator(bq2419x, pdata);
	if (ret < 0) {
		dev_err(&client->dev,
			"Charger regualtor init failed %d\n", ret);
		return ret;
	}

	ret = bq2419x_init_vbus_regulator(bq2419x, pdata);
	if (ret < 0) {
		dev_err(&client->dev,
			"VBUS regualtor init failed %d\n", ret);
		goto scrub_chg_reg;
	}

	init_kthread_worker(&bq2419x->bq_kworker);
	bq2419x->bq_kworker_task = kthread_run(kthread_worker_fn,
				&bq2419x->bq_kworker,
				dev_name(bq2419x->dev));
	if (IS_ERR(bq2419x->bq_kworker_task)) {
		ret = PTR_ERR(bq2419x->bq_kworker_task);
		dev_err(&client->dev, "Kworker task creation failed %d\n", ret);
		goto scrub_vbus_reg;
	}

	init_kthread_work(&bq2419x->bq_wdt_work, bq2419x_work_thread);
	sched_setscheduler(bq2419x->bq_kworker_task,
			SCHED_FIFO, &bq2419x_param);
	queue_kthread_work(&bq2419x->bq_kworker, &bq2419x->bq_wdt_work);

	ret = bq2419x_watchdog_init(bq2419x, bq2419x->wdt_time_sec, "PROBE");
	if (ret < 0) {
		dev_err(bq2419x->dev, "BQWDT init failed %d\n", ret);
		goto scrub_kthread;
	}

	ret = bq2419x_fault_clear_sts(bq2419x);
	if (ret < 0) {
		dev_err(bq2419x->dev, "fault clear status failed %d\n", ret);
		goto scrub_kthread;
	}

	ret = request_threaded_irq(bq2419x->irq, NULL,
		bq2419x_irq, IRQF_TRIGGER_FALLING,
			dev_name(bq2419x->dev), bq2419x);
	if (ret < 0) {
		dev_err(bq2419x->dev, "request IRQ %d fail, err = %d\n",
				bq2419x->irq, ret);
		goto scrub_kthread;
	}

	/* enable charging */
	ret = bq2419x_charger_enable(bq2419x);
	if (ret < 0)
		goto scrub_irq;

	return 0;
scrub_irq:
	free_irq(bq2419x->irq, bq2419x);
scrub_kthread:
	bq2419x->stop_thread = true;
	flush_kthread_worker(&bq2419x->bq_kworker);
	kthread_stop(bq2419x->bq_kworker_task);
scrub_vbus_reg:
	regulator_unregister(bq2419x->vbus_rdev);
scrub_chg_reg:
	regulator_unregister(bq2419x->chg_rdev);
	mutex_destroy(&bq2419x->mutex);
	return ret;
}
Ejemplo n.º 13
0
static long alarm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
	int rv = 0;
	unsigned long flags;
	struct timespec new_alarm_time;
	struct timespec new_rtc_time;
	struct timespec tmp_time;
	struct rtc_time new_rtc_tm;
	struct rtc_device *rtc_dev;
	struct rtc_wkalrm pwron_alm;
	enum android_alarm_type alarm_type = ANDROID_ALARM_IOCTL_TO_TYPE(cmd);
	uint32_t alarm_type_mask = 1U << alarm_type;

 	if (alarm_type >= ANDROID_ALARM_TYPE_COUNT &&
	    alarm_type != ANDROID_ALARM_POWER_ON &&
	    alarm_type != ANDROID_ALARM_POWER_ON_LOGO) {
		return -EINVAL;
	}
	
	if (ANDROID_ALARM_BASE_CMD(cmd) != ANDROID_ALARM_GET_TIME(0)) {
		if ((file->f_flags & O_ACCMODE) == O_RDONLY)
			return -EPERM;
		if (file->private_data == NULL &&
		    cmd != ANDROID_ALARM_SET_RTC) {
			spin_lock_irqsave(&alarm_slock, flags);
			if (alarm_opened) {
				spin_unlock_irqrestore(&alarm_slock, flags);
				return -EBUSY;
			}
			alarm_opened = 1;
			file->private_data = (void *)1;
			spin_unlock_irqrestore(&alarm_slock, flags);
		}
	}

	switch (ANDROID_ALARM_BASE_CMD(cmd)) {
	case ANDROID_ALARM_CLEAR(0):
		pr_alarm(IO, "alarm %d clear\n", alarm_type);
		if (alarm_type == ANDROID_ALARM_POWER_ON ||
			alarm_type == ANDROID_ALARM_POWER_ON_LOGO) {
			new_alarm_time.tv_sec = 0;
			alarm_set_power_on(new_alarm_time, false);
			break;
		}
		spin_lock_irqsave(&alarm_slock, flags);
		pr_alarm(IO, "alarm %d clear\n", alarm_type);
		devalarm_try_to_cancel(&alarms[alarm_type]);
		if (alarm_pending) {
			alarm_pending &= ~alarm_type_mask;
			if (!alarm_pending && !wait_pending)
				wake_unlock(&alarm_wake_lock);
		}
		alarm_enabled &= ~alarm_type_mask;
		spin_unlock_irqrestore(&alarm_slock, flags);
		break;

	case ANDROID_ALARM_SET_OLD:
	case ANDROID_ALARM_SET_AND_WAIT_OLD:
		if (get_user(new_alarm_time.tv_sec, (int __user *)arg)) {
			rv = -EFAULT;
			goto err1;
		}
		new_alarm_time.tv_nsec = 0;
		goto from_old_alarm_set;

	case ANDROID_ALARM_SET_AND_WAIT(0):
	case ANDROID_ALARM_SET(0):
		if (copy_from_user(&new_alarm_time, (void __user *)arg,
		    sizeof(new_alarm_time))) {
			rv = -EFAULT;
			goto err1;
		}
from_old_alarm_set:
		pr_alarm(IO, "alarm %d set %ld.%09ld\n", alarm_type,
			new_alarm_time.tv_sec, new_alarm_time.tv_nsec);

		if (alarm_type == ANDROID_ALARM_POWER_ON) {
			alarm_set_power_on(new_alarm_time, false);
			break;
		}
		if (alarm_type == ANDROID_ALARM_POWER_ON_LOGO) {
			alarm_set_power_on(new_alarm_time, true);
			break;
		}
		spin_lock_irqsave(&alarm_slock, flags);
	
		alarm_enabled |= alarm_type_mask;
		devalarm_start(&alarms[alarm_type],
			timespec_to_ktime(new_alarm_time));
		spin_unlock_irqrestore(&alarm_slock, flags);
		if (ANDROID_ALARM_BASE_CMD(cmd) != ANDROID_ALARM_SET_AND_WAIT(0)
		    && cmd != ANDROID_ALARM_SET_AND_WAIT_OLD)
			break;
		/* fall though */
	case ANDROID_ALARM_WAIT:
		spin_lock_irqsave(&alarm_slock, flags);
		pr_alarm(IO, "alarm wait\n");
		if (!alarm_pending && wait_pending) {
			wake_unlock(&alarm_wake_lock);
			wait_pending = 0;
		}
		spin_unlock_irqrestore(&alarm_slock, flags);
		rv = wait_event_interruptible(alarm_wait_queue, alarm_pending);
		if (rv)
			goto err1;
		spin_lock_irqsave(&alarm_slock, flags);
		rv = alarm_pending;
		wait_pending = 1;
		alarm_pending = 0;
		spin_unlock_irqrestore(&alarm_slock, flags);
		break;
	case ANDROID_ALARM_SET_RTC:
		if (copy_from_user(&new_rtc_time, (void __user *)arg,
		    sizeof(new_rtc_time))) {
			rv = -EFAULT;
			goto err1;
		}
		rtc_time_to_tm(new_rtc_time.tv_sec, &new_rtc_tm);
		
		pr_alarm(IO, "set rtc %ld %ld - rtc %02d:%02d:%02d %02d/%02d/%04d\n",
		new_rtc_time.tv_sec, new_rtc_time.tv_nsec,
		new_rtc_tm.tm_hour, new_rtc_tm.tm_min,
		new_rtc_tm.tm_sec, new_rtc_tm.tm_mon + 1,
		new_rtc_tm.tm_mday,
		new_rtc_tm.tm_year + 1900);

		rtc_dev = alarmtimer_get_rtcdev();
		rv = do_settimeofday(&new_rtc_time);
		if (rv < 0)
		{	
			goto err1;
		}
		if (rtc_dev)
		{
			rv = rtc_set_time(rtc_dev, &new_rtc_tm);
		}
		spin_lock_irqsave(&alarm_slock, flags);
		alarm_pending |= ANDROID_ALARM_TIME_CHANGE_MASK;
		wake_up(&alarm_wait_queue);
		spin_unlock_irqrestore(&alarm_slock, flags);
		if (rv < 0)
			goto err1;
		break;
	case ANDROID_ALARM_GET_TIME(0):
		switch (alarm_type) {
		case ANDROID_ALARM_RTC_WAKEUP:
		case ANDROID_ALARM_RTC:
			getnstimeofday(&tmp_time);
			break;
		case ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP:
		case ANDROID_ALARM_ELAPSED_REALTIME:
			get_monotonic_boottime(&tmp_time);
			break;
		case ANDROID_ALARM_TYPE_COUNT:
		case ANDROID_ALARM_SYSTEMTIME:
			ktime_get_ts(&tmp_time);
			break;
		case ANDROID_ALARM_POWER_ON:
		case ANDROID_ALARM_POWER_ON_LOGO:
			break;		
		}
		if (copy_to_user((void __user *)arg, &tmp_time,
		    sizeof(tmp_time))) {
			rv = -EFAULT;
			goto err1;
		}
		break;
	case ANDROID_ALARM_GET_POWER_ON:
		alarm_get_power_on(&pwron_alm);
		if (copy_to_user((void __user *)arg, &pwron_alm,
		    sizeof(struct rtc_wkalrm))) {
			rv = -EFAULT;
			goto err1;
		}
		break;

	default:
		rv = -EINVAL;
		goto err1;
	}
err1:
	return rv;
}
static long alarm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
    int rv = 0;
    unsigned long flags;
    struct timespec new_alarm_time;
    struct timespec new_rtc_time;
    struct timespec tmp_time;
    struct rtc_time new_rtc_tm;
    struct rtc_device *rtc_dev;
    enum android_alarm_type alarm_type = ANDROID_ALARM_IOCTL_TO_TYPE(cmd);
    uint32_t alarm_type_mask = 1U << alarm_type;

    if (alarm_type >= ANDROID_ALARM_TYPE_COUNT)
        return -EINVAL;

    if (ANDROID_ALARM_BASE_CMD(cmd) != ANDROID_ALARM_GET_TIME(0)) {
        if ((file->f_flags & O_ACCMODE) == O_RDONLY)
            return -EPERM;
        if (file->private_data == NULL &&
                cmd != ANDROID_ALARM_SET_RTC) {
            spin_lock_irqsave(&alarm_slock, flags);
            if (alarm_opened) {
                spin_unlock_irqrestore(&alarm_slock, flags);
                return -EBUSY;
            }
            alarm_opened = 1;
            file->private_data = (void *)1;
            spin_unlock_irqrestore(&alarm_slock, flags);
        }
    }

    switch (ANDROID_ALARM_BASE_CMD(cmd)) {
    case ANDROID_ALARM_CLEAR(0):
        switch (alarm_type) {
        case ANDROID_ALARM_POWER_UP:
            /* disable power up alarm interrupt */
            rv = alarm_irq_enable(0);
            break;
        case ANDROID_ALARM_RTC_WAKEUP:
        case ANDROID_ALARM_RTC:
        case ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP:
        case ANDROID_ALARM_ELAPSED_REALTIME:
        case ANDROID_ALARM_SYSTEMTIME:
            spin_lock_irqsave(&alarm_slock, flags);
            pr_alarm(IO, "alarm %d clear\n", alarm_type);
            devalarm_try_to_cancel(&alarms[alarm_type]);
            if (alarm_pending) {
                alarm_pending &= ~alarm_type_mask;
                if (!alarm_pending && !wait_pending)
                    wake_unlock(&alarm_wake_lock);
            }
            alarm_enabled &= ~alarm_type_mask;
            spin_unlock_irqrestore(&alarm_slock, flags);
            break;
        default:
            break;
        }
        break;

    case ANDROID_ALARM_SET_OLD:
    case ANDROID_ALARM_SET_AND_WAIT_OLD:
        if (get_user(new_alarm_time.tv_sec, (int __user *)arg)) {
            rv = -EFAULT;
            goto err1;
        }
        new_alarm_time.tv_nsec = 0;
        goto from_old_alarm_set;
#if defined(CONFIG_RTC_CHN_ALARM_BOOT)
    case ANDROID_ALARM_SET_ALARM:
    {
        char bootalarm_data[14];

        if (copy_from_user(bootalarm_data, (void __user *)arg, 14)) {
            rv = -EFAULT;
            goto err1;
        }

        alarm_set_bootalarm(bootalarm_data);

        break;
    }
#endif
    case ANDROID_ALARM_SET_AND_WAIT(0):
    case ANDROID_ALARM_SET(0):
        if (copy_from_user(&new_alarm_time, (void __user *)arg,
                           sizeof(new_alarm_time))) {
            rv = -EFAULT;
            goto err1;
        }
from_old_alarm_set:
        spin_lock_irqsave(&alarm_slock, flags);
        pr_alarm(IO, "alarm %d set %ld.%09ld\n", alarm_type,
                 new_alarm_time.tv_sec, new_alarm_time.tv_nsec);
        alarm_enabled |= alarm_type_mask;
        devalarm_start(&alarms[alarm_type],
                       timespec_to_ktime(new_alarm_time));
        spin_unlock_irqrestore(&alarm_slock, flags);
        if (alarm_type == ANDROID_ALARM_POWER_UP)
            alarm_set_rtc_ring(new_alarm_time);
        if (ANDROID_ALARM_BASE_CMD(cmd) != ANDROID_ALARM_SET_AND_WAIT(0)
                && cmd != ANDROID_ALARM_SET_AND_WAIT_OLD)
            break;
    /* fall though */
    case ANDROID_ALARM_WAIT:
        spin_lock_irqsave(&alarm_slock, flags);
        pr_alarm(IO, "alarm wait\n");
        if (!alarm_pending && wait_pending) {
            wake_unlock(&alarm_wake_lock);
            wait_pending = 0;
        }
        spin_unlock_irqrestore(&alarm_slock, flags);
        rv = wait_event_interruptible(alarm_wait_queue, alarm_pending);
        if (rv)
            goto err1;
        spin_lock_irqsave(&alarm_slock, flags);
        rv = alarm_pending;
        wait_pending = 1;
        alarm_pending = 0;
        spin_unlock_irqrestore(&alarm_slock, flags);
        break;
    case ANDROID_ALARM_SET_RTC:
        if (copy_from_user(&new_rtc_time, (void __user *)arg,
                           sizeof(new_rtc_time))) {
            rv = -EFAULT;
            goto err1;
        }
        rtc_time_to_tm(new_rtc_time.tv_sec, &new_rtc_tm);
        rtc_dev = alarmtimer_get_rtcdev();
        rv = do_settimeofday(&new_rtc_time);
        if (rv < 0)
            goto err1;
        if (rtc_dev)
            rv = rtc_set_time(rtc_dev, &new_rtc_tm);

        if (pwr_rtc_dev)
            rv = rtc_set_time(pwr_rtc_dev, &new_rtc_tm);

        spin_lock_irqsave(&alarm_slock, flags);
        alarm_pending |= ANDROID_ALARM_TIME_CHANGE_MASK;
        wake_up(&alarm_wait_queue);
        spin_unlock_irqrestore(&alarm_slock, flags);
        if (rv < 0)
            goto err1;
        break;
    case ANDROID_ALARM_GET_TIME(0):
        switch (alarm_type) {
        case ANDROID_ALARM_RTC_WAKEUP:
        case ANDROID_ALARM_POWER_UP:
        case ANDROID_ALARM_RTC:
            getnstimeofday(&tmp_time);
            break;
        case ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP:
        case ANDROID_ALARM_ELAPSED_REALTIME:
            get_monotonic_boottime(&tmp_time);
            break;
        case ANDROID_ALARM_TYPE_COUNT:
        case ANDROID_ALARM_SYSTEMTIME:
            ktime_get_ts(&tmp_time);
            break;
        }
        if (copy_to_user((void __user *)arg, &tmp_time,
                         sizeof(tmp_time))) {
            rv = -EFAULT;
            goto err1;
        }
        break;

    default:
        rv = -EINVAL;
        goto err1;
    }
err1:
    return rv;
}