Source
x
/*
* Motorola CPCAP PMIC RTC driver
*
* Based on cpcap-regulator.c from Motorola Linux kernel tree
* Copyright (C) 2009 Motorola, Inc.
*
* Rewritten for mainline kernel
* - use DT
* - use regmap
* - use standard interrupt framework
* - use managed device resources
* - remove custom "secure clock daemon" helpers
*
* Copyright (C) 2017 Sebastian Reichel <sre@kernel.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
struct cpcap_time {
int day;
int tod1;
int tod2;
};
struct cpcap_rtc {
struct regmap *regmap;
struct rtc_device *rtc_dev;
u16 vendor;
int alarm_irq;
bool alarm_enabled;
int update_irq;
bool update_enabled;
};
static void cpcap2rtc_time(struct rtc_time *rtc, struct cpcap_time *cpcap)
{
unsigned long int tod;
unsigned long int time;
tod = (cpcap->tod1 & TOD1_MASK) | ((cpcap->tod2 & TOD2_MASK) << 8);
time = tod + ((cpcap->day & DAY_MASK) * SECS_PER_DAY);
rtc_time_to_tm(time, rtc);
}
static void rtc2cpcap_time(struct cpcap_time *cpcap, struct rtc_time *rtc)
{
unsigned long time;
rtc_tm_to_time(rtc, &time);
cpcap->day = time / SECS_PER_DAY;
time %= SECS_PER_DAY;
cpcap->tod2 = (time >> 8) & TOD2_MASK;
cpcap->tod1 = time & TOD1_MASK;
}
static int cpcap_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
{
struct cpcap_rtc *rtc = dev_get_drvdata(dev);
if (rtc->alarm_enabled == enabled)
return 0;
if (enabled)
enable_irq(rtc->alarm_irq);
else
disable_irq(rtc->alarm_irq);