RTC for 5.6
Subsystem: - the VL_READ and VL_CLR ioctls are now documented and their behavior is unified across all the drivers. - RTC_I2C_AND_SPI Kconfig option rework to avoid selecting both REGMAP_I2C and REGMAP_SPI unecessarily. Drivers: - at91rm9200: remove deprecated procfs, add sam9x60, sama5d4 and sama5d2 compatibles. - cmos: solve lost interrupts issue on MS Surface 3 - hym8563: return proper errno when time is invalid - rv3029: many fixes, nvram support -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEycoQi/giopmpPgB12wIijOdRNOUFAl44lxsACgkQ2wIijOdR NOVF3BAAlQVFDklLqkS6MJplgZ06lgv4ZIbfxCHYFJPUNt/X/gTcHS1OSTwctmor 3qQamySGc74/GAI6lmNSSzDUz9vi2hwcwvLtR/e6+Kgdhg9EuWWvgsqKYRGAn573 TzHWsYY8bDpZ/mN5K+qqadGlzsP58gsEaw0fzcsPkZQQdq4mNSIrB5RILvsHX8cN +RviYOqR+ZvAegfQrAfb/9SCwxQAstUqRDaZXodQDEeIk5CEDWyr31+U9eLDdYoN 1FOHYp6uwUy6Vnl0ym7WU42L95tVWx9XOc/PEq8dZ1m09nfrMhqeIoQC8SUtxG9+ FWXN87lkLSlDaLUwVE8T22QII6jP+7Lc2t6SbI4fwwJdNDoPg+5hhabGjQbM2We9 nG1x7TsVwKjeUglfhqeVgGWYzmIhAeOEBXQhqCdtfVi13ocecVFJxOG6oolQGtlZ M+/t91hID6il7/nxGembcHKapMf9c41CXBPesEg0QjkvGvKj1Z8L9a5vYigzbxWW zb8m9cjIhY3bb8mns3aCs773PSXavsycLk1Hupw6RWrN1XnEXVMHQZDtvzCJe7EV 8CY40LI0VN6x5HC/d0EnqyrMvQbkgTBPXjLBhj54edCZM3vAny3xkYc03oDU8cKc 0PbLUXKpFmzFbTQB4w0sE2FgT0uZmL2SCXiFemUwxbl+/ZACkoc= =e1Xr -----END PGP SIGNATURE----- Merge tag 'rtc-5.6' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux Pull RTC updates from Alexandre Belloni: "The VL_READ and VL_CLR ioctls have been reworked to be more useful. This will not break userspace as there are very few users and they are using the integer value as a boolean. Apart from that, two drivers were reworked and a few fixes here and there for a net reduction of number of lines. Summary: Subsystem: - the VL_READ and VL_CLR ioctls are now documented and their behavior is unified across all the drivers. - RTC_I2C_AND_SPI Kconfig option rework to avoid selecting both REGMAP_I2C and REGMAP_SPI unecessarily. Drivers: - at91rm9200: remove deprecated procfs, add sam9x60, sama5d4 and sama5d2 compatibles. - cmos: solve lost interrupts issue on MS Surface 3 - hym8563: return proper errno when time is invalid - rv3029: many fixes, nvram support" * tag 'rtc-5.6' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux: (63 commits) dt-bindings: rtc: at91rm9200: document clocks property rtc: i2c/spi: Avoid inclusion of REGMAP support when not needed rtc: Kconfig: select REGMAP_I2C when necessary rtc: Kconfig: properly indent sd3078 entry rtc: cmos: Refactor code by using the new dmi_get_bios_year() helper rtc: cmos: Use predefined value for RTC IRQ on legacy x86 rtc: cmos: Stop using shared IRQ rtc: tps6586x: Use IRQ_NOAUTOEN flag rtc: at91rm9200: use FIELD_PREP/FIELD_GET rtc: at91rm9200: avoid time readout in at91_rtc_setalarm rtc: at91rm9200: move register definitions to C file rtc: at91rm9200: add sama5d4 and sama5d2 compatibles dt-bindings: rtc: at91rm9200: convert bindings to json-schema rtc: at91rm9200: remove procfs information dt-bindings: atmel, at91rm9200-rtc: add microchip, sam9x60-rtc rtc: pcf8563: Use BIT rtc: moxart: Convert to SPDX identifier rtc: ds1343: Remove unused struct spi_device in struct ds1343_priv rtc: rx8025: Remove struct i2c_client from struct rx8025_data rtc: hym8563: Read the valid flag directly instead of caching it ...
This commit is contained in:
commit
eadc4e40e6
1
.mailmap
1
.mailmap
|
@ -18,6 +18,7 @@ Aleksey Gorelov <aleksey_gorelov@phoenix.com>
|
|||
Aleksandar Markovic <aleksandar.markovic@mips.com> <aleksandar.markovic@imgtec.com>
|
||||
Alex Shi <alex.shi@linux.alibaba.com> <alex.shi@intel.com>
|
||||
Alex Shi <alex.shi@linux.alibaba.com> <alex.shi@linaro.org>
|
||||
Alexandre Belloni <alexandre.belloni@bootlin.com> <alexandre.belloni@free-electrons.com>
|
||||
Alexei Starovoitov <ast@kernel.org> <ast@plumgrid.com>
|
||||
Alexei Starovoitov <ast@kernel.org> <alexei.starovoitov@gmail.com>
|
||||
Alexei Starovoitov <ast@kernel.org> <ast@fb.com>
|
||||
|
|
|
@ -33,6 +33,14 @@ Description:
|
|||
Requires a separate RTC_PIE_ON call to enable the periodic
|
||||
interrupts.
|
||||
|
||||
* RTC_VL_READ: Read the voltage inputs status of the RTC when
|
||||
supported. The value is a bit field of RTC_VL_*, giving the
|
||||
status of the main and backup voltages.
|
||||
|
||||
* RTC_VL_CLEAR: Clear the voltage status of the RTC. Some RTCs
|
||||
need user interaction when the backup power provider is
|
||||
replaced or charged to be able to clear the status.
|
||||
|
||||
The ioctl() calls supported by the older /dev/rtc interface are
|
||||
also supported by the newer RTC class framework. However,
|
||||
because the chips and systems are not standardized, some PC/AT
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
Atmel AT91RM9200 Real Time Clock
|
||||
|
||||
Required properties:
|
||||
- compatible: should be: "atmel,at91rm9200-rtc" or "atmel,at91sam9x5-rtc"
|
||||
- reg: physical base address of the controller and length of memory mapped
|
||||
region.
|
||||
- interrupts: rtc alarm/event interrupt
|
||||
- clocks: phandle to input clock.
|
||||
|
||||
Example:
|
||||
|
||||
rtc@fffffe00 {
|
||||
compatible = "atmel,at91rm9200-rtc";
|
||||
reg = <0xfffffe00 0x100>;
|
||||
interrupts = <1 4 7>;
|
||||
clocks = <&clk32k>;
|
||||
};
|
|
@ -0,0 +1,49 @@
|
|||
# SPDX-License-Identifier: GPL-2.0
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/rtc/atmel,at91rm9200-rtc.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Atmel AT91 RTC Device Tree Bindings
|
||||
|
||||
allOf:
|
||||
- $ref: "rtc.yaml#"
|
||||
|
||||
maintainers:
|
||||
- Alexandre Belloni <alexandre.belloni@bootlin.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- atmel,at91rm9200-rtc
|
||||
- atmel,at91sam9x5-rtc
|
||||
- atmel,sama5d4-rtc
|
||||
- atmel,sama5d2-rtc
|
||||
- microchip,sam9x60-rtc
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- clocks
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
rtc@fffffe00 {
|
||||
compatible = "atmel,at91rm9200-rtc";
|
||||
reg = <0xfffffe00 0x100>;
|
||||
interrupts = <1 4 7>;
|
||||
clocks = <&clk32k>;
|
||||
};
|
||||
...
|
|
@ -240,6 +240,7 @@ config RTC_DRV_AS3722
|
|||
|
||||
config RTC_DRV_DS1307
|
||||
tristate "Dallas/Maxim DS1307/37/38/39/40/41, ST M41T00, EPSON RX-8025, ISL12057"
|
||||
select REGMAP_I2C
|
||||
help
|
||||
If you say yes here you get support for various compatible RTC
|
||||
chips (often with battery backup) connected with I2C. This driver
|
||||
|
@ -622,6 +623,7 @@ config RTC_DRV_RX8010
|
|||
|
||||
config RTC_DRV_RX8581
|
||||
tristate "Epson RX-8571/RX-8581"
|
||||
select REGMAP_I2C
|
||||
help
|
||||
If you say yes here you will get support for the Epson RX-8571/
|
||||
RX-8581.
|
||||
|
@ -649,6 +651,7 @@ config RTC_DRV_EM3027
|
|||
|
||||
config RTC_DRV_RV3028
|
||||
tristate "Micro Crystal RV3028"
|
||||
select REGMAP_I2C
|
||||
help
|
||||
If you say yes here you get support for the Micro Crystal
|
||||
RV3028.
|
||||
|
@ -677,13 +680,14 @@ config RTC_DRV_S5M
|
|||
will be called rtc-s5m.
|
||||
|
||||
config RTC_DRV_SD3078
|
||||
tristate "ZXW Shenzhen whwave SD3078"
|
||||
help
|
||||
If you say yes here you get support for the ZXW Shenzhen whwave
|
||||
SD3078 RTC chips.
|
||||
tristate "ZXW Shenzhen whwave SD3078"
|
||||
select REGMAP_I2C
|
||||
help
|
||||
If you say yes here you get support for the ZXW Shenzhen whwave
|
||||
SD3078 RTC chips.
|
||||
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called rtc-sd3078
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called rtc-sd3078
|
||||
|
||||
endif # I2C
|
||||
|
||||
|
@ -849,14 +853,14 @@ config RTC_I2C_AND_SPI
|
|||
default m if I2C=m
|
||||
default y if I2C=y
|
||||
default y if SPI_MASTER=y
|
||||
select REGMAP_I2C if I2C
|
||||
select REGMAP_SPI if SPI_MASTER
|
||||
|
||||
comment "SPI and I2C RTC drivers"
|
||||
|
||||
config RTC_DRV_DS3232
|
||||
tristate "Dallas/Maxim DS3232/DS3234"
|
||||
depends on RTC_I2C_AND_SPI
|
||||
select REGMAP_I2C if I2C
|
||||
select REGMAP_SPI if SPI_MASTER
|
||||
help
|
||||
If you say yes here you get support for Dallas Semiconductor
|
||||
DS3232 and DS3234 real-time clock chips. If an interrupt is associated
|
||||
|
@ -876,6 +880,8 @@ config RTC_DRV_DS3232_HWMON
|
|||
config RTC_DRV_PCF2127
|
||||
tristate "NXP PCF2127"
|
||||
depends on RTC_I2C_AND_SPI
|
||||
select REGMAP_I2C if I2C
|
||||
select REGMAP_SPI if SPI_MASTER
|
||||
select WATCHDOG_CORE if WATCHDOG
|
||||
help
|
||||
If you say yes here you get support for the NXP PCF2127/29 RTC
|
||||
|
@ -892,6 +898,8 @@ config RTC_DRV_PCF2127
|
|||
config RTC_DRV_RV3029C2
|
||||
tristate "Micro Crystal RV3029/3049"
|
||||
depends on RTC_I2C_AND_SPI
|
||||
select REGMAP_I2C if I2C
|
||||
select REGMAP_SPI if SPI_MASTER
|
||||
help
|
||||
If you say yes here you get support for the Micro Crystal
|
||||
RV3029 and RV3049 RTC chips.
|
||||
|
|
|
@ -523,12 +523,9 @@ static int abx80x_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
|
|||
if (status < 0)
|
||||
return status;
|
||||
|
||||
tmp = !!(status & ABX8XX_STATUS_BLF);
|
||||
tmp = status & ABX8XX_STATUS_BLF ? RTC_VL_BACKUP_LOW : 0;
|
||||
|
||||
if (copy_to_user((void __user *)arg, &tmp, sizeof(int)))
|
||||
return -EFAULT;
|
||||
|
||||
return 0;
|
||||
return put_user(tmp, (unsigned int __user *)arg);
|
||||
|
||||
case RTC_VL_CLR:
|
||||
status = i2c_smbus_read_byte_data(client, ABX8XX_REG_STATUS);
|
||||
|
|
|
@ -264,6 +264,9 @@ static int asm9260_rtc_probe(struct platform_device *pdev)
|
|||
return PTR_ERR(priv->iobase);
|
||||
|
||||
priv->clk = devm_clk_get(dev, "ahb");
|
||||
if (IS_ERR(priv->clk))
|
||||
return PTR_ERR(priv->clk);
|
||||
|
||||
ret = clk_prepare_enable(priv->clk);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to enable clk!\n");
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
*/
|
||||
|
||||
#include <linux/bcd.h>
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/completion.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
@ -30,7 +31,51 @@
|
|||
#include <linux/time.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
#include "rtc-at91rm9200.h"
|
||||
#define AT91_RTC_CR 0x00 /* Control Register */
|
||||
#define AT91_RTC_UPDTIM BIT(0) /* Update Request Time Register */
|
||||
#define AT91_RTC_UPDCAL BIT(1) /* Update Request Calendar Register */
|
||||
|
||||
#define AT91_RTC_MR 0x04 /* Mode Register */
|
||||
|
||||
#define AT91_RTC_TIMR 0x08 /* Time Register */
|
||||
#define AT91_RTC_SEC GENMASK(6, 0) /* Current Second */
|
||||
#define AT91_RTC_MIN GENMASK(14, 8) /* Current Minute */
|
||||
#define AT91_RTC_HOUR GENMASK(21, 16) /* Current Hour */
|
||||
#define AT91_RTC_AMPM BIT(22) /* Ante Meridiem Post Meridiem Indicator */
|
||||
|
||||
#define AT91_RTC_CALR 0x0c /* Calendar Register */
|
||||
#define AT91_RTC_CENT GENMASK(6, 0) /* Current Century */
|
||||
#define AT91_RTC_YEAR GENMASK(15, 8) /* Current Year */
|
||||
#define AT91_RTC_MONTH GENMASK(20, 16) /* Current Month */
|
||||
#define AT91_RTC_DAY GENMASK(23, 21) /* Current Day */
|
||||
#define AT91_RTC_DATE GENMASK(29, 24) /* Current Date */
|
||||
|
||||
#define AT91_RTC_TIMALR 0x10 /* Time Alarm Register */
|
||||
#define AT91_RTC_SECEN BIT(7) /* Second Alarm Enable */
|
||||
#define AT91_RTC_MINEN BIT(15) /* Minute Alarm Enable */
|
||||
#define AT91_RTC_HOUREN BIT(23) /* Hour Alarm Enable */
|
||||
|
||||
#define AT91_RTC_CALALR 0x14 /* Calendar Alarm Register */
|
||||
#define AT91_RTC_MTHEN BIT(23) /* Month Alarm Enable */
|
||||
#define AT91_RTC_DATEEN BIT(31) /* Date Alarm Enable */
|
||||
|
||||
#define AT91_RTC_SR 0x18 /* Status Register */
|
||||
#define AT91_RTC_ACKUPD BIT(0) /* Acknowledge for Update */
|
||||
#define AT91_RTC_ALARM BIT(1) /* Alarm Flag */
|
||||
#define AT91_RTC_SECEV BIT(2) /* Second Event */
|
||||
#define AT91_RTC_TIMEV BIT(3) /* Time Event */
|
||||
#define AT91_RTC_CALEV BIT(4) /* Calendar Event */
|
||||
|
||||
#define AT91_RTC_SCCR 0x1c /* Status Clear Command Register */
|
||||
#define AT91_RTC_IER 0x20 /* Interrupt Enable Register */
|
||||
#define AT91_RTC_IDR 0x24 /* Interrupt Disable Register */
|
||||
#define AT91_RTC_IMR 0x28 /* Interrupt Mask Register */
|
||||
|
||||
#define AT91_RTC_VER 0x2c /* Valid Entry Register */
|
||||
#define AT91_RTC_NVTIM BIT(0) /* Non valid Time */
|
||||
#define AT91_RTC_NVCAL BIT(1) /* Non valid Calendar */
|
||||
#define AT91_RTC_NVTIMALR BIT(2) /* Non valid Time Alarm */
|
||||
#define AT91_RTC_NVCALALR BIT(3) /* Non valid Calendar Alarm */
|
||||
|
||||
#define at91_rtc_read(field) \
|
||||
readl_relaxed(at91_rtc_regs + field)
|
||||
|
@ -117,20 +162,20 @@ static void at91_rtc_decodetime(unsigned int timereg, unsigned int calreg,
|
|||
} while ((time != at91_rtc_read(timereg)) ||
|
||||
(date != at91_rtc_read(calreg)));
|
||||
|
||||
tm->tm_sec = bcd2bin((time & AT91_RTC_SEC) >> 0);
|
||||
tm->tm_min = bcd2bin((time & AT91_RTC_MIN) >> 8);
|
||||
tm->tm_hour = bcd2bin((time & AT91_RTC_HOUR) >> 16);
|
||||
tm->tm_sec = bcd2bin(FIELD_GET(AT91_RTC_SEC, time));
|
||||
tm->tm_min = bcd2bin(FIELD_GET(AT91_RTC_MIN, time));
|
||||
tm->tm_hour = bcd2bin(FIELD_GET(AT91_RTC_HOUR, time));
|
||||
|
||||
/*
|
||||
* The Calendar Alarm register does not have a field for
|
||||
* the year - so these will return an invalid value.
|
||||
*/
|
||||
tm->tm_year = bcd2bin(date & AT91_RTC_CENT) * 100; /* century */
|
||||
tm->tm_year += bcd2bin((date & AT91_RTC_YEAR) >> 8); /* year */
|
||||
tm->tm_year += bcd2bin(FIELD_GET(AT91_RTC_YEAR, date)); /* year */
|
||||
|
||||
tm->tm_wday = bcd2bin((date & AT91_RTC_DAY) >> 21) - 1; /* day of the week [0-6], Sunday=0 */
|
||||
tm->tm_mon = bcd2bin((date & AT91_RTC_MONTH) >> 16) - 1;
|
||||
tm->tm_mday = bcd2bin((date & AT91_RTC_DATE) >> 24);
|
||||
tm->tm_wday = bcd2bin(FIELD_GET(AT91_RTC_DAY, date)) - 1; /* day of the week [0-6], Sunday=0 */
|
||||
tm->tm_mon = bcd2bin(FIELD_GET(AT91_RTC_MONTH, date)) - 1;
|
||||
tm->tm_mday = bcd2bin(FIELD_GET(AT91_RTC_DATE, date));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -167,16 +212,17 @@ static int at91_rtc_settime(struct device *dev, struct rtc_time *tm)
|
|||
at91_rtc_write_idr(AT91_RTC_ACKUPD);
|
||||
|
||||
at91_rtc_write(AT91_RTC_TIMR,
|
||||
bin2bcd(tm->tm_sec) << 0
|
||||
| bin2bcd(tm->tm_min) << 8
|
||||
| bin2bcd(tm->tm_hour) << 16);
|
||||
FIELD_PREP(AT91_RTC_SEC, bin2bcd(tm->tm_sec))
|
||||
| FIELD_PREP(AT91_RTC_MIN, bin2bcd(tm->tm_min))
|
||||
| FIELD_PREP(AT91_RTC_HOUR, bin2bcd(tm->tm_hour)));
|
||||
|
||||
at91_rtc_write(AT91_RTC_CALR,
|
||||
bin2bcd((tm->tm_year + 1900) / 100) /* century */
|
||||
| bin2bcd(tm->tm_year % 100) << 8 /* year */
|
||||
| bin2bcd(tm->tm_mon + 1) << 16 /* tm_mon starts at zero */
|
||||
| bin2bcd(tm->tm_wday + 1) << 21 /* day of the week [0-6], Sunday=0 */
|
||||
| bin2bcd(tm->tm_mday) << 24);
|
||||
FIELD_PREP(AT91_RTC_CENT,
|
||||
bin2bcd((tm->tm_year + 1900) / 100))
|
||||
| FIELD_PREP(AT91_RTC_YEAR, bin2bcd(tm->tm_year % 100))
|
||||
| FIELD_PREP(AT91_RTC_MONTH, bin2bcd(tm->tm_mon + 1))
|
||||
| FIELD_PREP(AT91_RTC_DAY, bin2bcd(tm->tm_wday + 1))
|
||||
| FIELD_PREP(AT91_RTC_DATE, bin2bcd(tm->tm_mday)));
|
||||
|
||||
/* Restart Time/Calendar */
|
||||
cr = at91_rtc_read(AT91_RTC_CR);
|
||||
|
@ -211,25 +257,17 @@ static int at91_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm)
|
|||
*/
|
||||
static int at91_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
|
||||
{
|
||||
struct rtc_time tm;
|
||||
|
||||
at91_rtc_decodetime(AT91_RTC_TIMR, AT91_RTC_CALR, &tm);
|
||||
|
||||
tm.tm_mon = alrm->time.tm_mon;
|
||||
tm.tm_mday = alrm->time.tm_mday;
|
||||
tm.tm_hour = alrm->time.tm_hour;
|
||||
tm.tm_min = alrm->time.tm_min;
|
||||
tm.tm_sec = alrm->time.tm_sec;
|
||||
struct rtc_time tm = alrm->time;
|
||||
|
||||
at91_rtc_write_idr(AT91_RTC_ALARM);
|
||||
at91_rtc_write(AT91_RTC_TIMALR,
|
||||
bin2bcd(tm.tm_sec) << 0
|
||||
| bin2bcd(tm.tm_min) << 8
|
||||
| bin2bcd(tm.tm_hour) << 16
|
||||
FIELD_PREP(AT91_RTC_SEC, bin2bcd(alrm->time.tm_sec))
|
||||
| FIELD_PREP(AT91_RTC_MIN, bin2bcd(alrm->time.tm_min))
|
||||
| FIELD_PREP(AT91_RTC_HOUR, bin2bcd(alrm->time.tm_hour))
|
||||
| AT91_RTC_HOUREN | AT91_RTC_MINEN | AT91_RTC_SECEN);
|
||||
at91_rtc_write(AT91_RTC_CALALR,
|
||||
bin2bcd(tm.tm_mon + 1) << 16 /* tm_mon starts at zero */
|
||||
| bin2bcd(tm.tm_mday) << 24
|
||||
FIELD_PREP(AT91_RTC_MONTH, bin2bcd(alrm->time.tm_mon + 1))
|
||||
| FIELD_PREP(AT91_RTC_DATE, bin2bcd(alrm->time.tm_mday))
|
||||
| AT91_RTC_DATEEN | AT91_RTC_MTHEN);
|
||||
|
||||
if (alrm->enabled) {
|
||||
|
@ -254,20 +292,6 @@ static int at91_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
|
|||
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* Provide additional RTC information in /proc/driver/rtc
|
||||
*/
|
||||
static int at91_rtc_proc(struct device *dev, struct seq_file *seq)
|
||||
{
|
||||
unsigned long imr = at91_rtc_read_imr();
|
||||
|
||||
seq_printf(seq, "update_IRQ\t: %s\n",
|
||||
(imr & AT91_RTC_ACKUPD) ? "yes" : "no");
|
||||
seq_printf(seq, "periodic_IRQ\t: %s\n",
|
||||
(imr & AT91_RTC_SECEV) ? "yes" : "no");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* IRQ handler for the RTC
|
||||
|
@ -326,6 +350,12 @@ static const struct of_device_id at91_rtc_dt_ids[] = {
|
|||
}, {
|
||||
.compatible = "atmel,at91sam9x5-rtc",
|
||||
.data = &at91sam9x5_config,
|
||||
}, {
|
||||
.compatible = "atmel,sama5d4-rtc",
|
||||
.data = &at91rm9200_config,
|
||||
}, {
|
||||
.compatible = "atmel,sama5d2-rtc",
|
||||
.data = &at91rm9200_config,
|
||||
}, {
|
||||
/* sentinel */
|
||||
}
|
||||
|
@ -337,7 +367,6 @@ static const struct rtc_class_ops at91_rtc_ops = {
|
|||
.set_time = at91_rtc_settime,
|
||||
.read_alarm = at91_rtc_readalarm,
|
||||
.set_alarm = at91_rtc_setalarm,
|
||||
.proc = at91_rtc_proc,
|
||||
.alarm_irq_enable = at91_rtc_alarm_irq_enable,
|
||||
};
|
||||
|
||||
|
|
|
@ -1,71 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* arch/arm/mach-at91/include/mach/at91_rtc.h
|
||||
*
|
||||
* Copyright (C) 2005 Ivan Kokshaysky
|
||||
* Copyright (C) SAN People
|
||||
*
|
||||
* Real Time Clock (RTC) - System peripheral registers.
|
||||
* Based on AT91RM9200 datasheet revision E.
|
||||
*/
|
||||
|
||||
#ifndef AT91_RTC_H
|
||||
#define AT91_RTC_H
|
||||
|
||||
#define AT91_RTC_CR 0x00 /* Control Register */
|
||||
#define AT91_RTC_UPDTIM (1 << 0) /* Update Request Time Register */
|
||||
#define AT91_RTC_UPDCAL (1 << 1) /* Update Request Calendar Register */
|
||||
#define AT91_RTC_TIMEVSEL (3 << 8) /* Time Event Selection */
|
||||
#define AT91_RTC_TIMEVSEL_MINUTE (0 << 8)
|
||||
#define AT91_RTC_TIMEVSEL_HOUR (1 << 8)
|
||||
#define AT91_RTC_TIMEVSEL_DAY24 (2 << 8)
|
||||
#define AT91_RTC_TIMEVSEL_DAY12 (3 << 8)
|
||||
#define AT91_RTC_CALEVSEL (3 << 16) /* Calendar Event Selection */
|
||||
#define AT91_RTC_CALEVSEL_WEEK (0 << 16)
|
||||
#define AT91_RTC_CALEVSEL_MONTH (1 << 16)
|
||||
#define AT91_RTC_CALEVSEL_YEAR (2 << 16)
|
||||
|
||||
#define AT91_RTC_MR 0x04 /* Mode Register */
|
||||
#define AT91_RTC_HRMOD (1 << 0) /* 12/24 Hour Mode */
|
||||
|
||||
#define AT91_RTC_TIMR 0x08 /* Time Register */
|
||||
#define AT91_RTC_SEC (0x7f << 0) /* Current Second */
|
||||
#define AT91_RTC_MIN (0x7f << 8) /* Current Minute */
|
||||
#define AT91_RTC_HOUR (0x3f << 16) /* Current Hour */
|
||||
#define AT91_RTC_AMPM (1 << 22) /* Ante Meridiem Post Meridiem Indicator */
|
||||
|
||||
#define AT91_RTC_CALR 0x0c /* Calendar Register */
|
||||
#define AT91_RTC_CENT (0x7f << 0) /* Current Century */
|
||||
#define AT91_RTC_YEAR (0xff << 8) /* Current Year */
|
||||
#define AT91_RTC_MONTH (0x1f << 16) /* Current Month */
|
||||
#define AT91_RTC_DAY (7 << 21) /* Current Day */
|
||||
#define AT91_RTC_DATE (0x3f << 24) /* Current Date */
|
||||
|
||||
#define AT91_RTC_TIMALR 0x10 /* Time Alarm Register */
|
||||
#define AT91_RTC_SECEN (1 << 7) /* Second Alarm Enable */
|
||||
#define AT91_RTC_MINEN (1 << 15) /* Minute Alarm Enable */
|
||||
#define AT91_RTC_HOUREN (1 << 23) /* Hour Alarm Enable */
|
||||
|
||||
#define AT91_RTC_CALALR 0x14 /* Calendar Alarm Register */
|
||||
#define AT91_RTC_MTHEN (1 << 23) /* Month Alarm Enable */
|
||||
#define AT91_RTC_DATEEN (1 << 31) /* Date Alarm Enable */
|
||||
|
||||
#define AT91_RTC_SR 0x18 /* Status Register */
|
||||
#define AT91_RTC_ACKUPD (1 << 0) /* Acknowledge for Update */
|
||||
#define AT91_RTC_ALARM (1 << 1) /* Alarm Flag */
|
||||
#define AT91_RTC_SECEV (1 << 2) /* Second Event */
|
||||
#define AT91_RTC_TIMEV (1 << 3) /* Time Event */
|
||||
#define AT91_RTC_CALEV (1 << 4) /* Calendar Event */
|
||||
|
||||
#define AT91_RTC_SCCR 0x1c /* Status Clear Command Register */
|
||||
#define AT91_RTC_IER 0x20 /* Interrupt Enable Register */
|
||||
#define AT91_RTC_IDR 0x24 /* Interrupt Disable Register */
|
||||
#define AT91_RTC_IMR 0x28 /* Interrupt Mask Register */
|
||||
|
||||
#define AT91_RTC_VER 0x2c /* Valid Entry Register */
|
||||
#define AT91_RTC_NVTIM (1 << 0) /* Non valid Time */
|
||||
#define AT91_RTC_NVCAL (1 << 1) /* Non valid Calendar */
|
||||
#define AT91_RTC_NVTIMALR (1 << 2) /* Non valid Time Alarm */
|
||||
#define AT91_RTC_NVCALALR (1 << 3) /* Non valid Calendar Alarm */
|
||||
|
||||
#endif
|
|
@ -850,7 +850,7 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
|
|||
rtc_cmos_int_handler = cmos_interrupt;
|
||||
|
||||
retval = request_irq(rtc_irq, rtc_cmos_int_handler,
|
||||
IRQF_SHARED, dev_name(&cmos_rtc.rtc->dev),
|
||||
0, dev_name(&cmos_rtc.rtc->dev),
|
||||
cmos_rtc.rtc);
|
||||
if (retval < 0) {
|
||||
dev_dbg(dev, "IRQ %d is already in use\n", rtc_irq);
|
||||
|
@ -1197,8 +1197,6 @@ static void rtc_wake_off(struct device *dev)
|
|||
/* Enable use_acpi_alarm mode for Intel platforms no earlier than 2015 */
|
||||
static void use_acpi_alarm_quirks(void)
|
||||
{
|
||||
int year;
|
||||
|
||||
if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL)
|
||||
return;
|
||||
|
||||
|
@ -1208,8 +1206,10 @@ static void use_acpi_alarm_quirks(void)
|
|||
if (!is_hpet_enabled())
|
||||
return;
|
||||
|
||||
if (dmi_get_date(DMI_BIOS_DATE, &year, NULL, NULL) && year >= 2015)
|
||||
use_acpi_alarm = true;
|
||||
if (dmi_get_bios_year() < 2015)
|
||||
return;
|
||||
|
||||
use_acpi_alarm = true;
|
||||
}
|
||||
#else
|
||||
static inline void use_acpi_alarm_quirks(void) { }
|
||||
|
@ -1305,7 +1305,7 @@ static int cmos_pnp_probe(struct pnp_dev *pnp, const struct pnp_device_id *id)
|
|||
* hardcode it on systems with a legacy PIC.
|
||||
*/
|
||||
if (nr_legacy_irqs())
|
||||
irq = 8;
|
||||
irq = RTC_IRQ;
|
||||
#endif
|
||||
return cmos_do_probe(&pnp->dev,
|
||||
pnp_get_resource(pnp, IORESOURCE_IO, 0), irq);
|
||||
|
|
|
@ -75,7 +75,6 @@ static const struct spi_device_id ds1343_id[] = {
|
|||
MODULE_DEVICE_TABLE(spi, ds1343_id);
|
||||
|
||||
struct ds1343_priv {
|
||||
struct spi_device *spi;
|
||||
struct rtc_device *rtc;
|
||||
struct regmap *map;
|
||||
int irq;
|
||||
|
@ -362,12 +361,13 @@ static int ds1343_probe(struct spi_device *spi)
|
|||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
priv->spi = spi;
|
||||
|
||||
/* RTC DS1347 works in spi mode 3 and
|
||||
* its chip select is active high
|
||||
* its chip select is active high. Active high should be defined as
|
||||
* "inverse polarity" as GPIO-based chip selects can be logically
|
||||
* active high but inverted by the GPIO library.
|
||||
*/
|
||||
spi->mode = SPI_MODE_3 | SPI_CS_HIGH;
|
||||
spi->mode |= SPI_MODE_3;
|
||||
spi->mode ^= SPI_CS_HIGH;
|
||||
spi->bits_per_word = 8;
|
||||
res = spi_setup(spi);
|
||||
if (res)
|
||||
|
|
|
@ -78,7 +78,6 @@
|
|||
struct hym8563 {
|
||||
struct i2c_client *client;
|
||||
struct rtc_device *rtc;
|
||||
bool valid;
|
||||
#ifdef CONFIG_COMMON_CLK
|
||||
struct clk_hw clkout_hw;
|
||||
#endif
|
||||
|
@ -91,19 +90,19 @@ struct hym8563 {
|
|||
static int hym8563_rtc_read_time(struct device *dev, struct rtc_time *tm)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct hym8563 *hym8563 = i2c_get_clientdata(client);
|
||||
u8 buf[7];
|
||||
int ret;
|
||||
|
||||
if (!hym8563->valid) {
|
||||
dev_warn(&client->dev, "no valid clock/calendar values available\n");
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
ret = i2c_smbus_read_i2c_block_data(client, HYM8563_SEC, 7, buf);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (buf[0] & HYM8563_SEC_VL) {
|
||||
dev_warn(&client->dev,
|
||||
"no valid clock/calendar values available\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
tm->tm_sec = bcd2bin(buf[0] & HYM8563_SEC_MASK);
|
||||
tm->tm_min = bcd2bin(buf[1] & HYM8563_MIN_MASK);
|
||||
tm->tm_hour = bcd2bin(buf[2] & HYM8563_HOUR_MASK);
|
||||
|
@ -118,7 +117,6 @@ static int hym8563_rtc_read_time(struct device *dev, struct rtc_time *tm)
|
|||
static int hym8563_rtc_set_time(struct device *dev, struct rtc_time *tm)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct hym8563 *hym8563 = i2c_get_clientdata(client);
|
||||
u8 buf[7];
|
||||
int ret;
|
||||
|
||||
|
@ -157,8 +155,6 @@ static int hym8563_rtc_set_time(struct device *dev, struct rtc_time *tm)
|
|||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
hym8563->valid = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -556,9 +552,8 @@ static int hym8563_probe(struct i2c_client *client,
|
|||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
hym8563->valid = !(ret & HYM8563_SEC_VL);
|
||||
dev_dbg(&client->dev, "rtc information is %s\n",
|
||||
hym8563->valid ? "valid" : "invalid");
|
||||
(ret & HYM8563_SEC_VL) ? "invalid" : "valid");
|
||||
|
||||
hym8563->rtc = devm_rtc_device_register(&client->dev, client->name,
|
||||
&hym8563_rtc_ops, THIS_MODULE);
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* MOXA ART RTC driver.
|
||||
*
|
||||
|
@ -7,10 +8,6 @@
|
|||
*
|
||||
* Based on code from
|
||||
* Moxa Technology Co., Ltd. <www.moxa.com>
|
||||
*
|
||||
* This file is licensed under the terms of the GNU General Public
|
||||
* License version 2. This program is licensed "as is" without any
|
||||
* warranty of any kind, whether express or implied.
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
|
|
|
@ -297,15 +297,7 @@ static int mtk_rtc_probe(struct platform_device *pdev)
|
|||
|
||||
rtc->rtc_dev->ops = &mtk_rtc_ops;
|
||||
|
||||
ret = rtc_register_device(rtc->rtc_dev);
|
||||
if (ret)
|
||||
goto out_free_irq;
|
||||
|
||||
return 0;
|
||||
|
||||
out_free_irq:
|
||||
free_irq(rtc->irq, rtc);
|
||||
return ret;
|
||||
return rtc_register_device(rtc->rtc_dev);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
|
|
|
@ -616,7 +616,7 @@ static int rtc_pinconf_get(struct pinctrl_dev *pctldev,
|
|||
break;
|
||||
default:
|
||||
return -ENOTSUPP;
|
||||
};
|
||||
}
|
||||
|
||||
*config = pinconf_to_config_packed(param, arg);
|
||||
|
||||
|
|
|
@ -199,11 +199,9 @@ static int pcf2127_rtc_ioctl(struct device *dev,
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
touser = touser & PCF2127_BIT_CTRL3_BLF ? 1 : 0;
|
||||
touser = touser & PCF2127_BIT_CTRL3_BLF ? RTC_VL_BACKUP_LOW : 0;
|
||||
|
||||
if (copy_to_user((void __user *)arg, &touser, sizeof(int)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
return put_user(touser, (unsigned int __user *)arg);
|
||||
default:
|
||||
return -ENOIOCTLCMD;
|
||||
}
|
||||
|
|
|
@ -289,21 +289,9 @@ static int pcf85063_ioctl(struct device *dev, unsigned int cmd,
|
|||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (status & PCF85063_REG_SC_OS)
|
||||
dev_warn(&pcf85063->rtc->dev, "Voltage low, data loss detected.\n");
|
||||
status = status & PCF85063_REG_SC_OS ? RTC_VL_DATA_INVALID : 0;
|
||||
|
||||
status &= PCF85063_REG_SC_OS;
|
||||
|
||||
if (copy_to_user((void __user *)arg, &status, sizeof(int)))
|
||||
return -EFAULT;
|
||||
|
||||
return 0;
|
||||
|
||||
case RTC_VL_CLR:
|
||||
ret = regmap_update_bits(pcf85063->regmap, PCF85063_REG_SC,
|
||||
PCF85063_REG_SC_OS, 0);
|
||||
|
||||
return ret;
|
||||
return put_user(status, (unsigned int __user *)arg);
|
||||
|
||||
default:
|
||||
return -ENOIOCTLCMD;
|
||||
|
|
|
@ -282,11 +282,11 @@ static int pcf8523_rtc_ioctl(struct device *dev, unsigned int cmd,
|
|||
ret = pcf8523_voltage_low(client);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (ret)
|
||||
ret = RTC_VL_BACKUP_LOW;
|
||||
|
||||
if (copy_to_user((void __user *)arg, &ret, sizeof(int)))
|
||||
return -EFAULT;
|
||||
return put_user(ret, (unsigned int __user *)arg);
|
||||
|
||||
return 0;
|
||||
default:
|
||||
return -ENOIOCTLCMD;
|
||||
}
|
||||
|
|
|
@ -22,8 +22,8 @@
|
|||
|
||||
#define PCF8563_REG_ST1 0x00 /* status */
|
||||
#define PCF8563_REG_ST2 0x01
|
||||
#define PCF8563_BIT_AIE (1 << 1)
|
||||
#define PCF8563_BIT_AF (1 << 3)
|
||||
#define PCF8563_BIT_AIE BIT(1)
|
||||
#define PCF8563_BIT_AF BIT(3)
|
||||
#define PCF8563_BITS_ST2_N (7 << 5)
|
||||
|
||||
#define PCF8563_REG_SC 0x02 /* datetime */
|
||||
|
@ -76,7 +76,6 @@ struct pcf8563 {
|
|||
* 1970...2069.
|
||||
*/
|
||||
int c_polarity; /* 0: MO_C=1 means 19xx, otherwise MO_C=1 means 20xx */
|
||||
int voltage_low; /* incicates if a low_voltage was detected */
|
||||
|
||||
struct i2c_client *client;
|
||||
#ifdef CONFIG_COMMON_CLK
|
||||
|
@ -208,7 +207,6 @@ static int pcf8563_rtc_read_time(struct device *dev, struct rtc_time *tm)
|
|||
return err;
|
||||
|
||||
if (buf[PCF8563_REG_SC] & PCF8563_SC_LV) {
|
||||
pcf8563->voltage_low = 1;
|
||||
dev_err(&client->dev,
|
||||
"low voltage detected, date/time is not reliable.\n");
|
||||
return -EINVAL;
|
||||
|
@ -276,43 +274,23 @@ static int pcf8563_rtc_set_time(struct device *dev, struct rtc_time *tm)
|
|||
9 - PCF8563_REG_SC, buf + PCF8563_REG_SC);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_RTC_INTF_DEV
|
||||
static int pcf8563_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
struct pcf8563 *pcf8563 = i2c_get_clientdata(to_i2c_client(dev));
|
||||
struct rtc_time tm;
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
int ret;
|
||||
|
||||
switch (cmd) {
|
||||
case RTC_VL_READ:
|
||||
if (pcf8563->voltage_low)
|
||||
dev_info(dev, "low voltage detected, date/time is not reliable.\n");
|
||||
ret = i2c_smbus_read_byte_data(client, PCF8563_REG_SC);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (copy_to_user((void __user *)arg, &pcf8563->voltage_low,
|
||||
sizeof(int)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
case RTC_VL_CLR:
|
||||
/*
|
||||
* Clear the VL bit in the seconds register in case
|
||||
* the time has not been set already (which would
|
||||
* have cleared it). This does not really matter
|
||||
* because of the cached voltage_low value but do it
|
||||
* anyway for consistency.
|
||||
*/
|
||||
if (pcf8563_rtc_read_time(dev, &tm))
|
||||
pcf8563_rtc_set_time(dev, &tm);
|
||||
|
||||
/* Clear the cached value. */
|
||||
pcf8563->voltage_low = 0;
|
||||
|
||||
return 0;
|
||||
return put_user(ret & PCF8563_SC_LV ? RTC_VL_DATA_INVALID : 0,
|
||||
(unsigned int __user *)arg);
|
||||
default:
|
||||
return -ENOIOCTLCMD;
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define pcf8563_rtc_ioctl NULL
|
||||
#endif
|
||||
|
||||
static int pcf8563_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *tm)
|
||||
{
|
||||
|
|
|
@ -428,21 +428,8 @@ static int rv3028_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
|
|||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (status & RV3028_STATUS_PORF)
|
||||
dev_warn(&rv3028->rtc->dev, "Voltage low, data loss detected.\n");
|
||||
|
||||
status &= RV3028_STATUS_PORF;
|
||||
|
||||
if (copy_to_user((void __user *)arg, &status, sizeof(int)))
|
||||
return -EFAULT;
|
||||
|
||||
return 0;
|
||||
|
||||
case RTC_VL_CLR:
|
||||
ret = regmap_update_bits(rv3028->regmap, RV3028_STATUS,
|
||||
RV3028_STATUS_PORF, 0);
|
||||
|
||||
return ret;
|
||||
status = status & RV3028_STATUS_PORF ? RTC_VL_DATA_INVALID : 0;
|
||||
return put_user(status, (unsigned int __user *)arg);
|
||||
|
||||
default:
|
||||
return -ENOIOCTLCMD;
|
||||
|
|
|
@ -109,10 +109,8 @@
|
|||
#define RV3029_CONTROL_E2P_TOV_MASK 0x3F /* XTAL turnover temp mask */
|
||||
|
||||
/* user ram section */
|
||||
#define RV3029_USR1_RAM_PAGE 0x38
|
||||
#define RV3029_USR1_SECTION_LEN 0x04
|
||||
#define RV3029_USR2_RAM_PAGE 0x3C
|
||||
#define RV3029_USR2_SECTION_LEN 0x04
|
||||
#define RV3029_RAM_PAGE 0x38
|
||||
#define RV3029_RAM_SECTION_LEN 8
|
||||
|
||||
struct rv3029_data {
|
||||
struct device *dev;
|
||||
|
@ -121,77 +119,13 @@ struct rv3029_data {
|
|||
int irq;
|
||||
};
|
||||
|
||||
static int rv3029_read_regs(struct device *dev, u8 reg, u8 *buf,
|
||||
unsigned int len)
|
||||
{
|
||||
struct rv3029_data *rv3029 = dev_get_drvdata(dev);
|
||||
|
||||
if ((reg > RV3029_USR1_RAM_PAGE + 7) ||
|
||||
(reg + len > RV3029_USR1_RAM_PAGE + 8))
|
||||
return -EINVAL;
|
||||
|
||||
return regmap_bulk_read(rv3029->regmap, reg, buf, len);
|
||||
}
|
||||
|
||||
static int rv3029_write_regs(struct device *dev, u8 reg, u8 const buf[],
|
||||
unsigned int len)
|
||||
{
|
||||
struct rv3029_data *rv3029 = dev_get_drvdata(dev);
|
||||
|
||||
if ((reg > RV3029_USR1_RAM_PAGE + 7) ||
|
||||
(reg + len > RV3029_USR1_RAM_PAGE + 8))
|
||||
return -EINVAL;
|
||||
|
||||
return regmap_bulk_write(rv3029->regmap, reg, buf, len);
|
||||
}
|
||||
|
||||
static int rv3029_update_bits(struct device *dev, u8 reg, u8 mask, u8 set)
|
||||
{
|
||||
u8 buf;
|
||||
int ret;
|
||||
|
||||
ret = rv3029_read_regs(dev, reg, &buf, 1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
buf &= ~mask;
|
||||
buf |= set & mask;
|
||||
ret = rv3029_write_regs(dev, reg, &buf, 1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rv3029_get_sr(struct device *dev, u8 *buf)
|
||||
{
|
||||
int ret = rv3029_read_regs(dev, RV3029_STATUS, buf, 1);
|
||||
|
||||
if (ret < 0)
|
||||
return -EIO;
|
||||
dev_dbg(dev, "status = 0x%.2x (%d)\n", buf[0], buf[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rv3029_set_sr(struct device *dev, u8 val)
|
||||
{
|
||||
u8 buf[1];
|
||||
int sr;
|
||||
|
||||
buf[0] = val;
|
||||
sr = rv3029_write_regs(dev, RV3029_STATUS, buf, 1);
|
||||
dev_dbg(dev, "status = 0x%.2x (%d)\n", buf[0], buf[0]);
|
||||
if (sr < 0)
|
||||
return -EIO;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rv3029_eeprom_busywait(struct device *dev)
|
||||
static int rv3029_eeprom_busywait(struct rv3029_data *rv3029)
|
||||
{
|
||||
unsigned int sr;
|
||||
int i, ret;
|
||||
u8 sr;
|
||||
|
||||
for (i = 100; i > 0; i--) {
|
||||
ret = rv3029_get_sr(dev, &sr);
|
||||
ret = regmap_read(rv3029->regmap, RV3029_STATUS, &sr);
|
||||
if (ret < 0)
|
||||
break;
|
||||
if (!(sr & RV3029_STATUS_EEBUSY))
|
||||
|
@ -199,126 +133,128 @@ static int rv3029_eeprom_busywait(struct device *dev)
|
|||
usleep_range(1000, 10000);
|
||||
}
|
||||
if (i <= 0) {
|
||||
dev_err(dev, "EEPROM busy wait timeout.\n");
|
||||
dev_err(rv3029->dev, "EEPROM busy wait timeout.\n");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rv3029_eeprom_exit(struct device *dev)
|
||||
static int rv3029_eeprom_exit(struct rv3029_data *rv3029)
|
||||
{
|
||||
/* Re-enable eeprom refresh */
|
||||
return rv3029_update_bits(dev, RV3029_ONOFF_CTRL,
|
||||
return regmap_update_bits(rv3029->regmap, RV3029_ONOFF_CTRL,
|
||||
RV3029_ONOFF_CTRL_EERE,
|
||||
RV3029_ONOFF_CTRL_EERE);
|
||||
}
|
||||
|
||||
static int rv3029_eeprom_enter(struct device *dev)
|
||||
static int rv3029_eeprom_enter(struct rv3029_data *rv3029)
|
||||
{
|
||||
unsigned int sr;
|
||||
int ret;
|
||||
u8 sr;
|
||||
|
||||
/* Check whether we are in the allowed voltage range. */
|
||||
ret = rv3029_get_sr(dev, &sr);
|
||||
ret = regmap_read(rv3029->regmap, RV3029_STATUS, &sr);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (sr & (RV3029_STATUS_VLOW1 | RV3029_STATUS_VLOW2)) {
|
||||
if (sr & RV3029_STATUS_VLOW2)
|
||||
return -ENODEV;
|
||||
if (sr & RV3029_STATUS_VLOW1) {
|
||||
/* We clear the bits and retry once just in case
|
||||
* we had a brown out in early startup.
|
||||
*/
|
||||
sr &= ~RV3029_STATUS_VLOW1;
|
||||
sr &= ~RV3029_STATUS_VLOW2;
|
||||
ret = rv3029_set_sr(dev, sr);
|
||||
ret = regmap_update_bits(rv3029->regmap, RV3029_STATUS,
|
||||
RV3029_STATUS_VLOW1, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
usleep_range(1000, 10000);
|
||||
ret = rv3029_get_sr(dev, &sr);
|
||||
ret = regmap_read(rv3029->regmap, RV3029_STATUS, &sr);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (sr & (RV3029_STATUS_VLOW1 | RV3029_STATUS_VLOW2)) {
|
||||
dev_err(dev,
|
||||
if (sr & RV3029_STATUS_VLOW1) {
|
||||
dev_err(rv3029->dev,
|
||||
"Supply voltage is too low to safely access the EEPROM.\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable eeprom refresh. */
|
||||
ret = rv3029_update_bits(dev, RV3029_ONOFF_CTRL, RV3029_ONOFF_CTRL_EERE,
|
||||
0);
|
||||
ret = regmap_update_bits(rv3029->regmap, RV3029_ONOFF_CTRL,
|
||||
RV3029_ONOFF_CTRL_EERE, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Wait for any previous eeprom accesses to finish. */
|
||||
ret = rv3029_eeprom_busywait(dev);
|
||||
ret = rv3029_eeprom_busywait(rv3029);
|
||||
if (ret < 0)
|
||||
rv3029_eeprom_exit(dev);
|
||||
rv3029_eeprom_exit(rv3029);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rv3029_eeprom_read(struct device *dev, u8 reg,
|
||||
static int rv3029_eeprom_read(struct rv3029_data *rv3029, u8 reg,
|
||||
u8 buf[], size_t len)
|
||||
{
|
||||
int ret, err;
|
||||
|
||||
err = rv3029_eeprom_enter(dev);
|
||||
err = rv3029_eeprom_enter(rv3029);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
ret = rv3029_read_regs(dev, reg, buf, len);
|
||||
ret = regmap_bulk_read(rv3029->regmap, reg, buf, len);
|
||||
|
||||
err = rv3029_eeprom_exit(dev);
|
||||
err = rv3029_eeprom_exit(rv3029);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rv3029_eeprom_write(struct device *dev, u8 reg,
|
||||
static int rv3029_eeprom_write(struct rv3029_data *rv3029, u8 reg,
|
||||
u8 const buf[], size_t len)
|
||||
{
|
||||
unsigned int tmp;
|
||||
int ret, err;
|
||||
size_t i;
|
||||
u8 tmp;
|
||||
|
||||
err = rv3029_eeprom_enter(dev);
|
||||
err = rv3029_eeprom_enter(rv3029);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
for (i = 0; i < len; i++, reg++) {
|
||||
ret = rv3029_read_regs(dev, reg, &tmp, 1);
|
||||
ret = regmap_read(rv3029->regmap, reg, &tmp);
|
||||
if (ret < 0)
|
||||
break;
|
||||
if (tmp != buf[i]) {
|
||||
ret = rv3029_write_regs(dev, reg, &buf[i], 1);
|
||||
tmp = buf[i];
|
||||
ret = regmap_write(rv3029->regmap, reg, tmp);
|
||||
if (ret < 0)
|
||||
break;
|
||||
}
|
||||
ret = rv3029_eeprom_busywait(dev);
|
||||
ret = rv3029_eeprom_busywait(rv3029);
|
||||
if (ret < 0)
|
||||
break;
|
||||
}
|
||||
|
||||
err = rv3029_eeprom_exit(dev);
|
||||
err = rv3029_eeprom_exit(rv3029);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rv3029_eeprom_update_bits(struct device *dev,
|
||||
static int rv3029_eeprom_update_bits(struct rv3029_data *rv3029,
|
||||
u8 reg, u8 mask, u8 set)
|
||||
{
|
||||
u8 buf;
|
||||
int ret;
|
||||
|
||||
ret = rv3029_eeprom_read(dev, reg, &buf, 1);
|
||||
ret = rv3029_eeprom_read(rv3029, reg, &buf, 1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
buf &= ~mask;
|
||||
buf |= set & mask;
|
||||
ret = rv3029_eeprom_write(dev, reg, &buf, 1);
|
||||
ret = rv3029_eeprom_write(rv3029, reg, &buf, 1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
@ -330,20 +266,20 @@ static irqreturn_t rv3029_handle_irq(int irq, void *dev_id)
|
|||
struct device *dev = dev_id;
|
||||
struct rv3029_data *rv3029 = dev_get_drvdata(dev);
|
||||
struct mutex *lock = &rv3029->rtc->ops_lock;
|
||||
unsigned int flags, controls;
|
||||
unsigned long events = 0;
|
||||
u8 flags, controls;
|
||||
int ret;
|
||||
|
||||
mutex_lock(lock);
|
||||
|
||||
ret = rv3029_read_regs(dev, RV3029_IRQ_CTRL, &controls, 1);
|
||||
ret = regmap_read(rv3029->regmap, RV3029_IRQ_CTRL, &controls);
|
||||
if (ret) {
|
||||
dev_warn(dev, "Read IRQ Control Register error %d\n", ret);
|
||||
mutex_unlock(lock);
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
ret = rv3029_read_regs(dev, RV3029_IRQ_FLAGS, &flags, 1);
|
||||
ret = regmap_read(rv3029->regmap, RV3029_IRQ_FLAGS, &flags);
|
||||
if (ret) {
|
||||
dev_warn(dev, "Read IRQ Flags Register error %d\n", ret);
|
||||
mutex_unlock(lock);
|
||||
|
@ -358,8 +294,8 @@ static irqreturn_t rv3029_handle_irq(int irq, void *dev_id)
|
|||
|
||||
if (events) {
|
||||
rtc_update_irq(rv3029->rtc, 1, events);
|
||||
rv3029_write_regs(dev, RV3029_IRQ_FLAGS, &flags, 1);
|
||||
rv3029_write_regs(dev, RV3029_IRQ_CTRL, &controls, 1);
|
||||
regmap_write(rv3029->regmap, RV3029_IRQ_FLAGS, flags);
|
||||
regmap_write(rv3029->regmap, RV3029_IRQ_CTRL, controls);
|
||||
}
|
||||
mutex_unlock(lock);
|
||||
|
||||
|
@ -368,22 +304,22 @@ static irqreturn_t rv3029_handle_irq(int irq, void *dev_id)
|
|||
|
||||
static int rv3029_read_time(struct device *dev, struct rtc_time *tm)
|
||||
{
|
||||
u8 buf[1];
|
||||
struct rv3029_data *rv3029 = dev_get_drvdata(dev);
|
||||
unsigned int sr;
|
||||
int ret;
|
||||
u8 regs[RV3029_WATCH_SECTION_LEN] = { 0, };
|
||||
|
||||
ret = rv3029_get_sr(dev, buf);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "%s: reading SR failed\n", __func__);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
ret = rv3029_read_regs(dev, RV3029_W_SEC, regs,
|
||||
RV3029_WATCH_SECTION_LEN);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "%s: reading RTC section failed\n", __func__);
|
||||
ret = regmap_read(rv3029->regmap, RV3029_STATUS, &sr);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (sr & (RV3029_STATUS_VLOW2 | RV3029_STATUS_PON))
|
||||
return -EINVAL;
|
||||
|
||||
ret = regmap_bulk_read(rv3029->regmap, RV3029_W_SEC, regs,
|
||||
RV3029_WATCH_SECTION_LEN);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
tm->tm_sec = bcd2bin(regs[RV3029_W_SEC - RV3029_W_SEC]);
|
||||
tm->tm_min = bcd2bin(regs[RV3029_W_MINUTES - RV3029_W_SEC]);
|
||||
|
@ -411,34 +347,24 @@ static int rv3029_read_time(struct device *dev, struct rtc_time *tm)
|
|||
|
||||
static int rv3029_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
|
||||
{
|
||||
struct rv3029_data *rv3029 = dev_get_drvdata(dev);
|
||||
struct rtc_time *const tm = &alarm->time;
|
||||
unsigned int controls, flags;
|
||||
int ret;
|
||||
u8 regs[8], controls, flags;
|
||||
u8 regs[8];
|
||||
|
||||
ret = rv3029_get_sr(dev, regs);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "%s: reading SR failed\n", __func__);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
ret = rv3029_read_regs(dev, RV3029_A_SC, regs,
|
||||
ret = regmap_bulk_read(rv3029->regmap, RV3029_A_SC, regs,
|
||||
RV3029_ALARM_SECTION_LEN);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "%s: reading alarm section failed\n", __func__);
|
||||
ret = regmap_read(rv3029->regmap, RV3029_IRQ_CTRL, &controls);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = rv3029_read_regs(dev, RV3029_IRQ_CTRL, &controls, 1);
|
||||
if (ret) {
|
||||
dev_err(dev, "Read IRQ Control Register error %d\n", ret);
|
||||
ret = regmap_read(rv3029->regmap, RV3029_IRQ_FLAGS, &flags);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
ret = rv3029_read_regs(dev, RV3029_IRQ_FLAGS, &flags, 1);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Read IRQ Flags Register error %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
tm->tm_sec = bcd2bin(regs[RV3029_A_SC - RV3029_A_SC] & 0x7f);
|
||||
tm->tm_min = bcd2bin(regs[RV3029_A_MN - RV3029_A_SC] & 0x7f);
|
||||
|
@ -456,50 +382,20 @@ static int rv3029_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
|
|||
|
||||
static int rv3029_alarm_irq_enable(struct device *dev, unsigned int enable)
|
||||
{
|
||||
int ret;
|
||||
u8 controls;
|
||||
struct rv3029_data *rv3029 = dev_get_drvdata(dev);
|
||||
|
||||
ret = rv3029_read_regs(dev, RV3029_IRQ_CTRL, &controls, 1);
|
||||
if (ret < 0) {
|
||||
dev_warn(dev, "Read IRQ Control Register error %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* enable/disable AIE irq */
|
||||
if (enable)
|
||||
controls |= RV3029_IRQ_CTRL_AIE;
|
||||
else
|
||||
controls &= ~RV3029_IRQ_CTRL_AIE;
|
||||
|
||||
ret = rv3029_write_regs(dev, RV3029_IRQ_CTRL, &controls, 1);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "can't update INT reg\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return regmap_update_bits(rv3029->regmap, RV3029_IRQ_CTRL,
|
||||
RV3029_IRQ_CTRL_AIE,
|
||||
enable ? RV3029_IRQ_CTRL_AIE : 0);
|
||||
}
|
||||
|
||||
static int rv3029_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
|
||||
{
|
||||
struct rv3029_data *rv3029 = dev_get_drvdata(dev);
|
||||
struct rtc_time *const tm = &alarm->time;
|
||||
int ret;
|
||||
u8 regs[8];
|
||||
|
||||
/*
|
||||
* The clock has an 8 bit wide bcd-coded register (they never learn)
|
||||
* for the year. tm_year is an offset from 1900 and we are interested
|
||||
* in the 2000-2099 range, so any value less than 100 is invalid.
|
||||
*/
|
||||
if (tm->tm_year < 100)
|
||||
return -EINVAL;
|
||||
|
||||
ret = rv3029_get_sr(dev, regs);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "%s: reading SR failed\n", __func__);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* Activate all the alarms with AE_x bit */
|
||||
regs[RV3029_A_SC - RV3029_A_SC] = bin2bcd(tm->tm_sec) | RV3029_A_AE_X;
|
||||
regs[RV3029_A_MN - RV3029_A_SC] = bin2bcd(tm->tm_min) | RV3029_A_AE_X;
|
||||
|
@ -515,39 +411,20 @@ static int rv3029_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
|
|||
| RV3029_A_AE_X;
|
||||
|
||||
/* Write the alarm */
|
||||
ret = rv3029_write_regs(dev, RV3029_A_SC, regs,
|
||||
ret = regmap_bulk_write(rv3029->regmap, RV3029_A_SC, regs,
|
||||
RV3029_ALARM_SECTION_LEN);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (alarm->enabled) {
|
||||
/* enable AIE irq */
|
||||
ret = rv3029_alarm_irq_enable(dev, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
} else {
|
||||
/* disable AIE irq */
|
||||
ret = rv3029_alarm_irq_enable(dev, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return rv3029_alarm_irq_enable(dev, alarm->enabled);
|
||||
}
|
||||
|
||||
static int rv3029_set_time(struct device *dev, struct rtc_time *tm)
|
||||
{
|
||||
struct rv3029_data *rv3029 = dev_get_drvdata(dev);
|
||||
u8 regs[8];
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* The clock has an 8 bit wide bcd-coded register (they never learn)
|
||||
* for the year. tm_year is an offset from 1900 and we are interested
|
||||
* in the 2000-2099 range, so any value less than 100 is invalid.
|
||||
*/
|
||||
if (tm->tm_year < 100)
|
||||
return -EINVAL;
|
||||
|
||||
regs[RV3029_W_SEC - RV3029_W_SEC] = bin2bcd(tm->tm_sec);
|
||||
regs[RV3029_W_MINUTES - RV3029_W_SEC] = bin2bcd(tm->tm_min);
|
||||
regs[RV3029_W_HOURS - RV3029_W_SEC] = bin2bcd(tm->tm_hour);
|
||||
|
@ -556,24 +433,55 @@ static int rv3029_set_time(struct device *dev, struct rtc_time *tm)
|
|||
regs[RV3029_W_DAYS - RV3029_W_SEC] = bin2bcd(tm->tm_wday + 1) & 0x7;
|
||||
regs[RV3029_W_YEARS - RV3029_W_SEC] = bin2bcd(tm->tm_year - 100);
|
||||
|
||||
ret = rv3029_write_regs(dev, RV3029_W_SEC, regs,
|
||||
ret = regmap_bulk_write(rv3029->regmap, RV3029_W_SEC, regs,
|
||||
RV3029_WATCH_SECTION_LEN);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = rv3029_get_sr(dev, regs);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "%s: reading SR failed\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
/* clear PON bit */
|
||||
ret = rv3029_set_sr(dev, (regs[0] & ~RV3029_STATUS_PON));
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "%s: reading SR failed\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
/* clear PON and VLOW2 bits */
|
||||
return regmap_update_bits(rv3029->regmap, RV3029_STATUS,
|
||||
RV3029_STATUS_PON | RV3029_STATUS_VLOW2, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
static int rv3029_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
struct rv3029_data *rv3029 = dev_get_drvdata(dev);
|
||||
unsigned long vl = 0;
|
||||
int sr, ret = 0;
|
||||
|
||||
switch (cmd) {
|
||||
case RTC_VL_READ:
|
||||
ret = regmap_read(rv3029->regmap, RV3029_STATUS, &sr);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (sr & RV3029_STATUS_VLOW1)
|
||||
vl = RTC_VL_ACCURACY_LOW;
|
||||
|
||||
if (sr & (RV3029_STATUS_VLOW2 | RV3029_STATUS_PON))
|
||||
vl |= RTC_VL_DATA_INVALID;
|
||||
|
||||
return put_user(vl, (unsigned int __user *)arg);
|
||||
|
||||
case RTC_VL_CLR:
|
||||
return regmap_update_bits(rv3029->regmap, RV3029_STATUS,
|
||||
RV3029_STATUS_VLOW1, 0);
|
||||
|
||||
default:
|
||||
return -ENOIOCTLCMD;
|
||||
}
|
||||
}
|
||||
|
||||
static int rv3029_nvram_write(void *priv, unsigned int offset, void *val,
|
||||
size_t bytes)
|
||||
{
|
||||
return regmap_bulk_write(priv, RV3029_RAM_PAGE + offset, val, bytes);
|
||||
}
|
||||
|
||||
static int rv3029_nvram_read(void *priv, unsigned int offset, void *val,
|
||||
size_t bytes)
|
||||
{
|
||||
return regmap_bulk_read(priv, RV3029_RAM_PAGE + offset, val, bytes);
|
||||
}
|
||||
|
||||
static const struct rv3029_trickle_tab_elem {
|
||||
|
@ -635,6 +543,7 @@ static const struct rv3029_trickle_tab_elem {
|
|||
|
||||
static void rv3029_trickle_config(struct device *dev)
|
||||
{
|
||||
struct rv3029_data *rv3029 = dev_get_drvdata(dev);
|
||||
struct device_node *of_node = dev->of_node;
|
||||
const struct rv3029_trickle_tab_elem *elem;
|
||||
int i, err;
|
||||
|
@ -661,7 +570,7 @@ static void rv3029_trickle_config(struct device *dev)
|
|||
"Trickle charger enabled at %d ohms resistance.\n",
|
||||
elem->r);
|
||||
}
|
||||
err = rv3029_eeprom_update_bits(dev, RV3029_CONTROL_E2P_EECTRL,
|
||||
err = rv3029_eeprom_update_bits(rv3029, RV3029_CONTROL_E2P_EECTRL,
|
||||
RV3029_TRICKLE_MASK,
|
||||
trickle_set_bits);
|
||||
if (err < 0)
|
||||
|
@ -670,12 +579,12 @@ static void rv3029_trickle_config(struct device *dev)
|
|||
|
||||
#ifdef CONFIG_RTC_DRV_RV3029_HWMON
|
||||
|
||||
static int rv3029_read_temp(struct device *dev, int *temp_mC)
|
||||
static int rv3029_read_temp(struct rv3029_data *rv3029, int *temp_mC)
|
||||
{
|
||||
unsigned int temp;
|
||||
int ret;
|
||||
u8 temp;
|
||||
|
||||
ret = rv3029_read_regs(dev, RV3029_TEMP_PAGE, &temp, 1);
|
||||
ret = regmap_read(rv3029->regmap, RV3029_TEMP_PAGE, &temp);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
@ -688,9 +597,10 @@ static ssize_t rv3029_hwmon_show_temp(struct device *dev,
|
|||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct rv3029_data *rv3029 = dev_get_drvdata(dev);
|
||||
int ret, temp_mC;
|
||||
|
||||
ret = rv3029_read_temp(dev, &temp_mC);
|
||||
ret = rv3029_read_temp(rv3029, &temp_mC);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
@ -702,9 +612,10 @@ static ssize_t rv3029_hwmon_set_update_interval(struct device *dev,
|
|||
const char *buf,
|
||||
size_t count)
|
||||
{
|
||||
struct rv3029_data *rv3029 = dev_get_drvdata(dev);
|
||||
unsigned int th_set_bits = 0;
|
||||
unsigned long interval_ms;
|
||||
int ret;
|
||||
u8 th_set_bits = 0;
|
||||
|
||||
ret = kstrtoul(buf, 10, &interval_ms);
|
||||
if (ret < 0)
|
||||
|
@ -715,7 +626,7 @@ static ssize_t rv3029_hwmon_set_update_interval(struct device *dev,
|
|||
if (interval_ms >= 16000)
|
||||
th_set_bits |= RV3029_EECTRL_THP;
|
||||
}
|
||||
ret = rv3029_eeprom_update_bits(dev, RV3029_CONTROL_E2P_EECTRL,
|
||||
ret = rv3029_eeprom_update_bits(rv3029, RV3029_CONTROL_E2P_EECTRL,
|
||||
RV3029_EECTRL_THE | RV3029_EECTRL_THP,
|
||||
th_set_bits);
|
||||
if (ret < 0)
|
||||
|
@ -728,10 +639,11 @@ static ssize_t rv3029_hwmon_show_update_interval(struct device *dev,
|
|||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct rv3029_data *rv3029 = dev_get_drvdata(dev);
|
||||
int ret, interval_ms;
|
||||
u8 eectrl;
|
||||
|
||||
ret = rv3029_eeprom_read(dev, RV3029_CONTROL_E2P_EECTRL,
|
||||
ret = rv3029_eeprom_read(rv3029, RV3029_CONTROL_E2P_EECTRL,
|
||||
&eectrl, 1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
@ -785,14 +697,23 @@ static void rv3029_hwmon_register(struct device *dev, const char *name)
|
|||
static struct rtc_class_ops rv3029_rtc_ops = {
|
||||
.read_time = rv3029_read_time,
|
||||
.set_time = rv3029_set_time,
|
||||
.ioctl = rv3029_ioctl,
|
||||
};
|
||||
|
||||
static int rv3029_probe(struct device *dev, struct regmap *regmap, int irq,
|
||||
const char *name)
|
||||
{
|
||||
struct rv3029_data *rv3029;
|
||||
struct nvmem_config nvmem_cfg = {
|
||||
.name = "rv3029_nvram",
|
||||
.word_size = 1,
|
||||
.stride = 1,
|
||||
.size = RV3029_RAM_SECTION_LEN,
|
||||
.type = NVMEM_TYPE_BATTERY_BACKED,
|
||||
.reg_read = rv3029_nvram_read,
|
||||
.reg_write = rv3029_nvram_write,
|
||||
};
|
||||
int rc = 0;
|
||||
u8 buf[1];
|
||||
|
||||
rv3029 = devm_kzalloc(dev, sizeof(*rv3029), GFP_KERNEL);
|
||||
if (!rv3029)
|
||||
|
@ -803,21 +724,12 @@ static int rv3029_probe(struct device *dev, struct regmap *regmap, int irq,
|
|||
rv3029->dev = dev;
|
||||
dev_set_drvdata(dev, rv3029);
|
||||
|
||||
rc = rv3029_get_sr(dev, buf);
|
||||
if (rc < 0) {
|
||||
dev_err(dev, "reading status failed\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
rv3029_trickle_config(dev);
|
||||
rv3029_hwmon_register(dev, name);
|
||||
|
||||
rv3029->rtc = devm_rtc_device_register(dev, name, &rv3029_rtc_ops,
|
||||
THIS_MODULE);
|
||||
if (IS_ERR(rv3029->rtc)) {
|
||||
dev_err(dev, "unable to register the class device\n");
|
||||
rv3029->rtc = devm_rtc_allocate_device(dev);
|
||||
if (IS_ERR(rv3029->rtc))
|
||||
return PTR_ERR(rv3029->rtc);
|
||||
}
|
||||
|
||||
if (rv3029->irq > 0) {
|
||||
rc = devm_request_threaded_irq(dev, rv3029->irq,
|
||||
|
@ -834,20 +746,48 @@ static int rv3029_probe(struct device *dev, struct regmap *regmap, int irq,
|
|||
}
|
||||
}
|
||||
|
||||
rv3029->rtc->ops = &rv3029_rtc_ops;
|
||||
rv3029->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
|
||||
rv3029->rtc->range_max = RTC_TIMESTAMP_END_2079;
|
||||
|
||||
rc = rtc_register_device(rv3029->rtc);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
nvmem_cfg.priv = rv3029->regmap;
|
||||
rtc_nvmem_register(rv3029->rtc, &nvmem_cfg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct regmap_range rv3029_holes_range[] = {
|
||||
regmap_reg_range(0x05, 0x07),
|
||||
regmap_reg_range(0x0f, 0x0f),
|
||||
regmap_reg_range(0x17, 0x17),
|
||||
regmap_reg_range(0x1a, 0x1f),
|
||||
regmap_reg_range(0x21, 0x27),
|
||||
regmap_reg_range(0x34, 0x37),
|
||||
};
|
||||
|
||||
static const struct regmap_access_table rv3029_regs = {
|
||||
.no_ranges = rv3029_holes_range,
|
||||
.n_no_ranges = ARRAY_SIZE(rv3029_holes_range),
|
||||
};
|
||||
|
||||
static const struct regmap_config config = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
.rd_table = &rv3029_regs,
|
||||
.wr_table = &rv3029_regs,
|
||||
.max_register = 0x3f,
|
||||
};
|
||||
|
||||
#if IS_ENABLED(CONFIG_I2C)
|
||||
|
||||
static int rv3029_i2c_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct regmap *regmap;
|
||||
static const struct regmap_config config = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
};
|
||||
|
||||
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK |
|
||||
I2C_FUNC_SMBUS_BYTE)) {
|
||||
dev_err(&client->dev, "Adapter does not support SMBUS_I2C_BLOCK or SMBUS_I2C_BYTE\n");
|
||||
|
@ -855,11 +795,8 @@ static int rv3029_i2c_probe(struct i2c_client *client,
|
|||
}
|
||||
|
||||
regmap = devm_regmap_init_i2c(client, &config);
|
||||
if (IS_ERR(regmap)) {
|
||||
dev_err(&client->dev, "%s: regmap allocation failed: %ld\n",
|
||||
__func__, PTR_ERR(regmap));
|
||||
if (IS_ERR(regmap))
|
||||
return PTR_ERR(regmap);
|
||||
}
|
||||
|
||||
return rv3029_probe(&client->dev, regmap, client->irq, client->name);
|
||||
}
|
||||
|
@ -873,24 +810,20 @@ MODULE_DEVICE_TABLE(i2c, rv3029_id);
|
|||
|
||||
static const struct of_device_id rv3029_of_match[] = {
|
||||
{ .compatible = "microcrystal,rv3029" },
|
||||
/* Backward compatibility only, do not use compatibles below: */
|
||||
{ .compatible = "rv3029" },
|
||||
{ .compatible = "rv3029c2" },
|
||||
{ .compatible = "mc,rv3029c2" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, rv3029_of_match);
|
||||
|
||||
static struct i2c_driver rv3029_driver = {
|
||||
.driver = {
|
||||
.name = "rtc-rv3029c2",
|
||||
.name = "rv3029",
|
||||
.of_match_table = of_match_ptr(rv3029_of_match),
|
||||
},
|
||||
.probe = rv3029_i2c_probe,
|
||||
.id_table = rv3029_id,
|
||||
};
|
||||
|
||||
static int rv3029_register_driver(void)
|
||||
static int __init rv3029_register_driver(void)
|
||||
{
|
||||
return i2c_add_driver(&rv3029_driver);
|
||||
}
|
||||
|
@ -902,7 +835,7 @@ static void rv3029_unregister_driver(void)
|
|||
|
||||
#else
|
||||
|
||||
static int rv3029_register_driver(void)
|
||||
static int __init rv3029_register_driver(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
@ -917,18 +850,11 @@ static void rv3029_unregister_driver(void)
|
|||
|
||||
static int rv3049_probe(struct spi_device *spi)
|
||||
{
|
||||
static const struct regmap_config config = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
};
|
||||
struct regmap *regmap;
|
||||
|
||||
regmap = devm_regmap_init_spi(spi, &config);
|
||||
if (IS_ERR(regmap)) {
|
||||
dev_err(&spi->dev, "%s: regmap allocation failed: %ld\n",
|
||||
__func__, PTR_ERR(regmap));
|
||||
if (IS_ERR(regmap))
|
||||
return PTR_ERR(regmap);
|
||||
}
|
||||
|
||||
return rv3029_probe(&spi->dev, regmap, spi->irq, "rv3049");
|
||||
}
|
||||
|
@ -940,24 +866,24 @@ static struct spi_driver rv3049_driver = {
|
|||
.probe = rv3049_probe,
|
||||
};
|
||||
|
||||
static int rv3049_register_driver(void)
|
||||
static int __init rv3049_register_driver(void)
|
||||
{
|
||||
return spi_register_driver(&rv3049_driver);
|
||||
}
|
||||
|
||||
static void rv3049_unregister_driver(void)
|
||||
static void __exit rv3049_unregister_driver(void)
|
||||
{
|
||||
spi_unregister_driver(&rv3049_driver);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static int rv3049_register_driver(void)
|
||||
static int __init rv3049_register_driver(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rv3049_unregister_driver(void)
|
||||
static void __exit rv3049_unregister_driver(void)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -968,16 +894,12 @@ static int __init rv30x9_init(void)
|
|||
int ret;
|
||||
|
||||
ret = rv3029_register_driver();
|
||||
if (ret) {
|
||||
pr_err("Failed to register rv3029 driver: %d\n", ret);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = rv3049_register_driver();
|
||||
if (ret) {
|
||||
pr_err("Failed to register rv3049 driver: %d\n", ret);
|
||||
if (ret)
|
||||
rv3029_unregister_driver();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -411,6 +411,7 @@ static int rv8803_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
|
|||
{
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct rv8803_data *rv8803 = dev_get_drvdata(dev);
|
||||
unsigned int vl = 0;
|
||||
int flags, ret = 0;
|
||||
|
||||
switch (cmd) {
|
||||
|
@ -419,18 +420,15 @@ static int rv8803_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
|
|||
if (flags < 0)
|
||||
return flags;
|
||||
|
||||
if (flags & RV8803_FLAG_V1F)
|
||||
if (flags & RV8803_FLAG_V1F) {
|
||||
dev_warn(&client->dev, "Voltage low, temperature compensation stopped.\n");
|
||||
vl = RTC_VL_ACCURACY_LOW;
|
||||
}
|
||||
|
||||
if (flags & RV8803_FLAG_V2F)
|
||||
dev_warn(&client->dev, "Voltage low, data loss detected.\n");
|
||||
vl |= RTC_VL_DATA_INVALID;
|
||||
|
||||
flags &= RV8803_FLAG_V1F | RV8803_FLAG_V2F;
|
||||
|
||||
if (copy_to_user((void __user *)arg, &flags, sizeof(int)))
|
||||
return -EFAULT;
|
||||
|
||||
return 0;
|
||||
return put_user(vl, (unsigned int __user *)arg);
|
||||
|
||||
case RTC_VL_CLR:
|
||||
mutex_lock(&rv8803->flags_lock);
|
||||
|
@ -440,7 +438,7 @@ static int rv8803_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
|
|||
return flags;
|
||||
}
|
||||
|
||||
flags &= ~(RV8803_FLAG_V1F | RV8803_FLAG_V2F);
|
||||
flags &= ~RV8803_FLAG_V1F;
|
||||
ret = rv8803_write_reg(client, RV8803_FLAG, flags);
|
||||
mutex_unlock(&rv8803->flags_lock);
|
||||
if (ret)
|
||||
|
|
|
@ -389,9 +389,8 @@ static int rx8010_alarm_irq_enable(struct device *dev,
|
|||
|
||||
static int rx8010_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct rx8010_data *rx8010 = dev_get_drvdata(dev);
|
||||
int ret, tmp;
|
||||
int tmp;
|
||||
int flagreg;
|
||||
|
||||
switch (cmd) {
|
||||
|
@ -400,24 +399,8 @@ static int rx8010_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
|
|||
if (flagreg < 0)
|
||||
return flagreg;
|
||||
|
||||
tmp = !!(flagreg & RX8010_FLAG_VLF);
|
||||
if (copy_to_user((void __user *)arg, &tmp, sizeof(int)))
|
||||
return -EFAULT;
|
||||
|
||||
return 0;
|
||||
|
||||
case RTC_VL_CLR:
|
||||
flagreg = i2c_smbus_read_byte_data(rx8010->client, RX8010_FLAG);
|
||||
if (flagreg < 0) {
|
||||
return flagreg;
|
||||
}
|
||||
|
||||
flagreg &= ~RX8010_FLAG_VLF;
|
||||
ret = i2c_smbus_write_byte_data(client, RX8010_FLAG, flagreg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
tmp = flagreg & RX8010_FLAG_VLF ? RTC_VL_DATA_INVALID : 0;
|
||||
return put_user(tmp, (unsigned int __user *)arg);
|
||||
|
||||
default:
|
||||
return -ENOIOCTLCMD;
|
||||
|
@ -482,7 +465,7 @@ static int rx8010_probe(struct i2c_client *client,
|
|||
|
||||
rx8010->rtc->max_user_freq = 1;
|
||||
|
||||
return err;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct i2c_driver rx8010_driver = {
|
||||
|
|
|
@ -67,7 +67,6 @@ static const struct i2c_device_id rx8025_id[] = {
|
|||
MODULE_DEVICE_TABLE(i2c, rx8025_id);
|
||||
|
||||
struct rx8025_data {
|
||||
struct i2c_client *client;
|
||||
struct rtc_device *rtc;
|
||||
u8 ctrl1;
|
||||
};
|
||||
|
@ -103,10 +102,10 @@ static s32 rx8025_write_regs(const struct i2c_client *client,
|
|||
|
||||
static int rx8025_check_validity(struct device *dev)
|
||||
{
|
||||
struct rx8025_data *rx8025 = dev_get_drvdata(dev);
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
int ctrl2;
|
||||
|
||||
ctrl2 = rx8025_read_reg(rx8025->client, RX8025_REG_CTRL2);
|
||||
ctrl2 = rx8025_read_reg(client, RX8025_REG_CTRL2);
|
||||
if (ctrl2 < 0)
|
||||
return ctrl2;
|
||||
|
||||
|
@ -178,6 +177,7 @@ out:
|
|||
|
||||
static int rx8025_get_time(struct device *dev, struct rtc_time *dt)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct rx8025_data *rx8025 = dev_get_drvdata(dev);
|
||||
u8 date[7];
|
||||
int err;
|
||||
|
@ -186,7 +186,7 @@ static int rx8025_get_time(struct device *dev, struct rtc_time *dt)
|
|||
if (err)
|
||||
return err;
|
||||
|
||||
err = rx8025_read_regs(rx8025->client, RX8025_REG_SEC, 7, date);
|
||||
err = rx8025_read_regs(client, RX8025_REG_SEC, 7, date);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
@ -211,6 +211,7 @@ static int rx8025_get_time(struct device *dev, struct rtc_time *dt)
|
|||
|
||||
static int rx8025_set_time(struct device *dev, struct rtc_time *dt)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct rx8025_data *rx8025 = dev_get_drvdata(dev);
|
||||
u8 date[7];
|
||||
int ret;
|
||||
|
@ -237,11 +238,11 @@ static int rx8025_set_time(struct device *dev, struct rtc_time *dt)
|
|||
|
||||
dev_dbg(dev, "%s: write %7ph\n", __func__, date);
|
||||
|
||||
ret = rx8025_write_regs(rx8025->client, RX8025_REG_SEC, 7, date);
|
||||
ret = rx8025_write_regs(client, RX8025_REG_SEC, 7, date);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return rx8025_reset_validity(rx8025->client);
|
||||
return rx8025_reset_validity(client);
|
||||
}
|
||||
|
||||
static int rx8025_init_client(struct i2c_client *client)
|
||||
|
@ -251,7 +252,7 @@ static int rx8025_init_client(struct i2c_client *client)
|
|||
int need_clear = 0;
|
||||
int err;
|
||||
|
||||
err = rx8025_read_regs(rx8025->client, RX8025_REG_CTRL1, 2, ctrl);
|
||||
err = rx8025_read_regs(client, RX8025_REG_CTRL1, 2, ctrl);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
|
@ -280,8 +281,8 @@ out:
|
|||
/* Alarm support */
|
||||
static int rx8025_read_alarm(struct device *dev, struct rtc_wkalrm *t)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct rx8025_data *rx8025 = dev_get_drvdata(dev);
|
||||
struct i2c_client *client = rx8025->client;
|
||||
u8 ald[2];
|
||||
int ctrl2, err;
|
||||
|
||||
|
@ -347,18 +348,18 @@ static int rx8025_set_alarm(struct device *dev, struct rtc_wkalrm *t)
|
|||
|
||||
if (rx8025->ctrl1 & RX8025_BIT_CTRL1_DALE) {
|
||||
rx8025->ctrl1 &= ~RX8025_BIT_CTRL1_DALE;
|
||||
err = rx8025_write_reg(rx8025->client, RX8025_REG_CTRL1,
|
||||
err = rx8025_write_reg(client, RX8025_REG_CTRL1,
|
||||
rx8025->ctrl1);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
err = rx8025_write_regs(rx8025->client, RX8025_REG_ALDMIN, 2, ald);
|
||||
err = rx8025_write_regs(client, RX8025_REG_ALDMIN, 2, ald);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (t->enabled) {
|
||||
rx8025->ctrl1 |= RX8025_BIT_CTRL1_DALE;
|
||||
err = rx8025_write_reg(rx8025->client, RX8025_REG_CTRL1,
|
||||
err = rx8025_write_reg(client, RX8025_REG_CTRL1,
|
||||
rx8025->ctrl1);
|
||||
if (err)
|
||||
return err;
|
||||
|
@ -369,6 +370,7 @@ static int rx8025_set_alarm(struct device *dev, struct rtc_wkalrm *t)
|
|||
|
||||
static int rx8025_alarm_irq_enable(struct device *dev, unsigned int enabled)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct rx8025_data *rx8025 = dev_get_drvdata(dev);
|
||||
u8 ctrl1;
|
||||
int err;
|
||||
|
@ -381,7 +383,7 @@ static int rx8025_alarm_irq_enable(struct device *dev, unsigned int enabled)
|
|||
|
||||
if (ctrl1 != rx8025->ctrl1) {
|
||||
rx8025->ctrl1 = ctrl1;
|
||||
err = rx8025_write_reg(rx8025->client, RX8025_REG_CTRL1,
|
||||
err = rx8025_write_reg(client, RX8025_REG_CTRL1,
|
||||
rx8025->ctrl1);
|
||||
if (err)
|
||||
return err;
|
||||
|
@ -516,7 +518,6 @@ static int rx8025_probe(struct i2c_client *client,
|
|||
if (!rx8025)
|
||||
return -ENOMEM;
|
||||
|
||||
rx8025->client = client;
|
||||
i2c_set_clientdata(client, rx8025);
|
||||
|
||||
err = rx8025_init_client(client);
|
||||
|
|
|
@ -897,8 +897,11 @@ static int stm32_rtc_resume(struct device *dev)
|
|||
}
|
||||
|
||||
ret = stm32_rtc_wait_sync(rtc);
|
||||
if (ret < 0)
|
||||
if (ret < 0) {
|
||||
if (rtc->data->has_pclk)
|
||||
clk_disable_unprepare(rtc->pclk);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (device_may_wakeup(dev))
|
||||
return disable_irq_wake(rtc->irq_alarm);
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include <linux/device.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mfd/tps6586x.h>
|
||||
#include <linux/module.h>
|
||||
|
@ -267,6 +268,8 @@ static int tps6586x_rtc_probe(struct platform_device *pdev)
|
|||
rtc->rtc->start_secs = mktime64(2009, 1, 1, 0, 0, 0);
|
||||
rtc->rtc->set_start_time = true;
|
||||
|
||||
irq_set_status_flags(rtc->irq, IRQ_NOAUTOEN);
|
||||
|
||||
ret = devm_request_threaded_irq(&pdev->dev, rtc->irq, NULL,
|
||||
tps6586x_rtc_irq,
|
||||
IRQF_ONESHOT,
|
||||
|
@ -276,7 +279,6 @@ static int tps6586x_rtc_probe(struct platform_device *pdev)
|
|||
rtc->irq, ret);
|
||||
goto fail_rtc_register;
|
||||
}
|
||||
disable_irq(rtc->irq);
|
||||
|
||||
ret = rtc_register_device(rtc->rtc);
|
||||
if (ret)
|
||||
|
|
|
@ -94,7 +94,7 @@ static int xlnx_rtc_read_time(struct device *dev, struct rtc_time *tm)
|
|||
* RTC has updated the CURRENT_TIME with the time written into
|
||||
* SET_TIME_WRITE register.
|
||||
*/
|
||||
rtc_time64_to_tm(readl(xrtcdev->reg_base + RTC_CUR_TM), tm);
|
||||
read_time = readl(xrtcdev->reg_base + RTC_CUR_TM);
|
||||
} else {
|
||||
/*
|
||||
* Time written in SET_TIME_WRITE has not yet updated into
|
||||
|
@ -104,8 +104,8 @@ static int xlnx_rtc_read_time(struct device *dev, struct rtc_time *tm)
|
|||
* reading.
|
||||
*/
|
||||
read_time = readl(xrtcdev->reg_base + RTC_SET_TM_RD) - 1;
|
||||
rtc_time64_to_tm(read_time, tm);
|
||||
}
|
||||
rtc_time64_to_tm(read_time, tm);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -167,6 +167,7 @@ struct rtc_device {
|
|||
#define RTC_TIMESTAMP_BEGIN_1900 -2208988800LL /* 1900-01-01 00:00:00 */
|
||||
#define RTC_TIMESTAMP_BEGIN_2000 946684800LL /* 2000-01-01 00:00:00 */
|
||||
#define RTC_TIMESTAMP_END_2063 2966371199LL /* 2063-12-31 23:59:59 */
|
||||
#define RTC_TIMESTAMP_END_2079 3471292799LL /* 2079-12-31 23:59:59 */
|
||||
#define RTC_TIMESTAMP_END_2099 4102444799LL /* 2099-12-31 23:59:59 */
|
||||
#define RTC_TIMESTAMP_END_2199 7258118399LL /* 2199-12-31 23:59:59 */
|
||||
#define RTC_TIMESTAMP_END_9999 253402300799LL /* 9999-12-31 23:59:59 */
|
||||
|
|
|
@ -92,7 +92,12 @@ struct rtc_pll_info {
|
|||
#define RTC_PLL_GET _IOR('p', 0x11, struct rtc_pll_info) /* Get PLL correction */
|
||||
#define RTC_PLL_SET _IOW('p', 0x12, struct rtc_pll_info) /* Set PLL correction */
|
||||
|
||||
#define RTC_VL_READ _IOR('p', 0x13, int) /* Voltage low detector */
|
||||
#define RTC_VL_DATA_INVALID BIT(0) /* Voltage too low, RTC data is invalid */
|
||||
#define RTC_VL_BACKUP_LOW BIT(1) /* Backup voltage is low */
|
||||
#define RTC_VL_BACKUP_EMPTY BIT(2) /* Backup empty or not present */
|
||||
#define RTC_VL_ACCURACY_LOW BIT(3) /* Voltage is low, RTC accuracy is reduced */
|
||||
|
||||
#define RTC_VL_READ _IOR('p', 0x13, unsigned int) /* Voltage low detection */
|
||||
#define RTC_VL_CLR _IO('p', 0x14) /* Clear voltage low information */
|
||||
|
||||
/* interrupt flags */
|
||||
|
|
Loading…
Reference in New Issue