mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 12:28:41 +08:00
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:
commit
fbe173e3ff
@ -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
|
||||||
|
28
Documentation/devicetree/bindings/rtc/isil,isl12026.txt
Normal file
28
Documentation/devicetree/bindings/rtc/isil,isl12026.txt
Normal 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>;
|
||||||
|
}
|
@ -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
|
||||||
|
@ -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)
|
||||||
|
@ -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.
|
||||||
*/
|
*/
|
||||||
|
@ -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.
|
||||||
|
@ -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
|
||||||
|
@ -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));
|
||||||
|
@ -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,
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
@ -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);
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
|
@ -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,
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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) {}
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
|
||||||
|
@ -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)
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
|
@ -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",
|
||||||
},
|
},
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -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),
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
|
@ -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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -235,3 +235,5 @@ static struct platform_driver goldfish_rtc = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
module_platform_driver(goldfish_rtc);
|
module_platform_driver(goldfish_rtc);
|
||||||
|
|
||||||
|
MODULE_LICENSE("GPL v2");
|
||||||
|
@ -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
501
drivers/rtc/rtc-isl12026.c
Normal 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");
|
@ -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
|
||||||
|
@ -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)
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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 = {
|
||||||
|
@ -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)
|
||||||
|
@ -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);
|
||||||
|
@ -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",
|
||||||
|
@ -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,
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
@ -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:
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
|
@ -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[] = {
|
||||||
|
@ -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)
|
||||||
|
@ -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);
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
|
@ -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 = {
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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)
|
||||||
|
@ -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[] = {
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
|
@ -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
Loading…
Reference in New Issue
Block a user