RTC for 4.17

Subsystem:
  - Add tracepoints
  - Rework of the RTC/nvmem API to allow drivers to discard struct nvmem_config
    after registration
  - New range API, drivers can now expose the useful range of the RTC
  - New offset API the core is now able to add an offset to the RTC time,
    modifying the supported range.
  - Multiple rtc_time64_to_tm fixes
  - Handle time_t overflow on 32 bit platforms in the core instead of letting
    drivers do crazy things.
  - remove rtc_control API
 
 New driver:
  - Intersil ISL12026
 
 Drivers:
  - Drivers exposing the RTC non volatile memory have been converted to use nvmem
  - Removed useless time and date validation
  - Removed an indirection pattern that was a cargo cult from ancient drivers
  - Removed VLA usage
  - Fixed a possible race condition in probe functions
  - AB8540 support is dropped from ab8500
  - pcf85363 now has alarm support
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEXx9Viay1+e7J/aM4AyWl4gNJNJIFAlrL3s4ACgkQAyWl4gNJ
 NJI+MxAAgc56UEXi5chqKpHE6GHL2aPWan9duHB6FmGrKWt/FJmpJ8UGylLFlvaW
 dpRGvW0Dynz45UztegcrbHMU6+B2O0hboL4/GVZpYAkcNAcu7Lf0ULho2rsQSDmW
 WJpemmdRxyQY1IkWmw7z7KAkMzhAfYZiVmWmVwMRZfMcKJ3DLEldfgRtkN+g0UdB
 tayWQY3mS02ki16e2figsgwZRmUUhQslDfpKlesInXOzUMmLgVWhf1QxJSEUcfs0
 AMp75vD2YvVJ/RHy/6BilQbqP9EVnaG4NHqJGFSOddazA7u+3HGubEFboI8NuPXb
 2fCvfrNux7pgtQsBF9dnpCqWlukE7sF5aDyIUvjYnr0vUm2D/CwdXglGvQSQVWea
 5GxPTWBdaCL0V7GD5OSZcfUGyz1TN/7NSUItdLSr9YK13dL+tqhcYYm5ytXJLzvO
 Z4GyUEoCOMprMJ9j5KU/TXSjauDmPDl8YZ5B93lPcNOh7y+b/2r3umBaInyZrFzX
 1WJ6FWtuhbRfEwuQtgQHBsobt9eTwZfo8C2y22HBo/fdWfBv45feiiHNXt3OVrA+
 aws6pwfVf1H0UsvpQkXtlPthAx3sbOTndDKAUhntb/U/zA9c7fTrfUyVOQ1bArJy
 p6tl/cmlpq68AjZB+0d3zUXQkQH4Syu+EqZrWItkE6XxZm+khDE=
 =l9i8
 -----END PGP SIGNATURE-----

Merge tag 'rtc-4.17' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux

Pull RTC updates from Alexandre Belloni:
 "This contains a few series that have been in preparation for a while
  and that will help systems with RTCs that will fail in 2038, 2069 or
  2100.

  Subsystem:
   - Add tracepoints
   - Rework of the RTC/nvmem API to allow drivers to discard struct
     nvmem_config after registration
   - New range API, drivers can now expose the useful range of the RTC
   - New offset API the core is now able to add an offset to the RTC
     time, modifying the supported range.
   - Multiple rtc_time64_to_tm fixes
   - Handle time_t overflow on 32 bit platforms in the core instead of
     letting drivers do crazy things.
   - remove rtc_control API

  New driver:
   - Intersil ISL12026

  Drivers:
   - Drivers exposing the RTC non volatile memory have been converted to
     use nvmem
   - Removed useless time and date validation
   - Removed an indirection pattern that was a cargo cult from ancient
     drivers
   - Removed VLA usage
   - Fixed a possible race condition in probe functions
   - AB8540 support is dropped from ab8500
   - pcf85363 now has alarm support"

* tag 'rtc-4.17' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux: (128 commits)
  rtc: snvs: Fix usage of snvs_rtc_enable
  rtc: mt7622: fix module autoloading for OF platform drivers
  rtc: isl12022: use true and false for boolean values
  rtc: ab8500: Drop AB8540 support
  rtc: remove a warning during scripts/kernel-doc step
  rtc: 88pm860x: remove artificial limitation
  rtc: 88pm80x: remove artificial limitation
  rtc: st-lpc: remove artificial limitation
  rtc: mrst: remove artificial limitation
  rtc: mv: remove artificial limitation
  rtc: hctosys: Ensure system time doesn't overflow time_t
  parisc: time: stop validating rtc_time in .read_time
  rtc: pcf85063: fix clearing bits in pcf85063_start_clock
  rtc: at91sam9: Set name of regmap_config
  rtc: s5m: Remove VLA usage
  rtc: s5m: Move enum from rtc.h to rtc-s5m.c
  rtc: remove VLA usage
  rtc: Add useful timestamp definitions
  rtc: Add one offset seconds to expand RTC range
  rtc: Factor out the RTC range validation into rtc_valid_range()
  ...
This commit is contained in:
Linus Torvalds 2018-04-10 10:22:27 -07:00
commit fbe173e3ff
123 changed files with 1812 additions and 1086 deletions

View File

@ -43,6 +43,14 @@ Contact: linux-rtc@vger.kernel.org
Description: Description:
(RO) The name of the RTC corresponding to this sysfs directory (RO) The name of the RTC corresponding to this sysfs directory
What: /sys/class/rtc/rtcX/range
Date: January 2018
KernelVersion: 4.16
Contact: linux-rtc@vger.kernel.org
Description:
Valid time range for the RTC, as seconds from epoch, formatted
as [min, max]
What: /sys/class/rtc/rtcX/since_epoch What: /sys/class/rtc/rtcX/since_epoch
Date: March 2006 Date: March 2006
KernelVersion: 2.6.17 KernelVersion: 2.6.17
@ -57,14 +65,6 @@ Contact: linux-rtc@vger.kernel.org
Description: Description:
(RO) RTC-provided time in 24-hour notation (hh:mm:ss) (RO) RTC-provided time in 24-hour notation (hh:mm:ss)
What: /sys/class/rtc/rtcX/*/nvmem
Date: February 2016
KernelVersion: 4.6
Contact: linux-rtc@vger.kernel.org
Description:
(RW) The non volatile storage exported as a raw file, as
described in Documentation/nvmem/nvmem.txt
What: /sys/class/rtc/rtcX/offset What: /sys/class/rtc/rtcX/offset
Date: February 2016 Date: February 2016
KernelVersion: 4.6 KernelVersion: 4.6

View File

@ -0,0 +1,28 @@
ISL12026 I2C RTC/EEPROM
ISL12026 is an I2C RTC/EEPROM combination device. The RTC and control
registers respond at bus address 0x6f, and the EEPROM array responds
at bus address 0x57. The canonical "reg" value will be for the RTC portion.
Required properties supported by the device:
- "compatible": must be "isil,isl12026"
- "reg": I2C bus address of the device (always 0x6f)
Optional properties:
- "isil,pwr-bsw": If present PWR.BSW bit must be set to the specified
value for proper operation.
- "isil,pwr-sbib": If present PWR.SBIB bit must be set to the specified
value for proper operation.
Example:
rtc@6f {
compatible = "isil,isl12026";
reg = <0x6f>;
isil,pwr-bsw = <0>;
isil,pwr-sbib = <1>;
}

View File

@ -11810,7 +11810,7 @@ X: kernel/torture.c
REAL TIME CLOCK (RTC) SUBSYSTEM REAL TIME CLOCK (RTC) SUBSYSTEM
M: Alessandro Zummo <a.zummo@towertech.it> M: Alessandro Zummo <a.zummo@towertech.it>
M: Alexandre Belloni <alexandre.belloni@free-electrons.com> M: Alexandre Belloni <alexandre.belloni@bootlin.com>
L: linux-rtc@vger.kernel.org L: linux-rtc@vger.kernel.org
Q: http://patchwork.ozlabs.org/project/rtc-linux/list/ Q: http://patchwork.ozlabs.org/project/rtc-linux/list/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux.git T: git git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux.git

View File

@ -174,7 +174,7 @@ static int rtc_generic_get_time(struct device *dev, struct rtc_time *tm)
/* we treat tod_sec as unsigned, so this can work until year 2106 */ /* we treat tod_sec as unsigned, so this can work until year 2106 */
rtc_time64_to_tm(tod_data.tod_sec, tm); rtc_time64_to_tm(tod_data.tod_sec, tm);
return rtc_valid_tm(tm); return 0;
} }
static int rtc_generic_set_time(struct device *dev, struct rtc_time *tm) static int rtc_generic_set_time(struct device *dev, struct rtc_time *tm)

View File

@ -809,89 +809,6 @@ static __poll_t rtc_poll(struct file *file, poll_table *wait)
} }
#endif #endif
int rtc_register(rtc_task_t *task)
{
#ifndef RTC_IRQ
return -EIO;
#else
if (task == NULL || task->func == NULL)
return -EINVAL;
spin_lock_irq(&rtc_lock);
if (rtc_status & RTC_IS_OPEN) {
spin_unlock_irq(&rtc_lock);
return -EBUSY;
}
spin_lock(&rtc_task_lock);
if (rtc_callback) {
spin_unlock(&rtc_task_lock);
spin_unlock_irq(&rtc_lock);
return -EBUSY;
}
rtc_status |= RTC_IS_OPEN;
rtc_callback = task;
spin_unlock(&rtc_task_lock);
spin_unlock_irq(&rtc_lock);
return 0;
#endif
}
EXPORT_SYMBOL(rtc_register);
int rtc_unregister(rtc_task_t *task)
{
#ifndef RTC_IRQ
return -EIO;
#else
unsigned char tmp;
spin_lock_irq(&rtc_lock);
spin_lock(&rtc_task_lock);
if (rtc_callback != task) {
spin_unlock(&rtc_task_lock);
spin_unlock_irq(&rtc_lock);
return -ENXIO;
}
rtc_callback = NULL;
/* disable controls */
if (!hpet_mask_rtc_irq_bit(RTC_PIE | RTC_AIE | RTC_UIE)) {
tmp = CMOS_READ(RTC_CONTROL);
tmp &= ~RTC_PIE;
tmp &= ~RTC_AIE;
tmp &= ~RTC_UIE;
CMOS_WRITE(tmp, RTC_CONTROL);
CMOS_READ(RTC_INTR_FLAGS);
}
if (rtc_status & RTC_TIMER_ON) {
rtc_status &= ~RTC_TIMER_ON;
del_timer(&rtc_irq_timer);
}
rtc_status &= ~RTC_IS_OPEN;
spin_unlock(&rtc_task_lock);
spin_unlock_irq(&rtc_lock);
return 0;
#endif
}
EXPORT_SYMBOL(rtc_unregister);
int rtc_control(rtc_task_t *task, unsigned int cmd, unsigned long arg)
{
#ifndef RTC_IRQ
return -EIO;
#else
unsigned long flags;
if (cmd != RTC_PIE_ON && cmd != RTC_PIE_OFF && cmd != RTC_IRQP_SET)
return -EINVAL;
spin_lock_irqsave(&rtc_task_lock, flags);
if (rtc_callback != task) {
spin_unlock_irqrestore(&rtc_task_lock, flags);
return -ENXIO;
}
spin_unlock_irqrestore(&rtc_task_lock, flags);
return rtc_do_ioctl(cmd, arg, 1);
#endif
}
EXPORT_SYMBOL(rtc_control);
/* /*
* The various file operations we support. * The various file operations we support.
*/ */

View File

@ -407,6 +407,16 @@ config RTC_DRV_ISL12022
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called rtc-isl12022. will be called rtc-isl12022.
config RTC_DRV_ISL12026
tristate "Intersil ISL12026"
depends on OF || COMPILE_TEST
help
If you say yes here you get support for the
Intersil ISL12026 RTC chip.
This driver can also be built as a module. If so, the module
will be called rtc-isl12026.
config RTC_DRV_X1205 config RTC_DRV_X1205
tristate "Xicor/Intersil X1205" tristate "Xicor/Intersil X1205"
help help
@ -1413,6 +1423,7 @@ config RTC_DRV_AT91RM9200
config RTC_DRV_AT91SAM9 config RTC_DRV_AT91SAM9
tristate "AT91SAM9 RTT as RTC" tristate "AT91SAM9 RTT as RTC"
depends on ARCH_AT91 || COMPILE_TEST depends on ARCH_AT91 || COMPILE_TEST
depends on HAS_IOMEM
select MFD_SYSCON select MFD_SYSCON
help help
Some AT91SAM9 SoCs provide an RTT (Real Time Timer) block which Some AT91SAM9 SoCs provide an RTT (Real Time Timer) block which
@ -1502,7 +1513,7 @@ config RTC_DRV_STARFIRE
config RTC_DRV_TX4939 config RTC_DRV_TX4939
tristate "TX4939 SoC" tristate "TX4939 SoC"
depends on SOC_TX4939 depends on SOC_TX4939 || COMPILE_TEST
help help
Driver for the internal RTC (Realtime Clock) module found on Driver for the internal RTC (Realtime Clock) module found on
Toshiba TX4939 SoC. Toshiba TX4939 SoC.

View File

@ -75,6 +75,7 @@ obj-$(CONFIG_RTC_DRV_HID_SENSOR_TIME) += rtc-hid-sensor-time.o
obj-$(CONFIG_RTC_DRV_HYM8563) += rtc-hym8563.o obj-$(CONFIG_RTC_DRV_HYM8563) += rtc-hym8563.o
obj-$(CONFIG_RTC_DRV_IMXDI) += rtc-imxdi.o obj-$(CONFIG_RTC_DRV_IMXDI) += rtc-imxdi.o
obj-$(CONFIG_RTC_DRV_ISL12022) += rtc-isl12022.o obj-$(CONFIG_RTC_DRV_ISL12022) += rtc-isl12022.o
obj-$(CONFIG_RTC_DRV_ISL12026) += rtc-isl12026.o
obj-$(CONFIG_RTC_DRV_ISL1208) += rtc-isl1208.o obj-$(CONFIG_RTC_DRV_ISL1208) += rtc-isl1208.o
obj-$(CONFIG_RTC_DRV_JZ4740) += rtc-jz4740.o obj-$(CONFIG_RTC_DRV_JZ4740) += rtc-jz4740.o
obj-$(CONFIG_RTC_DRV_LP8788) += rtc-lp8788.o obj-$(CONFIG_RTC_DRV_LP8788) += rtc-lp8788.o

View File

@ -211,6 +211,73 @@ static int rtc_device_get_id(struct device *dev)
return id; return id;
} }
static void rtc_device_get_offset(struct rtc_device *rtc)
{
time64_t range_secs;
u32 start_year;
int ret;
/*
* If RTC driver did not implement the range of RTC hardware device,
* then we can not expand the RTC range by adding or subtracting one
* offset.
*/
if (rtc->range_min == rtc->range_max)
return;
ret = device_property_read_u32(rtc->dev.parent, "start-year",
&start_year);
if (!ret) {
rtc->start_secs = mktime64(start_year, 1, 1, 0, 0, 0);
rtc->set_start_time = true;
}
/*
* If user did not implement the start time for RTC driver, then no
* need to expand the RTC range.
*/
if (!rtc->set_start_time)
return;
range_secs = rtc->range_max - rtc->range_min + 1;
/*
* If the start_secs is larger than the maximum seconds (rtc->range_max)
* supported by RTC hardware or the maximum seconds of new expanded
* range (start_secs + rtc->range_max - rtc->range_min) is less than
* rtc->range_min, which means the minimum seconds (rtc->range_min) of
* RTC hardware will be mapped to start_secs by adding one offset, so
* the offset seconds calculation formula should be:
* rtc->offset_secs = rtc->start_secs - rtc->range_min;
*
* If the start_secs is larger than the minimum seconds (rtc->range_min)
* supported by RTC hardware, then there is one region is overlapped
* between the original RTC hardware range and the new expanded range,
* and this overlapped region do not need to be mapped into the new
* expanded range due to it is valid for RTC device. So the minimum
* seconds of RTC hardware (rtc->range_min) should be mapped to
* rtc->range_max + 1, then the offset seconds formula should be:
* rtc->offset_secs = rtc->range_max - rtc->range_min + 1;
*
* If the start_secs is less than the minimum seconds (rtc->range_min),
* which is similar to case 2. So the start_secs should be mapped to
* start_secs + rtc->range_max - rtc->range_min + 1, then the
* offset seconds formula should be:
* rtc->offset_secs = -(rtc->range_max - rtc->range_min + 1);
*
* Otherwise the offset seconds should be 0.
*/
if (rtc->start_secs > rtc->range_max ||
rtc->start_secs + range_secs - 1 < rtc->range_min)
rtc->offset_secs = rtc->start_secs - rtc->range_min;
else if (rtc->start_secs > rtc->range_min)
rtc->offset_secs = range_secs;
else if (rtc->start_secs < rtc->range_min)
rtc->offset_secs = -range_secs;
else
rtc->offset_secs = 0;
}
/** /**
* rtc_device_register - register w/ RTC class * rtc_device_register - register w/ RTC class
* @dev: the device to register * @dev: the device to register
@ -247,6 +314,8 @@ struct rtc_device *rtc_device_register(const char *name, struct device *dev,
dev_set_name(&rtc->dev, "rtc%d", id); dev_set_name(&rtc->dev, "rtc%d", id);
rtc_device_get_offset(rtc);
/* Check to see if there is an ALARM already set in hw */ /* Check to see if there is an ALARM already set in hw */
err = __rtc_read_alarm(rtc, &alrm); err = __rtc_read_alarm(rtc, &alrm);
@ -293,8 +362,6 @@ EXPORT_SYMBOL_GPL(rtc_device_register);
*/ */
void rtc_device_unregister(struct rtc_device *rtc) void rtc_device_unregister(struct rtc_device *rtc)
{ {
rtc_nvmem_unregister(rtc);
mutex_lock(&rtc->ops_lock); mutex_lock(&rtc->ops_lock);
/* /*
* Remove innards of this RTC, then disable it, before * Remove innards of this RTC, then disable it, before
@ -312,6 +379,7 @@ static void devm_rtc_device_release(struct device *dev, void *res)
{ {
struct rtc_device *rtc = *(struct rtc_device **)res; struct rtc_device *rtc = *(struct rtc_device **)res;
rtc_nvmem_unregister(rtc);
rtc_device_unregister(rtc); rtc_device_unregister(rtc);
} }
@ -382,6 +450,8 @@ static void devm_rtc_release_device(struct device *dev, void *res)
{ {
struct rtc_device *rtc = *(struct rtc_device **)res; struct rtc_device *rtc = *(struct rtc_device **)res;
rtc_nvmem_unregister(rtc);
if (rtc->registered) if (rtc->registered)
rtc_device_unregister(rtc); rtc_device_unregister(rtc);
else else
@ -435,6 +505,7 @@ int __rtc_register_device(struct module *owner, struct rtc_device *rtc)
return -EINVAL; return -EINVAL;
rtc->owner = owner; rtc->owner = owner;
rtc_device_get_offset(rtc);
/* Check to see if there is an ALARM already set in hw */ /* Check to see if there is an ALARM already set in hw */
err = __rtc_read_alarm(rtc, &alrm); err = __rtc_read_alarm(rtc, &alrm);
@ -453,8 +524,6 @@ int __rtc_register_device(struct module *owner, struct rtc_device *rtc)
rtc_proc_add_device(rtc); rtc_proc_add_device(rtc);
rtc_nvmem_register(rtc);
rtc->registered = true; rtc->registered = true;
dev_info(rtc->dev.parent, "registered as %s\n", dev_info(rtc->dev.parent, "registered as %s\n",
dev_name(&rtc->dev)); dev_name(&rtc->dev));

View File

@ -49,6 +49,11 @@ static int __init rtc_hctosys(void)
tv64.tv_sec = rtc_tm_to_time64(&tm); tv64.tv_sec = rtc_tm_to_time64(&tm);
#if BITS_PER_LONG == 32
if (tv64.tv_sec > INT_MAX)
goto err_read;
#endif
err = do_settimeofday64(&tv64); err = do_settimeofday64(&tv64);
dev_info(rtc->dev.parent, dev_info(rtc->dev.parent,

View File

@ -17,9 +17,73 @@
#include <linux/log2.h> #include <linux/log2.h>
#include <linux/workqueue.h> #include <linux/workqueue.h>
#define CREATE_TRACE_POINTS
#include <trace/events/rtc.h>
static int rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer); static int rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer);
static void rtc_timer_remove(struct rtc_device *rtc, struct rtc_timer *timer); static void rtc_timer_remove(struct rtc_device *rtc, struct rtc_timer *timer);
static void rtc_add_offset(struct rtc_device *rtc, struct rtc_time *tm)
{
time64_t secs;
if (!rtc->offset_secs)
return;
secs = rtc_tm_to_time64(tm);
/*
* Since the reading time values from RTC device are always in the RTC
* original valid range, but we need to skip the overlapped region
* between expanded range and original range, which is no need to add
* the offset.
*/
if ((rtc->start_secs > rtc->range_min && secs >= rtc->start_secs) ||
(rtc->start_secs < rtc->range_min &&
secs <= (rtc->start_secs + rtc->range_max - rtc->range_min)))
return;
rtc_time64_to_tm(secs + rtc->offset_secs, tm);
}
static void rtc_subtract_offset(struct rtc_device *rtc, struct rtc_time *tm)
{
time64_t secs;
if (!rtc->offset_secs)
return;
secs = rtc_tm_to_time64(tm);
/*
* If the setting time values are in the valid range of RTC hardware
* device, then no need to subtract the offset when setting time to RTC
* device. Otherwise we need to subtract the offset to make the time
* values are valid for RTC hardware device.
*/
if (secs >= rtc->range_min && secs <= rtc->range_max)
return;
rtc_time64_to_tm(secs - rtc->offset_secs, tm);
}
static int rtc_valid_range(struct rtc_device *rtc, struct rtc_time *tm)
{
if (rtc->range_min != rtc->range_max) {
time64_t time = rtc_tm_to_time64(tm);
time64_t range_min = rtc->set_start_time ? rtc->start_secs :
rtc->range_min;
time64_t range_max = rtc->set_start_time ?
(rtc->start_secs + rtc->range_max - rtc->range_min) :
rtc->range_max;
if (time < range_min || time > range_max)
return -ERANGE;
}
return 0;
}
static int __rtc_read_time(struct rtc_device *rtc, struct rtc_time *tm) static int __rtc_read_time(struct rtc_device *rtc, struct rtc_time *tm)
{ {
int err; int err;
@ -36,6 +100,8 @@ static int __rtc_read_time(struct rtc_device *rtc, struct rtc_time *tm)
return err; return err;
} }
rtc_add_offset(rtc, tm);
err = rtc_valid_tm(tm); err = rtc_valid_tm(tm);
if (err < 0) if (err < 0)
dev_dbg(&rtc->dev, "read_time: rtc_time isn't valid\n"); dev_dbg(&rtc->dev, "read_time: rtc_time isn't valid\n");
@ -53,6 +119,8 @@ int rtc_read_time(struct rtc_device *rtc, struct rtc_time *tm)
err = __rtc_read_time(rtc, tm); err = __rtc_read_time(rtc, tm);
mutex_unlock(&rtc->ops_lock); mutex_unlock(&rtc->ops_lock);
trace_rtc_read_time(rtc_tm_to_time64(tm), err);
return err; return err;
} }
EXPORT_SYMBOL_GPL(rtc_read_time); EXPORT_SYMBOL_GPL(rtc_read_time);
@ -65,6 +133,12 @@ int rtc_set_time(struct rtc_device *rtc, struct rtc_time *tm)
if (err != 0) if (err != 0)
return err; return err;
err = rtc_valid_range(rtc, tm);
if (err)
return err;
rtc_subtract_offset(rtc, tm);
err = mutex_lock_interruptible(&rtc->ops_lock); err = mutex_lock_interruptible(&rtc->ops_lock);
if (err) if (err)
return err; return err;
@ -87,6 +161,8 @@ int rtc_set_time(struct rtc_device *rtc, struct rtc_time *tm)
mutex_unlock(&rtc->ops_lock); mutex_unlock(&rtc->ops_lock);
/* A timer might have just expired */ /* A timer might have just expired */
schedule_work(&rtc->irqwork); schedule_work(&rtc->irqwork);
trace_rtc_set_time(rtc_tm_to_time64(tm), err);
return err; return err;
} }
EXPORT_SYMBOL_GPL(rtc_set_time); EXPORT_SYMBOL_GPL(rtc_set_time);
@ -119,6 +195,8 @@ static int rtc_read_alarm_internal(struct rtc_device *rtc, struct rtc_wkalrm *al
} }
mutex_unlock(&rtc->ops_lock); mutex_unlock(&rtc->ops_lock);
trace_rtc_read_alarm(rtc_tm_to_time64(&alarm->time), err);
return err; return err;
} }
@ -316,6 +394,7 @@ int rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
} }
mutex_unlock(&rtc->ops_lock); mutex_unlock(&rtc->ops_lock);
trace_rtc_read_alarm(rtc_tm_to_time64(&alarm->time), err);
return err; return err;
} }
EXPORT_SYMBOL_GPL(rtc_read_alarm); EXPORT_SYMBOL_GPL(rtc_read_alarm);
@ -329,6 +408,8 @@ static int __rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
err = rtc_valid_tm(&alarm->time); err = rtc_valid_tm(&alarm->time);
if (err) if (err)
return err; return err;
rtc_subtract_offset(rtc, &alarm->time);
scheduled = rtc_tm_to_time64(&alarm->time); scheduled = rtc_tm_to_time64(&alarm->time);
/* Make sure we're not setting alarms in the past */ /* Make sure we're not setting alarms in the past */
@ -352,6 +433,7 @@ static int __rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
else else
err = rtc->ops->set_alarm(rtc->dev.parent, alarm); err = rtc->ops->set_alarm(rtc->dev.parent, alarm);
trace_rtc_set_alarm(rtc_tm_to_time64(&alarm->time), err);
return err; return err;
} }
@ -363,6 +445,10 @@ int rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
if (err != 0) if (err != 0)
return err; return err;
err = rtc_valid_range(rtc, &alarm->time);
if (err)
return err;
err = mutex_lock_interruptible(&rtc->ops_lock); err = mutex_lock_interruptible(&rtc->ops_lock);
if (err) if (err)
return err; return err;
@ -375,6 +461,8 @@ int rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
err = rtc_timer_enqueue(rtc, &rtc->aie_timer); err = rtc_timer_enqueue(rtc, &rtc->aie_timer);
mutex_unlock(&rtc->ops_lock); mutex_unlock(&rtc->ops_lock);
rtc_add_offset(rtc, &alarm->time);
return err; return err;
} }
EXPORT_SYMBOL_GPL(rtc_set_alarm); EXPORT_SYMBOL_GPL(rtc_set_alarm);
@ -406,6 +494,7 @@ int rtc_initialize_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
rtc->aie_timer.enabled = 1; rtc->aie_timer.enabled = 1;
timerqueue_add(&rtc->timerqueue, &rtc->aie_timer.node); timerqueue_add(&rtc->timerqueue, &rtc->aie_timer.node);
trace_rtc_timer_enqueue(&rtc->aie_timer);
} }
mutex_unlock(&rtc->ops_lock); mutex_unlock(&rtc->ops_lock);
return err; return err;
@ -435,6 +524,8 @@ int rtc_alarm_irq_enable(struct rtc_device *rtc, unsigned int enabled)
err = rtc->ops->alarm_irq_enable(rtc->dev.parent, enabled); err = rtc->ops->alarm_irq_enable(rtc->dev.parent, enabled);
mutex_unlock(&rtc->ops_lock); mutex_unlock(&rtc->ops_lock);
trace_rtc_alarm_irq_enable(enabled, err);
return err; return err;
} }
EXPORT_SYMBOL_GPL(rtc_alarm_irq_enable); EXPORT_SYMBOL_GPL(rtc_alarm_irq_enable);
@ -709,6 +800,8 @@ retry:
rtc->pie_enabled = enabled; rtc->pie_enabled = enabled;
} }
spin_unlock_irqrestore(&rtc->irq_task_lock, flags); spin_unlock_irqrestore(&rtc->irq_task_lock, flags);
trace_rtc_irq_set_state(enabled, err);
return err; return err;
} }
EXPORT_SYMBOL_GPL(rtc_irq_set_state); EXPORT_SYMBOL_GPL(rtc_irq_set_state);
@ -745,6 +838,8 @@ retry:
} }
} }
spin_unlock_irqrestore(&rtc->irq_task_lock, flags); spin_unlock_irqrestore(&rtc->irq_task_lock, flags);
trace_rtc_irq_set_freq(freq, err);
return err; return err;
} }
EXPORT_SYMBOL_GPL(rtc_irq_set_freq); EXPORT_SYMBOL_GPL(rtc_irq_set_freq);
@ -779,6 +874,7 @@ static int rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer)
} }
timerqueue_add(&rtc->timerqueue, &timer->node); timerqueue_add(&rtc->timerqueue, &timer->node);
trace_rtc_timer_enqueue(timer);
if (!next || ktime_before(timer->node.expires, next->expires)) { if (!next || ktime_before(timer->node.expires, next->expires)) {
struct rtc_wkalrm alarm; struct rtc_wkalrm alarm;
int err; int err;
@ -790,6 +886,7 @@ static int rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer)
schedule_work(&rtc->irqwork); schedule_work(&rtc->irqwork);
} else if (err) { } else if (err) {
timerqueue_del(&rtc->timerqueue, &timer->node); timerqueue_del(&rtc->timerqueue, &timer->node);
trace_rtc_timer_dequeue(timer);
timer->enabled = 0; timer->enabled = 0;
return err; return err;
} }
@ -803,6 +900,7 @@ static void rtc_alarm_disable(struct rtc_device *rtc)
return; return;
rtc->ops->alarm_irq_enable(rtc->dev.parent, false); rtc->ops->alarm_irq_enable(rtc->dev.parent, false);
trace_rtc_alarm_irq_enable(0, 0);
} }
/** /**
@ -821,6 +919,7 @@ static void rtc_timer_remove(struct rtc_device *rtc, struct rtc_timer *timer)
{ {
struct timerqueue_node *next = timerqueue_getnext(&rtc->timerqueue); struct timerqueue_node *next = timerqueue_getnext(&rtc->timerqueue);
timerqueue_del(&rtc->timerqueue, &timer->node); timerqueue_del(&rtc->timerqueue, &timer->node);
trace_rtc_timer_dequeue(timer);
timer->enabled = 0; timer->enabled = 0;
if (next == &timer->node) { if (next == &timer->node) {
struct rtc_wkalrm alarm; struct rtc_wkalrm alarm;
@ -871,16 +970,19 @@ again:
/* expire timer */ /* expire timer */
timer = container_of(next, struct rtc_timer, node); timer = container_of(next, struct rtc_timer, node);
timerqueue_del(&rtc->timerqueue, &timer->node); timerqueue_del(&rtc->timerqueue, &timer->node);
trace_rtc_timer_dequeue(timer);
timer->enabled = 0; timer->enabled = 0;
if (timer->task.func) if (timer->task.func)
timer->task.func(timer->task.private_data); timer->task.func(timer->task.private_data);
trace_rtc_timer_fired(timer);
/* Re-add/fwd periodic timers */ /* Re-add/fwd periodic timers */
if (ktime_to_ns(timer->period)) { if (ktime_to_ns(timer->period)) {
timer->node.expires = ktime_add(timer->node.expires, timer->node.expires = ktime_add(timer->node.expires,
timer->period); timer->period);
timer->enabled = 1; timer->enabled = 1;
timerqueue_add(&rtc->timerqueue, &timer->node); timerqueue_add(&rtc->timerqueue, &timer->node);
trace_rtc_timer_enqueue(timer);
} }
} }
@ -902,6 +1004,7 @@ reprogram:
timer = container_of(next, struct rtc_timer, node); timer = container_of(next, struct rtc_timer, node);
timerqueue_del(&rtc->timerqueue, &timer->node); timerqueue_del(&rtc->timerqueue, &timer->node);
trace_rtc_timer_dequeue(timer);
timer->enabled = 0; timer->enabled = 0;
dev_err(&rtc->dev, "__rtc_set_alarm: err=%d\n", err); dev_err(&rtc->dev, "__rtc_set_alarm: err=%d\n", err);
goto again; goto again;
@ -992,6 +1095,8 @@ int rtc_read_offset(struct rtc_device *rtc, long *offset)
mutex_lock(&rtc->ops_lock); mutex_lock(&rtc->ops_lock);
ret = rtc->ops->read_offset(rtc->dev.parent, offset); ret = rtc->ops->read_offset(rtc->dev.parent, offset);
mutex_unlock(&rtc->ops_lock); mutex_unlock(&rtc->ops_lock);
trace_rtc_read_offset(*offset, ret);
return ret; return ret;
} }
@ -1025,5 +1130,7 @@ int rtc_set_offset(struct rtc_device *rtc, long offset)
mutex_lock(&rtc->ops_lock); mutex_lock(&rtc->ops_lock);
ret = rtc->ops->set_offset(rtc->dev.parent, offset); ret = rtc->ops->set_offset(rtc->dev.parent, offset);
mutex_unlock(&rtc->ops_lock); mutex_unlock(&rtc->ops_lock);
trace_rtc_set_offset(offset, ret);
return ret; return ret;
} }

View File

@ -14,8 +14,6 @@
#include <linux/rtc.h> #include <linux/rtc.h>
#include <linux/sysfs.h> #include <linux/sysfs.h>
#include "rtc-core.h"
/* /*
* Deprecated ABI compatibility, this should be removed at some point * Deprecated ABI compatibility, this should be removed at some point
*/ */
@ -46,7 +44,7 @@ rtc_nvram_write(struct file *filp, struct kobject *kobj,
return nvmem_device_write(rtc->nvmem, off, count, buf); return nvmem_device_write(rtc->nvmem, off, count, buf);
} }
static int rtc_nvram_register(struct rtc_device *rtc) static int rtc_nvram_register(struct rtc_device *rtc, size_t size)
{ {
int err; int err;
@ -64,7 +62,7 @@ static int rtc_nvram_register(struct rtc_device *rtc)
rtc->nvram->read = rtc_nvram_read; rtc->nvram->read = rtc_nvram_read;
rtc->nvram->write = rtc_nvram_write; rtc->nvram->write = rtc_nvram_write;
rtc->nvram->size = rtc->nvmem_config->size; rtc->nvram->size = size;
err = sysfs_create_bin_file(&rtc->dev.parent->kobj, err = sysfs_create_bin_file(&rtc->dev.parent->kobj,
rtc->nvram); rtc->nvram);
@ -84,21 +82,28 @@ static void rtc_nvram_unregister(struct rtc_device *rtc)
/* /*
* New ABI, uses nvmem * New ABI, uses nvmem
*/ */
void rtc_nvmem_register(struct rtc_device *rtc) int rtc_nvmem_register(struct rtc_device *rtc,
struct nvmem_config *nvmem_config)
{ {
if (!rtc->nvmem_config) if (!IS_ERR_OR_NULL(rtc->nvmem))
return; return -EBUSY;
rtc->nvmem_config->dev = &rtc->dev; if (!nvmem_config)
rtc->nvmem_config->owner = rtc->owner; return -ENODEV;
rtc->nvmem = nvmem_register(rtc->nvmem_config);
nvmem_config->dev = rtc->dev.parent;
nvmem_config->owner = rtc->owner;
rtc->nvmem = nvmem_register(nvmem_config);
if (IS_ERR_OR_NULL(rtc->nvmem)) if (IS_ERR_OR_NULL(rtc->nvmem))
return; return PTR_ERR(rtc->nvmem);
/* Register the old ABI */ /* Register the old ABI */
if (rtc->nvram_old_abi) if (rtc->nvram_old_abi)
rtc_nvram_register(rtc); rtc_nvram_register(rtc, nvmem_config->size);
return 0;
} }
EXPORT_SYMBOL_GPL(rtc_nvmem_register);
void rtc_nvmem_unregister(struct rtc_device *rtc) void rtc_nvmem_unregister(struct rtc_device *rtc)
{ {

View File

@ -134,9 +134,9 @@ static int pm80x_rtc_set_time(struct device *dev, struct rtc_time *tm)
struct pm80x_rtc_info *info = dev_get_drvdata(dev); struct pm80x_rtc_info *info = dev_get_drvdata(dev);
unsigned char buf[4]; unsigned char buf[4];
unsigned long ticks, base, data; unsigned long ticks, base, data;
if ((tm->tm_year < 70) || (tm->tm_year > 138)) { if (tm->tm_year > 206) {
dev_dbg(info->dev, dev_dbg(info->dev,
"Set time %d out of range. Please set time between 1970 to 2038.\n", "Set time %d out of range. Please set time between 1970 to 2106.\n",
1900 + tm->tm_year); 1900 + tm->tm_year);
return -EINVAL; return -EINVAL;
} }

View File

@ -135,9 +135,9 @@ static int pm860x_rtc_set_time(struct device *dev, struct rtc_time *tm)
unsigned char buf[4]; unsigned char buf[4];
unsigned long ticks, base, data; unsigned long ticks, base, data;
if ((tm->tm_year < 70) || (tm->tm_year > 138)) { if (tm->tm_year > 206) {
dev_dbg(info->dev, "Set time %d out of range. " dev_dbg(info->dev, "Set time %d out of range. "
"Please set time between 1970 to 2038.\n", "Please set time between 1970 to 2106.\n",
1900 + tm->tm_year); 1900 + tm->tm_year);
return -EINVAL; return -EINVAL;
} }

View File

@ -217,7 +217,7 @@ static int _abb5zes3_rtc_read_time(struct device *dev, struct rtc_time *tm)
{ {
struct abb5zes3_rtc_data *data = dev_get_drvdata(dev); struct abb5zes3_rtc_data *data = dev_get_drvdata(dev);
u8 regs[ABB5ZES3_REG_RTC_SC + ABB5ZES3_RTC_SEC_LEN]; u8 regs[ABB5ZES3_REG_RTC_SC + ABB5ZES3_RTC_SEC_LEN];
int ret; int ret = 0;
/* /*
* As we need to read CTRL1 register anyway to access 24/12h * As we need to read CTRL1 register anyway to access 24/12h
@ -255,8 +255,6 @@ static int _abb5zes3_rtc_read_time(struct device *dev, struct rtc_time *tm)
tm->tm_mon = bcd2bin(regs[ABB5ZES3_REG_RTC_MO]) - 1; /* starts at 1 */ tm->tm_mon = bcd2bin(regs[ABB5ZES3_REG_RTC_MO]) - 1; /* starts at 1 */
tm->tm_year = bcd2bin(regs[ABB5ZES3_REG_RTC_YR]) + 100; tm->tm_year = bcd2bin(regs[ABB5ZES3_REG_RTC_YR]) + 100;
ret = rtc_valid_tm(tm);
err: err:
return ret; return ret;
} }

View File

@ -106,7 +106,7 @@ static int ab3100_rtc_read_time(struct device *dev, struct rtc_time *tm)
rtc_time64_to_tm(time, tm); rtc_time64_to_tm(time, tm);
return rtc_valid_tm(tm); return 0;
} }
static int ab3100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) static int ab3100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)

View File

@ -36,10 +36,6 @@
#define AB8500_RTC_FORCE_BKUP_REG 0x0D #define AB8500_RTC_FORCE_BKUP_REG 0x0D
#define AB8500_RTC_CALIB_REG 0x0E #define AB8500_RTC_CALIB_REG 0x0E
#define AB8500_RTC_SWITCH_STAT_REG 0x0F #define AB8500_RTC_SWITCH_STAT_REG 0x0F
#define AB8540_RTC_ALRM_SEC 0x22
#define AB8540_RTC_ALRM_MIN_LOW_REG 0x23
#define AB8540_RTC_ALRM_MIN_MID_REG 0x24
#define AB8540_RTC_ALRM_MIN_HI_REG 0x25
/* RtcReadRequest bits */ /* RtcReadRequest bits */
#define RTC_READ_REQUEST 0x01 #define RTC_READ_REQUEST 0x01
@ -63,11 +59,6 @@ static const u8 ab8500_rtc_alarm_regs[] = {
AB8500_RTC_ALRM_MIN_LOW_REG AB8500_RTC_ALRM_MIN_LOW_REG
}; };
static const u8 ab8540_rtc_alarm_regs[] = {
AB8540_RTC_ALRM_MIN_HI_REG, AB8540_RTC_ALRM_MIN_MID_REG,
AB8540_RTC_ALRM_MIN_LOW_REG, AB8540_RTC_ALRM_SEC
};
/* Calculate the seconds from 1970 to 01-01-2000 00:00:00 */ /* Calculate the seconds from 1970 to 01-01-2000 00:00:00 */
static unsigned long get_elapsed_seconds(int year) static unsigned long get_elapsed_seconds(int year)
{ {
@ -131,7 +122,7 @@ static int ab8500_rtc_read_time(struct device *dev, struct rtc_time *tm)
secs += get_elapsed_seconds(AB8500_RTC_EPOCH); secs += get_elapsed_seconds(AB8500_RTC_EPOCH);
rtc_time_to_tm(secs, tm); rtc_time_to_tm(secs, tm);
return rtc_valid_tm(tm); return 0;
} }
static int ab8500_rtc_set_time(struct device *dev, struct rtc_time *tm) static int ab8500_rtc_set_time(struct device *dev, struct rtc_time *tm)
@ -277,43 +268,6 @@ static int ab8500_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
return ab8500_rtc_irq_enable(dev, alarm->enabled); return ab8500_rtc_irq_enable(dev, alarm->enabled);
} }
static int ab8540_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
{
int retval, i;
unsigned char buf[ARRAY_SIZE(ab8540_rtc_alarm_regs)];
unsigned long mins, secs = 0;
if (alarm->time.tm_year < (AB8500_RTC_EPOCH - 1900)) {
dev_dbg(dev, "year should be equal to or greater than %d\n",
AB8500_RTC_EPOCH);
return -EINVAL;
}
/* Get the number of seconds since 1970 */
rtc_tm_to_time(&alarm->time, &secs);
/*
* Convert it to the number of seconds since 01-01-2000 00:00:00
*/
secs -= get_elapsed_seconds(AB8500_RTC_EPOCH);
mins = secs / 60;
buf[3] = secs % 60;
buf[2] = mins & 0xFF;
buf[1] = (mins >> 8) & 0xFF;
buf[0] = (mins >> 16) & 0xFF;
/* Set the alarm time */
for (i = 0; i < ARRAY_SIZE(ab8540_rtc_alarm_regs); i++) {
retval = abx500_set_register_interruptible(dev, AB8500_RTC,
ab8540_rtc_alarm_regs[i], buf[i]);
if (retval < 0)
return retval;
}
return ab8500_rtc_irq_enable(dev, alarm->enabled);
}
static int ab8500_rtc_set_calibration(struct device *dev, int calibration) static int ab8500_rtc_set_calibration(struct device *dev, int calibration)
{ {
int retval; int retval;
@ -435,17 +389,8 @@ static const struct rtc_class_ops ab8500_rtc_ops = {
.alarm_irq_enable = ab8500_rtc_irq_enable, .alarm_irq_enable = ab8500_rtc_irq_enable,
}; };
static const struct rtc_class_ops ab8540_rtc_ops = {
.read_time = ab8500_rtc_read_time,
.set_time = ab8500_rtc_set_time,
.read_alarm = ab8500_rtc_read_alarm,
.set_alarm = ab8540_rtc_set_alarm,
.alarm_irq_enable = ab8500_rtc_irq_enable,
};
static const struct platform_device_id ab85xx_rtc_ids[] = { static const struct platform_device_id ab85xx_rtc_ids[] = {
{ "ab8500-rtc", (kernel_ulong_t)&ab8500_rtc_ops, }, { "ab8500-rtc", (kernel_ulong_t)&ab8500_rtc_ops, },
{ "ab8540-rtc", (kernel_ulong_t)&ab8540_rtc_ops, },
{ /* sentinel */ } { /* sentinel */ }
}; };
MODULE_DEVICE_TABLE(platform, ab85xx_rtc_ids); MODULE_DEVICE_TABLE(platform, ab85xx_rtc_ids);

View File

@ -172,11 +172,7 @@ static int abx80x_rtc_read_time(struct device *dev, struct rtc_time *tm)
tm->tm_mon = bcd2bin(buf[ABX8XX_REG_MO] & 0x1F) - 1; tm->tm_mon = bcd2bin(buf[ABX8XX_REG_MO] & 0x1F) - 1;
tm->tm_year = bcd2bin(buf[ABX8XX_REG_YR]) + 100; tm->tm_year = bcd2bin(buf[ABX8XX_REG_YR]) + 100;
err = rtc_valid_tm(tm); return 0;
if (err < 0)
dev_err(&client->dev, "retrieved date/time is not valid.\n");
return err;
} }
static int abx80x_rtc_set_time(struct device *dev, struct rtc_time *tm) static int abx80x_rtc_set_time(struct device *dev, struct rtc_time *tm)

View File

@ -183,7 +183,29 @@ static int ac100_clkout_determine_rate(struct clk_hw *hw,
for (i = 0; i < num_parents; i++) { for (i = 0; i < num_parents; i++) {
struct clk_hw *parent = clk_hw_get_parent_by_index(hw, i); struct clk_hw *parent = clk_hw_get_parent_by_index(hw, i);
unsigned long tmp, prate = clk_hw_get_rate(parent); unsigned long tmp, prate;
/*
* The clock has two parents, one is a fixed clock which is
* internally registered by the ac100 driver. The other parent
* is a clock from the codec side of the chip, which we
* properly declare and reference in the devicetree and is
* not implemented in any driver right now.
* If the clock core looks for the parent of that second
* missing clock, it can't find one that is registered and
* returns NULL.
* So we end up in a situation where clk_hw_get_num_parents
* returns the amount of clocks we can be parented to, but
* clk_hw_get_parent_by_index will not return the orphan
* clocks.
* Thus we need to check if the parent exists before
* we get the parent rate, so we could use the RTC
* without waiting for the codec to be supported.
*/
if (!parent)
continue;
prate = clk_hw_get_rate(parent);
tmp = ac100_clkout_round_rate(hw, req->rate, prate); tmp = ac100_clkout_round_rate(hw, req->rate, prate);
@ -387,7 +409,7 @@ static int ac100_rtc_get_time(struct device *dev, struct rtc_time *rtc_tm)
rtc_tm->tm_year = bcd2bin(reg[6] & AC100_RTC_YEA_MASK) + rtc_tm->tm_year = bcd2bin(reg[6] & AC100_RTC_YEA_MASK) +
AC100_YEAR_OFF; AC100_YEAR_OFF;
return rtc_valid_tm(rtc_tm); return 0;
} }
static int ac100_rtc_set_time(struct device *dev, struct rtc_time *rtc_tm) static int ac100_rtc_set_time(struct device *dev, struct rtc_time *rtc_tm)

View File

@ -349,6 +349,7 @@ static const struct rtc_class_ops at91_rtc_ops = {
}; };
static const struct regmap_config gpbr_regmap_config = { static const struct regmap_config gpbr_regmap_config = {
.name = "gpbr",
.reg_bits = 32, .reg_bits = 32,
.val_bits = 32, .val_bits = 32,
.reg_stride = 4, .reg_stride = 4,

View File

@ -36,7 +36,7 @@ static int au1xtoy_rtc_read_time(struct device *dev, struct rtc_time *tm)
rtc_time_to_tm(t, tm); rtc_time_to_tm(t, tm);
return rtc_valid_tm(tm); return 0;
} }
static int au1xtoy_rtc_set_time(struct device *dev, struct rtc_time *tm) static int au1xtoy_rtc_set_time(struct device *dev, struct rtc_time *tm)

View File

@ -36,6 +36,10 @@
#define BQ32K_CFG2 0x09 /* Trickle charger control */ #define BQ32K_CFG2 0x09 /* Trickle charger control */
#define BQ32K_TCFE BIT(6) /* Trickle charge FET bypass */ #define BQ32K_TCFE BIT(6) /* Trickle charge FET bypass */
#define MAX_LEN 10 /* Maximum number of consecutive
* register for this particular RTC.
*/
struct bq32k_regs { struct bq32k_regs {
uint8_t seconds; uint8_t seconds;
uint8_t minutes; uint8_t minutes;
@ -74,7 +78,7 @@ static int bq32k_read(struct device *dev, void *data, uint8_t off, uint8_t len)
static int bq32k_write(struct device *dev, void *data, uint8_t off, uint8_t len) static int bq32k_write(struct device *dev, void *data, uint8_t off, uint8_t len)
{ {
struct i2c_client *client = to_i2c_client(dev); struct i2c_client *client = to_i2c_client(dev);
uint8_t buffer[len + 1]; uint8_t buffer[MAX_LEN + 1];
buffer[0] = off; buffer[0] = off;
memcpy(&buffer[1], data, len); memcpy(&buffer[1], data, len);
@ -110,7 +114,7 @@ static int bq32k_rtc_read_time(struct device *dev, struct rtc_time *tm)
tm->tm_year = bcd2bin(regs.years) + tm->tm_year = bcd2bin(regs.years) +
((regs.cent_hours & BQ32K_CENT) ? 100 : 0); ((regs.cent_hours & BQ32K_CENT) ? 100 : 0);
return rtc_valid_tm(tm); return 0;
} }
static int bq32k_rtc_set_time(struct device *dev, struct rtc_time *tm) static int bq32k_rtc_set_time(struct device *dev, struct rtc_time *tm)

View File

@ -60,6 +60,9 @@ static void brcmstb_waketmr_set_alarm(struct brcmstb_waketmr *timer,
{ {
brcmstb_waketmr_clear_alarm(timer); brcmstb_waketmr_clear_alarm(timer);
/* Make sure we are actually counting in seconds */
writel_relaxed(timer->rate, timer->base + BRCMSTB_WKTMR_PRESCALER);
writel_relaxed(secs + 1, timer->base + BRCMSTB_WKTMR_ALARM); writel_relaxed(secs + 1, timer->base + BRCMSTB_WKTMR_ALARM);
} }

View File

@ -541,11 +541,10 @@ static const struct rtc_class_ops cmos_rtc_ops = {
#define NVRAM_OFFSET (RTC_REG_D + 1) #define NVRAM_OFFSET (RTC_REG_D + 1)
static ssize_t static int cmos_nvram_read(void *priv, unsigned int off, void *val,
cmos_nvram_read(struct file *filp, struct kobject *kobj, size_t count)
struct bin_attribute *attr,
char *buf, loff_t off, size_t count)
{ {
unsigned char *buf = val;
int retval; int retval;
off += NVRAM_OFFSET; off += NVRAM_OFFSET;
@ -563,16 +562,13 @@ cmos_nvram_read(struct file *filp, struct kobject *kobj,
return retval; return retval;
} }
static ssize_t static int cmos_nvram_write(void *priv, unsigned int off, void *val,
cmos_nvram_write(struct file *filp, struct kobject *kobj, size_t count)
struct bin_attribute *attr,
char *buf, loff_t off, size_t count)
{ {
struct cmos_rtc *cmos; struct cmos_rtc *cmos = priv;
unsigned char *buf = val;
int retval; int retval;
cmos = dev_get_drvdata(container_of(kobj, struct device, kobj));
/* NOTE: on at least PCs and Ataris, the boot firmware uses a /* NOTE: on at least PCs and Ataris, the boot firmware uses a
* checksum on part of the NVRAM data. That's currently ignored * checksum on part of the NVRAM data. That's currently ignored
* here. If userspace is smart enough to know what fields of * here. If userspace is smart enough to know what fields of
@ -598,17 +594,6 @@ cmos_nvram_write(struct file *filp, struct kobject *kobj,
return retval; return retval;
} }
static struct bin_attribute nvram = {
.attr = {
.name = "nvram",
.mode = S_IRUGO | S_IWUSR,
},
.read = cmos_nvram_read,
.write = cmos_nvram_write,
/* size gets set up later */
};
/*----------------------------------------------------------------*/ /*----------------------------------------------------------------*/
static struct cmos_rtc cmos_rtc; static struct cmos_rtc cmos_rtc;
@ -675,6 +660,14 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
unsigned char rtc_control; unsigned char rtc_control;
unsigned address_space; unsigned address_space;
u32 flags = 0; u32 flags = 0;
struct nvmem_config nvmem_cfg = {
.name = "cmos_nvram",
.word_size = 1,
.stride = 1,
.reg_read = cmos_nvram_read,
.reg_write = cmos_nvram_write,
.priv = &cmos_rtc,
};
/* there can be only one ... */ /* there can be only one ... */
if (cmos_rtc.dev) if (cmos_rtc.dev)
@ -751,8 +744,7 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
cmos_rtc.dev = dev; cmos_rtc.dev = dev;
dev_set_drvdata(dev, &cmos_rtc); dev_set_drvdata(dev, &cmos_rtc);
cmos_rtc.rtc = rtc_device_register(driver_name, dev, cmos_rtc.rtc = devm_rtc_allocate_device(dev);
&cmos_rtc_ops, THIS_MODULE);
if (IS_ERR(cmos_rtc.rtc)) { if (IS_ERR(cmos_rtc.rtc)) {
retval = PTR_ERR(cmos_rtc.rtc); retval = PTR_ERR(cmos_rtc.rtc);
goto cleanup0; goto cleanup0;
@ -814,22 +806,25 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
} }
} }
/* export at least the first block of NVRAM */ cmos_rtc.rtc->ops = &cmos_rtc_ops;
nvram.size = address_space - NVRAM_OFFSET; cmos_rtc.rtc->nvram_old_abi = true;
retval = sysfs_create_bin_file(&dev->kobj, &nvram); retval = rtc_register_device(cmos_rtc.rtc);
if (retval < 0) { if (retval)
dev_dbg(dev, "can't create nvram file? %d\n", retval);
goto cleanup2; goto cleanup2;
}
dev_info(dev, "%s%s, %zd bytes nvram%s\n", /* export at least the first block of NVRAM */
!is_valid_irq(rtc_irq) ? "no alarms" : nvmem_cfg.size = address_space - NVRAM_OFFSET;
cmos_rtc.mon_alrm ? "alarms up to one year" : if (rtc_nvmem_register(cmos_rtc.rtc, &nvmem_cfg))
cmos_rtc.day_alrm ? "alarms up to one month" : dev_err(dev, "nvmem registration failed\n");
"alarms up to one day",
cmos_rtc.century ? ", y3k" : "", dev_info(dev, "%s%s, %d bytes nvram%s\n",
nvram.size, !is_valid_irq(rtc_irq) ? "no alarms" :
is_hpet_enabled() ? ", hpet irqs" : ""); cmos_rtc.mon_alrm ? "alarms up to one year" :
cmos_rtc.day_alrm ? "alarms up to one month" :
"alarms up to one day",
cmos_rtc.century ? ", y3k" : "",
nvmem_cfg.size,
is_hpet_enabled() ? ", hpet irqs" : "");
return 0; return 0;
@ -838,7 +833,6 @@ cleanup2:
free_irq(rtc_irq, cmos_rtc.rtc); free_irq(rtc_irq, cmos_rtc.rtc);
cleanup1: cleanup1:
cmos_rtc.dev = NULL; cmos_rtc.dev = NULL;
rtc_device_unregister(cmos_rtc.rtc);
cleanup0: cleanup0:
if (RTC_IOMAPPED) if (RTC_IOMAPPED)
release_region(ports->start, resource_size(ports)); release_region(ports->start, resource_size(ports));
@ -862,14 +856,11 @@ static void cmos_do_remove(struct device *dev)
cmos_do_shutdown(cmos->irq); cmos_do_shutdown(cmos->irq);
sysfs_remove_bin_file(&dev->kobj, &nvram);
if (is_valid_irq(cmos->irq)) { if (is_valid_irq(cmos->irq)) {
free_irq(cmos->irq, cmos->rtc); free_irq(cmos->irq, cmos->rtc);
hpet_unregister_irq_handler(cmos_interrupt); hpet_unregister_irq_handler(cmos_interrupt);
} }
rtc_device_unregister(cmos->rtc);
cmos->rtc = NULL; cmos->rtc = NULL;
ports = cmos->iomem; ports = cmos->iomem;
@ -1271,8 +1262,6 @@ MODULE_DEVICE_TABLE(of, of_cmos_match);
static __init void cmos_of_init(struct platform_device *pdev) static __init void cmos_of_init(struct platform_device *pdev)
{ {
struct device_node *node = pdev->dev.of_node; struct device_node *node = pdev->dev.of_node;
struct rtc_time time;
int ret;
const __be32 *val; const __be32 *val;
if (!node) if (!node)
@ -1285,16 +1274,6 @@ static __init void cmos_of_init(struct platform_device *pdev)
val = of_get_property(node, "freq-reg", NULL); val = of_get_property(node, "freq-reg", NULL);
if (val) if (val)
CMOS_WRITE(be32_to_cpup(val), RTC_FREQ_SELECT); CMOS_WRITE(be32_to_cpup(val), RTC_FREQ_SELECT);
cmos_read_time(&pdev->dev, &time);
ret = rtc_valid_tm(&time);
if (ret) {
struct rtc_time def_time = {
.tm_year = 1,
.tm_mday = 1,
};
cmos_set_time(&pdev->dev, &def_time);
}
} }
#else #else
static inline void cmos_of_init(struct platform_device *pdev) {} static inline void cmos_of_init(struct platform_device *pdev) {}

View File

@ -82,7 +82,7 @@ static int coh901331_read_time(struct device *dev, struct rtc_time *tm)
if (readl(rtap->virtbase + COH901331_VALID)) { if (readl(rtap->virtbase + COH901331_VALID)) {
rtc_time_to_tm(readl(rtap->virtbase + COH901331_CUR_TIME), tm); rtc_time_to_tm(readl(rtap->virtbase + COH901331_CUR_TIME), tm);
clk_disable(rtap->clk); clk_disable(rtap->clk);
return rtc_valid_tm(tm); return 0;
} }
clk_disable(rtap->clk); clk_disable(rtap->clk);
return -EINVAL; return -EINVAL;

View File

@ -46,11 +46,3 @@ static inline const struct attribute_group **rtc_get_dev_attribute_groups(void)
return NULL; return NULL;
} }
#endif #endif
#ifdef CONFIG_RTC_NVMEM
void rtc_nvmem_register(struct rtc_device *rtc);
void rtc_nvmem_unregister(struct rtc_device *rtc);
#else
static inline void rtc_nvmem_register(struct rtc_device *rtc) {}
static inline void rtc_nvmem_unregister(struct rtc_device *rtc) {}
#endif

View File

@ -119,7 +119,7 @@ static int cpcap_rtc_read_time(struct device *dev, struct rtc_time *tm)
cpcap2rtc_time(tm, &cpcap_tm); cpcap2rtc_time(tm, &cpcap_tm);
return rtc_valid_tm(tm); return 0;
} }
static int cpcap_rtc_set_time(struct device *dev, struct rtc_time *tm) static int cpcap_rtc_set_time(struct device *dev, struct rtc_time *tm)

View File

@ -197,10 +197,10 @@ static int cros_ec_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
cros_ec_rtc->saved_alarm = (u32)alarm_time; cros_ec_rtc->saved_alarm = (u32)alarm_time;
} else { } else {
/* Don't set an alarm in the past. */ /* Don't set an alarm in the past. */
if ((u32)alarm_time < current_time) if ((u32)alarm_time <= current_time)
alarm_offset = EC_RTC_ALARM_CLEAR; return -ETIME;
else
alarm_offset = (u32)alarm_time - current_time; alarm_offset = (u32)alarm_time - current_time;
} }
ret = cros_ec_rtc_set(cros_ec, EC_CMD_RTC_SET_ALARM, alarm_offset); ret = cros_ec_rtc_set(cros_ec, EC_CMD_RTC_SET_ALARM, alarm_offset);

View File

@ -187,8 +187,7 @@ static int da9052_rtc_read_time(struct device *dev, struct rtc_time *rtc_tm)
rtc_tm->tm_min = v[0][1] & DA9052_RTC_MIN; rtc_tm->tm_min = v[0][1] & DA9052_RTC_MIN;
rtc_tm->tm_sec = v[0][0] & DA9052_RTC_SEC; rtc_tm->tm_sec = v[0][0] & DA9052_RTC_SEC;
ret = rtc_valid_tm(rtc_tm); return 0;
return ret;
} }
idx = (1-idx); idx = (1-idx);

View File

@ -158,7 +158,7 @@ static int da9055_rtc_read_time(struct device *dev, struct rtc_time *rtc_tm)
rtc_tm->tm_min = v[1] & DA9055_RTC_MIN; rtc_tm->tm_min = v[1] & DA9055_RTC_MIN;
rtc_tm->tm_sec = v[0] & DA9055_RTC_SEC; rtc_tm->tm_sec = v[0] & DA9055_RTC_SEC;
return rtc_valid_tm(rtc_tm); return 0;
} }
static int da9055_rtc_set_time(struct device *dev, struct rtc_time *tm) static int da9055_rtc_set_time(struct device *dev, struct rtc_time *tm)

View File

@ -256,7 +256,7 @@ static int da9063_rtc_read_time(struct device *dev, struct rtc_time *tm)
else else
rtc->rtc_sync = false; rtc->rtc_sync = false;
return rtc_valid_tm(tm); return 0;
} }
static int da9063_rtc_set_time(struct device *dev, struct rtc_time *tm) static int da9063_rtc_set_time(struct device *dev, struct rtc_time *tm)

View File

@ -99,7 +99,7 @@ static int ds1216_rtc_read_time(struct device *dev, struct rtc_time *tm)
if (tm->tm_year < 70) if (tm->tm_year < 70)
tm->tm_year += 100; tm->tm_year += 100;
return rtc_valid_tm(tm); return 0;
} }
static int ds1216_rtc_set_time(struct device *dev, struct rtc_time *tm) static int ds1216_rtc_set_time(struct device *dev, struct rtc_time *tm)

View File

@ -211,7 +211,7 @@ static int ds1286_read_time(struct device *dev, struct rtc_time *tm)
tm->tm_mon--; tm->tm_mon--;
return rtc_valid_tm(tm); return 0;
} }
static int ds1286_set_time(struct device *dev, struct rtc_time *tm) static int ds1286_set_time(struct device *dev, struct rtc_time *tm)

View File

@ -43,7 +43,7 @@ static int ds1302_rtc_set_time(struct device *dev, struct rtc_time *time)
{ {
struct spi_device *spi = dev_get_drvdata(dev); struct spi_device *spi = dev_get_drvdata(dev);
u8 buf[1 + RTC_CLCK_LEN]; u8 buf[1 + RTC_CLCK_LEN];
u8 *bp = buf; u8 *bp;
int status; int status;
/* Enable writing */ /* Enable writing */
@ -98,8 +98,7 @@ static int ds1302_rtc_get_time(struct device *dev, struct rtc_time *time)
time->tm_mon = bcd2bin(buf[RTC_ADDR_MON]) - 1; time->tm_mon = bcd2bin(buf[RTC_ADDR_MON]) - 1;
time->tm_year = bcd2bin(buf[RTC_ADDR_YEAR]) + 100; time->tm_year = bcd2bin(buf[RTC_ADDR_YEAR]) + 100;
/* Time may not be set */ return 0;
return rtc_valid_tm(time);
} }
static const struct rtc_class_ops ds1302_rtc_ops = { static const struct rtc_class_ops ds1302_rtc_ops = {
@ -112,7 +111,7 @@ static int ds1302_probe(struct spi_device *spi)
struct rtc_device *rtc; struct rtc_device *rtc;
u8 addr; u8 addr;
u8 buf[4]; u8 buf[4];
u8 *bp = buf; u8 *bp;
int status; int status;
/* Sanity check board setup data. This may be hooked up /* Sanity check board setup data. This may be hooked up

View File

@ -203,8 +203,7 @@ static int ds1305_get_time(struct device *dev, struct rtc_time *time)
time->tm_hour, time->tm_mday, time->tm_hour, time->tm_mday,
time->tm_mon, time->tm_year, time->tm_wday); time->tm_mon, time->tm_year, time->tm_wday);
/* Time may not be set */ return 0;
return rtc_valid_tm(time);
} }
static int ds1305_set_time(struct device *dev, struct rtc_time *time) static int ds1305_set_time(struct device *dev, struct rtc_time *time)
@ -544,15 +543,6 @@ static int ds1305_nvram_write(void *priv, unsigned int off, void *buf,
return spi_sync(spi, &m); return spi_sync(spi, &m);
} }
static struct nvmem_config ds1305_nvmem_cfg = {
.name = "ds1305_nvram",
.word_size = 1,
.stride = 1,
.size = DS1305_NVRAM_LEN,
.reg_read = ds1305_nvram_read,
.reg_write = ds1305_nvram_write,
};
/*----------------------------------------------------------------------*/ /*----------------------------------------------------------------------*/
/* /*
@ -566,6 +556,14 @@ static int ds1305_probe(struct spi_device *spi)
u8 addr, value; u8 addr, value;
struct ds1305_platform_data *pdata = dev_get_platdata(&spi->dev); struct ds1305_platform_data *pdata = dev_get_platdata(&spi->dev);
bool write_ctrl = false; bool write_ctrl = false;
struct nvmem_config ds1305_nvmem_cfg = {
.name = "ds1305_nvram",
.word_size = 1,
.stride = 1,
.size = DS1305_NVRAM_LEN,
.reg_read = ds1305_nvram_read,
.reg_write = ds1305_nvram_write,
};
/* Sanity check board setup data. This may be hooked up /* Sanity check board setup data. This may be hooked up
* in 3wire mode, but we don't care. Note that unless * in 3wire mode, but we don't care. Note that unless
@ -703,15 +701,15 @@ static int ds1305_probe(struct spi_device *spi)
ds1305->rtc->ops = &ds1305_ops; ds1305->rtc->ops = &ds1305_ops;
ds1305_nvmem_cfg.priv = ds1305; ds1305_nvmem_cfg.priv = ds1305;
ds1305->rtc->nvmem_config = &ds1305_nvmem_cfg;
ds1305->rtc->nvram_old_abi = true; ds1305->rtc->nvram_old_abi = true;
status = rtc_register_device(ds1305->rtc); status = rtc_register_device(ds1305->rtc);
if (status) { if (status) {
dev_dbg(&spi->dev, "register rtc --> %d\n", status); dev_dbg(&spi->dev, "register rtc --> %d\n", status);
return status; return status;
} }
rtc_nvmem_register(ds1305->rtc, &ds1305_nvmem_cfg);
/* Maybe set up alarm IRQ; be ready to handle it triggering right /* Maybe set up alarm IRQ; be ready to handle it triggering right
* away. NOTE that we don't share this. The signal is active low, * away. NOTE that we don't share this. The signal is active low,
* and we can't ack it before a SPI message delay. We temporarily * and we can't ack it before a SPI message delay. We temporarily

View File

@ -114,7 +114,6 @@ enum ds_type {
# define RX8025_BIT_XST 0x20 # define RX8025_BIT_XST 0x20
struct ds1307 { struct ds1307 {
struct nvmem_config nvmem_cfg;
enum ds_type type; enum ds_type type;
unsigned long flags; unsigned long flags;
#define HAS_NVRAM 0 /* bit 0 == sysfs file active */ #define HAS_NVRAM 0 /* bit 0 == sysfs file active */
@ -438,8 +437,7 @@ static int ds1307_get_time(struct device *dev, struct rtc_time *t)
t->tm_hour, t->tm_mday, t->tm_hour, t->tm_mday,
t->tm_mon, t->tm_year, t->tm_wday); t->tm_mon, t->tm_year, t->tm_wday);
/* initial clock setting can be undefined */ return 0;
return rtc_valid_tm(t);
} }
static int ds1307_set_time(struct device *dev, struct rtc_time *t) static int ds1307_set_time(struct device *dev, struct rtc_time *t)
@ -1696,24 +1694,26 @@ read_rtc:
} }
} }
if (chip->nvram_size) {
ds1307->nvmem_cfg.name = "ds1307_nvram";
ds1307->nvmem_cfg.word_size = 1;
ds1307->nvmem_cfg.stride = 1;
ds1307->nvmem_cfg.size = chip->nvram_size;
ds1307->nvmem_cfg.reg_read = ds1307_nvram_read;
ds1307->nvmem_cfg.reg_write = ds1307_nvram_write;
ds1307->nvmem_cfg.priv = ds1307;
ds1307->rtc->nvmem_config = &ds1307->nvmem_cfg;
ds1307->rtc->nvram_old_abi = true;
}
ds1307->rtc->ops = chip->rtc_ops ?: &ds13xx_rtc_ops; ds1307->rtc->ops = chip->rtc_ops ?: &ds13xx_rtc_ops;
err = rtc_register_device(ds1307->rtc); err = rtc_register_device(ds1307->rtc);
if (err) if (err)
return err; return err;
if (chip->nvram_size) {
struct nvmem_config nvmem_cfg = {
.name = "ds1307_nvram",
.word_size = 1,
.stride = 1,
.size = chip->nvram_size,
.reg_read = ds1307_nvram_read,
.reg_write = ds1307_nvram_write,
.priv = ds1307,
};
ds1307->rtc->nvram_old_abi = true;
rtc_nvmem_register(ds1307->rtc, &nvmem_cfg);
}
ds1307_hwmon_register(ds1307); ds1307_hwmon_register(ds1307);
ds1307_clks_register(ds1307); ds1307_clks_register(ds1307);

View File

@ -153,120 +153,22 @@ static ssize_t ds1343_store_glitchfilter(struct device *dev,
static DEVICE_ATTR(glitch_filter, S_IRUGO | S_IWUSR, ds1343_show_glitchfilter, static DEVICE_ATTR(glitch_filter, S_IRUGO | S_IWUSR, ds1343_show_glitchfilter,
ds1343_store_glitchfilter); ds1343_store_glitchfilter);
static ssize_t ds1343_nvram_write(struct file *filp, struct kobject *kobj, static int ds1343_nvram_write(void *priv, unsigned int off, void *val,
struct bin_attribute *attr, size_t bytes)
char *buf, loff_t off, size_t count)
{ {
int ret; struct ds1343_priv *ds1343 = priv;
unsigned char address;
struct device *dev = kobj_to_dev(kobj);
struct ds1343_priv *priv = dev_get_drvdata(dev);
address = DS1343_NVRAM + off; return regmap_bulk_write(ds1343->map, DS1343_NVRAM + off, val, bytes);
ret = regmap_bulk_write(priv->map, address, buf, count);
if (ret < 0)
dev_err(&priv->spi->dev, "Error in nvram write %d", ret);
return (ret < 0) ? ret : count;
} }
static int ds1343_nvram_read(void *priv, unsigned int off, void *val,
static ssize_t ds1343_nvram_read(struct file *filp, struct kobject *kobj, size_t bytes)
struct bin_attribute *attr,
char *buf, loff_t off, size_t count)
{ {
int ret; struct ds1343_priv *ds1343 = priv;
unsigned char address;
struct device *dev = kobj_to_dev(kobj);
struct ds1343_priv *priv = dev_get_drvdata(dev);
address = DS1343_NVRAM + off; return regmap_bulk_read(ds1343->map, DS1343_NVRAM + off, val, bytes);
ret = regmap_bulk_read(priv->map, address, buf, count);
if (ret < 0)
dev_err(&priv->spi->dev, "Error in nvram read %d\n", ret);
return (ret < 0) ? ret : count;
} }
static struct bin_attribute nvram_attr = {
.attr.name = "nvram",
.attr.mode = S_IRUGO | S_IWUSR,
.read = ds1343_nvram_read,
.write = ds1343_nvram_write,
.size = DS1343_NVRAM_LEN,
};
static ssize_t ds1343_show_alarmstatus(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct ds1343_priv *priv = dev_get_drvdata(dev);
int alarmstatus, data;
regmap_read(priv->map, DS1343_CONTROL_REG, &data);
alarmstatus = !!(data & DS1343_A0IE);
if (alarmstatus)
return sprintf(buf, "enabled\n");
else
return sprintf(buf, "disabled\n");
}
static DEVICE_ATTR(alarm_status, S_IRUGO, ds1343_show_alarmstatus, NULL);
static ssize_t ds1343_show_alarmmode(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct ds1343_priv *priv = dev_get_drvdata(dev);
int alarm_mode, data;
char *alarm_str;
regmap_read(priv->map, DS1343_ALM0_SEC_REG, &data);
alarm_mode = (data & 0x80) >> 4;
regmap_read(priv->map, DS1343_ALM0_MIN_REG, &data);
alarm_mode |= (data & 0x80) >> 5;
regmap_read(priv->map, DS1343_ALM0_HOUR_REG, &data);
alarm_mode |= (data & 0x80) >> 6;
regmap_read(priv->map, DS1343_ALM0_DAY_REG, &data);
alarm_mode |= (data & 0x80) >> 7;
switch (alarm_mode) {
case 15:
alarm_str = "each second";
break;
case 7:
alarm_str = "seconds match";
break;
case 3:
alarm_str = "minutes and seconds match";
break;
case 1:
alarm_str = "hours, minutes and seconds match";
break;
case 0:
alarm_str = "day, hours, minutes and seconds match";
break;
default:
alarm_str = "invalid";
break;
}
return sprintf(buf, "%s\n", alarm_str);
}
static DEVICE_ATTR(alarm_mode, S_IRUGO, ds1343_show_alarmmode, NULL);
static ssize_t ds1343_show_tricklecharger(struct device *dev, static ssize_t ds1343_show_tricklecharger(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
@ -313,7 +215,6 @@ static DEVICE_ATTR(trickle_charger, S_IRUGO, ds1343_show_tricklecharger, NULL);
static int ds1343_sysfs_register(struct device *dev) static int ds1343_sysfs_register(struct device *dev)
{ {
struct ds1343_priv *priv = dev_get_drvdata(dev);
int err; int err;
err = device_create_file(dev, &dev_attr_glitch_filter); err = device_create_file(dev, &dev_attr_glitch_filter);
@ -321,33 +222,9 @@ static int ds1343_sysfs_register(struct device *dev)
return err; return err;
err = device_create_file(dev, &dev_attr_trickle_charger); err = device_create_file(dev, &dev_attr_trickle_charger);
if (err)
goto error1;
err = device_create_bin_file(dev, &nvram_attr);
if (err)
goto error2;
if (priv->irq <= 0)
return err;
err = device_create_file(dev, &dev_attr_alarm_mode);
if (err)
goto error3;
err = device_create_file(dev, &dev_attr_alarm_status);
if (!err) if (!err)
return err; return 0;
device_remove_file(dev, &dev_attr_alarm_mode);
error3:
device_remove_bin_file(dev, &nvram_attr);
error2:
device_remove_file(dev, &dev_attr_trickle_charger);
error1:
device_remove_file(dev, &dev_attr_glitch_filter); device_remove_file(dev, &dev_attr_glitch_filter);
return err; return err;
@ -355,17 +232,8 @@ error1:
static void ds1343_sysfs_unregister(struct device *dev) static void ds1343_sysfs_unregister(struct device *dev)
{ {
struct ds1343_priv *priv = dev_get_drvdata(dev);
device_remove_file(dev, &dev_attr_glitch_filter); device_remove_file(dev, &dev_attr_glitch_filter);
device_remove_file(dev, &dev_attr_trickle_charger); device_remove_file(dev, &dev_attr_trickle_charger);
device_remove_bin_file(dev, &nvram_attr);
if (priv->irq <= 0)
return;
device_remove_file(dev, &dev_attr_alarm_status);
device_remove_file(dev, &dev_attr_alarm_mode);
} }
static int ds1343_read_time(struct device *dev, struct rtc_time *dt) static int ds1343_read_time(struct device *dev, struct rtc_time *dt)
@ -386,7 +254,7 @@ static int ds1343_read_time(struct device *dev, struct rtc_time *dt)
dt->tm_mon = bcd2bin(buf[5] & 0x1F) - 1; dt->tm_mon = bcd2bin(buf[5] & 0x1F) - 1;
dt->tm_year = bcd2bin(buf[6]) + 100; /* year offset from 1900 */ dt->tm_year = bcd2bin(buf[6]) + 100; /* year offset from 1900 */
return rtc_valid_tm(dt); return 0;
} }
static int ds1343_set_time(struct device *dev, struct rtc_time *dt) static int ds1343_set_time(struct device *dev, struct rtc_time *dt)
@ -599,14 +467,18 @@ static const struct rtc_class_ops ds1343_rtc_ops = {
static int ds1343_probe(struct spi_device *spi) static int ds1343_probe(struct spi_device *spi)
{ {
struct ds1343_priv *priv; struct ds1343_priv *priv;
struct regmap_config config; struct regmap_config config = { .reg_bits = 8, .val_bits = 8,
.write_flag_mask = 0x80, };
unsigned int data; unsigned int data;
int res; int res;
struct nvmem_config nvmem_cfg = {
memset(&config, 0, sizeof(config)); .name = "ds1343-",
config.reg_bits = 8; .word_size = 1,
config.val_bits = 8; .stride = 1,
config.write_flag_mask = 0x80; .size = DS1343_NVRAM_LEN,
.reg_read = ds1343_nvram_read,
.reg_write = ds1343_nvram_write,
};
priv = devm_kzalloc(&spi->dev, sizeof(struct ds1343_priv), GFP_KERNEL); priv = devm_kzalloc(&spi->dev, sizeof(struct ds1343_priv), GFP_KERNEL);
if (!priv) if (!priv)
@ -646,12 +518,19 @@ static int ds1343_probe(struct spi_device *spi)
data &= ~(DS1343_OSF | DS1343_IRQF1 | DS1343_IRQF0); data &= ~(DS1343_OSF | DS1343_IRQF1 | DS1343_IRQF0);
regmap_write(priv->map, DS1343_STATUS_REG, data); regmap_write(priv->map, DS1343_STATUS_REG, data);
priv->rtc = devm_rtc_device_register(&spi->dev, "ds1343", priv->rtc = devm_rtc_allocate_device(&spi->dev);
&ds1343_rtc_ops, THIS_MODULE); if (IS_ERR(priv->rtc))
if (IS_ERR(priv->rtc)) {
dev_err(&spi->dev, "unable to register rtc ds1343\n");
return PTR_ERR(priv->rtc); return PTR_ERR(priv->rtc);
}
priv->rtc->nvram_old_abi = true;
priv->rtc->ops = &ds1343_rtc_ops;
res = rtc_register_device(priv->rtc);
if (res)
return res;
nvmem_cfg.priv = priv;
rtc_nvmem_register(priv->rtc, &nvmem_cfg);
priv->irq = spi->irq; priv->irq = spi->irq;

View File

@ -66,7 +66,7 @@ static int ds1347_read_time(struct device *dev, struct rtc_time *dt)
dt->tm_wday = bcd2bin(buf[5]) - 1; dt->tm_wday = bcd2bin(buf[5]) - 1;
dt->tm_year = bcd2bin(buf[6]) + 100; dt->tm_year = bcd2bin(buf[6]) + 100;
return rtc_valid_tm(dt); return 0;
} }
static int ds1347_set_time(struct device *dev, struct rtc_time *dt) static int ds1347_set_time(struct device *dev, struct rtc_time *dt)

View File

@ -153,7 +153,7 @@ static int ds1390_read_time(struct device *dev, struct rtc_time *dt)
/* adjust for century bit */ /* adjust for century bit */
dt->tm_year = bcd2bin(chip->txrx_buf[6]) + ((chip->txrx_buf[5] & 0x80) ? 100 : 0); dt->tm_year = bcd2bin(chip->txrx_buf[6]) + ((chip->txrx_buf[5] & 0x80) ? 100 : 0);
return rtc_valid_tm(dt); return 0;
} }
static int ds1390_set_time(struct device *dev, struct rtc_time *dt) static int ds1390_set_time(struct device *dev, struct rtc_time *dt)

View File

@ -277,10 +277,6 @@ static int ds1511_rtc_read_time(struct device *dev, struct rtc_time *rtc_tm)
rtc_tm->tm_mon--; rtc_tm->tm_mon--;
if (rtc_valid_tm(rtc_tm) < 0) {
dev_err(dev, "retrieved date/time is not valid.\n");
rtc_time_to_tm(0, rtc_tm);
}
return 0; return 0;
} }
@ -422,20 +418,20 @@ static int ds1511_nvram_write(void *priv, unsigned int pos, void *buf,
return 0; return 0;
} }
static struct nvmem_config ds1511_nvmem_cfg = {
.name = "ds1511_nvram",
.word_size = 1,
.stride = 1,
.size = DS1511_RAM_MAX,
.reg_read = ds1511_nvram_read,
.reg_write = ds1511_nvram_write,
};
static int ds1511_rtc_probe(struct platform_device *pdev) static int ds1511_rtc_probe(struct platform_device *pdev)
{ {
struct resource *res; struct resource *res;
struct rtc_plat_data *pdata; struct rtc_plat_data *pdata;
int ret = 0; int ret = 0;
struct nvmem_config ds1511_nvmem_cfg = {
.name = "ds1511_nvram",
.word_size = 1,
.stride = 1,
.size = DS1511_RAM_MAX,
.reg_read = ds1511_nvram_read,
.reg_write = ds1511_nvram_write,
.priv = &pdev->dev,
};
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata) if (!pdata)
@ -478,14 +474,14 @@ static int ds1511_rtc_probe(struct platform_device *pdev)
pdata->rtc->ops = &ds1511_rtc_ops; pdata->rtc->ops = &ds1511_rtc_ops;
ds1511_nvmem_cfg.priv = &pdev->dev;
pdata->rtc->nvmem_config = &ds1511_nvmem_cfg;
pdata->rtc->nvram_old_abi = true; pdata->rtc->nvram_old_abi = true;
ret = rtc_register_device(pdata->rtc); ret = rtc_register_device(pdata->rtc);
if (ret) if (ret)
return ret; return ret;
rtc_nvmem_register(pdata->rtc, &ds1511_nvmem_cfg);
/* /*
* if the platform has an interrupt in mind for this device, * if the platform has an interrupt in mind for this device,
* then by all means, set it * then by all means, set it

View File

@ -127,10 +127,6 @@ static int ds1553_rtc_read_time(struct device *dev, struct rtc_time *tm)
/* year is 1900 + tm->tm_year */ /* year is 1900 + tm->tm_year */
tm->tm_year = bcd2bin(year) + bcd2bin(century) * 100 - 1900; tm->tm_year = bcd2bin(year) + bcd2bin(century) * 100 - 1900;
if (rtc_valid_tm(tm) < 0) {
dev_err(dev, "retrieved date/time is not valid.\n");
rtc_time_to_tm(0, tm);
}
return 0; return 0;
} }
@ -233,46 +229,32 @@ static const struct rtc_class_ops ds1553_rtc_ops = {
.alarm_irq_enable = ds1553_rtc_alarm_irq_enable, .alarm_irq_enable = ds1553_rtc_alarm_irq_enable,
}; };
static ssize_t ds1553_nvram_read(struct file *filp, struct kobject *kobj, static int ds1553_nvram_read(void *priv, unsigned int pos, void *val,
struct bin_attribute *bin_attr, size_t bytes)
char *buf, loff_t pos, size_t size)
{ {
struct device *dev = container_of(kobj, struct device, kobj); struct platform_device *pdev = priv;
struct platform_device *pdev = to_platform_device(dev);
struct rtc_plat_data *pdata = platform_get_drvdata(pdev); struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
void __iomem *ioaddr = pdata->ioaddr; void __iomem *ioaddr = pdata->ioaddr;
ssize_t count; u8 *buf = val;
for (count = 0; count < size; count++) for (; bytes; bytes--)
*buf++ = readb(ioaddr + pos++); *buf++ = readb(ioaddr + pos++);
return count; return 0;
} }
static ssize_t ds1553_nvram_write(struct file *filp, struct kobject *kobj, static int ds1553_nvram_write(void *priv, unsigned int pos, void *val,
struct bin_attribute *bin_attr, size_t bytes)
char *buf, loff_t pos, size_t size)
{ {
struct device *dev = container_of(kobj, struct device, kobj); struct platform_device *pdev = priv;
struct platform_device *pdev = to_platform_device(dev);
struct rtc_plat_data *pdata = platform_get_drvdata(pdev); struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
void __iomem *ioaddr = pdata->ioaddr; void __iomem *ioaddr = pdata->ioaddr;
ssize_t count; u8 *buf = val;
for (count = 0; count < size; count++) for (; bytes; bytes--)
writeb(*buf++, ioaddr + pos++); writeb(*buf++, ioaddr + pos++);
return count; return 0;
} }
static struct bin_attribute ds1553_nvram_attr = {
.attr = {
.name = "nvram",
.mode = S_IRUGO | S_IWUSR,
},
.size = RTC_OFFSET,
.read = ds1553_nvram_read,
.write = ds1553_nvram_write,
};
static int ds1553_rtc_probe(struct platform_device *pdev) static int ds1553_rtc_probe(struct platform_device *pdev)
{ {
struct resource *res; struct resource *res;
@ -280,6 +262,15 @@ static int ds1553_rtc_probe(struct platform_device *pdev)
struct rtc_plat_data *pdata; struct rtc_plat_data *pdata;
void __iomem *ioaddr; void __iomem *ioaddr;
int ret = 0; int ret = 0;
struct nvmem_config nvmem_cfg = {
.name = "ds1553_nvram",
.word_size = 1,
.stride = 1,
.size = RTC_OFFSET,
.reg_read = ds1553_nvram_read,
.reg_write = ds1553_nvram_write,
.priv = pdev,
};
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata) if (!pdata)
@ -308,11 +299,17 @@ static int ds1553_rtc_probe(struct platform_device *pdev)
pdata->last_jiffies = jiffies; pdata->last_jiffies = jiffies;
platform_set_drvdata(pdev, pdata); platform_set_drvdata(pdev, pdata);
pdata->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, pdata->rtc = devm_rtc_allocate_device(&pdev->dev);
&ds1553_rtc_ops, THIS_MODULE);
if (IS_ERR(pdata->rtc)) if (IS_ERR(pdata->rtc))
return PTR_ERR(pdata->rtc); return PTR_ERR(pdata->rtc);
pdata->rtc->ops = &ds1553_rtc_ops;
pdata->rtc->nvram_old_abi = true;
ret = rtc_register_device(pdata->rtc);
if (ret)
return ret;
if (pdata->irq > 0) { if (pdata->irq > 0) {
writeb(0, ioaddr + RTC_INTERRUPTS); writeb(0, ioaddr + RTC_INTERRUPTS);
if (devm_request_irq(&pdev->dev, pdata->irq, if (devm_request_irq(&pdev->dev, pdata->irq,
@ -323,30 +320,17 @@ static int ds1553_rtc_probe(struct platform_device *pdev)
} }
} }
ret = sysfs_create_bin_file(&pdev->dev.kobj, &ds1553_nvram_attr); if (rtc_nvmem_register(pdata->rtc, &nvmem_cfg))
if (ret) dev_err(&pdev->dev, "unable to register nvmem\n");
dev_err(&pdev->dev, "unable to create sysfs file: %s\n",
ds1553_nvram_attr.attr.name);
return 0; return 0;
} }
static int ds1553_rtc_remove(struct platform_device *pdev)
{
struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
sysfs_remove_bin_file(&pdev->dev.kobj, &ds1553_nvram_attr);
if (pdata->irq > 0)
writeb(0, pdata->ioaddr + RTC_INTERRUPTS);
return 0;
}
/* work with hotplug and coldplug */ /* work with hotplug and coldplug */
MODULE_ALIAS("platform:rtc-ds1553"); MODULE_ALIAS("platform:rtc-ds1553");
static struct platform_driver ds1553_rtc_driver = { static struct platform_driver ds1553_rtc_driver = {
.probe = ds1553_rtc_probe, .probe = ds1553_rtc_probe,
.remove = ds1553_rtc_remove,
.driver = { .driver = {
.name = "rtc-ds1553", .name = "rtc-ds1553",
}, },

View File

@ -306,7 +306,7 @@ ds1685_rtc_read_time(struct device *dev, struct rtc_time *tm)
tm->tm_yday = rtc_year_days(tm->tm_mday, tm->tm_mon, tm->tm_year); tm->tm_yday = rtc_year_days(tm->tm_mday, tm->tm_mon, tm->tm_year);
tm->tm_isdst = 0; /* RTC has hardcoded timezone, so don't use. */ tm->tm_isdst = 0; /* RTC has hardcoded timezone, so don't use. */
return rtc_valid_tm(tm); return 0;
} }
/** /**

View File

@ -53,9 +53,7 @@
struct rtc_plat_data { struct rtc_plat_data {
void __iomem *ioaddr_nvram; void __iomem *ioaddr_nvram;
void __iomem *ioaddr_rtc; void __iomem *ioaddr_rtc;
size_t size_nvram;
unsigned long last_jiffies; unsigned long last_jiffies;
struct bin_attribute nvram_attr;
}; };
static int ds1742_rtc_set_time(struct device *dev, struct rtc_time *tm) static int ds1742_rtc_set_time(struct device *dev, struct rtc_time *tm)
@ -114,7 +112,7 @@ static int ds1742_rtc_read_time(struct device *dev, struct rtc_time *tm)
/* year is 1900 + tm->tm_year */ /* year is 1900 + tm->tm_year */
tm->tm_year = bcd2bin(year) + bcd2bin(century) * 100 - 1900; tm->tm_year = bcd2bin(year) + bcd2bin(century) * 100 - 1900;
return rtc_valid_tm(tm); return 0;
} }
static const struct rtc_class_ops ds1742_rtc_ops = { static const struct rtc_class_ops ds1742_rtc_ops = {
@ -122,34 +120,28 @@ static const struct rtc_class_ops ds1742_rtc_ops = {
.set_time = ds1742_rtc_set_time, .set_time = ds1742_rtc_set_time,
}; };
static ssize_t ds1742_nvram_read(struct file *filp, struct kobject *kobj, static int ds1742_nvram_read(void *priv, unsigned int pos, void *val,
struct bin_attribute *bin_attr, size_t bytes)
char *buf, loff_t pos, size_t size)
{ {
struct device *dev = container_of(kobj, struct device, kobj); struct rtc_plat_data *pdata = priv;
struct platform_device *pdev = to_platform_device(dev);
struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
void __iomem *ioaddr = pdata->ioaddr_nvram; void __iomem *ioaddr = pdata->ioaddr_nvram;
ssize_t count; u8 *buf = val;
for (count = 0; count < size; count++) for (; bytes; bytes--)
*buf++ = readb(ioaddr + pos++); *buf++ = readb(ioaddr + pos++);
return count; return 0;
} }
static ssize_t ds1742_nvram_write(struct file *filp, struct kobject *kobj, static int ds1742_nvram_write(void *priv, unsigned int pos, void *val,
struct bin_attribute *bin_attr, size_t bytes)
char *buf, loff_t pos, size_t size)
{ {
struct device *dev = container_of(kobj, struct device, kobj); struct rtc_plat_data *pdata = priv;
struct platform_device *pdev = to_platform_device(dev);
struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
void __iomem *ioaddr = pdata->ioaddr_nvram; void __iomem *ioaddr = pdata->ioaddr_nvram;
ssize_t count; u8 *buf = val;
for (count = 0; count < size; count++) for (; bytes; bytes--)
writeb(*buf++, ioaddr + pos++); writeb(*buf++, ioaddr + pos++);
return count; return 0;
} }
static int ds1742_rtc_probe(struct platform_device *pdev) static int ds1742_rtc_probe(struct platform_device *pdev)
@ -160,6 +152,14 @@ static int ds1742_rtc_probe(struct platform_device *pdev)
struct rtc_plat_data *pdata; struct rtc_plat_data *pdata;
void __iomem *ioaddr; void __iomem *ioaddr;
int ret = 0; int ret = 0;
struct nvmem_config nvmem_cfg = {
.name = "ds1742_nvram",
.word_size = 1,
.stride = 1,
.reg_read = ds1742_nvram_read,
.reg_write = ds1742_nvram_write,
};
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata) if (!pdata)
@ -171,15 +171,10 @@ static int ds1742_rtc_probe(struct platform_device *pdev)
return PTR_ERR(ioaddr); return PTR_ERR(ioaddr);
pdata->ioaddr_nvram = ioaddr; pdata->ioaddr_nvram = ioaddr;
pdata->size_nvram = resource_size(res) - RTC_SIZE; pdata->ioaddr_rtc = ioaddr + resource_size(res) - RTC_SIZE;
pdata->ioaddr_rtc = ioaddr + pdata->size_nvram;
sysfs_bin_attr_init(&pdata->nvram_attr); nvmem_cfg.size = resource_size(res) - RTC_SIZE;
pdata->nvram_attr.attr.name = "nvram"; nvmem_cfg.priv = pdata;
pdata->nvram_attr.attr.mode = S_IRUGO | S_IWUSR;
pdata->nvram_attr.read = ds1742_nvram_read;
pdata->nvram_attr.write = ds1742_nvram_write;
pdata->nvram_attr.size = pdata->size_nvram;
/* turn RTC on if it was not on */ /* turn RTC on if it was not on */
ioaddr = pdata->ioaddr_rtc; ioaddr = pdata->ioaddr_rtc;
@ -196,24 +191,21 @@ static int ds1742_rtc_probe(struct platform_device *pdev)
pdata->last_jiffies = jiffies; pdata->last_jiffies = jiffies;
platform_set_drvdata(pdev, pdata); platform_set_drvdata(pdev, pdata);
rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
&ds1742_rtc_ops, THIS_MODULE); rtc = devm_rtc_allocate_device(&pdev->dev);
if (IS_ERR(rtc)) if (IS_ERR(rtc))
return PTR_ERR(rtc); return PTR_ERR(rtc);
ret = sysfs_create_bin_file(&pdev->dev.kobj, &pdata->nvram_attr); rtc->ops = &ds1742_rtc_ops;
rtc->nvram_old_abi = true;
ret = rtc_register_device(rtc);
if (ret) if (ret)
dev_err(&pdev->dev, "Unable to create sysfs entry: %s\n", return ret;
pdata->nvram_attr.attr.name);
return 0; if (rtc_nvmem_register(rtc, &nvmem_cfg))
} dev_err(&pdev->dev, "Unable to register nvmem\n");
static int ds1742_rtc_remove(struct platform_device *pdev)
{
struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
sysfs_remove_bin_file(&pdev->dev.kobj, &pdata->nvram_attr);
return 0; return 0;
} }
@ -225,7 +217,6 @@ MODULE_DEVICE_TABLE(of, ds1742_rtc_of_match);
static struct platform_driver ds1742_rtc_driver = { static struct platform_driver ds1742_rtc_driver = {
.probe = ds1742_rtc_probe, .probe = ds1742_rtc_probe,
.remove = ds1742_rtc_remove,
.driver = { .driver = {
.name = "rtc-ds1742", .name = "rtc-ds1742",
.of_match_table = of_match_ptr(ds1742_rtc_of_match), .of_match_table = of_match_ptr(ds1742_rtc_of_match),

View File

@ -207,7 +207,7 @@ static int ds2404_read_time(struct device *dev, struct rtc_time *dt)
time = le32_to_cpu(time); time = le32_to_cpu(time);
rtc_time_to_tm(time, dt); rtc_time_to_tm(time, dt);
return rtc_valid_tm(dt); return 0;
} }
static int ds2404_set_mmss(struct device *dev, unsigned long secs) static int ds2404_set_mmss(struct device *dev, unsigned long secs)

View File

@ -145,7 +145,7 @@ static int ds3232_read_time(struct device *dev, struct rtc_time *time)
time->tm_year = bcd2bin(year) + add_century; time->tm_year = bcd2bin(year) + add_century;
return rtc_valid_tm(time); return 0;
} }
static int ds3232_set_time(struct device *dev, struct rtc_time *time) static int ds3232_set_time(struct device *dev, struct rtc_time *time)

View File

@ -176,7 +176,7 @@ static int efi_read_time(struct device *dev, struct rtc_time *tm)
if (!convert_from_efi_time(&eft, tm)) if (!convert_from_efi_time(&eft, tm))
return -EIO; return -EIO;
return rtc_valid_tm(tm); return 0;
} }
static int efi_set_time(struct device *dev, struct rtc_time *tm) static int efi_set_time(struct device *dev, struct rtc_time *tm)

View File

@ -136,8 +136,7 @@ static int fm3130_get_time(struct device *dev, struct rtc_time *t)
t->tm_hour, t->tm_mday, t->tm_hour, t->tm_mday,
t->tm_mon, t->tm_year, t->tm_wday); t->tm_mon, t->tm_year, t->tm_wday);
/* initial clock setting can be undefined */ return 0;
return rtc_valid_tm(t);
} }

View File

@ -235,3 +235,5 @@ static struct platform_driver goldfish_rtc = {
}; };
module_platform_driver(goldfish_rtc); module_platform_driver(goldfish_rtc);
MODULE_LICENSE("GPL v2");

View File

@ -104,8 +104,9 @@ static int isl12022_write_reg(struct i2c_client *client,
* In the routines that deal directly with the isl12022 hardware, we use * In the routines that deal directly with the isl12022 hardware, we use
* rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch. * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch.
*/ */
static int isl12022_get_datetime(struct i2c_client *client, struct rtc_time *tm) static int isl12022_rtc_read_time(struct device *dev, struct rtc_time *tm)
{ {
struct i2c_client *client = to_i2c_client(dev);
uint8_t buf[ISL12022_REG_INT + 1]; uint8_t buf[ISL12022_REG_INT + 1];
int ret; int ret;
@ -149,11 +150,12 @@ static int isl12022_get_datetime(struct i2c_client *client, struct rtc_time *tm)
tm->tm_sec, tm->tm_min, tm->tm_hour, tm->tm_sec, tm->tm_min, tm->tm_hour,
tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
return rtc_valid_tm(tm); return 0;
} }
static int isl12022_set_datetime(struct i2c_client *client, struct rtc_time *tm) static int isl12022_rtc_set_time(struct device *dev, struct rtc_time *tm)
{ {
struct i2c_client *client = to_i2c_client(dev);
struct isl12022 *isl12022 = i2c_get_clientdata(client); struct isl12022 *isl12022 = i2c_get_clientdata(client);
size_t i; size_t i;
int ret; int ret;
@ -199,7 +201,7 @@ static int isl12022_set_datetime(struct i2c_client *client, struct rtc_time *tm)
return ret; return ret;
} }
isl12022->write_enabled = 1; isl12022->write_enabled = true;
} }
/* hours, minutes and seconds */ /* hours, minutes and seconds */
@ -228,16 +230,6 @@ static int isl12022_set_datetime(struct i2c_client *client, struct rtc_time *tm)
return 0; return 0;
} }
static int isl12022_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
return isl12022_get_datetime(to_i2c_client(dev), tm);
}
static int isl12022_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
return isl12022_set_datetime(to_i2c_client(dev), tm);
}
static const struct rtc_class_ops isl12022_rtc_ops = { static const struct rtc_class_ops isl12022_rtc_ops = {
.read_time = isl12022_rtc_read_time, .read_time = isl12022_rtc_read_time,
.set_time = isl12022_rtc_set_time, .set_time = isl12022_rtc_set_time,

501
drivers/rtc/rtc-isl12026.c Normal file
View File

@ -0,0 +1,501 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* An I2C driver for the Intersil ISL 12026
*
* Copyright (c) 2018 Cavium, Inc.
*/
#include <linux/bcd.h>
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/nvmem-provider.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/rtc.h>
#include <linux/slab.h>
/* register offsets */
#define ISL12026_REG_PWR 0x14
# define ISL12026_REG_PWR_BSW BIT(6)
# define ISL12026_REG_PWR_SBIB BIT(7)
#define ISL12026_REG_SC 0x30
#define ISL12026_REG_HR 0x32
# define ISL12026_REG_HR_MIL BIT(7) /* military or 24 hour time */
#define ISL12026_REG_SR 0x3f
# define ISL12026_REG_SR_RTCF BIT(0)
# define ISL12026_REG_SR_WEL BIT(1)
# define ISL12026_REG_SR_RWEL BIT(2)
# define ISL12026_REG_SR_MBZ BIT(3)
# define ISL12026_REG_SR_OSCF BIT(4)
/* The EEPROM array responds at i2c address 0x57 */
#define ISL12026_EEPROM_ADDR 0x57
#define ISL12026_PAGESIZE 16
#define ISL12026_NVMEM_WRITE_TIME 20
struct isl12026 {
struct rtc_device *rtc;
struct i2c_client *nvm_client;
};
static int isl12026_read_reg(struct i2c_client *client, int reg)
{
u8 addr[] = {0, reg};
u8 val;
int ret;
struct i2c_msg msgs[] = {
{
.addr = client->addr,
.flags = 0,
.len = sizeof(addr),
.buf = addr
}, {
.addr = client->addr,
.flags = I2C_M_RD,
.len = 1,
.buf = &val
}
};
ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
if (ret != ARRAY_SIZE(msgs)) {
dev_err(&client->dev, "read reg error, ret=%d\n", ret);
ret = ret < 0 ? ret : -EIO;
} else {
ret = val;
}
return ret;
}
static int isl12026_arm_write(struct i2c_client *client)
{
int ret;
u8 op[3];
struct i2c_msg msg = {
.addr = client->addr,
.flags = 0,
.len = 1,
.buf = op
};
/* Set SR.WEL */
op[0] = 0;
op[1] = ISL12026_REG_SR;
op[2] = ISL12026_REG_SR_WEL;
msg.len = 3;
ret = i2c_transfer(client->adapter, &msg, 1);
if (ret != 1) {
dev_err(&client->dev, "write error SR.WEL, ret=%d\n", ret);
ret = ret < 0 ? ret : -EIO;
goto out;
}
/* Set SR.WEL and SR.RWEL */
op[2] = ISL12026_REG_SR_WEL | ISL12026_REG_SR_RWEL;
msg.len = 3;
ret = i2c_transfer(client->adapter, &msg, 1);
if (ret != 1) {
dev_err(&client->dev,
"write error SR.WEL|SR.RWEL, ret=%d\n", ret);
ret = ret < 0 ? ret : -EIO;
goto out;
} else {
ret = 0;
}
out:
return ret;
}
static int isl12026_disarm_write(struct i2c_client *client)
{
int ret;
u8 op[3] = {0, ISL12026_REG_SR, 0};
struct i2c_msg msg = {
.addr = client->addr,
.flags = 0,
.len = sizeof(op),
.buf = op
};
ret = i2c_transfer(client->adapter, &msg, 1);
if (ret != 1) {
dev_err(&client->dev,
"write error SR, ret=%d\n", ret);
ret = ret < 0 ? ret : -EIO;
} else {
ret = 0;
}
return ret;
}
static int isl12026_write_reg(struct i2c_client *client, int reg, u8 val)
{
int ret;
u8 op[3] = {0, reg, val};
struct i2c_msg msg = {
.addr = client->addr,
.flags = 0,
.len = sizeof(op),
.buf = op
};
ret = isl12026_arm_write(client);
if (ret)
return ret;
ret = i2c_transfer(client->adapter, &msg, 1);
if (ret != 1) {
dev_err(&client->dev, "write error CCR, ret=%d\n", ret);
ret = ret < 0 ? ret : -EIO;
goto out;
}
msleep(ISL12026_NVMEM_WRITE_TIME);
ret = isl12026_disarm_write(client);
out:
return ret;
}
static int isl12026_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
struct i2c_client *client = to_i2c_client(dev);
int ret;
u8 op[10];
struct i2c_msg msg = {
.addr = client->addr,
.flags = 0,
.len = sizeof(op),
.buf = op
};
ret = isl12026_arm_write(client);
if (ret)
return ret;
/* Set the CCR registers */
op[0] = 0;
op[1] = ISL12026_REG_SC;
op[2] = bin2bcd(tm->tm_sec); /* SC */
op[3] = bin2bcd(tm->tm_min); /* MN */
op[4] = bin2bcd(tm->tm_hour) | ISL12026_REG_HR_MIL; /* HR */
op[5] = bin2bcd(tm->tm_mday); /* DT */
op[6] = bin2bcd(tm->tm_mon + 1); /* MO */
op[7] = bin2bcd(tm->tm_year % 100); /* YR */
op[8] = bin2bcd(tm->tm_wday & 7); /* DW */
op[9] = bin2bcd(tm->tm_year >= 100 ? 20 : 19); /* Y2K */
ret = i2c_transfer(client->adapter, &msg, 1);
if (ret != 1) {
dev_err(&client->dev, "write error CCR, ret=%d\n", ret);
ret = ret < 0 ? ret : -EIO;
goto out;
}
ret = isl12026_disarm_write(client);
out:
return ret;
}
static int isl12026_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
struct i2c_client *client = to_i2c_client(dev);
u8 ccr[8];
u8 addr[2];
u8 sr;
int ret;
struct i2c_msg msgs[] = {
{
.addr = client->addr,
.flags = 0,
.len = sizeof(addr),
.buf = addr
}, {
.addr = client->addr,
.flags = I2C_M_RD,
}
};
/* First, read SR */
addr[0] = 0;
addr[1] = ISL12026_REG_SR;
msgs[1].len = 1;
msgs[1].buf = &sr;
ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
if (ret != ARRAY_SIZE(msgs)) {
dev_err(&client->dev, "read error, ret=%d\n", ret);
ret = ret < 0 ? ret : -EIO;
goto out;
}
if (sr & ISL12026_REG_SR_RTCF)
dev_warn(&client->dev, "Real-Time Clock Failure on read\n");
if (sr & ISL12026_REG_SR_OSCF)
dev_warn(&client->dev, "Oscillator Failure on read\n");
/* Second, CCR regs */
addr[0] = 0;
addr[1] = ISL12026_REG_SC;
msgs[1].len = sizeof(ccr);
msgs[1].buf = ccr;
ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
if (ret != ARRAY_SIZE(msgs)) {
dev_err(&client->dev, "read error, ret=%d\n", ret);
ret = ret < 0 ? ret : -EIO;
goto out;
}
tm->tm_sec = bcd2bin(ccr[0] & 0x7F);
tm->tm_min = bcd2bin(ccr[1] & 0x7F);
if (ccr[2] & ISL12026_REG_HR_MIL)
tm->tm_hour = bcd2bin(ccr[2] & 0x3F);
else
tm->tm_hour = bcd2bin(ccr[2] & 0x1F) +
((ccr[2] & 0x20) ? 12 : 0);
tm->tm_mday = bcd2bin(ccr[3] & 0x3F);
tm->tm_mon = bcd2bin(ccr[4] & 0x1F) - 1;
tm->tm_year = bcd2bin(ccr[5]);
if (bcd2bin(ccr[7]) == 20)
tm->tm_year += 100;
tm->tm_wday = ccr[6] & 0x07;
ret = 0;
out:
return ret;
}
static const struct rtc_class_ops isl12026_rtc_ops = {
.read_time = isl12026_rtc_read_time,
.set_time = isl12026_rtc_set_time,
};
static int isl12026_nvm_read(void *p, unsigned int offset,
void *val, size_t bytes)
{
struct isl12026 *priv = p;
int ret;
u8 addr[2];
struct i2c_msg msgs[] = {
{
.addr = priv->nvm_client->addr,
.flags = 0,
.len = sizeof(addr),
.buf = addr
}, {
.addr = priv->nvm_client->addr,
.flags = I2C_M_RD,
.buf = val
}
};
/*
* offset and bytes checked and limited by nvmem core, so
* proceed without further checks.
*/
ret = mutex_lock_interruptible(&priv->rtc->ops_lock);
if (ret)
return ret;
/* 2 bytes of address, most significant first */
addr[0] = offset >> 8;
addr[1] = offset;
msgs[1].len = bytes;
ret = i2c_transfer(priv->nvm_client->adapter, msgs, ARRAY_SIZE(msgs));
mutex_unlock(&priv->rtc->ops_lock);
if (ret != ARRAY_SIZE(msgs)) {
dev_err(&priv->nvm_client->dev,
"nvmem read error, ret=%d\n", ret);
return ret < 0 ? ret : -EIO;
}
return 0;
}
static int isl12026_nvm_write(void *p, unsigned int offset,
void *val, size_t bytes)
{
struct isl12026 *priv = p;
int ret;
u8 *v = val;
size_t chunk_size, num_written;
u8 payload[ISL12026_PAGESIZE + 2]; /* page + 2 address bytes */
struct i2c_msg msgs[] = {
{
.addr = priv->nvm_client->addr,
.flags = 0,
.buf = payload
}
};
/*
* offset and bytes checked and limited by nvmem core, so
* proceed without further checks.
*/
ret = mutex_lock_interruptible(&priv->rtc->ops_lock);
if (ret)
return ret;
num_written = 0;
while (bytes) {
chunk_size = round_down(offset, ISL12026_PAGESIZE) +
ISL12026_PAGESIZE - offset;
chunk_size = min(bytes, chunk_size);
/*
* 2 bytes of address, most significant first, followed
* by page data bytes
*/
memcpy(payload + 2, v + num_written, chunk_size);
payload[0] = offset >> 8;
payload[1] = offset;
msgs[0].len = chunk_size + 2;
ret = i2c_transfer(priv->nvm_client->adapter,
msgs, ARRAY_SIZE(msgs));
if (ret != ARRAY_SIZE(msgs)) {
dev_err(&priv->nvm_client->dev,
"nvmem write error, ret=%d\n", ret);
ret = ret < 0 ? ret : -EIO;
break;
}
ret = 0;
bytes -= chunk_size;
offset += chunk_size;
num_written += chunk_size;
msleep(ISL12026_NVMEM_WRITE_TIME);
}
mutex_unlock(&priv->rtc->ops_lock);
return ret;
}
static void isl12026_force_power_modes(struct i2c_client *client)
{
int ret;
int pwr, requested_pwr;
u32 bsw_val, sbib_val;
bool set_bsw, set_sbib;
/*
* If we can read the of_property, set the specified value.
* If there is an error reading the of_property (likely
* because it does not exist), keep the current value.
*/
ret = of_property_read_u32(client->dev.of_node,
"isil,pwr-bsw", &bsw_val);
set_bsw = (ret == 0);
ret = of_property_read_u32(client->dev.of_node,
"isil,pwr-sbib", &sbib_val);
set_sbib = (ret == 0);
/* Check if PWR.BSW and/or PWR.SBIB need specified values */
if (!set_bsw && !set_sbib)
return;
pwr = isl12026_read_reg(client, ISL12026_REG_PWR);
if (pwr < 0) {
dev_warn(&client->dev, "Error: Failed to read PWR %d\n", pwr);
return;
}
requested_pwr = pwr;
if (set_bsw) {
if (bsw_val)
requested_pwr |= ISL12026_REG_PWR_BSW;
else
requested_pwr &= ~ISL12026_REG_PWR_BSW;
} /* else keep current BSW */
if (set_sbib) {
if (sbib_val)
requested_pwr |= ISL12026_REG_PWR_SBIB;
else
requested_pwr &= ~ISL12026_REG_PWR_SBIB;
} /* else keep current SBIB */
if (pwr >= 0 && pwr != requested_pwr) {
dev_dbg(&client->dev, "PWR: %02x\n", pwr);
dev_dbg(&client->dev, "Updating PWR to: %02x\n", requested_pwr);
isl12026_write_reg(client, ISL12026_REG_PWR, requested_pwr);
}
}
static int isl12026_probe_new(struct i2c_client *client)
{
struct isl12026 *priv;
int ret;
struct nvmem_config nvm_cfg = {
.name = "isl12026-",
.base_dev = &client->dev,
.stride = 1,
.word_size = 1,
.size = 512,
.reg_read = isl12026_nvm_read,
.reg_write = isl12026_nvm_write,
};
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
return -ENODEV;
priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
i2c_set_clientdata(client, priv);
isl12026_force_power_modes(client);
priv->nvm_client = i2c_new_dummy(client->adapter, ISL12026_EEPROM_ADDR);
if (!priv->nvm_client)
return -ENOMEM;
priv->rtc = devm_rtc_allocate_device(&client->dev);
ret = PTR_ERR_OR_ZERO(priv->rtc);
if (ret)
return ret;
priv->rtc->ops = &isl12026_rtc_ops;
nvm_cfg.priv = priv;
ret = rtc_nvmem_register(priv->rtc, &nvm_cfg);
if (ret)
return ret;
return rtc_register_device(priv->rtc);
}
static int isl12026_remove(struct i2c_client *client)
{
struct isl12026 *priv = i2c_get_clientdata(client);
i2c_unregister_device(priv->nvm_client);
return 0;
}
static const struct of_device_id isl12026_dt_match[] = {
{ .compatible = "isil,isl12026" },
{ }
};
MODULE_DEVICE_TABLE(of, isl12026_dt_match);
static struct i2c_driver isl12026_driver = {
.driver = {
.name = "rtc-isl12026",
.of_match_table = isl12026_dt_match,
},
.probe_new = isl12026_probe_new,
.remove = isl12026_remove,
};
module_i2c_driver(isl12026_driver);
MODULE_DESCRIPTION("ISL 12026 RTC driver");
MODULE_LICENSE("GPL");

View File

@ -459,6 +459,11 @@ isl1208_i2c_set_time(struct i2c_client *client, struct rtc_time const *tm)
} }
/* clear WRTC again */ /* clear WRTC again */
sr = isl1208_i2c_get_sr(client);
if (sr < 0) {
dev_err(&client->dev, "%s: reading SR failed\n", __func__);
return sr;
}
sr = i2c_smbus_write_byte_data(client, ISL1208_REG_SR, sr = i2c_smbus_write_byte_data(client, ISL1208_REG_SR,
sr & ~ISL1208_REG_SR_WRTC); sr & ~ISL1208_REG_SR_WRTC);
if (sr < 0) { if (sr < 0) {
@ -630,29 +635,12 @@ isl1208_probe(struct i2c_client *client, const struct i2c_device_id *id)
if (isl1208_i2c_validate_client(client) < 0) if (isl1208_i2c_validate_client(client) < 0)
return -ENODEV; return -ENODEV;
if (client->irq > 0) { rtc = devm_rtc_allocate_device(&client->dev);
rc = devm_request_threaded_irq(&client->dev, client->irq, NULL,
isl1208_rtc_interrupt,
IRQF_SHARED | IRQF_ONESHOT,
isl1208_driver.driver.name,
client);
if (!rc) {
device_init_wakeup(&client->dev, 1);
enable_irq_wake(client->irq);
} else {
dev_err(&client->dev,
"Unable to request irq %d, no alarm support\n",
client->irq);
client->irq = 0;
}
}
rtc = devm_rtc_device_register(&client->dev, isl1208_driver.driver.name,
&isl1208_rtc_ops,
THIS_MODULE);
if (IS_ERR(rtc)) if (IS_ERR(rtc))
return PTR_ERR(rtc); return PTR_ERR(rtc);
rtc->ops = &isl1208_rtc_ops;
i2c_set_clientdata(client, rtc); i2c_set_clientdata(client, rtc);
rc = isl1208_i2c_get_sr(client); rc = isl1208_i2c_get_sr(client);
@ -669,7 +657,24 @@ isl1208_probe(struct i2c_client *client, const struct i2c_device_id *id)
if (rc) if (rc)
return rc; return rc;
return 0; if (client->irq > 0) {
rc = devm_request_threaded_irq(&client->dev, client->irq, NULL,
isl1208_rtc_interrupt,
IRQF_SHARED | IRQF_ONESHOT,
isl1208_driver.driver.name,
client);
if (!rc) {
device_init_wakeup(&client->dev, 1);
enable_irq_wake(client->irq);
} else {
dev_err(&client->dev,
"Unable to request irq %d, no alarm support\n",
client->irq);
client->irq = 0;
}
}
return rtc_register_device(rtc);
} }
static int static int

View File

@ -173,7 +173,7 @@ static int jz4740_rtc_read_time(struct device *dev, struct rtc_time *time)
rtc_time_to_tm(secs, time); rtc_time_to_tm(secs, time);
return rtc_valid_tm(time); return 0;
} }
static int jz4740_rtc_set_mmss(struct device *dev, unsigned long secs) static int jz4740_rtc_set_mmss(struct device *dev, unsigned long secs)

View File

@ -52,13 +52,11 @@ EXPORT_SYMBOL(rtc_year_days);
*/ */
void rtc_time64_to_tm(time64_t time, struct rtc_time *tm) void rtc_time64_to_tm(time64_t time, struct rtc_time *tm)
{ {
unsigned int month, year; unsigned int month, year, secs;
unsigned long secs;
int days; int days;
/* time must be positive */ /* time must be positive */
days = div_s64(time, 86400); days = div_s64_rem(time, 86400, &secs);
secs = time - (unsigned int) days * 86400;
/* day of the week, 1970-01-01 was a Thursday */ /* day of the week, 1970-01-01 was a Thursday */
tm->tm_wday = (days + 4) % 7; tm->tm_wday = (days + 4) % 7;
@ -67,7 +65,7 @@ void rtc_time64_to_tm(time64_t time, struct rtc_time *tm)
days -= (year - 1970) * 365 days -= (year - 1970) * 365
+ LEAPS_THRU_END_OF(year - 1) + LEAPS_THRU_END_OF(year - 1)
- LEAPS_THRU_END_OF(1970 - 1); - LEAPS_THRU_END_OF(1970 - 1);
if (days < 0) { while (days < 0) {
year -= 1; year -= 1;
days += 365 + is_leap_year(year); days += 365 + is_leap_year(year);
} }

View File

@ -110,7 +110,7 @@ static int lpc24xx_rtc_read_time(struct device *dev, struct rtc_time *tm)
tm->tm_year = CT1_YEAR(ct1); tm->tm_year = CT1_YEAR(ct1);
tm->tm_yday = CT2_DOY(ct2); tm->tm_yday = CT2_DOY(ct2);
return rtc_valid_tm(tm); return 0;
} }
static int lpc24xx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *wkalrm) static int lpc24xx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)

View File

@ -70,7 +70,7 @@ static int lpc32xx_rtc_read_time(struct device *dev, struct rtc_time *time)
elapsed_sec = rtc_readl(rtc, LPC32XX_RTC_UCOUNT); elapsed_sec = rtc_readl(rtc, LPC32XX_RTC_UCOUNT);
rtc_time_to_tm(elapsed_sec, time); rtc_time_to_tm(elapsed_sec, time);
return rtc_valid_tm(time); return 0;
} }
static int lpc32xx_rtc_set_mmss(struct device *dev, unsigned long secs) static int lpc32xx_rtc_set_mmss(struct device *dev, unsigned long secs)

View File

@ -98,7 +98,7 @@ static int ls1x_rtc_read_time(struct device *dev, struct rtc_time *rtm)
ls1x_get_min(v), ls1x_get_sec(v)); ls1x_get_min(v), ls1x_get_sec(v));
rtc_time_to_tm(t, rtm); rtc_time_to_tm(t, rtm);
return rtc_valid_tm(rtm); return 0;
} }
static int ls1x_rtc_set_time(struct device *dev, struct rtc_time *rtm) static int ls1x_rtc_set_time(struct device *dev, struct rtc_time *rtm)

View File

@ -73,7 +73,6 @@
#define M41T80_FEATURE_WD BIT(3) /* Extra watchdog resolution */ #define M41T80_FEATURE_WD BIT(3) /* Extra watchdog resolution */
#define M41T80_FEATURE_SQ_ALT BIT(4) /* RSx bits are in reg 4 */ #define M41T80_FEATURE_SQ_ALT BIT(4) /* RSx bits are in reg 4 */
static DEFINE_MUTEX(m41t80_rtc_mutex);
static const struct i2c_device_id m41t80_id[] = { static const struct i2c_device_id m41t80_id[] = {
{ "m41t62", M41T80_FEATURE_SQ | M41T80_FEATURE_SQ_ALT }, { "m41t62", M41T80_FEATURE_SQ | M41T80_FEATURE_SQ_ALT },
{ "m41t65", M41T80_FEATURE_HT | M41T80_FEATURE_WD }, { "m41t65", M41T80_FEATURE_HT | M41T80_FEATURE_WD },
@ -199,9 +198,9 @@ static irqreturn_t m41t80_handle_irq(int irq, void *dev_id)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static int m41t80_get_datetime(struct i2c_client *client, static int m41t80_rtc_read_time(struct device *dev, struct rtc_time *tm)
struct rtc_time *tm)
{ {
struct i2c_client *client = to_i2c_client(dev);
unsigned char buf[8]; unsigned char buf[8];
int err, flags; int err, flags;
@ -230,12 +229,12 @@ static int m41t80_get_datetime(struct i2c_client *client,
/* assume 20YY not 19YY, and ignore the Century Bit */ /* assume 20YY not 19YY, and ignore the Century Bit */
tm->tm_year = bcd2bin(buf[M41T80_REG_YEAR]) + 100; tm->tm_year = bcd2bin(buf[M41T80_REG_YEAR]) + 100;
return rtc_valid_tm(tm); return 0;
} }
/* Sets the given date and time to the real time clock. */ static int m41t80_rtc_set_time(struct device *dev, struct rtc_time *tm)
static int m41t80_set_datetime(struct i2c_client *client, struct rtc_time *tm)
{ {
struct i2c_client *client = to_i2c_client(dev);
struct m41t80_data *clientdata = i2c_get_clientdata(client); struct m41t80_data *clientdata = i2c_get_clientdata(client);
unsigned char buf[8]; unsigned char buf[8];
int err, flags; int err, flags;
@ -298,16 +297,6 @@ static int m41t80_rtc_proc(struct device *dev, struct seq_file *seq)
return 0; return 0;
} }
static int m41t80_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
return m41t80_get_datetime(to_i2c_client(dev), tm);
}
static int m41t80_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
return m41t80_set_datetime(to_i2c_client(dev), tm);
}
static int m41t80_alarm_irq_enable(struct device *dev, unsigned int enabled) static int m41t80_alarm_irq_enable(struct device *dev, unsigned int enabled)
{ {
struct i2c_client *client = to_i2c_client(dev); struct i2c_client *client = to_i2c_client(dev);
@ -598,6 +587,7 @@ static struct clk *m41t80_sqw_register_clk(struct m41t80_data *m41t80)
* *
***************************************************************************** *****************************************************************************
*/ */
static DEFINE_MUTEX(m41t80_rtc_mutex);
static struct i2c_client *save_client; static struct i2c_client *save_client;
/* Default margin */ /* Default margin */
@ -885,7 +875,6 @@ static int m41t80_probe(struct i2c_client *client,
{ {
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
int rc = 0; int rc = 0;
struct rtc_device *rtc = NULL;
struct rtc_time tm; struct rtc_time tm;
struct m41t80_data *m41t80_data = NULL; struct m41t80_data *m41t80_data = NULL;
bool wakeup_source = false; bool wakeup_source = false;
@ -909,6 +898,10 @@ static int m41t80_probe(struct i2c_client *client,
m41t80_data->features = id->driver_data; m41t80_data->features = id->driver_data;
i2c_set_clientdata(client, m41t80_data); i2c_set_clientdata(client, m41t80_data);
m41t80_data->rtc = devm_rtc_allocate_device(&client->dev);
if (IS_ERR(m41t80_data->rtc))
return PTR_ERR(m41t80_data->rtc);
#ifdef CONFIG_OF #ifdef CONFIG_OF
wakeup_source = of_property_read_bool(client->dev.of_node, wakeup_source = of_property_read_bool(client->dev.of_node,
"wakeup-source"); "wakeup-source");
@ -932,15 +925,11 @@ static int m41t80_probe(struct i2c_client *client,
device_init_wakeup(&client->dev, true); device_init_wakeup(&client->dev, true);
} }
rtc = devm_rtc_device_register(&client->dev, client->name, m41t80_data->rtc->ops = &m41t80_rtc_ops;
&m41t80_rtc_ops, THIS_MODULE);
if (IS_ERR(rtc))
return PTR_ERR(rtc);
m41t80_data->rtc = rtc;
if (client->irq <= 0) { if (client->irq <= 0) {
/* We cannot support UIE mode if we do not have an IRQ line */ /* We cannot support UIE mode if we do not have an IRQ line */
rtc->uie_unsupported = 1; m41t80_data->rtc->uie_unsupported = 1;
} }
/* Make sure HT (Halt Update) bit is cleared */ /* Make sure HT (Halt Update) bit is cleared */
@ -948,7 +937,7 @@ static int m41t80_probe(struct i2c_client *client,
if (rc >= 0 && rc & M41T80_ALHOUR_HT) { if (rc >= 0 && rc & M41T80_ALHOUR_HT) {
if (m41t80_data->features & M41T80_FEATURE_HT) { if (m41t80_data->features & M41T80_FEATURE_HT) {
m41t80_get_datetime(client, &tm); m41t80_rtc_read_time(&client->dev, &tm);
dev_info(&client->dev, "HT bit was set!\n"); dev_info(&client->dev, "HT bit was set!\n");
dev_info(&client->dev, dev_info(&client->dev,
"Power Down at %04i-%02i-%02i %02i:%02i:%02i\n", "Power Down at %04i-%02i-%02i %02i:%02i:%02i\n",
@ -993,6 +982,11 @@ static int m41t80_probe(struct i2c_client *client,
if (m41t80_data->features & M41T80_FEATURE_SQ) if (m41t80_data->features & M41T80_FEATURE_SQ)
m41t80_sqw_register_clk(m41t80_data); m41t80_sqw_register_clk(m41t80_data);
#endif #endif
rc = rtc_register_device(m41t80_data->rtc);
if (rc)
return rc;
return 0; return 0;
} }

View File

@ -159,7 +159,7 @@ static int m41t93_get_time(struct device *dev, struct rtc_time *tm)
tm->tm_hour, tm->tm_mday, tm->tm_hour, tm->tm_mday,
tm->tm_mon, tm->tm_year, tm->tm_wday); tm->tm_mon, tm->tm_year, tm->tm_wday);
return ret < 0 ? ret : rtc_valid_tm(tm); return ret;
} }

View File

@ -99,8 +99,7 @@ static int m41t94_read_time(struct device *dev, struct rtc_time *tm)
tm->tm_hour, tm->tm_mday, tm->tm_hour, tm->tm_mday,
tm->tm_mon, tm->tm_year, tm->tm_wday); tm->tm_mon, tm->tm_year, tm->tm_wday);
/* initial clock setting can be undefined */ return 0;
return rtc_valid_tm(tm);
} }
static const struct rtc_class_ops m41t94_rtc_ops = { static const struct rtc_class_ops m41t94_rtc_ops = {

View File

@ -84,7 +84,7 @@ static int m48t35_read_time(struct device *dev, struct rtc_time *tm)
tm->tm_year += 100; tm->tm_year += 100;
tm->tm_mon--; tm->tm_mon--;
return rtc_valid_tm(tm); return 0;
} }
static int m48t35_set_time(struct device *dev, struct rtc_time *tm) static int m48t35_set_time(struct device *dev, struct rtc_time *tm)

View File

@ -105,7 +105,7 @@ static int m48t59_rtc_read_time(struct device *dev, struct rtc_time *tm)
dev_dbg(dev, "RTC read time %04d-%02d-%02d %02d/%02d/%02d\n", dev_dbg(dev, "RTC read time %04d-%02d-%02d %02d/%02d/%02d\n",
tm->tm_year + 1900, tm->tm_mon, tm->tm_mday, tm->tm_year + 1900, tm->tm_mon, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec); tm->tm_hour, tm->tm_min, tm->tm_sec);
return rtc_valid_tm(tm); return 0;
} }
static int m48t59_rtc_set_time(struct device *dev, struct rtc_time *tm) static int m48t59_rtc_set_time(struct device *dev, struct rtc_time *tm)
@ -334,16 +334,16 @@ static const struct rtc_class_ops m48t02_rtc_ops = {
.set_time = m48t59_rtc_set_time, .set_time = m48t59_rtc_set_time,
}; };
static ssize_t m48t59_nvram_read(struct file *filp, struct kobject *kobj, static int m48t59_nvram_read(void *priv, unsigned int offset, void *val,
struct bin_attribute *bin_attr, size_t size)
char *buf, loff_t pos, size_t size)
{ {
struct device *dev = container_of(kobj, struct device, kobj); struct platform_device *pdev = priv;
struct platform_device *pdev = to_platform_device(dev); struct device *dev = &pdev->dev;
struct m48t59_plat_data *pdata = dev_get_platdata(&pdev->dev); struct m48t59_plat_data *pdata = dev_get_platdata(&pdev->dev);
struct m48t59_private *m48t59 = platform_get_drvdata(pdev); struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
ssize_t cnt = 0; ssize_t cnt = 0;
unsigned long flags; unsigned long flags;
u8 *buf = val;
spin_lock_irqsave(&m48t59->lock, flags); spin_lock_irqsave(&m48t59->lock, flags);
@ -352,19 +352,19 @@ static ssize_t m48t59_nvram_read(struct file *filp, struct kobject *kobj,
spin_unlock_irqrestore(&m48t59->lock, flags); spin_unlock_irqrestore(&m48t59->lock, flags);
return cnt; return 0;
} }
static ssize_t m48t59_nvram_write(struct file *filp, struct kobject *kobj, static int m48t59_nvram_write(void *priv, unsigned int offset, void *val,
struct bin_attribute *bin_attr, size_t size)
char *buf, loff_t pos, size_t size)
{ {
struct device *dev = container_of(kobj, struct device, kobj); struct platform_device *pdev = priv;
struct platform_device *pdev = to_platform_device(dev); struct device *dev = &pdev->dev;
struct m48t59_plat_data *pdata = dev_get_platdata(&pdev->dev); struct m48t59_plat_data *pdata = dev_get_platdata(&pdev->dev);
struct m48t59_private *m48t59 = platform_get_drvdata(pdev); struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
ssize_t cnt = 0; ssize_t cnt = 0;
unsigned long flags; unsigned long flags;
u8 *buf = val;
spin_lock_irqsave(&m48t59->lock, flags); spin_lock_irqsave(&m48t59->lock, flags);
@ -373,18 +373,9 @@ static ssize_t m48t59_nvram_write(struct file *filp, struct kobject *kobj,
spin_unlock_irqrestore(&m48t59->lock, flags); spin_unlock_irqrestore(&m48t59->lock, flags);
return cnt; return 0;
} }
static struct bin_attribute m48t59_nvram_attr = {
.attr = {
.name = "nvram",
.mode = S_IRUGO | S_IWUSR,
},
.read = m48t59_nvram_read,
.write = m48t59_nvram_write,
};
static int m48t59_rtc_probe(struct platform_device *pdev) static int m48t59_rtc_probe(struct platform_device *pdev)
{ {
struct m48t59_plat_data *pdata = dev_get_platdata(&pdev->dev); struct m48t59_plat_data *pdata = dev_get_platdata(&pdev->dev);
@ -393,6 +384,14 @@ static int m48t59_rtc_probe(struct platform_device *pdev)
int ret = -ENOMEM; int ret = -ENOMEM;
char *name; char *name;
const struct rtc_class_ops *ops; const struct rtc_class_ops *ops;
struct nvmem_config nvmem_cfg = {
.name = "m48t59-",
.word_size = 1,
.stride = 1,
.reg_read = m48t59_nvram_read,
.reg_write = m48t59_nvram_write,
.priv = pdev,
};
/* This chip could be memory-mapped or I/O-mapped */ /* This chip could be memory-mapped or I/O-mapped */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@ -480,23 +479,22 @@ static int m48t59_rtc_probe(struct platform_device *pdev)
spin_lock_init(&m48t59->lock); spin_lock_init(&m48t59->lock);
platform_set_drvdata(pdev, m48t59); platform_set_drvdata(pdev, m48t59);
m48t59->rtc = devm_rtc_device_register(&pdev->dev, name, ops, m48t59->rtc = devm_rtc_allocate_device(&pdev->dev);
THIS_MODULE);
if (IS_ERR(m48t59->rtc)) if (IS_ERR(m48t59->rtc))
return PTR_ERR(m48t59->rtc); return PTR_ERR(m48t59->rtc);
m48t59_nvram_attr.size = pdata->offset; m48t59->rtc->nvram_old_abi = true;
m48t59->rtc->ops = ops;
ret = sysfs_create_bin_file(&pdev->dev.kobj, &m48t59_nvram_attr); nvmem_cfg.size = pdata->offset;
ret = rtc_nvmem_register(m48t59->rtc, &nvmem_cfg);
if (ret) if (ret)
return ret; return ret;
return 0; ret = rtc_register_device(m48t59->rtc);
} if (ret)
return ret;
static int m48t59_rtc_remove(struct platform_device *pdev)
{
sysfs_remove_bin_file(&pdev->dev.kobj, &m48t59_nvram_attr);
return 0; return 0;
} }
@ -508,7 +506,6 @@ static struct platform_driver m48t59_rtc_driver = {
.name = "rtc-m48t59", .name = "rtc-m48t59",
}, },
.probe = m48t59_rtc_probe, .probe = m48t59_rtc_probe,
.remove = m48t59_rtc_remove,
}; };
module_platform_driver(m48t59_rtc_driver); module_platform_driver(m48t59_rtc_driver);

View File

@ -100,7 +100,7 @@ static int m48t86_rtc_read_time(struct device *dev, struct rtc_time *tm)
if (m48t86_readb(dev, M48T86_HOUR) & 0x80) if (m48t86_readb(dev, M48T86_HOUR) & 0x80)
tm->tm_hour += 12; tm->tm_hour += 12;
return rtc_valid_tm(tm); return 0;
} }
static int m48t86_rtc_set_time(struct device *dev, struct rtc_time *tm) static int m48t86_rtc_set_time(struct device *dev, struct rtc_time *tm)
@ -218,21 +218,21 @@ static bool m48t86_verify_chip(struct platform_device *pdev)
return false; return false;
} }
static struct nvmem_config m48t86_nvmem_cfg = {
.name = "m48t86_nvram",
.word_size = 1,
.stride = 1,
.size = M48T86_NVRAM_LEN,
.reg_read = m48t86_nvram_read,
.reg_write = m48t86_nvram_write,
};
static int m48t86_rtc_probe(struct platform_device *pdev) static int m48t86_rtc_probe(struct platform_device *pdev)
{ {
struct m48t86_rtc_info *info; struct m48t86_rtc_info *info;
struct resource *res; struct resource *res;
unsigned char reg; unsigned char reg;
int err; int err;
struct nvmem_config m48t86_nvmem_cfg = {
.name = "m48t86_nvram",
.word_size = 1,
.stride = 1,
.size = M48T86_NVRAM_LEN,
.reg_read = m48t86_nvram_read,
.reg_write = m48t86_nvram_write,
.priv = &pdev->dev,
};
info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
if (!info) if (!info)
@ -264,15 +264,14 @@ static int m48t86_rtc_probe(struct platform_device *pdev)
return PTR_ERR(info->rtc); return PTR_ERR(info->rtc);
info->rtc->ops = &m48t86_rtc_ops; info->rtc->ops = &m48t86_rtc_ops;
m48t86_nvmem_cfg.priv = &pdev->dev;
info->rtc->nvmem_config = &m48t86_nvmem_cfg;
info->rtc->nvram_old_abi = true; info->rtc->nvram_old_abi = true;
err = rtc_register_device(info->rtc); err = rtc_register_device(info->rtc);
if (err) if (err)
return err; return err;
rtc_nvmem_register(info->rtc, &m48t86_nvmem_cfg);
/* read battery status */ /* read battery status */
reg = m48t86_readb(&pdev->dev, M48T86_D); reg = m48t86_readb(&pdev->dev, M48T86_D);
dev_info(&pdev->dev, "battery %s\n", dev_info(&pdev->dev, "battery %s\n",

View File

@ -139,8 +139,9 @@ static int max6900_i2c_write_regs(struct i2c_client *client, u8 const *buf)
return -EIO; return -EIO;
} }
static int max6900_i2c_read_time(struct i2c_client *client, struct rtc_time *tm) static int max6900_rtc_read_time(struct device *dev, struct rtc_time *tm)
{ {
struct i2c_client *client = to_i2c_client(dev);
int rc; int rc;
u8 regs[MAX6900_REG_LEN]; u8 regs[MAX6900_REG_LEN];
@ -157,7 +158,7 @@ static int max6900_i2c_read_time(struct i2c_client *client, struct rtc_time *tm)
bcd2bin(regs[MAX6900_REG_CENTURY]) * 100 - 1900; bcd2bin(regs[MAX6900_REG_CENTURY]) * 100 - 1900;
tm->tm_wday = bcd2bin(regs[MAX6900_REG_DW]); tm->tm_wday = bcd2bin(regs[MAX6900_REG_DW]);
return rtc_valid_tm(tm); return 0;
} }
static int max6900_i2c_clear_write_protect(struct i2c_client *client) static int max6900_i2c_clear_write_protect(struct i2c_client *client)
@ -165,9 +166,9 @@ static int max6900_i2c_clear_write_protect(struct i2c_client *client)
return i2c_smbus_write_byte_data(client, MAX6900_REG_CONTROL_WRITE, 0); return i2c_smbus_write_byte_data(client, MAX6900_REG_CONTROL_WRITE, 0);
} }
static int static int max6900_rtc_set_time(struct device *dev, struct rtc_time *tm)
max6900_i2c_set_time(struct i2c_client *client, struct rtc_time const *tm)
{ {
struct i2c_client *client = to_i2c_client(dev);
u8 regs[MAX6900_REG_LEN]; u8 regs[MAX6900_REG_LEN];
int rc; int rc;
@ -193,16 +194,6 @@ max6900_i2c_set_time(struct i2c_client *client, struct rtc_time const *tm)
return 0; return 0;
} }
static int max6900_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
return max6900_i2c_read_time(to_i2c_client(dev), tm);
}
static int max6900_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
return max6900_i2c_set_time(to_i2c_client(dev), tm);
}
static const struct rtc_class_ops max6900_rtc_ops = { static const struct rtc_class_ops max6900_rtc_ops = {
.read_time = max6900_rtc_read_time, .read_time = max6900_rtc_read_time,
.set_time = max6900_rtc_set_time, .set_time = max6900_rtc_set_time,

View File

@ -85,7 +85,7 @@ static int max6902_read_time(struct device *dev, struct rtc_time *dt)
dt->tm_year += century; dt->tm_year += century;
dt->tm_year -= 1900; dt->tm_year -= 1900;
return rtc_valid_tm(dt); return 0;
} }
static int max6902_set_time(struct device *dev, struct rtc_time *dt) static int max6902_set_time(struct device *dev, struct rtc_time *dt)

View File

@ -75,7 +75,7 @@ static int max6916_read_time(struct device *dev, struct rtc_time *dt)
dt->tm_wday = bcd2bin(buf[5]) - 1; dt->tm_wday = bcd2bin(buf[5]) - 1;
dt->tm_year = bcd2bin(buf[6]) + 100; dt->tm_year = bcd2bin(buf[6]) + 100;
return rtc_valid_tm(dt); return 0;
} }
static int max6916_set_time(struct device *dev, struct rtc_time *dt) static int max6916_set_time(struct device *dev, struct rtc_time *dt)

View File

@ -364,11 +364,9 @@ static int max77686_rtc_read_time(struct device *dev, struct rtc_time *tm)
max77686_rtc_data_to_tm(data, tm, info); max77686_rtc_data_to_tm(data, tm, info);
ret = rtc_valid_tm(tm);
out: out:
mutex_unlock(&info->lock); mutex_unlock(&info->lock);
return ret; return 0;
} }
static int max77686_rtc_set_time(struct device *dev, struct rtc_time *tm) static int max77686_rtc_set_time(struct device *dev, struct rtc_time *tm)

View File

@ -153,7 +153,7 @@ static int max8997_rtc_read_time(struct device *dev, struct rtc_time *tm)
max8997_rtc_data_to_tm(data, tm, info->rtc_24hr_mode); max8997_rtc_data_to_tm(data, tm, info->rtc_24hr_mode);
return rtc_valid_tm(tm); return 0;
} }
static int max8997_rtc_set_time(struct device *dev, struct rtc_time *tm) static int max8997_rtc_set_time(struct device *dev, struct rtc_time *tm)

View File

@ -120,7 +120,7 @@ static int max8998_rtc_read_time(struct device *dev, struct rtc_time *tm)
max8998_data_to_tm(data, tm); max8998_data_to_tm(data, tm);
return rtc_valid_tm(tm); return 0;
} }
static int max8998_rtc_set_time(struct device *dev, struct rtc_time *tm) static int max8998_rtc_set_time(struct device *dev, struct rtc_time *tm)

View File

@ -85,7 +85,7 @@ static int mc13xxx_rtc_read_time(struct device *dev, struct rtc_time *tm)
rtc_time64_to_tm((time64_t)days1 * SEC_PER_DAY + seconds, tm); rtc_time64_to_tm((time64_t)days1 * SEC_PER_DAY + seconds, tm);
return rtc_valid_tm(tm); return 0;
} }
static int mc13xxx_rtc_set_mmss(struct device *dev, time64_t secs) static int mc13xxx_rtc_set_mmss(struct device *dev, time64_t secs)

View File

@ -82,7 +82,7 @@ static int mcp795_rtcc_write(struct device *dev, u8 addr, u8 *data, u8 count)
{ {
struct spi_device *spi = to_spi_device(dev); struct spi_device *spi = to_spi_device(dev);
int ret; int ret;
u8 tx[2 + count]; u8 tx[257];
tx[0] = MCP795_WRITE; tx[0] = MCP795_WRITE;
tx[1] = addr; tx[1] = addr;
@ -262,7 +262,7 @@ static int mcp795_read_time(struct device *dev, struct rtc_time *tim)
tim->tm_year + 1900, tim->tm_mon, tim->tm_mday, tim->tm_year + 1900, tim->tm_mon, tim->tm_mday,
tim->tm_wday, tim->tm_hour, tim->tm_min, tim->tm_sec); tim->tm_wday, tim->tm_hour, tim->tm_min, tim->tm_sec);
return rtc_valid_tm(tim); return 0;
} }
static int mcp795_set_alarm(struct device *dev, struct rtc_wkalrm *alm) static int mcp795_set_alarm(struct device *dev, struct rtc_wkalrm *alm)

View File

@ -122,7 +122,7 @@ static int mpc5121_rtc_read_time(struct device *dev, struct rtc_time *tm)
*/ */
mpc5121_rtc_update_smh(regs, tm); mpc5121_rtc_update_smh(regs, tm);
return rtc_valid_tm(tm); return 0;
} }
static int mpc5121_rtc_set_time(struct device *dev, struct rtc_time *tm) static int mpc5121_rtc_set_time(struct device *dev, struct rtc_time *tm)

View File

@ -105,7 +105,7 @@ static int mrst_read_time(struct device *dev, struct rtc_time *time)
/* Adjust for the 1972/1900 */ /* Adjust for the 1972/1900 */
time->tm_year += 72; time->tm_year += 72;
time->tm_mon--; time->tm_mon--;
return rtc_valid_tm(time); return 0;
} }
static int mrst_set_time(struct device *dev, struct rtc_time *time) static int mrst_set_time(struct device *dev, struct rtc_time *time)
@ -122,7 +122,7 @@ static int mrst_set_time(struct device *dev, struct rtc_time *time)
min = time->tm_min; min = time->tm_min;
sec = time->tm_sec; sec = time->tm_sec;
if (yrs < 72 || yrs > 138) if (yrs < 72 || yrs > 172)
return -EINVAL; return -EINVAL;
yrs -= 72; yrs -= 72;

View File

@ -155,7 +155,7 @@ static int msm6242_read_time(struct device *dev, struct rtc_time *tm)
msm6242_unlock(priv); msm6242_unlock(priv);
return rtc_valid_tm(tm); return 0;
} }
static int msm6242_set_time(struct device *dev, struct rtc_time *tm) static int msm6242_set_time(struct device *dev, struct rtc_time *tm)

View File

@ -232,7 +232,7 @@ static int mtk_rtc_gettime(struct device *dev, struct rtc_time *tm)
mtk_rtc_get_alarm_or_time(hw, tm, MTK_TC); mtk_rtc_get_alarm_or_time(hw, tm, MTK_TC);
return rtc_valid_tm(tm); return 0;
} }
static int mtk_rtc_settime(struct device *dev, struct rtc_time *tm) static int mtk_rtc_settime(struct device *dev, struct rtc_time *tm)
@ -307,6 +307,7 @@ static const struct of_device_id mtk_rtc_match[] = {
{ .compatible = "mediatek,soc-rtc" }, { .compatible = "mediatek,soc-rtc" },
{}, {},
}; };
MODULE_DEVICE_TABLE(of, mtk_rtc_match);
static int mtk_rtc_probe(struct platform_device *pdev) static int mtk_rtc_probe(struct platform_device *pdev)
{ {

View File

@ -94,7 +94,7 @@ static int mv_rtc_read_time(struct device *dev, struct rtc_time *tm)
/* hw counts from year 2000, but tm_year is relative to 1900 */ /* hw counts from year 2000, but tm_year is relative to 1900 */
tm->tm_year = bcd2bin(year) + 100; tm->tm_year = bcd2bin(year) + 100;
return rtc_valid_tm(tm); return 0;
} }
static int mv_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) static int mv_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
@ -223,7 +223,6 @@ static int __init mv_rtc_probe(struct platform_device *pdev)
struct resource *res; struct resource *res;
struct rtc_plat_data *pdata; struct rtc_plat_data *pdata;
u32 rtc_time; u32 rtc_time;
u32 rtc_date;
int ret = 0; int ret = 0;
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
@ -259,17 +258,6 @@ static int __init mv_rtc_probe(struct platform_device *pdev)
} }
} }
/*
* A date after January 19th, 2038 does not fit on 32 bits and
* will confuse the kernel and userspace. Reset to a sane date
* (January 1st, 2013) if we're after 2038.
*/
rtc_date = readl(pdata->ioaddr + RTC_DATE_REG_OFFS);
if (bcd2bin((rtc_date >> RTC_YEAR_OFFS) & 0xff) >= 38) {
dev_info(&pdev->dev, "invalid RTC date, resetting to January 1st, 2013\n");
writel(0x130101, pdata->ioaddr + RTC_DATE_REG_OFFS);
}
pdata->irq = platform_get_irq(pdev, 0); pdata->irq = platform_get_irq(pdev, 0);
platform_set_drvdata(pdev, pdata); platform_set_drvdata(pdev, pdata);

View File

@ -273,7 +273,7 @@ static const struct rtc_class_ops mxc_rtc_ops = {
.alarm_irq_enable = mxc_rtc_alarm_irq_enable, .alarm_irq_enable = mxc_rtc_alarm_irq_enable,
}; };
static int mxc_rtc_wait_for_flag(void *__iomem ioaddr, int flag) static int mxc_rtc_wait_for_flag(void __iomem *ioaddr, int flag)
{ {
unsigned int timeout = REG_READ_TIMEOUT; unsigned int timeout = REG_READ_TIMEOUT;

View File

@ -102,8 +102,8 @@ static int *check_rtc_access_enable(struct nuc900_rtc *nuc900_rtc)
return NULL; return NULL;
} }
static int nuc900_rtc_bcd2bin(unsigned int timereg, static void nuc900_rtc_bcd2bin(unsigned int timereg,
unsigned int calreg, struct rtc_time *tm) unsigned int calreg, struct rtc_time *tm)
{ {
tm->tm_mday = bcd2bin(calreg >> 0); tm->tm_mday = bcd2bin(calreg >> 0);
tm->tm_mon = bcd2bin(calreg >> 8); tm->tm_mon = bcd2bin(calreg >> 8);
@ -112,8 +112,6 @@ static int nuc900_rtc_bcd2bin(unsigned int timereg,
tm->tm_sec = bcd2bin(timereg >> 0); tm->tm_sec = bcd2bin(timereg >> 0);
tm->tm_min = bcd2bin(timereg >> 8); tm->tm_min = bcd2bin(timereg >> 8);
tm->tm_hour = bcd2bin(timereg >> 16); tm->tm_hour = bcd2bin(timereg >> 16);
return rtc_valid_tm(tm);
} }
static void nuc900_rtc_bin2bcd(struct device *dev, struct rtc_time *settm, static void nuc900_rtc_bin2bcd(struct device *dev, struct rtc_time *settm,
@ -156,7 +154,9 @@ static int nuc900_rtc_read_time(struct device *dev, struct rtc_time *tm)
timeval = __raw_readl(rtc->rtc_reg + REG_RTC_TLR); timeval = __raw_readl(rtc->rtc_reg + REG_RTC_TLR);
clrval = __raw_readl(rtc->rtc_reg + REG_RTC_CLR); clrval = __raw_readl(rtc->rtc_reg + REG_RTC_CLR);
return nuc900_rtc_bcd2bin(timeval, clrval, tm); nuc900_rtc_bcd2bin(timeval, clrval, tm);
return 0;
} }
static int nuc900_rtc_set_time(struct device *dev, struct rtc_time *tm) static int nuc900_rtc_set_time(struct device *dev, struct rtc_time *tm)
@ -189,7 +189,9 @@ static int nuc900_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
timeval = __raw_readl(rtc->rtc_reg + REG_RTC_TAR); timeval = __raw_readl(rtc->rtc_reg + REG_RTC_TAR);
carval = __raw_readl(rtc->rtc_reg + REG_RTC_CAR); carval = __raw_readl(rtc->rtc_reg + REG_RTC_CAR);
return nuc900_rtc_bcd2bin(timeval, carval, &alrm->time); nuc900_rtc_bcd2bin(timeval, carval, &alrm->time);
return rtc_valid_tm(&alrm->time);
} }
static int nuc900_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) static int nuc900_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)

View File

@ -273,9 +273,6 @@ static int omap_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
/* this hardware doesn't support "don't care" alarm fields */ /* this hardware doesn't support "don't care" alarm fields */
static int tm2bcd(struct rtc_time *tm) static int tm2bcd(struct rtc_time *tm)
{ {
if (rtc_valid_tm(tm) != 0)
return -EINVAL;
tm->tm_sec = bin2bcd(tm->tm_sec); tm->tm_sec = bin2bcd(tm->tm_sec);
tm->tm_min = bin2bcd(tm->tm_min); tm->tm_min = bin2bcd(tm->tm_min);
tm->tm_hour = bin2bcd(tm->tm_hour); tm->tm_hour = bin2bcd(tm->tm_hour);
@ -850,7 +847,6 @@ static int omap_rtc_probe(struct platform_device *pdev)
rtc->rtc->ops = &omap_rtc_ops; rtc->rtc->ops = &omap_rtc_ops;
omap_rtc_nvmem_config.priv = rtc; omap_rtc_nvmem_config.priv = rtc;
rtc->rtc->nvmem_config = &omap_rtc_nvmem_config;
/* handle periodic and alarm irqs */ /* handle periodic and alarm irqs */
ret = devm_request_irq(&pdev->dev, rtc->irq_timer, rtc_irq, 0, ret = devm_request_irq(&pdev->dev, rtc->irq_timer, rtc_irq, 0,
@ -886,6 +882,8 @@ static int omap_rtc_probe(struct platform_device *pdev)
if (ret) if (ret)
goto err; goto err;
rtc_nvmem_register(rtc->rtc, &omap_rtc_nvmem_config);
return 0; return 0;
err: err:

View File

@ -95,7 +95,7 @@ static int pcap_rtc_read_time(struct device *dev, struct rtc_time *tm)
rtc_time_to_tm(secs, tm); rtc_time_to_tm(secs, tm);
return rtc_valid_tm(tm); return 0;
} }
static int pcap_rtc_set_mmss(struct device *dev, unsigned long secs) static int pcap_rtc_set_mmss(struct device *dev, unsigned long secs)

View File

@ -289,7 +289,7 @@ static int pcf2123_rtc_read_time(struct device *dev, struct rtc_time *tm)
tm->tm_sec, tm->tm_min, tm->tm_hour, tm->tm_sec, tm->tm_min, tm->tm_hour,
tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
return rtc_valid_tm(tm); return 0;
} }
static int pcf2123_rtc_set_time(struct device *dev, struct rtc_time *tm) static int pcf2123_rtc_set_time(struct device *dev, struct rtc_time *tm)

View File

@ -111,7 +111,7 @@ static int pcf2127_rtc_read_time(struct device *dev, struct rtc_time *tm)
tm->tm_sec, tm->tm_min, tm->tm_hour, tm->tm_sec, tm->tm_min, tm->tm_hour,
tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
return rtc_valid_tm(tm); return 0;
} }
static int pcf2127_rtc_set_time(struct device *dev, struct rtc_time *tm) static int pcf2127_rtc_set_time(struct device *dev, struct rtc_time *tm)

View File

@ -135,7 +135,7 @@ static int pcf50633_rtc_read_time(struct device *dev, struct rtc_time *tm)
tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_mday, tm->tm_mon, tm->tm_year,
tm->tm_hour, tm->tm_min, tm->tm_sec); tm->tm_hour, tm->tm_min, tm->tm_sec);
return rtc_valid_tm(tm); return 0;
} }
static int pcf50633_rtc_set_time(struct device *dev, struct rtc_time *tm) static int pcf50633_rtc_set_time(struct device *dev, struct rtc_time *tm)

View File

@ -70,7 +70,7 @@ static int pcf85063_start_clock(struct i2c_client *client, u8 ctrl1)
s32 ret; s32 ret;
/* start the clock */ /* start the clock */
ctrl1 &= PCF85063_REG_CTRL1_STOP; ctrl1 &= ~PCF85063_REG_CTRL1_STOP;
ret = i2c_smbus_write_byte_data(client, PCF85063_REG_CTRL1, ctrl1); ret = i2c_smbus_write_byte_data(client, PCF85063_REG_CTRL1, ctrl1);
if (ret < 0) { if (ret < 0) {
@ -81,8 +81,9 @@ static int pcf85063_start_clock(struct i2c_client *client, u8 ctrl1)
return 0; return 0;
} }
static int pcf85063_get_datetime(struct i2c_client *client, struct rtc_time *tm) static int pcf85063_rtc_read_time(struct device *dev, struct rtc_time *tm)
{ {
struct i2c_client *client = to_i2c_client(dev);
int rc; int rc;
u8 regs[7]; u8 regs[7];
@ -114,11 +115,12 @@ static int pcf85063_get_datetime(struct i2c_client *client, struct rtc_time *tm)
tm->tm_year = bcd2bin(regs[6]); tm->tm_year = bcd2bin(regs[6]);
tm->tm_year += 100; tm->tm_year += 100;
return rtc_valid_tm(tm); return 0;
} }
static int pcf85063_set_datetime(struct i2c_client *client, struct rtc_time *tm) static int pcf85063_rtc_set_time(struct device *dev, struct rtc_time *tm)
{ {
struct i2c_client *client = to_i2c_client(dev);
int rc; int rc;
u8 regs[7]; u8 regs[7];
u8 ctrl1; u8 ctrl1;
@ -172,16 +174,6 @@ static int pcf85063_set_datetime(struct i2c_client *client, struct rtc_time *tm)
return 0; return 0;
} }
static int pcf85063_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
return pcf85063_get_datetime(to_i2c_client(dev), tm);
}
static int pcf85063_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
return pcf85063_set_datetime(to_i2c_client(dev), tm);
}
static const struct rtc_class_ops pcf85063_rtc_ops = { static const struct rtc_class_ops pcf85063_rtc_ops = {
.read_time = pcf85063_rtc_read_time, .read_time = pcf85063_rtc_read_time,
.set_time = pcf85063_rtc_set_time .set_time = pcf85063_rtc_set_time

View File

@ -192,7 +192,7 @@ static int pcf8523_rtc_read_time(struct device *dev, struct rtc_time *tm)
tm->tm_mon = bcd2bin(regs[5] & 0x1f) - 1; tm->tm_mon = bcd2bin(regs[5] & 0x1f) - 1;
tm->tm_year = bcd2bin(regs[6]) + 100; tm->tm_year = bcd2bin(regs[6]) + 100;
return rtc_valid_tm(tm); return 0;
} }
static int pcf8523_rtc_set_time(struct device *dev, struct rtc_time *tm) static int pcf8523_rtc_set_time(struct device *dev, struct rtc_time *tm)

View File

@ -73,6 +73,43 @@
#define CTRL_RESETS 0x2f #define CTRL_RESETS 0x2f
#define CTRL_RAM 0x40 #define CTRL_RAM 0x40
#define ALRM_SEC_A1E BIT(0)
#define ALRM_MIN_A1E BIT(1)
#define ALRM_HR_A1E BIT(2)
#define ALRM_DAY_A1E BIT(3)
#define ALRM_MON_A1E BIT(4)
#define ALRM_MIN_A2E BIT(5)
#define ALRM_HR_A2E BIT(6)
#define ALRM_DAY_A2E BIT(7)
#define INT_WDIE BIT(0)
#define INT_BSIE BIT(1)
#define INT_TSRIE BIT(2)
#define INT_A2IE BIT(3)
#define INT_A1IE BIT(4)
#define INT_OIE BIT(5)
#define INT_PIE BIT(6)
#define INT_ILP BIT(7)
#define FLAGS_TSR1F BIT(0)
#define FLAGS_TSR2F BIT(1)
#define FLAGS_TSR3F BIT(2)
#define FLAGS_BSF BIT(3)
#define FLAGS_WDF BIT(4)
#define FLAGS_A1F BIT(5)
#define FLAGS_A2F BIT(6)
#define FLAGS_PIF BIT(7)
#define PIN_IO_INTAPM GENMASK(1, 0)
#define PIN_IO_INTA_CLK 0
#define PIN_IO_INTA_BAT 1
#define PIN_IO_INTA_OUT 2
#define PIN_IO_INTA_HIZ 3
#define STOP_EN_STOP BIT(0)
#define RESET_CPR 0xa4
#define NVRAM_SIZE 0x40 #define NVRAM_SIZE 0x40
static struct i2c_driver pcf85363_driver; static struct i2c_driver pcf85363_driver;
@ -80,7 +117,6 @@ static struct i2c_driver pcf85363_driver;
struct pcf85363 { struct pcf85363 {
struct device *dev; struct device *dev;
struct rtc_device *rtc; struct rtc_device *rtc;
struct nvmem_config nvmem_cfg;
struct regmap *regmap; struct regmap *regmap;
}; };
@ -116,8 +152,12 @@ static int pcf85363_rtc_read_time(struct device *dev, struct rtc_time *tm)
static int pcf85363_rtc_set_time(struct device *dev, struct rtc_time *tm) static int pcf85363_rtc_set_time(struct device *dev, struct rtc_time *tm)
{ {
struct pcf85363 *pcf85363 = dev_get_drvdata(dev); struct pcf85363 *pcf85363 = dev_get_drvdata(dev);
unsigned char buf[DT_YEARS + 1]; unsigned char tmp[11];
int len = sizeof(buf); unsigned char *buf = &tmp[2];
int ret;
tmp[0] = STOP_EN_STOP;
tmp[1] = RESET_CPR;
buf[DT_100THS] = 0; buf[DT_100THS] = 0;
buf[DT_SECS] = bin2bcd(tm->tm_sec); buf[DT_SECS] = bin2bcd(tm->tm_sec);
@ -128,8 +168,116 @@ static int pcf85363_rtc_set_time(struct device *dev, struct rtc_time *tm)
buf[DT_MONTHS] = bin2bcd(tm->tm_mon + 1); buf[DT_MONTHS] = bin2bcd(tm->tm_mon + 1);
buf[DT_YEARS] = bin2bcd(tm->tm_year % 100); buf[DT_YEARS] = bin2bcd(tm->tm_year % 100);
return regmap_bulk_write(pcf85363->regmap, DT_100THS, ret = regmap_bulk_write(pcf85363->regmap, CTRL_STOP_EN,
buf, len); tmp, sizeof(tmp));
if (ret)
return ret;
return regmap_write(pcf85363->regmap, CTRL_STOP_EN, 0);
}
static int pcf85363_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
struct pcf85363 *pcf85363 = dev_get_drvdata(dev);
unsigned char buf[DT_MONTH_ALM1 - DT_SECOND_ALM1 + 1];
unsigned int val;
int ret;
ret = regmap_bulk_read(pcf85363->regmap, DT_SECOND_ALM1, buf,
sizeof(buf));
if (ret)
return ret;
alrm->time.tm_sec = bcd2bin(buf[0]);
alrm->time.tm_min = bcd2bin(buf[1]);
alrm->time.tm_hour = bcd2bin(buf[2]);
alrm->time.tm_mday = bcd2bin(buf[3]);
alrm->time.tm_mon = bcd2bin(buf[4]) - 1;
ret = regmap_read(pcf85363->regmap, CTRL_INTA_EN, &val);
if (ret)
return ret;
alrm->enabled = !!(val & INT_A1IE);
return 0;
}
static int _pcf85363_rtc_alarm_irq_enable(struct pcf85363 *pcf85363, unsigned
int enabled)
{
unsigned int alarm_flags = ALRM_SEC_A1E | ALRM_MIN_A1E | ALRM_HR_A1E |
ALRM_DAY_A1E | ALRM_MON_A1E;
int ret;
ret = regmap_update_bits(pcf85363->regmap, DT_ALARM_EN, alarm_flags,
enabled ? alarm_flags : 0);
if (ret)
return ret;
ret = regmap_update_bits(pcf85363->regmap, CTRL_INTA_EN,
INT_A1IE, enabled ? INT_A1IE : 0);
if (ret || enabled)
return ret;
/* clear current flags */
return regmap_update_bits(pcf85363->regmap, CTRL_FLAGS, FLAGS_A1F, 0);
}
static int pcf85363_rtc_alarm_irq_enable(struct device *dev,
unsigned int enabled)
{
struct pcf85363 *pcf85363 = dev_get_drvdata(dev);
return _pcf85363_rtc_alarm_irq_enable(pcf85363, enabled);
}
static int pcf85363_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
struct pcf85363 *pcf85363 = dev_get_drvdata(dev);
unsigned char buf[DT_MONTH_ALM1 - DT_SECOND_ALM1 + 1];
int ret;
buf[0] = bin2bcd(alrm->time.tm_sec);
buf[1] = bin2bcd(alrm->time.tm_min);
buf[2] = bin2bcd(alrm->time.tm_hour);
buf[3] = bin2bcd(alrm->time.tm_mday);
buf[4] = bin2bcd(alrm->time.tm_mon + 1);
/*
* Disable the alarm interrupt before changing the value to avoid
* spurious interrupts
*/
ret = _pcf85363_rtc_alarm_irq_enable(pcf85363, 0);
if (ret)
return ret;
ret = regmap_bulk_write(pcf85363->regmap, DT_SECOND_ALM1, buf,
sizeof(buf));
if (ret)
return ret;
return _pcf85363_rtc_alarm_irq_enable(pcf85363, alrm->enabled);
}
static irqreturn_t pcf85363_rtc_handle_irq(int irq, void *dev_id)
{
struct pcf85363 *pcf85363 = i2c_get_clientdata(dev_id);
unsigned int flags;
int err;
err = regmap_read(pcf85363->regmap, CTRL_FLAGS, &flags);
if (err)
return IRQ_NONE;
if (flags & FLAGS_A1F) {
rtc_update_irq(pcf85363->rtc, 1, RTC_IRQF | RTC_AF);
regmap_update_bits(pcf85363->regmap, CTRL_FLAGS, FLAGS_A1F, 0);
return IRQ_HANDLED;
}
return IRQ_NONE;
} }
static const struct rtc_class_ops rtc_ops = { static const struct rtc_class_ops rtc_ops = {
@ -137,6 +285,14 @@ static const struct rtc_class_ops rtc_ops = {
.set_time = pcf85363_rtc_set_time, .set_time = pcf85363_rtc_set_time,
}; };
static const struct rtc_class_ops rtc_ops_alarm = {
.read_time = pcf85363_rtc_read_time,
.set_time = pcf85363_rtc_set_time,
.read_alarm = pcf85363_rtc_read_alarm,
.set_alarm = pcf85363_rtc_set_alarm,
.alarm_irq_enable = pcf85363_rtc_alarm_irq_enable,
};
static int pcf85363_nvram_read(void *priv, unsigned int offset, void *val, static int pcf85363_nvram_read(void *priv, unsigned int offset, void *val,
size_t bytes) size_t bytes)
{ {
@ -158,12 +314,22 @@ static int pcf85363_nvram_write(void *priv, unsigned int offset, void *val,
static const struct regmap_config regmap_config = { static const struct regmap_config regmap_config = {
.reg_bits = 8, .reg_bits = 8,
.val_bits = 8, .val_bits = 8,
.max_register = 0x7f,
}; };
static int pcf85363_probe(struct i2c_client *client, static int pcf85363_probe(struct i2c_client *client,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
struct pcf85363 *pcf85363; struct pcf85363 *pcf85363;
struct nvmem_config nvmem_cfg = {
.name = "pcf85363-",
.word_size = 1,
.stride = 1,
.size = NVRAM_SIZE,
.reg_read = pcf85363_nvram_read,
.reg_write = pcf85363_nvram_write,
};
int ret;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
return -ENODEV; return -ENODEV;
@ -186,17 +352,28 @@ static int pcf85363_probe(struct i2c_client *client,
if (IS_ERR(pcf85363->rtc)) if (IS_ERR(pcf85363->rtc))
return PTR_ERR(pcf85363->rtc); return PTR_ERR(pcf85363->rtc);
pcf85363->nvmem_cfg.name = "pcf85363-";
pcf85363->nvmem_cfg.word_size = 1;
pcf85363->nvmem_cfg.stride = 1;
pcf85363->nvmem_cfg.size = NVRAM_SIZE;
pcf85363->nvmem_cfg.reg_read = pcf85363_nvram_read;
pcf85363->nvmem_cfg.reg_write = pcf85363_nvram_write;
pcf85363->nvmem_cfg.priv = pcf85363;
pcf85363->rtc->nvmem_config = &pcf85363->nvmem_cfg;
pcf85363->rtc->ops = &rtc_ops; pcf85363->rtc->ops = &rtc_ops;
return rtc_register_device(pcf85363->rtc); if (client->irq > 0) {
regmap_write(pcf85363->regmap, CTRL_FLAGS, 0);
regmap_update_bits(pcf85363->regmap, CTRL_PIN_IO,
PIN_IO_INTA_OUT, PIN_IO_INTAPM);
ret = devm_request_threaded_irq(pcf85363->dev, client->irq,
NULL, pcf85363_rtc_handle_irq,
IRQF_TRIGGER_LOW | IRQF_ONESHOT,
"pcf85363", client);
if (ret)
dev_warn(&client->dev, "unable to request IRQ, alarms disabled\n");
else
pcf85363->rtc->ops = &rtc_ops_alarm;
}
ret = rtc_register_device(pcf85363->rtc);
nvmem_cfg.priv = pcf85363;
rtc_nvmem_register(pcf85363->rtc, &nvmem_cfg);
return ret;
} }
static const struct of_device_id dev_ids[] = { static const struct of_device_id dev_ids[] = {

View File

@ -175,7 +175,7 @@ static int pic32_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
rtc_tm->tm_hour, rtc_tm->tm_min, rtc_tm->tm_sec); rtc_tm->tm_hour, rtc_tm->tm_min, rtc_tm->tm_sec);
clk_disable(pdata->clk); clk_disable(pdata->clk);
return rtc_valid_tm(rtc_tm); return 0;
} }
static int pic32_rtc_settime(struct device *dev, struct rtc_time *tm) static int pic32_rtc_settime(struct device *dev, struct rtc_time *tm)

View File

@ -74,16 +74,18 @@ struct pm8xxx_rtc {
/* /*
* Steps to write the RTC registers. * Steps to write the RTC registers.
* 1. Disable alarm if enabled. * 1. Disable alarm if enabled.
* 2. Write 0x00 to LSB. * 2. Disable rtc if enabled.
* 3. Write Byte[1], Byte[2], Byte[3] then Byte[0]. * 3. Write 0x00 to LSB.
* 4. Enable alarm if disabled in step 1. * 4. Write Byte[1], Byte[2], Byte[3] then Byte[0].
* 5. Enable rtc if disabled in step 2.
* 6. Enable alarm if disabled in step 1.
*/ */
static int pm8xxx_rtc_set_time(struct device *dev, struct rtc_time *tm) static int pm8xxx_rtc_set_time(struct device *dev, struct rtc_time *tm)
{ {
int rc, i; int rc, i;
unsigned long secs, irq_flags; unsigned long secs, irq_flags;
u8 value[NUM_8_BIT_RTC_REGS], alarm_enabled = 0; u8 value[NUM_8_BIT_RTC_REGS], alarm_enabled = 0, rtc_disabled = 0;
unsigned int ctrl_reg; unsigned int ctrl_reg, rtc_ctrl_reg;
struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev); struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev);
const struct pm8xxx_rtc_regs *regs = rtc_dd->regs; const struct pm8xxx_rtc_regs *regs = rtc_dd->regs;
@ -92,23 +94,38 @@ static int pm8xxx_rtc_set_time(struct device *dev, struct rtc_time *tm)
rtc_tm_to_time(tm, &secs); rtc_tm_to_time(tm, &secs);
dev_dbg(dev, "Seconds value to be written to RTC = %lu\n", secs);
for (i = 0; i < NUM_8_BIT_RTC_REGS; i++) { for (i = 0; i < NUM_8_BIT_RTC_REGS; i++) {
value[i] = secs & 0xFF; value[i] = secs & 0xFF;
secs >>= 8; secs >>= 8;
} }
dev_dbg(dev, "Seconds value to be written to RTC = %lu\n", secs);
spin_lock_irqsave(&rtc_dd->ctrl_reg_lock, irq_flags); spin_lock_irqsave(&rtc_dd->ctrl_reg_lock, irq_flags);
rc = regmap_read(rtc_dd->regmap, regs->ctrl, &ctrl_reg); rc = regmap_read(rtc_dd->regmap, regs->alarm_ctrl, &ctrl_reg);
if (rc) if (rc)
goto rtc_rw_fail; goto rtc_rw_fail;
if (ctrl_reg & regs->alarm_en) { if (ctrl_reg & regs->alarm_en) {
alarm_enabled = 1; alarm_enabled = 1;
ctrl_reg &= ~regs->alarm_en; ctrl_reg &= ~regs->alarm_en;
rc = regmap_write(rtc_dd->regmap, regs->ctrl, ctrl_reg); rc = regmap_write(rtc_dd->regmap, regs->alarm_ctrl, ctrl_reg);
if (rc) {
dev_err(dev, "Write to RTC Alarm control register failed\n");
goto rtc_rw_fail;
}
}
/* Disable RTC H/w before writing on RTC register */
rc = regmap_read(rtc_dd->regmap, regs->ctrl, &rtc_ctrl_reg);
if (rc)
goto rtc_rw_fail;
if (rtc_ctrl_reg & PM8xxx_RTC_ENABLE) {
rtc_disabled = 1;
rtc_ctrl_reg &= ~PM8xxx_RTC_ENABLE;
rc = regmap_write(rtc_dd->regmap, regs->ctrl, rtc_ctrl_reg);
if (rc) { if (rc) {
dev_err(dev, "Write to RTC control register failed\n"); dev_err(dev, "Write to RTC control register failed\n");
goto rtc_rw_fail; goto rtc_rw_fail;
@ -137,15 +154,25 @@ static int pm8xxx_rtc_set_time(struct device *dev, struct rtc_time *tm)
goto rtc_rw_fail; goto rtc_rw_fail;
} }
if (alarm_enabled) { /* Enable RTC H/w after writing on RTC register */
ctrl_reg |= regs->alarm_en; if (rtc_disabled) {
rc = regmap_write(rtc_dd->regmap, regs->ctrl, ctrl_reg); rtc_ctrl_reg |= PM8xxx_RTC_ENABLE;
rc = regmap_write(rtc_dd->regmap, regs->ctrl, rtc_ctrl_reg);
if (rc) { if (rc) {
dev_err(dev, "Write to RTC control register failed\n"); dev_err(dev, "Write to RTC control register failed\n");
goto rtc_rw_fail; goto rtc_rw_fail;
} }
} }
if (alarm_enabled) {
ctrl_reg |= regs->alarm_en;
rc = regmap_write(rtc_dd->regmap, regs->alarm_ctrl, ctrl_reg);
if (rc) {
dev_err(dev, "Write to RTC Alarm control register failed\n");
goto rtc_rw_fail;
}
}
rtc_rw_fail: rtc_rw_fail:
spin_unlock_irqrestore(&rtc_dd->ctrl_reg_lock, irq_flags); spin_unlock_irqrestore(&rtc_dd->ctrl_reg_lock, irq_flags);
@ -190,12 +217,6 @@ static int pm8xxx_rtc_read_time(struct device *dev, struct rtc_time *tm)
rtc_time_to_tm(secs, tm); rtc_time_to_tm(secs, tm);
rc = rtc_valid_tm(tm);
if (rc < 0) {
dev_err(dev, "Invalid time read from RTC\n");
return rc;
}
dev_dbg(dev, "secs = %lu, h:m:s == %d:%d:%d, d/m/y = %d/%d/%d\n", dev_dbg(dev, "secs = %lu, h:m:s == %d:%d:%d, d/m/y = %d/%d/%d\n",
secs, tm->tm_hour, tm->tm_min, tm->tm_sec, secs, tm->tm_hour, tm->tm_min, tm->tm_sec,
tm->tm_mday, tm->tm_mon, tm->tm_year); tm->tm_mday, tm->tm_mon, tm->tm_year);

View File

@ -41,7 +41,7 @@ static u64 read_rtc(void)
static int ps3_get_time(struct device *dev, struct rtc_time *tm) static int ps3_get_time(struct device *dev, struct rtc_time *tm)
{ {
rtc_time_to_tm(read_rtc() + ps3_os_area_get_rtc_diff(), tm); rtc_time_to_tm(read_rtc() + ps3_os_area_get_rtc_diff(), tm);
return rtc_valid_tm(tm); return 0;
} }
static int ps3_set_time(struct device *dev, struct rtc_time *tm) static int ps3_set_time(struct device *dev, struct rtc_time *tm)

View File

@ -224,7 +224,7 @@ static int rtc7301_read_time(struct device *dev, struct rtc_time *tm)
spin_unlock_irqrestore(&priv->lock, flags); spin_unlock_irqrestore(&priv->lock, flags);
return err ? err : rtc_valid_tm(tm); return err;
} }
static int rtc7301_set_time(struct device *dev, struct rtc_time *tm) static int rtc7301_set_time(struct device *dev, struct rtc_time *tm)

View File

@ -92,7 +92,7 @@ static int r9701_get_datetime(struct device *dev, struct rtc_time *dt)
* according to the data sheet. make sure they are valid. * according to the data sheet. make sure they are valid.
*/ */
return rtc_valid_tm(dt); return 0;
} }
static int r9701_set_datetime(struct device *dev, struct rtc_time *dt) static int r9701_set_datetime(struct device *dev, struct rtc_time *dt)

View File

@ -375,7 +375,6 @@ static int rk808_rtc_probe(struct platform_device *pdev)
{ {
struct rk808 *rk808 = dev_get_drvdata(pdev->dev.parent); struct rk808 *rk808 = dev_get_drvdata(pdev->dev.parent);
struct rk808_rtc *rk808_rtc; struct rk808_rtc *rk808_rtc;
struct rtc_time tm;
int ret; int ret;
rk808_rtc = devm_kzalloc(&pdev->dev, sizeof(*rk808_rtc), GFP_KERNEL); rk808_rtc = devm_kzalloc(&pdev->dev, sizeof(*rk808_rtc), GFP_KERNEL);
@ -404,24 +403,13 @@ static int rk808_rtc_probe(struct platform_device *pdev)
return ret; return ret;
} }
/* set init time */
ret = rk808_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_warn(&pdev->dev, "invalid date/time\n");
device_init_wakeup(&pdev->dev, 1); device_init_wakeup(&pdev->dev, 1);
rk808_rtc->rtc = devm_rtc_device_register(&pdev->dev, "rk808-rtc", rk808_rtc->rtc = devm_rtc_allocate_device(&pdev->dev);
&rk808_rtc_ops, THIS_MODULE); if (IS_ERR(rk808_rtc->rtc))
if (IS_ERR(rk808_rtc->rtc)) { return PTR_ERR(rk808_rtc->rtc);
ret = PTR_ERR(rk808_rtc->rtc);
return ret; rk808_rtc->rtc->ops = &rk808_rtc_ops;
}
rk808_rtc->irq = platform_get_irq(pdev, 0); rk808_rtc->irq = platform_get_irq(pdev, 0);
if (rk808_rtc->irq < 0) { if (rk808_rtc->irq < 0) {
@ -438,9 +426,10 @@ static int rk808_rtc_probe(struct platform_device *pdev)
if (ret) { if (ret) {
dev_err(&pdev->dev, "Failed to request alarm IRQ %d: %d\n", dev_err(&pdev->dev, "Failed to request alarm IRQ %d: %d\n",
rk808_rtc->irq, ret); rk808_rtc->irq, ret);
return ret;
} }
return ret; return rtc_register_device(rk808_rtc->rtc);
} }
static struct platform_driver rk808_rtc_driver = { static struct platform_driver rk808_rtc_driver = {

View File

@ -64,7 +64,6 @@ struct rp5c01_priv {
u32 __iomem *regs; u32 __iomem *regs;
struct rtc_device *rtc; struct rtc_device *rtc;
spinlock_t lock; /* against concurrent RTC/NVRAM access */ spinlock_t lock; /* against concurrent RTC/NVRAM access */
struct bin_attribute nvram_attr;
}; };
static inline unsigned int rp5c01_read(struct rp5c01_priv *priv, static inline unsigned int rp5c01_read(struct rp5c01_priv *priv,
@ -116,7 +115,7 @@ static int rp5c01_read_time(struct device *dev, struct rtc_time *tm)
rp5c01_unlock(priv); rp5c01_unlock(priv);
spin_unlock_irq(&priv->lock); spin_unlock_irq(&priv->lock);
return rtc_valid_tm(tm); return 0;
} }
static int rp5c01_set_time(struct device *dev, struct rtc_time *tm) static int rp5c01_set_time(struct device *dev, struct rtc_time *tm)
@ -160,17 +159,15 @@ static const struct rtc_class_ops rp5c01_rtc_ops = {
* byte is stored in BLOCK10, the low nibble in BLOCK11. * byte is stored in BLOCK10, the low nibble in BLOCK11.
*/ */
static ssize_t rp5c01_nvram_read(struct file *filp, struct kobject *kobj, static int rp5c01_nvram_read(void *_priv, unsigned int pos, void *val,
struct bin_attribute *bin_attr, size_t bytes)
char *buf, loff_t pos, size_t size)
{ {
struct device *dev = container_of(kobj, struct device, kobj); struct rp5c01_priv *priv = _priv;
struct rp5c01_priv *priv = dev_get_drvdata(dev); u8 *buf = val;
ssize_t count;
spin_lock_irq(&priv->lock); spin_lock_irq(&priv->lock);
for (count = 0; count < size; count++) { for (; bytes; bytes--) {
u8 data; u8 data;
rp5c01_write(priv, rp5c01_write(priv,
@ -187,20 +184,18 @@ static ssize_t rp5c01_nvram_read(struct file *filp, struct kobject *kobj,
} }
spin_unlock_irq(&priv->lock); spin_unlock_irq(&priv->lock);
return count; return 0;
} }
static ssize_t rp5c01_nvram_write(struct file *filp, struct kobject *kobj, static int rp5c01_nvram_write(void *_priv, unsigned int pos, void *val,
struct bin_attribute *bin_attr, size_t bytes)
char *buf, loff_t pos, size_t size)
{ {
struct device *dev = container_of(kobj, struct device, kobj); struct rp5c01_priv *priv = _priv;
struct rp5c01_priv *priv = dev_get_drvdata(dev); u8 *buf = val;
ssize_t count;
spin_lock_irq(&priv->lock); spin_lock_irq(&priv->lock);
for (count = 0; count < size; count++) { for (; bytes; bytes--) {
u8 data = *buf++; u8 data = *buf++;
rp5c01_write(priv, rp5c01_write(priv,
@ -216,7 +211,7 @@ static ssize_t rp5c01_nvram_write(struct file *filp, struct kobject *kobj,
} }
spin_unlock_irq(&priv->lock); spin_unlock_irq(&priv->lock);
return count; return 0;
} }
static int __init rp5c01_rtc_probe(struct platform_device *dev) static int __init rp5c01_rtc_probe(struct platform_device *dev)
@ -225,6 +220,14 @@ static int __init rp5c01_rtc_probe(struct platform_device *dev)
struct rp5c01_priv *priv; struct rp5c01_priv *priv;
struct rtc_device *rtc; struct rtc_device *rtc;
int error; int error;
struct nvmem_config nvmem_cfg = {
.name = "rp5c01_nvram",
.word_size = 1,
.stride = 1,
.size = RP5C01_MODE,
.reg_read = rp5c01_nvram_read,
.reg_write = rp5c01_nvram_write,
};
res = platform_get_resource(dev, IORESOURCE_MEM, 0); res = platform_get_resource(dev, IORESOURCE_MEM, 0);
if (!res) if (!res)
@ -238,43 +241,31 @@ static int __init rp5c01_rtc_probe(struct platform_device *dev)
if (!priv->regs) if (!priv->regs)
return -ENOMEM; return -ENOMEM;
sysfs_bin_attr_init(&priv->nvram_attr);
priv->nvram_attr.attr.name = "nvram";
priv->nvram_attr.attr.mode = S_IRUGO | S_IWUSR;
priv->nvram_attr.read = rp5c01_nvram_read;
priv->nvram_attr.write = rp5c01_nvram_write;
priv->nvram_attr.size = RP5C01_MODE;
spin_lock_init(&priv->lock); spin_lock_init(&priv->lock);
platform_set_drvdata(dev, priv); platform_set_drvdata(dev, priv);
rtc = devm_rtc_device_register(&dev->dev, "rtc-rp5c01", &rp5c01_rtc_ops, rtc = devm_rtc_allocate_device(&dev->dev);
THIS_MODULE);
if (IS_ERR(rtc)) if (IS_ERR(rtc))
return PTR_ERR(rtc); return PTR_ERR(rtc);
rtc->ops = &rp5c01_rtc_ops;
rtc->nvram_old_abi = true;
priv->rtc = rtc; priv->rtc = rtc;
error = sysfs_create_bin_file(&dev->dev.kobj, &priv->nvram_attr); nvmem_cfg.priv = priv;
error = rtc_nvmem_register(rtc, &nvmem_cfg);
if (error) if (error)
return error; return error;
return 0; return rtc_register_device(rtc);
}
static int __exit rp5c01_rtc_remove(struct platform_device *dev)
{
struct rp5c01_priv *priv = platform_get_drvdata(dev);
sysfs_remove_bin_file(&dev->dev.kobj, &priv->nvram_attr);
return 0;
} }
static struct platform_driver rp5c01_rtc_driver = { static struct platform_driver rp5c01_rtc_driver = {
.driver = { .driver = {
.name = "rtc-rp5c01", .name = "rtc-rp5c01",
}, },
.remove = __exit_p(rp5c01_rtc_remove),
}; };
module_platform_driver_probe(rp5c01_rtc_driver, rp5c01_rtc_probe); module_platform_driver_probe(rp5c01_rtc_driver, rp5c01_rtc_probe);

View File

@ -135,11 +135,6 @@ rs5c348_rtc_read_time(struct device *dev, struct rtc_time *tm)
tm->tm_year = bcd2bin(rxbuf[RS5C348_REG_YEAR]) + tm->tm_year = bcd2bin(rxbuf[RS5C348_REG_YEAR]) +
((rxbuf[RS5C348_REG_MONTH] & RS5C348_BIT_Y2K) ? 100 : 0); ((rxbuf[RS5C348_REG_MONTH] & RS5C348_BIT_Y2K) ? 100 : 0);
if (rtc_valid_tm(tm) < 0) {
dev_err(&spi->dev, "retrieved date/time is not valid.\n");
rtc_time_to_tm(0, tm);
}
return 0; return 0;
} }

View File

@ -207,8 +207,9 @@ static unsigned rs5c_hr2reg(struct rs5c372 *rs5c, unsigned hour)
return bin2bcd(hour); return bin2bcd(hour);
} }
static int rs5c372_get_datetime(struct i2c_client *client, struct rtc_time *tm) static int rs5c372_rtc_read_time(struct device *dev, struct rtc_time *tm)
{ {
struct i2c_client *client = to_i2c_client(dev);
struct rs5c372 *rs5c = i2c_get_clientdata(client); struct rs5c372 *rs5c = i2c_get_clientdata(client);
int status = rs5c_get_regs(rs5c); int status = rs5c_get_regs(rs5c);
@ -234,12 +235,12 @@ static int rs5c372_get_datetime(struct i2c_client *client, struct rtc_time *tm)
tm->tm_sec, tm->tm_min, tm->tm_hour, tm->tm_sec, tm->tm_min, tm->tm_hour,
tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
/* rtc might need initialization */ return 0;
return rtc_valid_tm(tm);
} }
static int rs5c372_set_datetime(struct i2c_client *client, struct rtc_time *tm) static int rs5c372_rtc_set_time(struct device *dev, struct rtc_time *tm)
{ {
struct i2c_client *client = to_i2c_client(dev);
struct rs5c372 *rs5c = i2c_get_clientdata(client); struct rs5c372 *rs5c = i2c_get_clientdata(client);
unsigned char buf[7]; unsigned char buf[7];
int addr; int addr;
@ -305,17 +306,6 @@ static int rs5c372_get_trim(struct i2c_client *client, int *osc, int *trim)
} }
#endif #endif
static int rs5c372_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
return rs5c372_get_datetime(to_i2c_client(dev), tm);
}
static int rs5c372_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
return rs5c372_set_datetime(to_i2c_client(dev), tm);
}
static int rs5c_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) static int rs5c_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
{ {
struct i2c_client *client = to_i2c_client(dev); struct i2c_client *client = to_i2c_client(dev);
@ -581,7 +571,6 @@ static int rs5c372_probe(struct i2c_client *client,
int err = 0; int err = 0;
int smbus_mode = 0; int smbus_mode = 0;
struct rs5c372 *rs5c372; struct rs5c372 *rs5c372;
struct rtc_time tm;
dev_dbg(&client->dev, "%s\n", __func__); dev_dbg(&client->dev, "%s\n", __func__);
@ -662,9 +651,6 @@ static int rs5c372_probe(struct i2c_client *client,
goto exit; goto exit;
} }
if (rs5c372_get_datetime(client, &tm) < 0)
dev_warn(&client->dev, "clock needs to be set\n");
dev_info(&client->dev, "%s found, %s\n", dev_info(&client->dev, "%s found, %s\n",
({ char *s; switch (rs5c372->type) { ({ char *s; switch (rs5c372->type) {
case rtc_r2025sd: s = "r2025sd"; break; case rtc_r2025sd: s = "r2025sd"; break;

View File

@ -68,7 +68,6 @@ struct rv8803_data {
struct mutex flags_lock; struct mutex flags_lock;
u8 ctrl; u8 ctrl;
enum rv8803_type type; enum rv8803_type type;
struct nvmem_config nvmem_cfg;
}; };
static int rv8803_read_reg(const struct i2c_client *client, u8 reg) static int rv8803_read_reg(const struct i2c_client *client, u8 reg)
@ -528,6 +527,15 @@ static int rv8803_probe(struct i2c_client *client,
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
struct rv8803_data *rv8803; struct rv8803_data *rv8803;
int err, flags; int err, flags;
struct nvmem_config nvmem_cfg = {
.name = "rv8803_nvram",
.word_size = 1,
.stride = 1,
.size = 1,
.reg_read = rv8803_nvram_read,
.reg_write = rv8803_nvram_write,
.priv = client,
};
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
I2C_FUNC_SMBUS_I2C_BLOCK)) { I2C_FUNC_SMBUS_I2C_BLOCK)) {
@ -582,21 +590,6 @@ static int rv8803_probe(struct i2c_client *client,
} }
} }
rv8803->nvmem_cfg.name = "rv8803_nvram",
rv8803->nvmem_cfg.word_size = 1,
rv8803->nvmem_cfg.stride = 1,
rv8803->nvmem_cfg.size = 1,
rv8803->nvmem_cfg.reg_read = rv8803_nvram_read,
rv8803->nvmem_cfg.reg_write = rv8803_nvram_write,
rv8803->nvmem_cfg.priv = client;
rv8803->rtc->ops = &rv8803_rtc_ops;
rv8803->rtc->nvmem_config = &rv8803->nvmem_cfg;
rv8803->rtc->nvram_old_abi = true;
err = rtc_register_device(rv8803->rtc);
if (err)
return err;
err = rv8803_write_reg(rv8803->client, RV8803_EXT, RV8803_EXT_WADA); err = rv8803_write_reg(rv8803->client, RV8803_EXT, RV8803_EXT_WADA);
if (err) if (err)
return err; return err;
@ -607,6 +600,14 @@ static int rv8803_probe(struct i2c_client *client,
return err; return err;
} }
rv8803->rtc->ops = &rv8803_rtc_ops;
rv8803->rtc->nvram_old_abi = true;
err = rtc_register_device(rv8803->rtc);
if (err)
return err;
rtc_nvmem_register(rv8803->rtc, &nvmem_cfg);
rv8803->rtc->max_user_freq = 1; rv8803->rtc->max_user_freq = 1;
return 0; return 0;

View File

@ -172,11 +172,7 @@ static int rx4581_get_datetime(struct device *dev, struct rtc_time *tm)
tm->tm_sec, tm->tm_min, tm->tm_hour, tm->tm_sec, tm->tm_min, tm->tm_hour,
tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
err = rtc_valid_tm(tm); return 0;
if (err < 0)
dev_err(dev, "retrieved date/time is not valid.\n");
return err;
} }
static int rx4581_set_datetime(struct device *dev, struct rtc_time *tm) static int rx4581_set_datetime(struct device *dev, struct rtc_time *tm)

View File

@ -252,7 +252,7 @@ static int rx6110_get_time(struct device *dev, struct rtc_time *tm)
tm->tm_sec, tm->tm_min, tm->tm_hour, tm->tm_sec, tm->tm_min, tm->tm_hour,
tm->tm_mday, tm->tm_mon, tm->tm_year); tm->tm_mday, tm->tm_mon, tm->tm_year);
return rtc_valid_tm(tm); return 0;
} }
static const struct reg_sequence rx6110_default_regs[] = { static const struct reg_sequence rx6110_default_regs[] = {

View File

@ -138,7 +138,7 @@ static int rx8010_get_time(struct device *dev, struct rtc_time *dt)
dt->tm_year = bcd2bin(date[RX8010_YEAR - RX8010_SEC]) + 100; dt->tm_year = bcd2bin(date[RX8010_YEAR - RX8010_SEC]) + 100;
dt->tm_wday = ffs(date[RX8010_WDAY - RX8010_SEC] & 0x7f); dt->tm_wday = ffs(date[RX8010_WDAY - RX8010_SEC] & 0x7f);
return rtc_valid_tm(dt); return 0;
} }
static int rx8010_set_time(struct device *dev, struct rtc_time *dt) static int rx8010_set_time(struct device *dev, struct rtc_time *dt)

View File

@ -214,7 +214,7 @@ static int rx8025_get_time(struct device *dev, struct rtc_time *dt)
dt->tm_sec, dt->tm_min, dt->tm_hour, dt->tm_sec, dt->tm_min, dt->tm_hour,
dt->tm_mday, dt->tm_mon, dt->tm_year); dt->tm_mday, dt->tm_mon, dt->tm_year);
return rtc_valid_tm(dt); return 0;
} }
static int rx8025_set_time(struct device *dev, struct rtc_time *dt) static int rx8025_set_time(struct device *dev, struct rtc_time *dt)

View File

@ -164,11 +164,7 @@ static int rx8581_get_datetime(struct i2c_client *client, struct rtc_time *tm)
tm->tm_sec, tm->tm_min, tm->tm_hour, tm->tm_sec, tm->tm_min, tm->tm_hour,
tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
err = rtc_valid_tm(tm); return 0;
if (err < 0)
dev_err(&client->dev, "retrieved date/time is not valid.\n");
return err;
} }
static int rx8581_set_datetime(struct i2c_client *client, struct rtc_time *tm) static int rx8581_set_datetime(struct i2c_client *client, struct rtc_time *tm)

View File

@ -210,8 +210,9 @@ static int s35390a_reg2hr(struct s35390a *s35390a, char reg)
return hour; return hour;
} }
static int s35390a_set_datetime(struct i2c_client *client, struct rtc_time *tm) static int s35390a_rtc_set_time(struct device *dev, struct rtc_time *tm)
{ {
struct i2c_client *client = to_i2c_client(dev);
struct s35390a *s35390a = i2c_get_clientdata(client); struct s35390a *s35390a = i2c_get_clientdata(client);
int i, err; int i, err;
char buf[7], status; char buf[7], status;
@ -241,8 +242,9 @@ static int s35390a_set_datetime(struct i2c_client *client, struct rtc_time *tm)
return err; return err;
} }
static int s35390a_get_datetime(struct i2c_client *client, struct rtc_time *tm) static int s35390a_rtc_read_time(struct device *dev, struct rtc_time *tm)
{ {
struct i2c_client *client = to_i2c_client(dev);
struct s35390a *s35390a = i2c_get_clientdata(client); struct s35390a *s35390a = i2c_get_clientdata(client);
char buf[7], status; char buf[7], status;
int i, err; int i, err;
@ -271,11 +273,12 @@ static int s35390a_get_datetime(struct i2c_client *client, struct rtc_time *tm)
tm->tm_min, tm->tm_hour, tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_min, tm->tm_hour, tm->tm_mday, tm->tm_mon, tm->tm_year,
tm->tm_wday); tm->tm_wday);
return rtc_valid_tm(tm); return 0;
} }
static int s35390a_set_alarm(struct i2c_client *client, struct rtc_wkalrm *alm) static int s35390a_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
{ {
struct i2c_client *client = to_i2c_client(dev);
struct s35390a *s35390a = i2c_get_clientdata(client); struct s35390a *s35390a = i2c_get_clientdata(client);
char buf[3], sts = 0; char buf[3], sts = 0;
int err, i; int err, i;
@ -329,8 +332,9 @@ static int s35390a_set_alarm(struct i2c_client *client, struct rtc_wkalrm *alm)
return err; return err;
} }
static int s35390a_read_alarm(struct i2c_client *client, struct rtc_wkalrm *alm) static int s35390a_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
{ {
struct i2c_client *client = to_i2c_client(dev);
struct s35390a *s35390a = i2c_get_clientdata(client); struct s35390a *s35390a = i2c_get_clientdata(client);
char buf[3], sts; char buf[3], sts;
int i, err; int i, err;
@ -384,26 +388,6 @@ static int s35390a_read_alarm(struct i2c_client *client, struct rtc_wkalrm *alm)
return 0; return 0;
} }
static int s35390a_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
{
return s35390a_read_alarm(to_i2c_client(dev), alm);
}
static int s35390a_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
{
return s35390a_set_alarm(to_i2c_client(dev), alm);
}
static int s35390a_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
return s35390a_get_datetime(to_i2c_client(dev), tm);
}
static int s35390a_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
return s35390a_set_datetime(to_i2c_client(dev), tm);
}
static int s35390a_rtc_ioctl(struct device *dev, unsigned int cmd, static int s35390a_rtc_ioctl(struct device *dev, unsigned int cmd,
unsigned long arg) unsigned long arg)
{ {
@ -450,7 +434,6 @@ static int s35390a_probe(struct i2c_client *client,
int err, err_read; int err, err_read;
unsigned int i; unsigned int i;
struct s35390a *s35390a; struct s35390a *s35390a;
struct rtc_time tm;
char buf, status1; char buf, status1;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
@ -508,9 +491,6 @@ static int s35390a_probe(struct i2c_client *client,
} }
} }
if (err_read > 0 || s35390a_get_datetime(client, &tm) < 0)
dev_warn(&client->dev, "clock needs to be set\n");
device_set_wakeup_capable(&client->dev, 1); device_set_wakeup_capable(&client->dev, 1);
s35390a->rtc = devm_rtc_device_register(&client->dev, s35390a->rtc = devm_rtc_device_register(&client->dev,

Some files were not shown because too many files have changed in this diff Show More