Exemple #1
0
static int tps65910_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
{
	unsigned char alarm_data[NUM_TIME_REGS];
	struct tps65910 *tps = dev_get_drvdata(dev->parent);
	int ret;

	ret = tps65910_rtc_alarm_irq_enable(dev, 0);
	if (ret)
		return ret;

	alarm_data[0] = bin2bcd(alm->time.tm_sec);
	alarm_data[1] = bin2bcd(alm->time.tm_min);
	alarm_data[2] = bin2bcd(alm->time.tm_hour);
	alarm_data[3] = bin2bcd(alm->time.tm_mday);
	alarm_data[4] = bin2bcd(alm->time.tm_mon + 1);
	alarm_data[5] = bin2bcd(alm->time.tm_year - 100);

	/* update all the alarm registers in one shot */
	ret = regmap_bulk_write(tps->regmap, TPS65910_ALARM_SECONDS,
		alarm_data, NUM_TIME_REGS);
	if (ret) {
		dev_err(dev, "rtc_set_alarm error %d\n", ret);
		return ret;
	}

	if (alm->enabled)
		ret = tps65910_rtc_alarm_irq_enable(dev, 1);

	return ret;
}
Exemple #2
0
/*
 * Disable tps65910 RTC interrupts.
 * Sets status flag to free.
 */
static int tps65910_rtc_remove(struct platform_device *pdev)
{
	/* leave rtc running, but disable irqs */
	struct tps65910_rtc *tps_rtc = platform_get_drvdata(pdev);

	tps65910_rtc_alarm_irq_enable(&pdev->dev, 0);

	rtc_device_unregister(tps_rtc->rtc);
	return 0;
}
static int tps65910_rtc_probe(struct platform_device *pdev)
{
	struct tps65910 *tps65910 = dev_get_drvdata(pdev->dev.parent);
	struct tps65910_rtc *tps65910_rtc;
	int per_irq;
	int alm_irq;
	int ret = 0;
	u8 rtc_ctl;
	
	struct rtc_time tm;
	struct rtc_time tm_def = {	//	2012.1.1 12:00:00 Saturday
			.tm_wday = 6,
			.tm_year = 111,
			.tm_mon = 0,
			.tm_mday = 1,
			.tm_hour = 12,
			.tm_min = 0,
			.tm_sec = 0,
		};
	
	tps65910_rtc = kzalloc(sizeof(*tps65910_rtc), GFP_KERNEL);
	if (tps65910_rtc == NULL)
		return -ENOMEM;

	platform_set_drvdata(pdev, tps65910_rtc);
	tps65910_rtc->tps65910 = tps65910;
	per_irq = tps65910->irq_base + TPS65910_IRQ_RTC_PERIOD;
	alm_irq = tps65910->irq_base + TPS65910_IRQ_RTC_ALARM;
	
	/* Take rtc out of reset */
	ret = tps65910_reg_read(tps65910, TPS65910_DEVCTRL);
	if (ret < 0) {
		dev_err(&pdev->dev, "Failed to read TPS65910_DEVCTRL: %d\n", ret);
		return ret;
	}

	if(ret & BIT_RTC_PWDN)
	{
		rtc_ctl = ret & (~BIT_RTC_PWDN);

		ret = tps65910_reg_write(tps65910, TPS65910_DEVCTRL, rtc_ctl);
		if (ret < 0) {
			dev_err(&pdev->dev, "Failed to write RTC control: %d\n", ret);
			return ret;
		}
	}
	
	/*start rtc default*/
	ret = tps65910_reg_read(tps65910, TPS65910_RTC_CTRL);
	if (ret < 0) {
		dev_err(&pdev->dev, "Failed to read RTC control: %d\n", ret);
		return ret;
	}

	if(!(ret & BIT_RTC_CTRL_REG_STOP_RTC_M))
	{
		rtc_ctl = ret | BIT_RTC_CTRL_REG_STOP_RTC_M;

		ret = tps65910_reg_write(tps65910, TPS65910_RTC_CTRL, rtc_ctl);
		if (ret < 0) {
			dev_err(&pdev->dev, "Failed to write RTC control: %d\n", ret);
			return ret;
		}
	}
	
	ret = tps65910_reg_read(tps65910, TPS65910_RTC_STATUS);
	if (ret < 0) {
		dev_err(&pdev->dev, "Failed to read RTC status: %d\n", ret);
		return ret;
	}
		
	/*set init time*/
	ret = tps65910_rtc_readtime(&pdev->dev, &tm);
	if (ret)
	{
		dev_err(&pdev->dev, "Failed to read RTC time\n");
		return ret;
	}
	
	ret = rtc_valid_tm(&tm);
	if (ret) {
		dev_err(&pdev->dev,"invalid date/time and init time\n");
		tps65910_rtc_set_time(&pdev->dev, &tm_def); // 2011-01-01 12:00:00
		dev_info(&pdev->dev, "set RTC date/time %4d-%02d-%02d(%d) %02d:%02d:%02d\n",
				1900 + tm_def.tm_year, tm_def.tm_mon + 1, tm_def.tm_mday, tm_def.tm_wday,
				tm_def.tm_hour, tm_def.tm_min, tm_def.tm_sec);
	}

	device_init_wakeup(&pdev->dev, 1);

	tps65910_rtc->rtc = rtc_device_register("tps65910", &pdev->dev,
					      &tps65910_rtc_ops, THIS_MODULE);
	if (IS_ERR(tps65910_rtc->rtc)) {
		ret = PTR_ERR(tps65910_rtc->rtc);
		goto err;
	}

	/*request rtc and alarm irq of tps65910*/
	ret = request_threaded_irq(per_irq, NULL, tps65910_per_irq,
				   IRQF_TRIGGER_RISING, "RTC period",
				   tps65910_rtc);
	if (ret != 0) {
		dev_err(&pdev->dev, "Failed to request periodic IRQ %d: %d\n",
			per_irq, ret);
	}

	ret = request_threaded_irq(alm_irq, NULL, tps65910_alm_irq,
				   IRQF_TRIGGER_RISING, "RTC alarm",
				   tps65910_rtc);
	if (ret != 0) {
		dev_err(&pdev->dev, "Failed to request alarm IRQ %d: %d\n",
			alm_irq, ret);
	}

	//for rtc irq test
	//tps65910_set_bits(tps65910_rtc->tps65910, TPS65910_RTC_INTERRUPTS,
	//			       BIT_RTC_INTERRUPTS_REG_IT_TIMER_M);

	enable_irq_wake(alm_irq); // so tps65910 alarm irq can wake up system
	g_pdev = pdev;
	
	printk("%s:ok\n",__func__);
	
	return 0;

err:
	kfree(tps65910_rtc);
	return ret;
}

static int __devexit tps65910_rtc_remove(struct platform_device *pdev)
{
	struct tps65910_rtc *tps65910_rtc = platform_get_drvdata(pdev);
	int per_irq = tps65910_rtc->tps65910->irq_base + TPS65910_IRQ_RTC_PERIOD;
	int alm_irq = tps65910_rtc->tps65910->irq_base + TPS65910_IRQ_RTC_ALARM;

	free_irq(alm_irq, tps65910_rtc);
	free_irq(per_irq, tps65910_rtc);
	rtc_device_unregister(tps65910_rtc->rtc);
	kfree(tps65910_rtc);

	return 0;
}

static const struct dev_pm_ops tps65910_rtc_pm_ops = {
	.suspend = tps65910_rtc_suspend,
	.resume = tps65910_rtc_resume,

	.freeze = tps65910_rtc_freeze,
	.thaw = tps65910_rtc_resume,
	.restore = tps65910_rtc_resume,

	.poweroff = tps65910_rtc_suspend,
};

static struct platform_driver tps65910_rtc_driver = {
	.probe = tps65910_rtc_probe,
	.remove = __devexit_p(tps65910_rtc_remove),
	.driver = {
		.name = "tps65910-rtc",
		.pm = &tps65910_rtc_pm_ops,
	},
};

static ssize_t rtc_tps65910_test_write(struct file *file, 
			const char __user *buf, size_t count, loff_t *offset)
{
	char nr_buf[8];
	int nr = 0, ret;
	struct platform_device *pdev;	
	struct rtc_time tm;
	struct rtc_wkalrm alrm;
	struct tps65910_rtc *tps65910_rtc;
	
	if(count > 3)
		return -EFAULT;
	ret = copy_from_user(nr_buf, buf, count);
	if(ret < 0)
		return -EFAULT;

	sscanf(nr_buf, "%d", &nr);
	if(nr > 5 || nr < 0)
	{
		printk("%s:data is error\n",__func__);
		return -EFAULT;
	}

	if(!g_pdev)
		return -EFAULT;
	else
		pdev = g_pdev;

	
	tps65910_rtc = dev_get_drvdata(&pdev->dev);
	
	//test rtc time
	if(nr == 0)
	{	
		tm.tm_wday = 6;
		tm.tm_year = 111;
		tm.tm_mon = 0;
		tm.tm_mday = 1;
		tm.tm_hour = 12;
		tm.tm_min = 0;
		tm.tm_sec = 0;
	
		ret = tps65910_rtc_set_time(&pdev->dev, &tm); // 2011-01-01 12:00:00
		if (ret)
		{
			dev_err(&pdev->dev, "Failed to set RTC time\n");
			return -EFAULT;
		}

	}
	
	/*set init time*/
	ret = tps65910_rtc_readtime(&pdev->dev, &tm);
	if (ret)
		dev_err(&pdev->dev, "Failed to read RTC time\n");
	else
		dev_info(&pdev->dev, "RTC date/time %4d-%02d-%02d(%d) %02d:%02d:%02d\n",
			1900 + tm.tm_year, tm.tm_mon + 1, tm.tm_mday, tm.tm_wday,
			tm.tm_hour, tm.tm_min, tm.tm_sec);
		
	if(!ret)
	printk("%s:ok\n",__func__);
	else
	printk("%s:error\n",__func__);
	

	//test rtc alarm
	if(nr == 2)
	{
		//2000-01-01 00:00:30
		if(tm.tm_sec < 30)
		{
			alrm.time.tm_sec = tm.tm_sec+30;	
			alrm.time.tm_min = tm.tm_min;
		}
		else
		{
			alrm.time.tm_sec = tm.tm_sec-30;
			alrm.time.tm_min = tm.tm_min+1;
		}
		alrm.time.tm_hour = tm.tm_hour;
		alrm.time.tm_mday = tm.tm_mday;
		alrm.time.tm_mon = tm.tm_mon;
		alrm.time.tm_year = tm.tm_year;		
		tps65910_rtc_alarm_irq_enable(&pdev->dev, 1);
		tps65910_rtc_setalarm(&pdev->dev, &alrm);

		dev_info(&pdev->dev, "Set alarm %4d-%02d-%02d(%d) %02d:%02d:%02d\n",
				1900 + alrm.time.tm_year, alrm.time.tm_mon + 1, alrm.time.tm_mday, alrm.time.tm_wday,
				alrm.time.tm_hour, alrm.time.tm_min, alrm.time.tm_sec);
	}

	
	if(nr == 3)
	{	
		ret = tps65910_reg_read(tps65910_rtc->tps65910, TPS65910_RTC_STATUS);
		if (ret < 0) {
			printk("%s:Failed to read RTC status: %d\n", __func__, ret);
			return ret;
		}
		printk("%s:ret=0x%x\n",__func__,ret&0xff);

		ret = tps65910_reg_write(tps65910_rtc->tps65910, TPS65910_RTC_STATUS, ret&0xff);
		if (ret < 0) {
			printk("%s:Failed to read RTC status: %d\n", __func__, ret);
			return ret;
		}
	}

	if(nr == 4)
	tps65910_rtc_update_irq_enable(&pdev->dev, 1);

	if(nr == 5)
	tps65910_rtc_update_irq_enable(&pdev->dev, 0);
	
	return count;
}
Exemple #4
0
/*
 * Disable tps65910 RTC interrupts.
 * Sets status flag to free.
 */
static int tps65910_rtc_remove(struct platform_device *pdev)
{
	tps65910_rtc_alarm_irq_enable(&pdev->dev, 0);

	return 0;
}