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; }
/* * 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; }
/* * 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; }