Commit c7b7eefa authored by Linus Torvalds's avatar Linus Torvalds

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

Pull RTC updates from Alexandre Belloni:
 "This cycle, there were mostly non urgent fixes in drivers. I also
  finally unexported the non managed registration.

  Subsystem:

   - non devm managed registration is now removed from the driver API

   - all the unnecessary rtc_valid_tm() calls have been removed

  Drivers:

   - abx80X: watchdog support

   - cmos: fix non ACPI support

   - sc27xx: fix alarm support

   - Remove a possible sysfs race condition for ab8500, ds1307, ds1685,
     isl1208

   - Fix a possible race condition where an irq handler may be called
     before the rtc_device struct is allocated for mt6397, pl030,
     menelaus, armada38x"

* tag 'rtc-4.20' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux: (54 commits)
  rtc: sc27xx: Always read normal alarm when registering RTC device
  rtc: sc27xx: Add check to see if need to enable the alarm interrupt
  rtc: sc27xx: Remove interrupts disable and clear in probe()
  rtc: sc27xx: Clear SPG value update interrupt status
  rtc: sc27xx: Set wakeup capability before registering rtc device
  rtc: s35390a: Change buf's type to u8 in s35390a_init
  rtc: ds1307: fix ds1339 wakealarm support
  rtc: ds1685: simplify getting .driver_data
  rtc: m41t80: mark expected switch fall-through
  rtc: tegra: Propagate errors from platform_get_irq()
  rtc: cmos: Remove the `use_acpi_alarm' module parameter for !ACPI
  rtc: cmos: Fix non-ACPI undefined reference to `hpet_rtc_interrupt'
  rtc: mv: let the core handle invalid alarms
  rtc: vr41xx: switch to rtc_time64_to_tm/rtc_tm_to_time64
  rtc: ab8500: remove useless check
  rtc: ab8500: let the core handle range
  rtc: ab8500: use rtc_add_group
  rtc: rs5c348: report error when time is invalid
  rtc: rs5c348: remove forward declaration
  rtc: rs5c348: remove useless label
  ...
parents e5585453 3822d1bb
...@@ -75,7 +75,7 @@ config MIPS ...@@ -75,7 +75,7 @@ config MIPS
select MODULES_USE_ELF_RELA if MODULES && 64BIT select MODULES_USE_ELF_RELA if MODULES && 64BIT
select MODULES_USE_ELF_REL if MODULES select MODULES_USE_ELF_REL if MODULES
select PERF_USE_VMALLOC select PERF_USE_VMALLOC
select RTC_LIB if !MACH_LOONGSON64 select RTC_LIB
select SYSCTL_EXCEPTION_TRACE select SYSCTL_EXCEPTION_TRACE
select VIRT_TO_BUS select VIRT_TO_BUS
select NO_BOOTMEM select NO_BOOTMEM
......
...@@ -268,7 +268,7 @@ if RTC_LIB=n ...@@ -268,7 +268,7 @@ if RTC_LIB=n
config RTC config RTC
tristate "Enhanced Real Time Clock Support (legacy PC RTC driver)" tristate "Enhanced Real Time Clock Support (legacy PC RTC driver)"
depends on ALPHA || (MIPS && MACH_LOONGSON64) depends on ALPHA
---help--- ---help---
If you say Y here and create a character special file /dev/rtc with If you say Y here and create a character special file /dev/rtc with
major number 10 and minor number 135 using mknod ("man mknod"), you major number 10 and minor number 135 using mknod ("man mknod"), you
......
...@@ -187,6 +187,7 @@ config RTC_DRV_ABB5ZES3 ...@@ -187,6 +187,7 @@ config RTC_DRV_ABB5ZES3
config RTC_DRV_ABX80X config RTC_DRV_ABX80X
tristate "Abracon ABx80x" tristate "Abracon ABx80x"
select WATCHDOG_CORE if WATCHDOG
help help
If you say yes here you get support for Abracon AB080X and AB180X If you say yes here you get support for Abracon AB080X and AB180X
families of ultra-low-power battery- and capacitor-backed real-time families of ultra-low-power battery- and capacitor-backed real-time
...@@ -1007,17 +1008,6 @@ config RTC_DRV_DS17885 ...@@ -1007,17 +1008,6 @@ config RTC_DRV_DS17885
endchoice endchoice
config RTC_DS1685_PROC_REGS
bool "Display register values in /proc"
depends on RTC_DRV_DS1685_FAMILY && PROC_FS
help
Enable this to display a readout of all of the RTC registers in
/proc/drivers/rtc. Keep in mind that this can potentially lead
to lost interrupts, as reading Control Register C will clear
all pending IRQ flags.
Unless you are debugging this driver, choose N.
config RTC_DRV_DS1742 config RTC_DRV_DS1742
tristate "Maxim/Dallas DS1742/1743" tristate "Maxim/Dallas DS1742/1743"
depends on HAS_IOMEM depends on HAS_IOMEM
...@@ -1587,7 +1577,7 @@ config RTC_DRV_MPC5121 ...@@ -1587,7 +1577,7 @@ config RTC_DRV_MPC5121
config RTC_DRV_JZ4740 config RTC_DRV_JZ4740
tristate "Ingenic JZ4740 SoC" tristate "Ingenic JZ4740 SoC"
depends on MACH_INGENIC || COMPILE_TEST depends on MIPS || COMPILE_TEST
help help
If you say yes here you get support for the Ingenic JZ47xx SoCs RTC If you say yes here you get support for the Ingenic JZ47xx SoCs RTC
controllers. controllers.
......
...@@ -36,9 +36,9 @@ obj-$(CONFIG_RTC_DRV_ASM9260) += rtc-asm9260.o ...@@ -36,9 +36,9 @@ obj-$(CONFIG_RTC_DRV_ASM9260) += rtc-asm9260.o
obj-$(CONFIG_RTC_DRV_AT91RM9200)+= rtc-at91rm9200.o obj-$(CONFIG_RTC_DRV_AT91RM9200)+= rtc-at91rm9200.o
obj-$(CONFIG_RTC_DRV_AT91SAM9) += rtc-at91sam9.o obj-$(CONFIG_RTC_DRV_AT91SAM9) += rtc-at91sam9.o
obj-$(CONFIG_RTC_DRV_AU1XXX) += rtc-au1xxx.o obj-$(CONFIG_RTC_DRV_AU1XXX) += rtc-au1xxx.o
obj-$(CONFIG_RTC_DRV_BRCMSTB) += rtc-brcmstb-waketimer.o
obj-$(CONFIG_RTC_DRV_BQ32K) += rtc-bq32k.o obj-$(CONFIG_RTC_DRV_BQ32K) += rtc-bq32k.o
obj-$(CONFIG_RTC_DRV_BQ4802) += rtc-bq4802.o obj-$(CONFIG_RTC_DRV_BQ4802) += rtc-bq4802.o
obj-$(CONFIG_RTC_DRV_BRCMSTB) += rtc-brcmstb-waketimer.o
obj-$(CONFIG_RTC_DRV_CMOS) += rtc-cmos.o obj-$(CONFIG_RTC_DRV_CMOS) += rtc-cmos.o
obj-$(CONFIG_RTC_DRV_COH901331) += rtc-coh901331.o obj-$(CONFIG_RTC_DRV_COH901331) += rtc-coh901331.o
obj-$(CONFIG_RTC_DRV_CPCAP) += rtc-cpcap.o obj-$(CONFIG_RTC_DRV_CPCAP) += rtc-cpcap.o
...@@ -71,6 +71,7 @@ obj-$(CONFIG_RTC_DRV_EP93XX) += rtc-ep93xx.o ...@@ -71,6 +71,7 @@ obj-$(CONFIG_RTC_DRV_EP93XX) += rtc-ep93xx.o
obj-$(CONFIG_RTC_DRV_FM3130) += rtc-fm3130.o obj-$(CONFIG_RTC_DRV_FM3130) += rtc-fm3130.o
obj-$(CONFIG_RTC_DRV_FTRTC010) += rtc-ftrtc010.o obj-$(CONFIG_RTC_DRV_FTRTC010) += rtc-ftrtc010.o
obj-$(CONFIG_RTC_DRV_GENERIC) += rtc-generic.o obj-$(CONFIG_RTC_DRV_GENERIC) += rtc-generic.o
obj-$(CONFIG_RTC_DRV_GOLDFISH) += rtc-goldfish.o
obj-$(CONFIG_RTC_DRV_HID_SENSOR_TIME) += rtc-hid-sensor-time.o 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
...@@ -78,10 +79,10 @@ obj-$(CONFIG_RTC_DRV_ISL12022) += rtc-isl12022.o ...@@ -78,10 +79,10 @@ obj-$(CONFIG_RTC_DRV_ISL12022) += rtc-isl12022.o
obj-$(CONFIG_RTC_DRV_ISL12026) += rtc-isl12026.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_LOONGSON1) += rtc-ls1x.o
obj-$(CONFIG_RTC_DRV_LP8788) += rtc-lp8788.o obj-$(CONFIG_RTC_DRV_LP8788) += rtc-lp8788.o
obj-$(CONFIG_RTC_DRV_LPC24XX) += rtc-lpc24xx.o obj-$(CONFIG_RTC_DRV_LPC24XX) += rtc-lpc24xx.o
obj-$(CONFIG_RTC_DRV_LPC32XX) += rtc-lpc32xx.o obj-$(CONFIG_RTC_DRV_LPC32XX) += rtc-lpc32xx.o
obj-$(CONFIG_RTC_DRV_LOONGSON1) += rtc-ls1x.o
obj-$(CONFIG_RTC_DRV_M41T80) += rtc-m41t80.o obj-$(CONFIG_RTC_DRV_M41T80) += rtc-m41t80.o
obj-$(CONFIG_RTC_DRV_M41T93) += rtc-m41t93.o obj-$(CONFIG_RTC_DRV_M41T93) += rtc-m41t93.o
obj-$(CONFIG_RTC_DRV_M41T94) += rtc-m41t94.o obj-$(CONFIG_RTC_DRV_M41T94) += rtc-m41t94.o
...@@ -100,7 +101,6 @@ obj-$(CONFIG_RTC_DRV_MC13XXX) += rtc-mc13xxx.o ...@@ -100,7 +101,6 @@ obj-$(CONFIG_RTC_DRV_MC13XXX) += rtc-mc13xxx.o
obj-$(CONFIG_RTC_DRV_MCP795) += rtc-mcp795.o obj-$(CONFIG_RTC_DRV_MCP795) += rtc-mcp795.o
obj-$(CONFIG_RTC_DRV_MOXART) += rtc-moxart.o obj-$(CONFIG_RTC_DRV_MOXART) += rtc-moxart.o
obj-$(CONFIG_RTC_DRV_MPC5121) += rtc-mpc5121.o obj-$(CONFIG_RTC_DRV_MPC5121) += rtc-mpc5121.o
obj-$(CONFIG_RTC_DRV_VRTC) += rtc-mrst.o
obj-$(CONFIG_RTC_DRV_MSM6242) += rtc-msm6242.o obj-$(CONFIG_RTC_DRV_MSM6242) += rtc-msm6242.o
obj-$(CONFIG_RTC_DRV_MT6397) += rtc-mt6397.o obj-$(CONFIG_RTC_DRV_MT6397) += rtc-mt6397.o
obj-$(CONFIG_RTC_DRV_MT7622) += rtc-mt7622.o obj-$(CONFIG_RTC_DRV_MT7622) += rtc-mt7622.o
...@@ -116,8 +116,8 @@ obj-$(CONFIG_RTC_DRV_PCF2123) += rtc-pcf2123.o ...@@ -116,8 +116,8 @@ obj-$(CONFIG_RTC_DRV_PCF2123) += rtc-pcf2123.o
obj-$(CONFIG_RTC_DRV_PCF2127) += rtc-pcf2127.o obj-$(CONFIG_RTC_DRV_PCF2127) += rtc-pcf2127.o
obj-$(CONFIG_RTC_DRV_PCF50633) += rtc-pcf50633.o obj-$(CONFIG_RTC_DRV_PCF50633) += rtc-pcf50633.o
obj-$(CONFIG_RTC_DRV_PCF85063) += rtc-pcf85063.o obj-$(CONFIG_RTC_DRV_PCF85063) += rtc-pcf85063.o
obj-$(CONFIG_RTC_DRV_PCF85363) += rtc-pcf85363.o
obj-$(CONFIG_RTC_DRV_PCF8523) += rtc-pcf8523.o obj-$(CONFIG_RTC_DRV_PCF8523) += rtc-pcf8523.o
obj-$(CONFIG_RTC_DRV_PCF85363) += rtc-pcf85363.o
obj-$(CONFIG_RTC_DRV_PCF8563) += rtc-pcf8563.o obj-$(CONFIG_RTC_DRV_PCF8563) += rtc-pcf8563.o
obj-$(CONFIG_RTC_DRV_PCF8583) += rtc-pcf8583.o obj-$(CONFIG_RTC_DRV_PCF8583) += rtc-pcf8583.o
obj-$(CONFIG_RTC_DRV_PIC32) += rtc-pic32.o obj-$(CONFIG_RTC_DRV_PIC32) += rtc-pic32.o
...@@ -154,9 +154,9 @@ obj-$(CONFIG_RTC_DRV_SNVS) += rtc-snvs.o ...@@ -154,9 +154,9 @@ obj-$(CONFIG_RTC_DRV_SNVS) += rtc-snvs.o
obj-$(CONFIG_RTC_DRV_SPEAR) += rtc-spear.o obj-$(CONFIG_RTC_DRV_SPEAR) += rtc-spear.o
obj-$(CONFIG_RTC_DRV_STARFIRE) += rtc-starfire.o obj-$(CONFIG_RTC_DRV_STARFIRE) += rtc-starfire.o
obj-$(CONFIG_RTC_DRV_STK17TA8) += rtc-stk17ta8.o obj-$(CONFIG_RTC_DRV_STK17TA8) += rtc-stk17ta8.o
obj-$(CONFIG_RTC_DRV_ST_LPC) += rtc-st-lpc.o
obj-$(CONFIG_RTC_DRV_STM32) += rtc-stm32.o obj-$(CONFIG_RTC_DRV_STM32) += rtc-stm32.o
obj-$(CONFIG_RTC_DRV_STMP) += rtc-stmp3xxx.o obj-$(CONFIG_RTC_DRV_STMP) += rtc-stmp3xxx.o
obj-$(CONFIG_RTC_DRV_ST_LPC) += rtc-st-lpc.o
obj-$(CONFIG_RTC_DRV_SUN4V) += rtc-sun4v.o obj-$(CONFIG_RTC_DRV_SUN4V) += rtc-sun4v.o
obj-$(CONFIG_RTC_DRV_SUN6I) += rtc-sun6i.o obj-$(CONFIG_RTC_DRV_SUN6I) += rtc-sun6i.o
obj-$(CONFIG_RTC_DRV_SUNXI) += rtc-sunxi.o obj-$(CONFIG_RTC_DRV_SUNXI) += rtc-sunxi.o
...@@ -169,10 +169,10 @@ obj-$(CONFIG_RTC_DRV_TWL4030) += rtc-twl.o ...@@ -169,10 +169,10 @@ obj-$(CONFIG_RTC_DRV_TWL4030) += rtc-twl.o
obj-$(CONFIG_RTC_DRV_TX4939) += rtc-tx4939.o obj-$(CONFIG_RTC_DRV_TX4939) += rtc-tx4939.o
obj-$(CONFIG_RTC_DRV_V3020) += rtc-v3020.o obj-$(CONFIG_RTC_DRV_V3020) += rtc-v3020.o
obj-$(CONFIG_RTC_DRV_VR41XX) += rtc-vr41xx.o obj-$(CONFIG_RTC_DRV_VR41XX) += rtc-vr41xx.o
obj-$(CONFIG_RTC_DRV_VRTC) += rtc-mrst.o
obj-$(CONFIG_RTC_DRV_VT8500) += rtc-vt8500.o obj-$(CONFIG_RTC_DRV_VT8500) += rtc-vt8500.o
obj-$(CONFIG_RTC_DRV_WM831X) += rtc-wm831x.o obj-$(CONFIG_RTC_DRV_WM831X) += rtc-wm831x.o
obj-$(CONFIG_RTC_DRV_WM8350) += rtc-wm8350.o obj-$(CONFIG_RTC_DRV_WM8350) += rtc-wm8350.o
obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o
obj-$(CONFIG_RTC_DRV_XGENE) += rtc-xgene.o obj-$(CONFIG_RTC_DRV_XGENE) += rtc-xgene.o
obj-$(CONFIG_RTC_DRV_ZYNQMP) += rtc-zynqmp.o obj-$(CONFIG_RTC_DRV_ZYNQMP) += rtc-zynqmp.o
obj-$(CONFIG_RTC_DRV_GOLDFISH) += rtc-goldfish.o
...@@ -286,9 +286,10 @@ static void rtc_device_get_offset(struct rtc_device *rtc) ...@@ -286,9 +286,10 @@ static void rtc_device_get_offset(struct rtc_device *rtc)
* *
* Returns the pointer to the new struct class device. * Returns the pointer to the new struct class device.
*/ */
struct rtc_device *rtc_device_register(const char *name, struct device *dev, static struct rtc_device *rtc_device_register(const char *name,
const struct rtc_class_ops *ops, struct device *dev,
struct module *owner) const struct rtc_class_ops *ops,
struct module *owner)
{ {
struct rtc_device *rtc; struct rtc_device *rtc;
struct rtc_wkalrm alrm; struct rtc_wkalrm alrm;
...@@ -351,15 +352,13 @@ struct rtc_device *rtc_device_register(const char *name, struct device *dev, ...@@ -351,15 +352,13 @@ struct rtc_device *rtc_device_register(const char *name, struct device *dev,
name, err); name, err);
return ERR_PTR(err); return ERR_PTR(err);
} }
EXPORT_SYMBOL_GPL(rtc_device_register);
/** /**
* rtc_device_unregister - removes the previously registered RTC class device * rtc_device_unregister - removes the previously registered RTC class device
* *
* @rtc: the RTC class device to destroy * @rtc: the RTC class device to destroy
*/ */
void rtc_device_unregister(struct rtc_device *rtc) static void rtc_device_unregister(struct rtc_device *rtc)
{ {
mutex_lock(&rtc->ops_lock); mutex_lock(&rtc->ops_lock);
/* /*
...@@ -372,7 +371,6 @@ void rtc_device_unregister(struct rtc_device *rtc) ...@@ -372,7 +371,6 @@ void rtc_device_unregister(struct rtc_device *rtc)
mutex_unlock(&rtc->ops_lock); mutex_unlock(&rtc->ops_lock);
put_device(&rtc->dev); put_device(&rtc->dev);
} }
EXPORT_SYMBOL_GPL(rtc_device_unregister);
static void devm_rtc_device_release(struct device *dev, void *res) static void devm_rtc_device_release(struct device *dev, void *res)
{ {
......
...@@ -596,7 +596,6 @@ EXPORT_SYMBOL_GPL(rtc_update_irq_enable); ...@@ -596,7 +596,6 @@ EXPORT_SYMBOL_GPL(rtc_update_irq_enable);
* This function is called when an AIE, UIE or PIE mode interrupt * This function is called when an AIE, UIE or PIE mode interrupt
* has occurred (or been emulated). * has occurred (or been emulated).
* *
* Triggers the registered irq_task function callback.
*/ */
void rtc_handle_legacy_irq(struct rtc_device *rtc, int num, int mode) void rtc_handle_legacy_irq(struct rtc_device *rtc, int num, int mode)
{ {
...@@ -741,7 +740,6 @@ static int rtc_update_hrtimer(struct rtc_device *rtc, int enabled) ...@@ -741,7 +740,6 @@ static int rtc_update_hrtimer(struct rtc_device *rtc, int enabled)
/** /**
* rtc_irq_set_state - enable/disable 2^N Hz periodic IRQs * rtc_irq_set_state - enable/disable 2^N Hz periodic IRQs
* @rtc: the rtc device * @rtc: the rtc device
* @task: currently registered with rtc_irq_register()
* @enabled: true to enable periodic IRQs * @enabled: true to enable periodic IRQs
* Context: any * Context: any
* *
...@@ -764,7 +762,6 @@ int rtc_irq_set_state(struct rtc_device *rtc, int enabled) ...@@ -764,7 +762,6 @@ int rtc_irq_set_state(struct rtc_device *rtc, int enabled)
/** /**
* rtc_irq_set_freq - set 2^N Hz periodic IRQ frequency for IRQ * rtc_irq_set_freq - set 2^N Hz periodic IRQ frequency for IRQ
* @rtc: the rtc device * @rtc: the rtc device
* @task: currently registered with rtc_irq_register()
* @freq: positive frequency * @freq: positive frequency
* Context: any * Context: any
* *
......
...@@ -46,7 +46,6 @@ ...@@ -46,7 +46,6 @@
#define RTC_STATUS_DATA 0x01 #define RTC_STATUS_DATA 0x01
#define COUNTS_PER_SEC (0xF000 / 60) #define COUNTS_PER_SEC (0xF000 / 60)
#define AB8500_RTC_EPOCH 2000
static const u8 ab8500_rtc_time_regs[] = { static const u8 ab8500_rtc_time_regs[] = {
AB8500_RTC_WATCH_TMIN_HI_REG, AB8500_RTC_WATCH_TMIN_MID_REG, AB8500_RTC_WATCH_TMIN_HI_REG, AB8500_RTC_WATCH_TMIN_MID_REG,
...@@ -59,23 +58,6 @@ static const u8 ab8500_rtc_alarm_regs[] = { ...@@ -59,23 +58,6 @@ static const u8 ab8500_rtc_alarm_regs[] = {
AB8500_RTC_ALRM_MIN_LOW_REG AB8500_RTC_ALRM_MIN_LOW_REG
}; };
/* Calculate the seconds from 1970 to 01-01-2000 00:00:00 */
static unsigned long get_elapsed_seconds(int year)
{
unsigned long secs;
struct rtc_time tm = {
.tm_year = year - 1900,
.tm_mday = 1,
};
/*
* This function calculates secs from 1970 and not from
* 1900, even if we supply the offset from year 1900.
*/
rtc_tm_to_time(&tm, &secs);
return secs;
}
static int ab8500_rtc_read_time(struct device *dev, struct rtc_time *tm) static int ab8500_rtc_read_time(struct device *dev, struct rtc_time *tm)
{ {
unsigned long timeout = jiffies + HZ; unsigned long timeout = jiffies + HZ;
...@@ -118,9 +100,6 @@ static int ab8500_rtc_read_time(struct device *dev, struct rtc_time *tm) ...@@ -118,9 +100,6 @@ static int ab8500_rtc_read_time(struct device *dev, struct rtc_time *tm)
secs = secs / COUNTS_PER_SEC; secs = secs / COUNTS_PER_SEC;
secs = secs + (mins * 60); secs = secs + (mins * 60);
/* Add back the initially subtracted number of seconds */
secs += get_elapsed_seconds(AB8500_RTC_EPOCH);
rtc_time_to_tm(secs, tm); rtc_time_to_tm(secs, tm);
return 0; return 0;
} }
...@@ -131,21 +110,8 @@ static int ab8500_rtc_set_time(struct device *dev, struct rtc_time *tm) ...@@ -131,21 +110,8 @@ static int ab8500_rtc_set_time(struct device *dev, struct rtc_time *tm)
unsigned char buf[ARRAY_SIZE(ab8500_rtc_time_regs)]; unsigned char buf[ARRAY_SIZE(ab8500_rtc_time_regs)];
unsigned long no_secs, no_mins, secs = 0; unsigned long no_secs, no_mins, secs = 0;
if (tm->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(tm, &secs); rtc_tm_to_time(tm, &secs);
/*
* Convert it to the number of seconds since 01-01-2000 00:00:00, since
* we only have a small counter in the RTC.
*/
secs -= get_elapsed_seconds(AB8500_RTC_EPOCH);
no_mins = secs / 60; no_mins = secs / 60;
no_secs = secs % 60; no_secs = secs % 60;
...@@ -202,12 +168,9 @@ static int ab8500_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) ...@@ -202,12 +168,9 @@ static int ab8500_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
mins = (buf[0] << 16) | (buf[1] << 8) | (buf[2]); mins = (buf[0] << 16) | (buf[1] << 8) | (buf[2]);
secs = mins * 60; secs = mins * 60;
/* Add back the initially subtracted number of seconds */
secs += get_elapsed_seconds(AB8500_RTC_EPOCH);
rtc_time_to_tm(secs, &alarm->time); rtc_time_to_tm(secs, &alarm->time);
return rtc_valid_tm(&alarm->time); return 0;
} }
static int ab8500_rtc_irq_enable(struct device *dev, unsigned int enabled) static int ab8500_rtc_irq_enable(struct device *dev, unsigned int enabled)
...@@ -224,12 +187,6 @@ static int ab8500_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) ...@@ -224,12 +187,6 @@ static int ab8500_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
unsigned long mins, secs = 0, cursec = 0; unsigned long mins, secs = 0, cursec = 0;
struct rtc_time curtm; struct rtc_time curtm;
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 */ /* Get the number of seconds since 1970 */
rtc_tm_to_time(&alarm->time, &secs); rtc_tm_to_time(&alarm->time, &secs);
...@@ -245,12 +202,6 @@ static int ab8500_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) ...@@ -245,12 +202,6 @@ static int ab8500_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
return -EINVAL; return -EINVAL;
} }
/*
* Convert it to the number of seconds since 01-01-2000 00:00:00, since
* we only have a small counter in the RTC.
*/
secs -= get_elapsed_seconds(AB8500_RTC_EPOCH);
mins = secs / 60; mins = secs / 60;
buf[2] = mins & 0xFF; buf[2] = mins & 0xFF;
...@@ -360,15 +311,14 @@ static DEVICE_ATTR(rtc_calibration, S_IRUGO | S_IWUSR, ...@@ -360,15 +311,14 @@ static DEVICE_ATTR(rtc_calibration, S_IRUGO | S_IWUSR,
ab8500_sysfs_show_rtc_calibration, ab8500_sysfs_show_rtc_calibration,
ab8500_sysfs_store_rtc_calibration); ab8500_sysfs_store_rtc_calibration);
static int ab8500_sysfs_rtc_register(struct device *dev) static struct attribute *ab8500_rtc_attrs[] = {
{ &dev_attr_rtc_calibration.attr,
return device_create_file(dev, &dev_attr_rtc_calibration); NULL
} };
static void ab8500_sysfs_rtc_unregister(struct device *dev) static const struct attribute_group ab8500_rtc_sysfs_files = {
{ .attrs = ab8500_rtc_attrs,
device_remove_file(dev, &dev_attr_rtc_calibration); };
}
static irqreturn_t rtc_alarm_handler(int irq, void *data) static irqreturn_t rtc_alarm_handler(int irq, void *data)
{ {
...@@ -429,14 +379,11 @@ static int ab8500_rtc_probe(struct platform_device *pdev) ...@@ -429,14 +379,11 @@ static int ab8500_rtc_probe(struct platform_device *pdev)
device_init_wakeup(&pdev->dev, true); device_init_wakeup(&pdev->dev, true);
rtc = devm_rtc_device_register(&pdev->dev, "ab8500-rtc", rtc = devm_rtc_allocate_device(&pdev->dev);
(struct rtc_class_ops *)platid->driver_data, if (IS_ERR(rtc))
THIS_MODULE); return PTR_ERR(rtc);
if (IS_ERR(rtc)) {
dev_err(&pdev->dev, "Registration failed\n"); rtc->ops = (struct rtc_class_ops *)platid->driver_data;
err = PTR_ERR(rtc);
return err;
}
err = devm_request_threaded_irq(&pdev->dev, irq, NULL, err = devm_request_threaded_irq(&pdev->dev, irq, NULL,
rtc_alarm_handler, IRQF_ONESHOT, rtc_alarm_handler, IRQF_ONESHOT,
...@@ -447,22 +394,23 @@ static int ab8500_rtc_probe(struct platform_device *pdev) ...@@ -447,22 +394,23 @@ static int ab8500_rtc_probe(struct platform_device *pdev)
dev_pm_set_wake_irq(&pdev->dev, irq); dev_pm_set_wake_irq(&pdev->dev, irq);
platform_set_drvdata(pdev, rtc); platform_set_drvdata(pdev, rtc);
err = ab8500_sysfs_rtc_register(&pdev->dev);
if (err) {
dev_err(&pdev->dev, "sysfs RTC failed to register\n");
return err;
}
rtc->uie_unsupported = 1; rtc->uie_unsupported = 1;
return 0; rtc->range_max = (1ULL << 24) * 60 - 1; // 24-bit minutes + 59 secs
rtc->start_secs = RTC_TIMESTAMP_BEGIN_2000;
rtc->set_start_time = true;
err = rtc_add_group(rtc, &ab8500_rtc_sysfs_files);
if (err)
return err;
return rtc_register_device(rtc);
} }
static int ab8500_rtc_remove(struct platform_device *pdev) static int ab8500_rtc_remove(struct platform_device *pdev)
{ {
dev_pm_clear_wake_irq(&pdev->dev); dev_pm_clear_wake_irq(&pdev->dev);
device_init_wakeup(&pdev->dev, false); device_init_wakeup(&pdev->dev, false);
ab8500_sysfs_rtc_unregister(&pdev->dev);
return 0; return 0;
} }
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/rtc.h> #include <linux/rtc.h>
#include <linux/watchdog.h>
#define ABX8XX_REG_HTH 0x00 #define ABX8XX_REG_HTH 0x00
#define ABX8XX_REG_SC 0x01 #define ABX8XX_REG_SC 0x01
...@@ -37,6 +38,7 @@ ...@@ -37,6 +38,7 @@
#define ABX8XX_REG_STATUS 0x0f #define ABX8XX_REG_STATUS 0x0f
#define ABX8XX_STATUS_AF BIT(2) #define ABX8XX_STATUS_AF BIT(2)
#define ABX8XX_STATUS_WDT BIT(6)
#define ABX8XX_REG_CTRL1 0x10 #define ABX8XX_REG_CTRL1 0x10
#define ABX8XX_CTRL_WRITE BIT(0) #define ABX8XX_CTRL_WRITE BIT(0)
...@@ -61,6 +63,14 @@ ...@@ -61,6 +63,14 @@
#define ABX8XX_OSS_OF BIT(1) #define ABX8XX_OSS_OF BIT(1)
#define ABX8XX_OSS_OMODE BIT(4) #define ABX8XX_OSS_OMODE BIT(4)
#define ABX8XX_REG_WDT 0x1b
#define ABX8XX_WDT_WDS BIT(7)
#define ABX8XX_WDT_BMB_MASK 0x7c
#define ABX8XX_WDT_BMB_SHIFT 2
#define ABX8XX_WDT_MAX_TIME (ABX8XX_WDT_BMB_MASK >> ABX8XX_WDT_BMB_SHIFT)
#define ABX8XX_WDT_WRB_MASK 0x03
#define ABX8XX_WDT_WRB_1HZ 0x02
#define ABX8XX_REG_CFG_KEY 0x1f #define ABX8XX_REG_CFG_KEY 0x1f
#define ABX8XX_CFG_KEY_OSC 0xa1 #define ABX8XX_CFG_KEY_OSC 0xa1
#define ABX8XX_CFG_KEY_MISC 0x9d #define ABX8XX_CFG_KEY_MISC 0x9d
...@@ -80,20 +90,27 @@ enum abx80x_chip {AB0801, AB0803, AB0804, AB0805, ...@@ -80,20 +90,27 @@ enum abx80x_chip {AB0801, AB0803, AB0804, AB0805,
struct abx80x_cap { struct abx80x_cap {
u16 pn; u16 pn;
bool has_tc; bool has_tc;
bool has_wdog;
}; };
static struct abx80x_cap abx80x_caps[] = { static struct abx80x_cap abx80x_caps[] = {
[AB0801] = {.pn = 0x0801}, [AB0801] = {.pn = 0x0801},
[AB0803] = {.pn = 0x0803}, [AB0803] = {.pn = 0x0803},
[AB0804] = {.pn = 0x0804, .has_tc = true}, [AB0804] = {.pn = 0x0804, .has_tc = true, .has_wdog = true},
[AB0805] = {.pn = 0x0805, .has_tc = true}, [AB0805] = {.pn = 0x0805, .has_tc = true, .has_wdog = true},
[AB1801] = {.pn = 0x1801}, [AB1801] = {.pn = 0x1801},
[AB1803] = {.pn = 0x1803}, [AB1803] = {.pn = 0x1803},
[AB1804] = {.pn = 0x1804, .has_tc = true}, [AB1804] = {.pn = 0x1804, .has_tc = true, .has_wdog = true},
[AB1805] = {.pn = 0x1805, .has_tc = true}, [AB1805] = {.pn = 0x1805, .has_tc = true, .has_wdog = true},
[ABX80X] = {.pn = 0} [ABX80X] = {.pn = 0}
}; };
struct abx80x_priv {
struct rtc_device *rtc;
struct i2c_client *client;
struct watchdog_device wdog;
};
static int abx80x_is_rc_mode(struct i2c_client *client) static int abx80x_is_rc_mode(struct i2c_client *client)
{ {
int flags = 0; int flags = 0;
...@@ -218,7 +235,8 @@ static int abx80x_rtc_set_time(struct device *dev, struct rtc_time *tm) ...@@ -218,7 +235,8 @@ static int abx80x_rtc_set_time(struct device *dev, struct rtc_time *tm)
static irqreturn_t abx80x_handle_irq(int irq, void *dev_id) static irqreturn_t abx80x_handle_irq(int irq, void *dev_id)
{ {
struct i2c_client *client = dev_id; struct i2c_client *client = dev_id;
struct rtc_device *rtc = i2c_get_clientdata(client); struct abx80x_priv *priv = i2c_get_clientdata(client);
struct rtc_device *rtc = priv->rtc;
int status; int status;
status = i2c_smbus_read_byte_data(client, ABX8XX_REG_STATUS); status = i2c_smbus_read_byte_data(client, ABX8XX_REG_STATUS);
...@@ -228,6 +246,13 @@ static irqreturn_t abx80x_handle_irq(int irq, void *dev_id) ...@@ -228,6 +246,13 @@ static irqreturn_t abx80x_handle_irq(int irq, void *dev_id)
if (status & ABX8XX_STATUS_AF) if (status & ABX8XX_STATUS_AF)
rtc_update_irq(rtc, 1, RTC_AF | RTC_IRQF); rtc_update_irq(rtc, 1, RTC_AF | RTC_IRQF);
/*
* It is unclear if we'll get an interrupt before the external
* reset kicks in.
*/
if (status & ABX8XX_STATUS_WDT)
dev_alert(&client->dev, "watchdog timeout interrupt.\n");
i2c_smbus_write_byte_data(client, ABX8XX_REG_STATUS, 0); i2c_smbus_write_byte_data(client, ABX8XX_REG_STATUS, 0);
return IRQ_HANDLED; return IRQ_HANDLED;
...@@ -529,11 +554,94 @@ static void rtc_calib_remove_sysfs_group(void *_dev) ...@@ -529,11 +554,94 @@ static void rtc_calib_remove_sysfs_group(void *_dev)
sysfs_remove_group(&dev->kobj, &rtc_calib_attr_group); sysfs_remove_group(&dev->kobj, &rtc_calib_attr_group);
} }
#ifdef CONFIG_WATCHDOG
static inline u8 timeout_bits(unsigned int timeout)
{
return ((timeout << ABX8XX_WDT_BMB_SHIFT) & ABX8XX_WDT_BMB_MASK) |
ABX8XX_WDT_WRB_1HZ;
}
static int __abx80x_wdog_set_timeout(struct watchdog_device *wdog,
unsigned int timeout)
{
struct abx80x_priv *priv = watchdog_get_drvdata(wdog);
u8 val = ABX8XX_WDT_WDS | timeout_bits(timeout);
/*
* Writing any timeout to the WDT register resets the watchdog timer.
* Writing 0 disables it.
*/
return i2c_smbus_write_byte_data(priv->client, ABX8XX_REG_WDT, val);
}
static int abx80x_wdog_set_timeout(struct watchdog_device *wdog,
unsigned int new_timeout)
{
int err = 0;
if (watchdog_hw_running(wdog))
err = __abx80x_wdog_set_timeout(wdog, new_timeout);
if (err == 0)
wdog->timeout = new_timeout;
return err;
}
static int abx80x_wdog_ping(struct watchdog_device *wdog)
{
return __abx80x_wdog_set_timeout(wdog, wdog->timeout);
}
static int abx80x_wdog_start(struct watchdog_device *wdog)
{
return __abx80x_wdog_set_timeout(wdog, wdog->timeout);
}
static int abx80x_wdog_stop(struct watchdog_device *wdog)
{
return __abx80x_wdog_set_timeout(wdog, 0);
}
static const struct watchdog_info abx80x_wdog_info = {
.identity = "abx80x watchdog",
.options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE,
};
static const struct watchdog_ops abx80x_wdog_ops = {
.owner = THIS_MODULE,
.start = abx80x_wdog_start,
.stop = abx80x_wdog_stop,
.ping = abx80x_wdog_ping,
.set_timeout = abx80x_wdog_set_timeout,
};
static int abx80x_setup_watchdog(struct abx80x_priv *priv)
{
priv->wdog.parent = &priv->client->dev;
priv->wdog.ops = &abx80x_wdog_ops;
priv->wdog.info = &abx80x_wdog_info;
priv->wdog.min_timeout = 1;
priv->wdog.max_timeout = ABX8XX_WDT_MAX_TIME;
priv->wdog.timeout = ABX8XX_WDT_MAX_TIME;
watchdog_set_drvdata(&priv->wdog, priv);
return devm_watchdog_register_device(&priv->client->dev, &priv->wdog);
}
#else
static int abx80x_setup_watchdog(struct abx80x_priv *priv)
{
return 0;
}
#endif
static int abx80x_probe(struct i2c_client *client, static int abx80x_probe(struct i2c_client *client,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
struct device_node *np = client->dev.of_node; struct device_node *np = client->dev.of_node;
struct rtc_device *rtc; struct abx80x_priv *priv;
int i, data, err, trickle_cfg = -EINVAL; int i, data, err, trickle_cfg = -EINVAL;
char buf[7]; char buf[7];
unsigned int part = id->driver_data; unsigned int part = id->driver_data;
...@@ -610,13 +718,24 @@ static int abx80x_probe(struct i2c_client *client, ...@@ -610,13 +718,24 @@ static int abx80x_probe(struct i2c_client *client,
if (err) if (err)
return err; return err;
rtc = devm_rtc_allocate_device(&client->dev); priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
if (IS_ERR(rtc)) if (priv == NULL)
return PTR_ERR(rtc); return -ENOMEM;
priv->rtc = devm_rtc_allocate_device(&client->dev);
if (IS_ERR(priv->rtc))
return PTR_ERR(priv->rtc);
priv->rtc->ops = &abx80x_rtc_ops;
priv->client = client;
rtc->ops = &abx80x_rtc_ops; i2c_set_clientdata(client, priv);
i2c_set_clientdata(client, rtc); if (abx80x_caps[part].has_wdog) {
err = abx80x_setup_watchdog(priv);
if (err)
return err;
}
if (client->irq > 0) { if (client->irq > 0) {
dev_info(&client->dev, "IRQ %d supplied\n", client->irq); dev_info(&client->dev, "IRQ %d supplied\n", client->irq);
...@@ -649,7 +768,7 @@ static int abx80x_probe(struct i2c_client *client, ...@@ -649,7 +768,7 @@ static int abx80x_probe(struct i2c_client *client,
return err; return err;
} }
err = rtc_register_device(rtc); err = rtc_register_device(priv->rtc);
return err; return err;
} }
......
...@@ -224,7 +224,7 @@ static int armada38x_rtc_read_time(struct device *dev, struct rtc_time *tm) ...@@ -224,7 +224,7 @@ static int armada38x_rtc_read_time(struct device *dev, struct rtc_time *tm)
time = rtc->data->read_rtc_reg(rtc, RTC_TIME); time = rtc->data->read_rtc_reg(rtc, RTC_TIME);
spin_unlock_irqrestore(&rtc->lock, flags); spin_unlock_irqrestore(&rtc->lock, flags);
rtc_time_to_tm(time, tm); rtc_time64_to_tm(time, tm);
return 0; return 0;
} }
...@@ -249,13 +249,9 @@ static void armada38x_rtc_reset(struct armada38x_rtc *rtc) ...@@ -249,13 +249,9 @@ static void armada38x_rtc_reset(struct armada38x_rtc *rtc)
static int armada38x_rtc_set_time(struct device *dev, struct rtc_time *tm) static int armada38x_rtc_set_time(struct device *dev, struct rtc_time *tm)
{ {
struct armada38x_rtc *rtc = dev_get_drvdata(dev); struct armada38x_rtc *rtc = dev_get_drvdata(dev);
int ret = 0;
unsigned long time, flags; unsigned long time, flags;
ret = rtc_tm_to_time(tm, &time); time = rtc_tm_to_time64(tm);
if (ret)
goto out;
if (!rtc->initialized) if (!rtc->initialized)
armada38x_rtc_reset(rtc); armada38x_rtc_reset(rtc);
...@@ -264,8 +260,7 @@ static int armada38x_rtc_set_time(struct device *dev, struct rtc_time *tm) ...@@ -264,8 +260,7 @@ static int armada38x_rtc_set_time(struct device *dev, struct rtc_time *tm)
rtc_delayed_write(time, rtc, RTC_TIME); rtc_delayed_write(time, rtc, RTC_TIME);
spin_unlock_irqrestore(&rtc->lock, flags); spin_unlock_irqrestore(&rtc->lock, flags);
out: return 0;
return ret;
} }
static int armada38x_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) static int armada38x_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
...@@ -284,7 +279,7 @@ static int armada38x_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) ...@@ -284,7 +279,7 @@ static int armada38x_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
spin_unlock_irqrestore(&rtc->lock, flags); spin_unlock_irqrestore(&rtc->lock, flags);
alrm->enabled = val ? 1 : 0; alrm->enabled = val ? 1 : 0;
rtc_time_to_tm(time, &alrm->time); rtc_time64_to_tm(time, &alrm->time);
return 0; return 0;
} }
...@@ -295,12 +290,8 @@ static int armada38x_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) ...@@ -295,12 +290,8 @@ static int armada38x_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
u32 reg = ALARM_REG(RTC_ALARM1, rtc->data->alarm); u32 reg = ALARM_REG(RTC_ALARM1, rtc->data->alarm);
u32 reg_irq = ALARM_REG(RTC_IRQ1_CONF, rtc->data->alarm); u32 reg_irq = ALARM_REG(RTC_IRQ1_CONF, rtc->data->alarm);
unsigned long time, flags; unsigned long time, flags;
int ret = 0;
ret = rtc_tm_to_time(&alrm->time, &time); time = rtc_tm_to_time64(&alrm->time);
if (ret)
goto out;
spin_lock_irqsave(&rtc->lock, flags); spin_lock_irqsave(&rtc->lock, flags);
...@@ -313,8 +304,7 @@ static int armada38x_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) ...@@ -313,8 +304,7 @@ static int armada38x_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
spin_unlock_irqrestore(&rtc->lock, flags); spin_unlock_irqrestore(&rtc->lock, flags);
out: return 0;
return ret;
} }
static int armada38x_rtc_alarm_irq_enable(struct device *dev, static int armada38x_rtc_alarm_irq_enable(struct device *dev,
...@@ -514,7 +504,6 @@ MODULE_DEVICE_TABLE(of, armada38x_rtc_of_match_table); ...@@ -514,7 +504,6 @@ MODULE_DEVICE_TABLE(of, armada38x_rtc_of_match_table);
static __init int armada38x_rtc_probe(struct platform_device *pdev) static __init int armada38x_rtc_probe(struct platform_device *pdev)
{ {
const struct rtc_class_ops *ops;
struct resource *res; struct resource *res;
struct armada38x_rtc *rtc; struct armada38x_rtc *rtc;
const struct of_device_id *match; const struct of_device_id *match;
...@@ -551,6 +540,11 @@ static __init int armada38x_rtc_probe(struct platform_device *pdev) ...@@ -551,6 +540,11 @@ static __init int armada38x_rtc_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "no irq\n"); dev_err(&pdev->dev, "no irq\n");
return rtc->irq; return rtc->irq;
} }
rtc->rtc_dev = devm_rtc_allocate_device(&pdev->dev);
if (IS_ERR(rtc->rtc_dev))
return PTR_ERR(rtc->rtc_dev);
if (devm_request_irq(&pdev->dev, rtc->irq, armada38x_rtc_alarm_irq, if (devm_request_irq(&pdev->dev, rtc->irq, armada38x_rtc_alarm_irq,
0, pdev->name, rtc) < 0) { 0, pdev->name, rtc) < 0) {
dev_warn(&pdev->dev, "Interrupt not available.\n"); dev_warn(&pdev->dev, "Interrupt not available.\n");
...@@ -560,28 +554,26 @@ static __init int armada38x_rtc_probe(struct platform_device *pdev) ...@@ -560,28 +554,26 @@ static __init int armada38x_rtc_probe(struct platform_device *pdev)
if (rtc->irq != -1) { if (rtc->irq != -1) {
device_init_wakeup(&pdev->dev, 1); device_init_wakeup(&pdev->dev, 1);
ops = &armada38x_rtc_ops; rtc->rtc_dev->ops = &armada38x_rtc_ops;
} else { } else {
/* /*
* If there is no interrupt available then we can't * If there is no interrupt available then we can't
* use the alarm * use the alarm
*/ */
ops = &armada38x_rtc_ops_noirq; rtc->rtc_dev->ops = &armada38x_rtc_ops_noirq;
} }
rtc->data = (struct armada38x_rtc_data *)match->data; rtc->data = (struct armada38x_rtc_data *)match->data;
/* Update RTC-MBUS bridge timing parameters */ /* Update RTC-MBUS bridge timing parameters */
rtc->data->update_mbus_timing(rtc); rtc->data->update_mbus_timing(rtc);
rtc->rtc_dev = devm_rtc_device_register(&pdev->dev, pdev->name, rtc->rtc_dev->range_max = U32_MAX;
ops, THIS_MODULE);
if (IS_ERR(rtc->rtc_dev)) { ret = rtc_register_device(rtc->rtc_dev);
ret = PTR_ERR(rtc->rtc_dev); if (ret)
dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret); dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret);
return ret;
} return ret;
return 0;
} }
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
......
...@@ -50,6 +50,7 @@ ...@@ -50,6 +50,7 @@
/* this is for "generic access to PC-style RTC" using CMOS_READ/CMOS_WRITE */ /* this is for "generic access to PC-style RTC" using CMOS_READ/CMOS_WRITE */
#include <linux/mc146818rtc.h> #include <linux/mc146818rtc.h>
#ifdef CONFIG_ACPI
/* /*
* Use ACPI SCI to replace HPET interrupt for RTC Alarm event * Use ACPI SCI to replace HPET interrupt for RTC Alarm event
* *
...@@ -61,6 +62,18 @@ ...@@ -61,6 +62,18 @@
static bool use_acpi_alarm; static bool use_acpi_alarm;
module_param(use_acpi_alarm, bool, 0444); module_param(use_acpi_alarm, bool, 0444);
static inline int cmos_use_acpi_alarm(void)
{
return use_acpi_alarm;
}
#else /* !CONFIG_ACPI */
static inline int cmos_use_acpi_alarm(void)
{
return 0;
}
#endif
struct cmos_rtc { struct cmos_rtc {
struct rtc_device *rtc; struct rtc_device *rtc;
struct device *dev; struct device *dev;
...@@ -167,9 +180,9 @@ static inline int hpet_unregister_irq_handler(irq_handler_t handler) ...@@ -167,9 +180,9 @@ static inline int hpet_unregister_irq_handler(irq_handler_t handler)
#endif #endif
/* Don't use HPET for RTC Alarm event if ACPI Fixed event is used */ /* Don't use HPET for RTC Alarm event if ACPI Fixed event is used */
static int use_hpet_alarm(void) static inline int use_hpet_alarm(void)
{ {
return is_hpet_enabled() && !use_acpi_alarm; return is_hpet_enabled() && !cmos_use_acpi_alarm();
} }
/*----------------------------------------------------------------*/ /*----------------------------------------------------------------*/
...@@ -340,7 +353,7 @@ static void cmos_irq_enable(struct cmos_rtc *cmos, unsigned char mask) ...@@ -340,7 +353,7 @@ static void cmos_irq_enable(struct cmos_rtc *cmos, unsigned char mask)
if (use_hpet_alarm()) if (use_hpet_alarm())
hpet_set_rtc_irq_bit(mask); hpet_set_rtc_irq_bit(mask);
if ((mask & RTC_AIE) && use_acpi_alarm) { if ((mask & RTC_AIE) && cmos_use_acpi_alarm()) {
if (cmos->wake_on) if (cmos->wake_on)
cmos->wake_on(cmos->dev); cmos->wake_on(cmos->dev);
} }
...@@ -358,7 +371,7 @@ static void cmos_irq_disable(struct cmos_rtc *cmos, unsigned char mask) ...@@ -358,7 +371,7 @@ static void cmos_irq_disable(struct cmos_rtc *cmos, unsigned char mask)
if (use_hpet_alarm()) if (use_hpet_alarm())
hpet_mask_rtc_irq_bit(mask); hpet_mask_rtc_irq_bit(mask);
if ((mask & RTC_AIE) && use_acpi_alarm) { if ((mask & RTC_AIE) && cmos_use_acpi_alarm()) {
if (cmos->wake_off) if (cmos->wake_off)
cmos->wake_off(cmos->dev); cmos->wake_off(cmos->dev);
} }
...@@ -980,7 +993,7 @@ static int cmos_suspend(struct device *dev) ...@@ -980,7 +993,7 @@ static int cmos_suspend(struct device *dev)
} }
spin_unlock_irq(&rtc_lock); spin_unlock_irq(&rtc_lock);
if ((tmp & RTC_AIE) && !use_acpi_alarm) { if ((tmp & RTC_AIE) && !cmos_use_acpi_alarm()) {
cmos->enabled_wake = 1; cmos->enabled_wake = 1;
if (cmos->wake_on) if (cmos->wake_on)
cmos->wake_on(dev); cmos->wake_on(dev);
...@@ -1031,7 +1044,7 @@ static void cmos_check_wkalrm(struct device *dev) ...@@ -1031,7 +1044,7 @@ static void cmos_check_wkalrm(struct device *dev)
* ACPI RTC wake event is cleared after resume from STR, * ACPI RTC wake event is cleared after resume from STR,
* ACK the rtc irq here * ACK the rtc irq here
*/ */
if (t_now >= cmos->alarm_expires && use_acpi_alarm) { if (t_now >= cmos->alarm_expires && cmos_use_acpi_alarm()) {
cmos_interrupt(0, (void *)cmos->rtc); cmos_interrupt(0, (void *)cmos->rtc);
return; return;
} }
...@@ -1053,7 +1066,7 @@ static int __maybe_unused cmos_resume(struct device *dev) ...@@ -1053,7 +1066,7 @@ static int __maybe_unused cmos_resume(struct device *dev)
struct cmos_rtc *cmos = dev_get_drvdata(dev); struct cmos_rtc *cmos = dev_get_drvdata(dev);
unsigned char tmp; unsigned char tmp;
if (cmos->enabled_wake && !use_acpi_alarm) { if (cmos->enabled_wake && !cmos_use_acpi_alarm()) {
if (cmos->wake_off) if (cmos->wake_off)
cmos->wake_off(dev); cmos->wake_off(dev);
else else
...@@ -1132,7 +1145,7 @@ static u32 rtc_handler(void *context) ...@@ -1132,7 +1145,7 @@ static u32 rtc_handler(void *context)
* Or else, ACPI SCI is enabled during suspend/resume only, * Or else, ACPI SCI is enabled during suspend/resume only,
* update rtc irq in that case. * update rtc irq in that case.
*/ */
if (use_acpi_alarm) if (cmos_use_acpi_alarm())
cmos_interrupt(0, (void *)cmos->rtc); cmos_interrupt(0, (void *)cmos->rtc);
else { else {
/* Fix me: can we use cmos_interrupt() here as well? */ /* Fix me: can we use cmos_interrupt() here as well? */
......
...@@ -40,23 +40,9 @@ static inline void rtc_proc_del_device(struct rtc_device *rtc) ...@@ -40,23 +40,9 @@ static inline void rtc_proc_del_device(struct rtc_device *rtc)
#ifdef CONFIG_RTC_INTF_SYSFS #ifdef CONFIG_RTC_INTF_SYSFS
const struct attribute_group **rtc_get_dev_attribute_groups(void); const struct attribute_group **rtc_get_dev_attribute_groups(void);
int rtc_add_group(struct rtc_device *rtc, const struct attribute_group *grp);
int rtc_add_groups(struct rtc_device *rtc, const struct attribute_group **grps);
#else #else
static inline const struct attribute_group **rtc_get_dev_attribute_groups(void) static inline const struct attribute_group **rtc_get_dev_attribute_groups(void)
{ {
return NULL; return NULL;
} }
static inline
int rtc_add_group(struct rtc_device *rtc, const struct attribute_group *grp)
{
return 0;
}
static inline
int rtc_add_groups(struct rtc_device *rtc, const struct attribute_group **grps)
{
return 0;
}
#endif #endif
...@@ -114,6 +114,20 @@ enum ds_type { ...@@ -114,6 +114,20 @@ enum ds_type {
# define RX8025_BIT_VDET 0x40 # define RX8025_BIT_VDET 0x40
# define RX8025_BIT_XST 0x20 # define RX8025_BIT_XST 0x20
#define M41TXX_REG_CONTROL 0x07
# define M41TXX_BIT_OUT BIT(7)
# define M41TXX_BIT_FT BIT(6)
# define M41TXX_BIT_CALIB_SIGN BIT(5)
# define M41TXX_M_CALIBRATION GENMASK(4, 0)
/* negative offset step is -2.034ppm */
#define M41TXX_NEG_OFFSET_STEP_PPB 2034
/* positive offset step is +4.068ppm */
#define M41TXX_POS_OFFSET_STEP_PPB 4068
/* Min and max values supported with 'offset' interface by M41TXX */
#define M41TXX_MIN_OFFSET ((-31) * M41TXX_NEG_OFFSET_STEP_PPB)
#define M41TXX_MAX_OFFSET ((31) * M41TXX_POS_OFFSET_STEP_PPB)
struct ds1307 { struct ds1307 {
enum ds_type type; enum ds_type type;
unsigned long flags; unsigned long flags;
...@@ -146,6 +160,9 @@ struct chip_desc { ...@@ -146,6 +160,9 @@ struct chip_desc {
static int ds1307_get_time(struct device *dev, struct rtc_time *t); static int ds1307_get_time(struct device *dev, struct rtc_time *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);
static int ds1337_read_alarm(struct device *dev, struct rtc_wkalrm *t);
static int ds1337_set_alarm(struct device *dev, struct rtc_wkalrm *t);
static int ds1307_alarm_irq_enable(struct device *dev, unsigned int enabled);
static u8 do_trickle_setup_ds1339(struct ds1307 *, u32 ohms, bool diode); static u8 do_trickle_setup_ds1339(struct ds1307 *, u32 ohms, bool diode);
static irqreturn_t rx8130_irq(int irq, void *dev_id); static irqreturn_t rx8130_irq(int irq, void *dev_id);
static int rx8130_read_alarm(struct device *dev, struct rtc_wkalrm *t); static int rx8130_read_alarm(struct device *dev, struct rtc_wkalrm *t);
...@@ -155,6 +172,8 @@ static irqreturn_t mcp794xx_irq(int irq, void *dev_id); ...@@ -155,6 +172,8 @@ static irqreturn_t mcp794xx_irq(int irq, void *dev_id);
static int mcp794xx_read_alarm(struct device *dev, struct rtc_wkalrm *t); static int mcp794xx_read_alarm(struct device *dev, struct rtc_wkalrm *t);
static int mcp794xx_set_alarm(struct device *dev, struct rtc_wkalrm *t); static int mcp794xx_set_alarm(struct device *dev, struct rtc_wkalrm *t);
static int mcp794xx_alarm_irq_enable(struct device *dev, unsigned int enabled); static int mcp794xx_alarm_irq_enable(struct device *dev, unsigned int enabled);
static int m41txx_rtc_read_offset(struct device *dev, long *offset);
static int m41txx_rtc_set_offset(struct device *dev, long offset);
static const struct rtc_class_ops rx8130_rtc_ops = { static const struct rtc_class_ops rx8130_rtc_ops = {
.read_time = ds1307_get_time, .read_time = ds1307_get_time,
...@@ -172,6 +191,16 @@ static const struct rtc_class_ops mcp794xx_rtc_ops = { ...@@ -172,6 +191,16 @@ static const struct rtc_class_ops mcp794xx_rtc_ops = {
.alarm_irq_enable = mcp794xx_alarm_irq_enable, .alarm_irq_enable = mcp794xx_alarm_irq_enable,
}; };
static const struct rtc_class_ops m41txx_rtc_ops = {
.read_time = ds1307_get_time,
.set_time = ds1307_set_time,
.read_alarm = ds1337_read_alarm,
.set_alarm = ds1337_set_alarm,
.alarm_irq_enable = ds1307_alarm_irq_enable,
.read_offset = m41txx_rtc_read_offset,
.set_offset = m41txx_rtc_set_offset,
};
static const struct chip_desc chips[last_ds_type] = { static const struct chip_desc chips[last_ds_type] = {
[ds_1307] = { [ds_1307] = {
.nvram_offset = 8, .nvram_offset = 8,
...@@ -228,10 +257,17 @@ static const struct chip_desc chips[last_ds_type] = { ...@@ -228,10 +257,17 @@ static const struct chip_desc chips[last_ds_type] = {
.irq_handler = rx8130_irq, .irq_handler = rx8130_irq,
.rtc_ops = &rx8130_rtc_ops, .rtc_ops = &rx8130_rtc_ops,
}, },
[m41t0] = {
.rtc_ops = &m41txx_rtc_ops,
},
[m41t00] = {
.rtc_ops = &m41txx_rtc_ops,
},
[m41t11] = { [m41t11] = {
/* this is battery backed SRAM */ /* this is battery backed SRAM */
.nvram_offset = 8, .nvram_offset = 8,
.nvram_size = 56, .nvram_size = 56,
.rtc_ops = &m41txx_rtc_ops,
}, },
[mcp794xx] = { [mcp794xx] = {
.alarm = 1, .alarm = 1,
...@@ -973,6 +1009,110 @@ static int mcp794xx_alarm_irq_enable(struct device *dev, unsigned int enabled) ...@@ -973,6 +1009,110 @@ static int mcp794xx_alarm_irq_enable(struct device *dev, unsigned int enabled)
enabled ? MCP794XX_BIT_ALM0_EN : 0); enabled ? MCP794XX_BIT_ALM0_EN : 0);
} }
static int m41txx_rtc_read_offset(struct device *dev, long *offset)
{
struct ds1307 *ds1307 = dev_get_drvdata(dev);
unsigned int ctrl_reg;
u8 val;
regmap_read(ds1307->regmap, M41TXX_REG_CONTROL, &ctrl_reg);
val = ctrl_reg & M41TXX_M_CALIBRATION;
/* check if positive */
if (ctrl_reg & M41TXX_BIT_CALIB_SIGN)
*offset = (val * M41TXX_POS_OFFSET_STEP_PPB);
else
*offset = -(val * M41TXX_NEG_OFFSET_STEP_PPB);
return 0;
}
static int m41txx_rtc_set_offset(struct device *dev, long offset)
{
struct ds1307 *ds1307 = dev_get_drvdata(dev);
unsigned int ctrl_reg;
if ((offset < M41TXX_MIN_OFFSET) || (offset > M41TXX_MAX_OFFSET))
return -ERANGE;
if (offset >= 0) {
ctrl_reg = DIV_ROUND_CLOSEST(offset,
M41TXX_POS_OFFSET_STEP_PPB);
ctrl_reg |= M41TXX_BIT_CALIB_SIGN;
} else {
ctrl_reg = DIV_ROUND_CLOSEST(abs(offset),
M41TXX_NEG_OFFSET_STEP_PPB);
}
return regmap_update_bits(ds1307->regmap, M41TXX_REG_CONTROL,
M41TXX_M_CALIBRATION | M41TXX_BIT_CALIB_SIGN,
ctrl_reg);
}
static ssize_t frequency_test_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct ds1307 *ds1307 = dev_get_drvdata(dev->parent);
bool freq_test_en;
int ret;
ret = kstrtobool(buf, &freq_test_en);
if (ret) {
dev_err(dev, "Failed to store RTC Frequency Test attribute\n");
return ret;
}
regmap_update_bits(ds1307->regmap, M41TXX_REG_CONTROL, M41TXX_BIT_FT,
freq_test_en ? M41TXX_BIT_FT : 0);
return count;
}
static ssize_t frequency_test_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct ds1307 *ds1307 = dev_get_drvdata(dev->parent);
unsigned int ctrl_reg;
regmap_read(ds1307->regmap, M41TXX_REG_CONTROL, &ctrl_reg);
return scnprintf(buf, PAGE_SIZE, (ctrl_reg & M41TXX_BIT_FT) ? "on\n" :
"off\n");
}
static DEVICE_ATTR_RW(frequency_test);
static struct attribute *rtc_freq_test_attrs[] = {
&dev_attr_frequency_test.attr,
NULL,
};
static const struct attribute_group rtc_freq_test_attr_group = {
.attrs = rtc_freq_test_attrs,
};
static int ds1307_add_frequency_test(struct ds1307 *ds1307)
{
int err;
switch (ds1307->type) {
case m41t0:
case m41t00:
case m41t11:
err = rtc_add_group(ds1307->rtc, &rtc_freq_test_attr_group);
if (err)
return err;
break;
default:
break;
}
return 0;
}
/*----------------------------------------------------------------------*/ /*----------------------------------------------------------------------*/
static int ds1307_nvram_read(void *priv, unsigned int offset, void *val, static int ds1307_nvram_read(void *priv, unsigned int offset, void *val,
...@@ -1384,7 +1524,6 @@ static void ds1307_clks_register(struct ds1307 *ds1307) ...@@ -1384,7 +1524,6 @@ static void ds1307_clks_register(struct ds1307 *ds1307)
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 = 0x9,
}; };
static int ds1307_probe(struct i2c_client *client, static int ds1307_probe(struct i2c_client *client,
...@@ -1711,6 +1850,10 @@ static int ds1307_probe(struct i2c_client *client, ...@@ -1711,6 +1850,10 @@ static int ds1307_probe(struct i2c_client *client,
} }
ds1307->rtc->ops = chip->rtc_ops ?: &ds13xx_rtc_ops; ds1307->rtc->ops = chip->rtc_ops ?: &ds13xx_rtc_ops;
err = ds1307_add_frequency_test(ds1307);
if (err)
return err;
err = rtc_register_device(ds1307->rtc); err = rtc_register_device(ds1307->rtc);
if (err) if (err)
return err; return err;
......
...@@ -770,33 +770,6 @@ static const char *ds1685_rtc_sqw_freq[16] = { ...@@ -770,33 +770,6 @@ static const char *ds1685_rtc_sqw_freq[16] = {
"512Hz", "256Hz", "128Hz", "64Hz", "32Hz", "16Hz", "8Hz", "4Hz", "2Hz" "512Hz", "256Hz", "128Hz", "64Hz", "32Hz", "16Hz", "8Hz", "4Hz", "2Hz"
}; };
#ifdef CONFIG_RTC_DS1685_PROC_REGS
/**
* ds1685_rtc_print_regs - helper function to print register values.
* @hex: hex byte to convert into binary bits.
* @dest: destination char array.
*
* This is basically a hex->binary function, just with extra spacing between
* the digits. It only works on 1-byte values (8 bits).
*/
static char*
ds1685_rtc_print_regs(u8 hex, char *dest)
{
u32 i, j;
char *tmp = dest;
for (i = 0; i < NUM_BITS; i++) {
*tmp++ = ((hex & 0x80) != 0 ? '1' : '0');
for (j = 0; j < NUM_SPACES; j++)
*tmp++ = ' ';
hex <<= 1;
}
*tmp++ = '\0';
return dest;
}
#endif
/** /**
* ds1685_rtc_proc - procfs access function. * ds1685_rtc_proc - procfs access function.
* @dev: pointer to device structure. * @dev: pointer to device structure.
...@@ -805,13 +778,9 @@ ds1685_rtc_print_regs(u8 hex, char *dest) ...@@ -805,13 +778,9 @@ ds1685_rtc_print_regs(u8 hex, char *dest)
static int static int
ds1685_rtc_proc(struct device *dev, struct seq_file *seq) ds1685_rtc_proc(struct device *dev, struct seq_file *seq)
{ {
struct platform_device *pdev = to_platform_device(dev); struct ds1685_priv *rtc = dev_get_drvdata(dev);
struct ds1685_priv *rtc = platform_get_drvdata(pdev);
u8 ctrla, ctrlb, ctrlc, ctrld, ctrl4a, ctrl4b, ssn[8]; u8 ctrla, ctrlb, ctrlc, ctrld, ctrl4a, ctrl4b, ssn[8];
char *model; char *model;
#ifdef CONFIG_RTC_DS1685_PROC_REGS
char bits[NUM_REGS][(NUM_BITS * NUM_SPACES) + NUM_BITS + 1];
#endif
/* Read all the relevant data from the control registers. */ /* Read all the relevant data from the control registers. */
ds1685_rtc_switch_to_bank1(rtc); ds1685_rtc_switch_to_bank1(rtc);
...@@ -859,28 +828,7 @@ ds1685_rtc_proc(struct device *dev, struct seq_file *seq) ...@@ -859,28 +828,7 @@ ds1685_rtc_proc(struct device *dev, struct seq_file *seq)
"Periodic IRQ\t: %s\n" "Periodic IRQ\t: %s\n"
"Periodic Rate\t: %s\n" "Periodic Rate\t: %s\n"
"SQW Freq\t: %s\n" "SQW Freq\t: %s\n"
#ifdef CONFIG_RTC_DS1685_PROC_REGS
"Serial #\t: %8phC\n"
"Register Status\t:\n"
" Ctrl A\t: UIP DV2 DV1 DV0 RS3 RS2 RS1 RS0\n"
"\t\t: %s\n"
" Ctrl B\t: SET PIE AIE UIE SQWE DM 2412 DSE\n"
"\t\t: %s\n"
" Ctrl C\t: IRQF PF AF UF --- --- --- ---\n"
"\t\t: %s\n"
" Ctrl D\t: VRT --- --- --- --- --- --- ---\n"
"\t\t: %s\n"
#if !defined(CONFIG_RTC_DRV_DS1685) && !defined(CONFIG_RTC_DRV_DS1689)
" Ctrl 4A\t: VRT2 INCR BME --- PAB RF WF KF\n"
#else
" Ctrl 4A\t: VRT2 INCR --- --- PAB RF WF KF\n"
#endif
"\t\t: %s\n"
" Ctrl 4B\t: ABE E32k CS RCE PRS RIE WIE KSE\n"
"\t\t: %s\n",
#else
"Serial #\t: %8phC\n", "Serial #\t: %8phC\n",
#endif
model, model,
((ctrla & RTC_CTRL_A_DV1) ? "enabled" : "disabled"), ((ctrla & RTC_CTRL_A_DV1) ? "enabled" : "disabled"),
((ctrlb & RTC_CTRL_B_2412) ? "24-hour" : "12-hour"), ((ctrlb & RTC_CTRL_B_2412) ? "24-hour" : "12-hour"),
...@@ -894,17 +842,7 @@ ds1685_rtc_proc(struct device *dev, struct seq_file *seq) ...@@ -894,17 +842,7 @@ ds1685_rtc_proc(struct device *dev, struct seq_file *seq)
ds1685_rtc_pirq_rate[(ctrla & RTC_CTRL_A_RS_MASK)] : "none"), ds1685_rtc_pirq_rate[(ctrla & RTC_CTRL_A_RS_MASK)] : "none"),
(!((ctrl4b & RTC_CTRL_4B_E32K)) ? (!((ctrl4b & RTC_CTRL_4B_E32K)) ?
ds1685_rtc_sqw_freq[(ctrla & RTC_CTRL_A_RS_MASK)] : "32768Hz"), ds1685_rtc_sqw_freq[(ctrla & RTC_CTRL_A_RS_MASK)] : "32768Hz"),
#ifdef CONFIG_RTC_DS1685_PROC_REGS
ssn,
ds1685_rtc_print_regs(ctrla, bits[0]),
ds1685_rtc_print_regs(ctrlb, bits[1]),
ds1685_rtc_print_regs(ctrlc, bits[2]),
ds1685_rtc_print_regs(ctrld, bits[3]),
ds1685_rtc_print_regs(ctrl4a, bits[4]),
ds1685_rtc_print_regs(ctrl4b, bits[5]));
#else
ssn); ssn);
#endif
return 0; return 0;
} }
#else #else
...@@ -927,30 +865,13 @@ ds1685_rtc_ops = { ...@@ -927,30 +865,13 @@ ds1685_rtc_ops = {
}; };
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
static int ds1685_nvram_read(void *priv, unsigned int pos, void *val,
/* ----------------------------------------------------------------------- */ size_t size)
/* SysFS interface */
#ifdef CONFIG_SYSFS
/**
* ds1685_rtc_sysfs_nvram_read - reads rtc nvram via sysfs.
* @file: pointer to file structure.
* @kobj: pointer to kobject structure.
* @bin_attr: pointer to bin_attribute structure.
* @buf: pointer to char array to hold the output.
* @pos: current file position pointer.
* @size: size of the data to read.
*/
static ssize_t
ds1685_rtc_sysfs_nvram_read(struct file *filp, struct kobject *kobj,
struct bin_attribute *bin_attr, char *buf,
loff_t pos, size_t size)
{ {
struct platform_device *pdev = struct ds1685_priv *rtc = priv;
to_platform_device(container_of(kobj, struct device, kobj));
struct ds1685_priv *rtc = platform_get_drvdata(pdev);
ssize_t count; ssize_t count;
unsigned long flags = 0; unsigned long flags = 0;
u8 *buf = val;
spin_lock_irqsave(&rtc->lock, flags); spin_lock_irqsave(&rtc->lock, flags);
ds1685_rtc_switch_to_bank0(rtc); ds1685_rtc_switch_to_bank0(rtc);
...@@ -1004,33 +925,16 @@ ds1685_rtc_sysfs_nvram_read(struct file *filp, struct kobject *kobj, ...@@ -1004,33 +925,16 @@ ds1685_rtc_sysfs_nvram_read(struct file *filp, struct kobject *kobj,
#endif /* !CONFIG_RTC_DRV_DS1689 */ #endif /* !CONFIG_RTC_DRV_DS1689 */
spin_unlock_irqrestore(&rtc->lock, flags); spin_unlock_irqrestore(&rtc->lock, flags);
/* return 0;
* XXX: Bug? this appears to cause the function to get executed
* several times in succession. But it's the only way to actually get
* data written out to a file.
*/
return count;
} }
/** static int ds1685_nvram_write(void *priv, unsigned int pos, void *val,
* ds1685_rtc_sysfs_nvram_write - writes rtc nvram via sysfs. size_t size)
* @file: pointer to file structure.
* @kobj: pointer to kobject structure.
* @bin_attr: pointer to bin_attribute structure.
* @buf: pointer to char array to hold the input.
* @pos: current file position pointer.
* @size: size of the data to write.
*/
static ssize_t
ds1685_rtc_sysfs_nvram_write(struct file *filp, struct kobject *kobj,
struct bin_attribute *bin_attr, char *buf,
loff_t pos, size_t size)
{ {
struct platform_device *pdev = struct ds1685_priv *rtc = priv;
to_platform_device(container_of(kobj, struct device, kobj));
struct ds1685_priv *rtc = platform_get_drvdata(pdev);
ssize_t count; ssize_t count;
unsigned long flags = 0; unsigned long flags = 0;
u8 *buf = val;
spin_lock_irqsave(&rtc->lock, flags); spin_lock_irqsave(&rtc->lock, flags);
ds1685_rtc_switch_to_bank0(rtc); ds1685_rtc_switch_to_bank0(rtc);
...@@ -1084,26 +988,11 @@ ds1685_rtc_sysfs_nvram_write(struct file *filp, struct kobject *kobj, ...@@ -1084,26 +988,11 @@ ds1685_rtc_sysfs_nvram_write(struct file *filp, struct kobject *kobj,
#endif /* !CONFIG_RTC_DRV_DS1689 */ #endif /* !CONFIG_RTC_DRV_DS1689 */
spin_unlock_irqrestore(&rtc->lock, flags); spin_unlock_irqrestore(&rtc->lock, flags);
return count; return 0;
} }
/** /* ----------------------------------------------------------------------- */
* struct ds1685_rtc_sysfs_nvram_attr - sysfs attributes for rtc nvram. /* SysFS interface */
* @attr: nvram attributes.
* @read: nvram read function.
* @write: nvram write function.
* @size: nvram total size (bank0 + extended).
*/
static struct bin_attribute
ds1685_rtc_sysfs_nvram_attr = {
.attr = {
.name = "nvram",
.mode = S_IRUGO | S_IWUSR,
},
.read = ds1685_rtc_sysfs_nvram_read,
.write = ds1685_rtc_sysfs_nvram_write,
.size = NVRAM_TOTAL_SZ
};
/** /**
* ds1685_rtc_sysfs_battery_show - sysfs file for main battery status. * ds1685_rtc_sysfs_battery_show - sysfs file for main battery status.
...@@ -1188,43 +1077,6 @@ ds1685_rtc_sysfs_misc_grp = { ...@@ -1188,43 +1077,6 @@ ds1685_rtc_sysfs_misc_grp = {
.attrs = ds1685_rtc_sysfs_misc_attrs, .attrs = ds1685_rtc_sysfs_misc_attrs,
}; };
/**
* ds1685_rtc_sysfs_register - register sysfs files.
* @dev: pointer to device structure.
*/
static int
ds1685_rtc_sysfs_register(struct device *dev)
{
int ret = 0;
sysfs_bin_attr_init(&ds1685_rtc_sysfs_nvram_attr);
ret = sysfs_create_bin_file(&dev->kobj, &ds1685_rtc_sysfs_nvram_attr);
if (ret)
return ret;
ret = sysfs_create_group(&dev->kobj, &ds1685_rtc_sysfs_misc_grp);
if (ret)
return ret;
return 0;
}
/**
* ds1685_rtc_sysfs_unregister - unregister sysfs files.
* @dev: pointer to device structure.
*/
static int
ds1685_rtc_sysfs_unregister(struct device *dev)
{
sysfs_remove_bin_file(&dev->kobj, &ds1685_rtc_sysfs_nvram_attr);
sysfs_remove_group(&dev->kobj, &ds1685_rtc_sysfs_misc_grp);
return 0;
}
#endif /* CONFIG_SYSFS */
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
/* Driver Probe/Removal */ /* Driver Probe/Removal */
...@@ -1242,6 +1094,12 @@ ds1685_rtc_probe(struct platform_device *pdev) ...@@ -1242,6 +1094,12 @@ ds1685_rtc_probe(struct platform_device *pdev)
u8 ctrla, ctrlb, hours; u8 ctrla, ctrlb, hours;
unsigned char am_pm; unsigned char am_pm;
int ret = 0; int ret = 0;
struct nvmem_config nvmem_cfg = {
.name = "ds1685_nvram",
.size = NVRAM_TOTAL_SZ,
.reg_read = ds1685_nvram_read,
.reg_write = ds1685_nvram_write,
};
/* Get the platform data. */ /* Get the platform data. */
pdata = (struct ds1685_rtc_platform_data *) pdev->dev.platform_data; pdata = (struct ds1685_rtc_platform_data *) pdev->dev.platform_data;
...@@ -1499,11 +1357,15 @@ ds1685_rtc_probe(struct platform_device *pdev) ...@@ -1499,11 +1357,15 @@ ds1685_rtc_probe(struct platform_device *pdev)
/* Setup complete. */ /* Setup complete. */
ds1685_rtc_switch_to_bank0(rtc); ds1685_rtc_switch_to_bank0(rtc);
#ifdef CONFIG_SYSFS ret = rtc_add_group(rtc_dev, &ds1685_rtc_sysfs_misc_grp);
ret = ds1685_rtc_sysfs_register(&pdev->dev); if (ret)
return ret;
rtc_dev->nvram_old_abi = true;
nvmem_cfg.priv = rtc;
ret = rtc_nvmem_register(rtc_dev, &nvmem_cfg);
if (ret) if (ret)
return ret; return ret;
#endif
return rtc_register_device(rtc_dev); return rtc_register_device(rtc_dev);
} }
...@@ -1517,10 +1379,6 @@ ds1685_rtc_remove(struct platform_device *pdev) ...@@ -1517,10 +1379,6 @@ ds1685_rtc_remove(struct platform_device *pdev)
{ {
struct ds1685_priv *rtc = platform_get_drvdata(pdev); struct ds1685_priv *rtc = platform_get_drvdata(pdev);
#ifdef CONFIG_SYSFS
ds1685_rtc_sysfs_unregister(&pdev->dev);
#endif
/* Read Ctrl B and clear PIE/AIE/UIE. */ /* Read Ctrl B and clear PIE/AIE/UIE. */
rtc->write(rtc, RTC_CTRL_B, rtc->write(rtc, RTC_CTRL_B,
(rtc->read(rtc, RTC_CTRL_B) & (rtc->read(rtc, RTC_CTRL_B) &
......
...@@ -10,12 +10,11 @@ ...@@ -10,12 +10,11 @@
* *
*/ */
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/bcd.h> #include <linux/bcd.h>
#include <linux/rtc.h> #include <linux/i2c.h>
#include "rtc-core.h" #include <linux/module.h>
#include <linux/of_irq.h> #include <linux/of_irq.h>
#include <linux/rtc.h>
/* Register map */ /* Register map */
/* rtc section */ /* rtc section */
...@@ -518,7 +517,7 @@ static ssize_t timestamp0_store(struct device *dev, ...@@ -518,7 +517,7 @@ static ssize_t timestamp0_store(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr,
const char *buf, size_t count) const char *buf, size_t count)
{ {
struct i2c_client *client = dev_get_drvdata(dev); struct i2c_client *client = to_i2c_client(dev->parent);
int sr; int sr;
sr = isl1208_i2c_get_sr(client); sr = isl1208_i2c_get_sr(client);
...@@ -540,7 +539,7 @@ static ssize_t timestamp0_store(struct device *dev, ...@@ -540,7 +539,7 @@ static ssize_t timestamp0_store(struct device *dev,
static ssize_t timestamp0_show(struct device *dev, static ssize_t timestamp0_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct i2c_client *client = dev_get_drvdata(dev); struct i2c_client *client = to_i2c_client(dev->parent);
u8 regs[ISL1219_EVT_SECTION_LEN] = { 0, }; u8 regs[ISL1219_EVT_SECTION_LEN] = { 0, };
struct rtc_time tm; struct rtc_time tm;
int sr; int sr;
...@@ -650,7 +649,7 @@ static ssize_t ...@@ -650,7 +649,7 @@ static ssize_t
isl1208_sysfs_show_atrim(struct device *dev, isl1208_sysfs_show_atrim(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
int atr = isl1208_i2c_get_atr(to_i2c_client(dev)); int atr = isl1208_i2c_get_atr(to_i2c_client(dev->parent));
if (atr < 0) if (atr < 0)
return atr; return atr;
...@@ -663,7 +662,7 @@ static ssize_t ...@@ -663,7 +662,7 @@ static ssize_t
isl1208_sysfs_show_dtrim(struct device *dev, isl1208_sysfs_show_dtrim(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
int dtr = isl1208_i2c_get_dtr(to_i2c_client(dev)); int dtr = isl1208_i2c_get_dtr(to_i2c_client(dev->parent));
if (dtr < 0) if (dtr < 0)
return dtr; return dtr;
...@@ -676,7 +675,7 @@ static ssize_t ...@@ -676,7 +675,7 @@ static ssize_t
isl1208_sysfs_show_usr(struct device *dev, isl1208_sysfs_show_usr(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
int usr = isl1208_i2c_get_usr(to_i2c_client(dev)); int usr = isl1208_i2c_get_usr(to_i2c_client(dev->parent));
if (usr < 0) if (usr < 0)
return usr; return usr;
...@@ -701,7 +700,10 @@ isl1208_sysfs_store_usr(struct device *dev, ...@@ -701,7 +700,10 @@ isl1208_sysfs_store_usr(struct device *dev,
if (usr < 0 || usr > 0xffff) if (usr < 0 || usr > 0xffff)
return -EINVAL; return -EINVAL;
return isl1208_i2c_set_usr(to_i2c_client(dev), usr) ? -EIO : count; if (isl1208_i2c_set_usr(to_i2c_client(dev->parent), usr))
return -EIO;
return count;
} }
static DEVICE_ATTR(usr, S_IRUGO | S_IWUSR, isl1208_sysfs_show_usr, static DEVICE_ATTR(usr, S_IRUGO | S_IWUSR, isl1208_sysfs_show_usr,
...@@ -765,7 +767,6 @@ isl1208_probe(struct i2c_client *client, const struct i2c_device_id *id) ...@@ -765,7 +767,6 @@ isl1208_probe(struct i2c_client *client, const struct i2c_device_id *id)
rtc->ops = &isl1208_rtc_ops; rtc->ops = &isl1208_rtc_ops;
i2c_set_clientdata(client, rtc); i2c_set_clientdata(client, rtc);
dev_set_drvdata(&rtc->dev, client);
rc = isl1208_i2c_get_sr(client); rc = isl1208_i2c_get_sr(client);
if (rc < 0) { if (rc < 0) {
...@@ -804,7 +805,7 @@ isl1208_probe(struct i2c_client *client, const struct i2c_device_id *id) ...@@ -804,7 +805,7 @@ isl1208_probe(struct i2c_client *client, const struct i2c_device_id *id)
evdet_irq = of_irq_get_byname(np, "evdet"); evdet_irq = of_irq_get_byname(np, "evdet");
} }
rc = sysfs_create_group(&client->dev.kobj, &isl1208_rtc_sysfs_files); rc = rtc_add_group(rtc, &isl1208_rtc_sysfs_files);
if (rc) if (rc)
return rc; return rc;
...@@ -821,14 +822,6 @@ isl1208_probe(struct i2c_client *client, const struct i2c_device_id *id) ...@@ -821,14 +822,6 @@ isl1208_probe(struct i2c_client *client, const struct i2c_device_id *id)
return rtc_register_device(rtc); return rtc_register_device(rtc);
} }
static int
isl1208_remove(struct i2c_client *client)
{
sysfs_remove_group(&client->dev.kobj, &isl1208_rtc_sysfs_files);
return 0;
}
static const struct i2c_device_id isl1208_id[] = { static const struct i2c_device_id isl1208_id[] = {
{ "isl1208", TYPE_ISL1208 }, { "isl1208", TYPE_ISL1208 },
{ "isl1218", TYPE_ISL1218 }, { "isl1218", TYPE_ISL1218 },
...@@ -851,7 +844,6 @@ static struct i2c_driver isl1208_driver = { ...@@ -851,7 +844,6 @@ static struct i2c_driver isl1208_driver = {
.of_match_table = of_match_ptr(isl1208_of_match), .of_match_table = of_match_ptr(isl1208_of_match),
}, },
.probe = isl1208_probe, .probe = isl1208_probe,
.remove = isl1208_remove,
.id_table = isl1208_id, .id_table = isl1208_id,
}; };
......
...@@ -47,7 +47,7 @@ EXPORT_SYMBOL(rtc_year_days); ...@@ -47,7 +47,7 @@ EXPORT_SYMBOL(rtc_year_days);
/* /*
* rtc_time_to_tm64 - Converts time64_t to rtc_time. * rtc_time64_to_tm - Converts time64_t to rtc_time.
* Convert seconds since 01-01-1970 00:00:00 to Gregorian date. * Convert seconds since 01-01-1970 00:00:00 to Gregorian date.
*/ */
void rtc_time64_to_tm(time64_t time, struct rtc_time *tm) void rtc_time64_to_tm(time64_t time, struct rtc_time *tm)
......
...@@ -745,7 +745,7 @@ static int wdt_ioctl(struct file *file, unsigned int cmd, ...@@ -745,7 +745,7 @@ static int wdt_ioctl(struct file *file, unsigned int cmd,
return -EINVAL; return -EINVAL;
wdt_margin = new_margin; wdt_margin = new_margin;
wdt_ping(); wdt_ping();
/* Fall */ /* Fall through */
case WDIOC_GETTIMEOUT: case WDIOC_GETTIMEOUT:
return put_user(wdt_margin, (int __user *)arg); return put_user(wdt_margin, (int __user *)arg);
......
...@@ -90,7 +90,7 @@ static int mrst_read_time(struct device *dev, struct rtc_time *time) ...@@ -90,7 +90,7 @@ static int mrst_read_time(struct device *dev, struct rtc_time *time)
unsigned long flags; unsigned long flags;
if (vrtc_is_updating()) if (vrtc_is_updating())
mdelay(20); msleep(20);
spin_lock_irqsave(&rtc_lock, flags); spin_lock_irqsave(&rtc_lock, flags);
time->tm_sec = vrtc_cmos_read(RTC_SECONDS); time->tm_sec = vrtc_cmos_read(RTC_SECONDS);
...@@ -261,11 +261,10 @@ static int mrst_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) ...@@ -261,11 +261,10 @@ static int mrst_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
static int mrst_procfs(struct device *dev, struct seq_file *seq) static int mrst_procfs(struct device *dev, struct seq_file *seq)
{ {
unsigned char rtc_control, valid; unsigned char rtc_control;
spin_lock_irq(&rtc_lock); spin_lock_irq(&rtc_lock);
rtc_control = vrtc_cmos_read(RTC_CONTROL); rtc_control = vrtc_cmos_read(RTC_CONTROL);
valid = vrtc_cmos_read(RTC_VALID);
spin_unlock_irq(&rtc_lock); spin_unlock_irq(&rtc_lock);
seq_printf(seq, seq_printf(seq,
......
...@@ -332,6 +332,10 @@ static int mtk_rtc_probe(struct platform_device *pdev) ...@@ -332,6 +332,10 @@ static int mtk_rtc_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, rtc); platform_set_drvdata(pdev, rtc);
rtc->rtc_dev = devm_rtc_allocate_device(rtc->dev);
if (IS_ERR(rtc->rtc_dev))
return PTR_ERR(rtc->rtc_dev);
ret = request_threaded_irq(rtc->irq, NULL, ret = request_threaded_irq(rtc->irq, NULL,
mtk_rtc_irq_handler_thread, mtk_rtc_irq_handler_thread,
IRQF_ONESHOT | IRQF_TRIGGER_HIGH, IRQF_ONESHOT | IRQF_TRIGGER_HIGH,
...@@ -344,11 +348,11 @@ static int mtk_rtc_probe(struct platform_device *pdev) ...@@ -344,11 +348,11 @@ static int mtk_rtc_probe(struct platform_device *pdev)
device_init_wakeup(&pdev->dev, 1); device_init_wakeup(&pdev->dev, 1);
rtc->rtc_dev = rtc_device_register("mt6397-rtc", &pdev->dev, rtc->rtc_dev->ops = &mtk_rtc_ops;
&mtk_rtc_ops, THIS_MODULE);
if (IS_ERR(rtc->rtc_dev)) { ret = rtc_register_device(rtc->rtc_dev);
if (ret) {
dev_err(&pdev->dev, "register rtc device failed\n"); dev_err(&pdev->dev, "register rtc device failed\n");
ret = PTR_ERR(rtc->rtc_dev);
goto out_free_irq; goto out_free_irq;
} }
...@@ -365,7 +369,6 @@ static int mtk_rtc_remove(struct platform_device *pdev) ...@@ -365,7 +369,6 @@ static int mtk_rtc_remove(struct platform_device *pdev)
{ {
struct mt6397_rtc *rtc = platform_get_drvdata(pdev); struct mt6397_rtc *rtc = platform_get_drvdata(pdev);
rtc_device_unregister(rtc->rtc_dev);
free_irq(rtc->irq, rtc->rtc_dev); free_irq(rtc->irq, rtc->rtc_dev);
irq_dispose_mapping(rtc->irq); irq_dispose_mapping(rtc->irq);
......
...@@ -125,13 +125,9 @@ static int mv_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) ...@@ -125,13 +125,9 @@ static int mv_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
/* hw counts from year 2000, but tm_year is relative to 1900 */ /* hw counts from year 2000, but tm_year is relative to 1900 */
alm->time.tm_year = bcd2bin(year) + 100; alm->time.tm_year = bcd2bin(year) + 100;
if (rtc_valid_tm(&alm->time) < 0) {
dev_err(dev, "retrieved alarm date/time is not valid.\n");
rtc_time_to_tm(0, &alm->time);
}
alm->enabled = !!readl(ioaddr + RTC_ALARM_INTERRUPT_MASK_REG_OFFS); alm->enabled = !!readl(ioaddr + RTC_ALARM_INTERRUPT_MASK_REG_OFFS);
return 0;
return rtc_valid_tm(&alm->time);
} }
static int mv_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) static int mv_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
......
...@@ -421,12 +421,6 @@ static struct omap_rtc *omap_rtc_power_off_rtc; ...@@ -421,12 +421,6 @@ static struct omap_rtc *omap_rtc_power_off_rtc;
* The RTC can be used to control an external PMIC via the pmic_power_en pin, * The RTC can be used to control an external PMIC via the pmic_power_en pin,
* which can be configured to transition to OFF on ALARM2 events. * which can be configured to transition to OFF on ALARM2 events.
* *
* Notes:
* The two-second alarm offset is the shortest offset possible as the alarm
* registers must be set before the next timer update and the offset
* calculation is too heavy for everything to be done within a single access
* period (~15 us).
*
* Called with local interrupts disabled. * Called with local interrupts disabled.
*/ */
static void omap_rtc_power_off(void) static void omap_rtc_power_off(void)
...@@ -434,6 +428,7 @@ static void omap_rtc_power_off(void) ...@@ -434,6 +428,7 @@ static void omap_rtc_power_off(void)
struct omap_rtc *rtc = omap_rtc_power_off_rtc; struct omap_rtc *rtc = omap_rtc_power_off_rtc;
struct rtc_time tm; struct rtc_time tm;
unsigned long now; unsigned long now;
int seconds;
u32 val; u32 val;
rtc->type->unlock(rtc); rtc->type->unlock(rtc);
...@@ -441,11 +436,13 @@ static void omap_rtc_power_off(void) ...@@ -441,11 +436,13 @@ static void omap_rtc_power_off(void)
val = rtc_readl(rtc, OMAP_RTC_PMIC_REG); val = rtc_readl(rtc, OMAP_RTC_PMIC_REG);
rtc_writel(rtc, OMAP_RTC_PMIC_REG, val | OMAP_RTC_PMIC_POWER_EN_EN); rtc_writel(rtc, OMAP_RTC_PMIC_REG, val | OMAP_RTC_PMIC_POWER_EN_EN);
/* set alarm two seconds from now */ again:
/* set alarm one second from now */
omap_rtc_read_time_raw(rtc, &tm); omap_rtc_read_time_raw(rtc, &tm);
seconds = tm.tm_sec;
bcd2tm(&tm); bcd2tm(&tm);
rtc_tm_to_time(&tm, &now); rtc_tm_to_time(&tm, &now);
rtc_time_to_tm(now + 2, &tm); rtc_time_to_tm(now + 1, &tm);
if (tm2bcd(&tm) < 0) { if (tm2bcd(&tm) < 0) {
dev_err(&rtc->rtc->dev, "power off failed\n"); dev_err(&rtc->rtc->dev, "power off failed\n");
...@@ -470,14 +467,22 @@ static void omap_rtc_power_off(void) ...@@ -470,14 +467,22 @@ static void omap_rtc_power_off(void)
val = rtc_read(rtc, OMAP_RTC_INTERRUPTS_REG); val = rtc_read(rtc, OMAP_RTC_INTERRUPTS_REG);
rtc_writel(rtc, OMAP_RTC_INTERRUPTS_REG, rtc_writel(rtc, OMAP_RTC_INTERRUPTS_REG,
val | OMAP_RTC_INTERRUPTS_IT_ALARM2); val | OMAP_RTC_INTERRUPTS_IT_ALARM2);
/* Retry in case roll over happened before alarm was armed. */
if (rtc_read(rtc, OMAP_RTC_SECONDS_REG) != seconds) {
val = rtc_read(rtc, OMAP_RTC_STATUS_REG);
if (!(val & OMAP_RTC_STATUS_ALARM2))
goto again;
}
rtc->type->lock(rtc); rtc->type->lock(rtc);
/* /*
* Wait for alarm to trigger (within two seconds) and external PMIC to * Wait for alarm to trigger (within one second) and external PMIC to
* power off the system. Add a 500 ms margin for external latencies * power off the system. Add a 500 ms margin for external latencies
* (e.g. debounce circuits). * (e.g. debounce circuits).
*/ */
mdelay(2500); mdelay(1500);
} }
static const struct rtc_class_ops omap_rtc_ops = { static const struct rtc_class_ops omap_rtc_ops = {
...@@ -721,8 +726,7 @@ static int omap_rtc_probe(struct platform_device *pdev) ...@@ -721,8 +726,7 @@ static int omap_rtc_probe(struct platform_device *pdev)
if (of_id) { if (of_id) {
rtc->type = of_id->data; rtc->type = of_id->data;
rtc->is_pmic_controller = rtc->type->has_pmic_mode && rtc->is_pmic_controller = rtc->type->has_pmic_mode &&
of_property_read_bool(pdev->dev.of_node, of_device_is_system_power_controller(pdev->dev.of_node);
"system-power-controller");
} else { } else {
id_entry = platform_get_device_id(pdev); id_entry = platform_get_device_id(pdev);
rtc->type = (void *)id_entry->driver_data; rtc->type = (void *)id_entry->driver_data;
......
...@@ -112,6 +112,13 @@ static int pl030_probe(struct amba_device *dev, const struct amba_id *id) ...@@ -112,6 +112,13 @@ static int pl030_probe(struct amba_device *dev, const struct amba_id *id)
goto err_rtc; goto err_rtc;
} }
rtc->rtc = devm_rtc_allocate_device(&dev->dev);
if (IS_ERR(rtc->rtc)) {
ret = PTR_ERR(rtc->rtc);
goto err_rtc;
}
rtc->rtc->ops = &pl030_ops;
rtc->base = ioremap(dev->res.start, resource_size(&dev->res)); rtc->base = ioremap(dev->res.start, resource_size(&dev->res));
if (!rtc->base) { if (!rtc->base) {
ret = -ENOMEM; ret = -ENOMEM;
...@@ -128,12 +135,9 @@ static int pl030_probe(struct amba_device *dev, const struct amba_id *id) ...@@ -128,12 +135,9 @@ static int pl030_probe(struct amba_device *dev, const struct amba_id *id)
if (ret) if (ret)
goto err_irq; goto err_irq;
rtc->rtc = rtc_device_register("pl030", &dev->dev, &pl030_ops, ret = rtc_register_device(rtc->rtc);
THIS_MODULE); if (ret)
if (IS_ERR(rtc->rtc)) {
ret = PTR_ERR(rtc->rtc);
goto err_reg; goto err_reg;
}
return 0; return 0;
...@@ -154,7 +158,6 @@ static int pl030_remove(struct amba_device *dev) ...@@ -154,7 +158,6 @@ static int pl030_remove(struct amba_device *dev)
writel(0, rtc->base + RTC_CR); writel(0, rtc->base + RTC_CR);
free_irq(dev->irq[0], rtc); free_irq(dev->irq[0], rtc);
rtc_device_unregister(rtc->rtc);
iounmap(rtc->base); iounmap(rtc->base);
amba_release_regions(dev); amba_release_regions(dev);
......
...@@ -310,7 +310,6 @@ static int pl031_remove(struct amba_device *adev) ...@@ -310,7 +310,6 @@ static int pl031_remove(struct amba_device *adev)
device_init_wakeup(&adev->dev, false); device_init_wakeup(&adev->dev, false);
if (adev->irq[0]) if (adev->irq[0])
free_irq(adev->irq[0], ldata); free_irq(adev->irq[0], ldata);
rtc_device_unregister(ldata->rtc);
amba_release_regions(adev); amba_release_regions(adev);
return 0; return 0;
...@@ -383,24 +382,25 @@ static int pl031_probe(struct amba_device *adev, const struct amba_id *id) ...@@ -383,24 +382,25 @@ static int pl031_probe(struct amba_device *adev, const struct amba_id *id)
} }
device_init_wakeup(&adev->dev, true); device_init_wakeup(&adev->dev, true);
ldata->rtc = rtc_device_register("pl031", &adev->dev, ops, ldata->rtc = devm_rtc_allocate_device(&adev->dev);
THIS_MODULE); if (IS_ERR(ldata->rtc))
if (IS_ERR(ldata->rtc)) { return PTR_ERR(ldata->rtc);
ret = PTR_ERR(ldata->rtc);
ldata->rtc->ops = ops;
ret = rtc_register_device(ldata->rtc);
if (ret)
goto out; goto out;
}
if (adev->irq[0]) { if (adev->irq[0]) {
ret = request_irq(adev->irq[0], pl031_interrupt, ret = request_irq(adev->irq[0], pl031_interrupt,
vendor->irqflags, "rtc-pl031", ldata); vendor->irqflags, "rtc-pl031", ldata);
if (ret) if (ret)
goto out_no_irq; goto out;
dev_pm_set_wake_irq(&adev->dev, adev->irq[0]); dev_pm_set_wake_irq(&adev->dev, adev->irq[0]);
} }
return 0; return 0;
out_no_irq:
rtc_device_unregister(ldata->rtc);
out: out:
amba_release_regions(adev); amba_release_regions(adev);
err_req: err_req:
......
...@@ -66,6 +66,17 @@ rs5c348_rtc_set_time(struct device *dev, struct rtc_time *tm) ...@@ -66,6 +66,17 @@ rs5c348_rtc_set_time(struct device *dev, struct rtc_time *tm)
u8 txbuf[5+7], *txp; u8 txbuf[5+7], *txp;
int ret; int ret;
ret = spi_w8r8(spi, RS5C348_CMD_R(RS5C348_REG_CTL2));
if (ret < 0)
return ret;
if (ret & RS5C348_BIT_XSTP) {
txbuf[0] = RS5C348_CMD_W(RS5C348_REG_CTL2);
txbuf[1] = 0;
ret = spi_write_then_read(spi, txbuf, 2, NULL, 0);
if (ret < 0)
return ret;
}
/* Transfer 5 bytes before writing SEC. This gives 31us for carry. */ /* Transfer 5 bytes before writing SEC. This gives 31us for carry. */
txp = txbuf; txp = txbuf;
txbuf[0] = RS5C348_CMD_R(RS5C348_REG_CTL2); /* cmd, ctl2 */ txbuf[0] = RS5C348_CMD_R(RS5C348_REG_CTL2); /* cmd, ctl2 */
...@@ -102,6 +113,16 @@ rs5c348_rtc_read_time(struct device *dev, struct rtc_time *tm) ...@@ -102,6 +113,16 @@ rs5c348_rtc_read_time(struct device *dev, struct rtc_time *tm)
u8 txbuf[5], rxbuf[7]; u8 txbuf[5], rxbuf[7];
int ret; int ret;
ret = spi_w8r8(spi, RS5C348_CMD_R(RS5C348_REG_CTL2));
if (ret < 0)
return ret;
if (ret & RS5C348_BIT_VDET)
dev_warn(&spi->dev, "voltage-low detected.\n");
if (ret & RS5C348_BIT_XSTP) {
dev_warn(&spi->dev, "oscillator-stop detected.\n");
return -EINVAL;
}
/* Transfer 5 byte befores reading SEC. This gives 31us for carry. */ /* Transfer 5 byte befores reading SEC. This gives 31us for carry. */
txbuf[0] = RS5C348_CMD_R(RS5C348_REG_CTL2); /* cmd, ctl2 */ txbuf[0] = RS5C348_CMD_R(RS5C348_REG_CTL2); /* cmd, ctl2 */
txbuf[1] = 0; /* dummy */ txbuf[1] = 0; /* dummy */
...@@ -143,8 +164,6 @@ static const struct rtc_class_ops rs5c348_rtc_ops = { ...@@ -143,8 +164,6 @@ static const struct rtc_class_ops rs5c348_rtc_ops = {
.set_time = rs5c348_rtc_set_time, .set_time = rs5c348_rtc_set_time,
}; };
static struct spi_driver rs5c348_driver;
static int rs5c348_probe(struct spi_device *spi) static int rs5c348_probe(struct spi_device *spi)
{ {
int ret; int ret;
...@@ -161,53 +180,27 @@ static int rs5c348_probe(struct spi_device *spi) ...@@ -161,53 +180,27 @@ static int rs5c348_probe(struct spi_device *spi)
ret = spi_w8r8(spi, RS5C348_CMD_R(RS5C348_REG_SECS)); ret = spi_w8r8(spi, RS5C348_CMD_R(RS5C348_REG_SECS));
if (ret < 0 || (ret & 0x80)) { if (ret < 0 || (ret & 0x80)) {
dev_err(&spi->dev, "not found.\n"); dev_err(&spi->dev, "not found.\n");
goto kfree_exit; return ret;
} }
dev_info(&spi->dev, "spiclk %u KHz.\n", dev_info(&spi->dev, "spiclk %u KHz.\n",
(spi->max_speed_hz + 500) / 1000); (spi->max_speed_hz + 500) / 1000);
/* turn RTC on if it was not on */
ret = spi_w8r8(spi, RS5C348_CMD_R(RS5C348_REG_CTL2));
if (ret < 0)
goto kfree_exit;
if (ret & (RS5C348_BIT_XSTP | RS5C348_BIT_VDET)) {
u8 buf[2];
struct rtc_time tm;
if (ret & RS5C348_BIT_VDET)
dev_warn(&spi->dev, "voltage-low detected.\n");
if (ret & RS5C348_BIT_XSTP)
dev_warn(&spi->dev, "oscillator-stop detected.\n");
rtc_time_to_tm(0, &tm); /* 1970/1/1 */
ret = rs5c348_rtc_set_time(&spi->dev, &tm);
if (ret < 0)
goto kfree_exit;
buf[0] = RS5C348_CMD_W(RS5C348_REG_CTL2);
buf[1] = 0;
ret = spi_write_then_read(spi, buf, sizeof(buf), NULL, 0);
if (ret < 0)
goto kfree_exit;
}
ret = spi_w8r8(spi, RS5C348_CMD_R(RS5C348_REG_CTL1)); ret = spi_w8r8(spi, RS5C348_CMD_R(RS5C348_REG_CTL1));
if (ret < 0) if (ret < 0)
goto kfree_exit; return ret;
if (ret & RS5C348_BIT_24H) if (ret & RS5C348_BIT_24H)
pdata->rtc_24h = 1; pdata->rtc_24h = 1;
rtc = devm_rtc_device_register(&spi->dev, rs5c348_driver.driver.name, rtc = devm_rtc_allocate_device(&spi->dev);
&rs5c348_rtc_ops, THIS_MODULE); if (IS_ERR(rtc))
return PTR_ERR(rtc);
if (IS_ERR(rtc)) {
ret = PTR_ERR(rtc);
goto kfree_exit;
}
pdata->rtc = rtc; pdata->rtc = rtc;
return 0; rtc->ops = &rs5c348_rtc_ops;
kfree_exit:
return ret; return rtc_register_device(rtc);
} }
static struct spi_driver rs5c348_driver = { static struct spi_driver rs5c348_driver = {
......
...@@ -615,6 +615,7 @@ static int rv8803_probe(struct i2c_client *client, ...@@ -615,6 +615,7 @@ static int rv8803_probe(struct i2c_client *client,
static const struct i2c_device_id rv8803_id[] = { static const struct i2c_device_id rv8803_id[] = {
{ "rv8803", rv_8803 }, { "rv8803", rv_8803 },
{ "rx8803", rv_8803 },
{ "rx8900", rx_8900 }, { "rx8900", rx_8900 },
{ } { }
}; };
...@@ -623,7 +624,11 @@ MODULE_DEVICE_TABLE(i2c, rv8803_id); ...@@ -623,7 +624,11 @@ MODULE_DEVICE_TABLE(i2c, rv8803_id);
static const struct of_device_id rv8803_of_match[] = { static const struct of_device_id rv8803_of_match[] = {
{ {
.compatible = "microcrystal,rv8803", .compatible = "microcrystal,rv8803",
.data = (void *)rx_8900 .data = (void *)rv_8803
},
{
.compatible = "epson,rx8803",
.data = (void *)rv_8803
}, },
{ {
.compatible = "epson,rx8900", .compatible = "epson,rx8900",
......
...@@ -108,7 +108,7 @@ static int s35390a_get_reg(struct s35390a *s35390a, int reg, char *buf, int len) ...@@ -108,7 +108,7 @@ static int s35390a_get_reg(struct s35390a *s35390a, int reg, char *buf, int len)
static int s35390a_init(struct s35390a *s35390a) static int s35390a_init(struct s35390a *s35390a)
{ {
char buf; u8 buf;
int ret; int ret;
unsigned initcount = 0; unsigned initcount = 0;
......
...@@ -129,19 +129,6 @@ static int sprd_rtc_clear_alarm_ints(struct sprd_rtc *rtc) ...@@ -129,19 +129,6 @@ static int sprd_rtc_clear_alarm_ints(struct sprd_rtc *rtc)
SPRD_RTC_ALM_INT_MASK); SPRD_RTC_ALM_INT_MASK);
} }
static int sprd_rtc_disable_ints(struct sprd_rtc *rtc)
{
int ret;
ret = regmap_update_bits(rtc->regmap, rtc->base + SPRD_RTC_INT_EN,
SPRD_RTC_INT_MASK, 0);
if (ret)
return ret;
return regmap_write(rtc->regmap, rtc->base + SPRD_RTC_INT_CLR,
SPRD_RTC_INT_MASK);
}
static int sprd_rtc_lock_alarm(struct sprd_rtc *rtc, bool lock) static int sprd_rtc_lock_alarm(struct sprd_rtc *rtc, bool lock)
{ {
int ret; int ret;
...@@ -172,7 +159,8 @@ static int sprd_rtc_lock_alarm(struct sprd_rtc *rtc, bool lock) ...@@ -172,7 +159,8 @@ static int sprd_rtc_lock_alarm(struct sprd_rtc *rtc, bool lock)
return ret; return ret;
} }
return 0; return regmap_write(rtc->regmap, rtc->base + SPRD_RTC_INT_CLR,
SPRD_RTC_SPG_UPD_EN);
} }
static int sprd_rtc_get_secs(struct sprd_rtc *rtc, enum sprd_rtc_reg_types type, static int sprd_rtc_get_secs(struct sprd_rtc *rtc, enum sprd_rtc_reg_types type,
...@@ -427,10 +415,14 @@ static int sprd_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) ...@@ -427,10 +415,14 @@ static int sprd_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
u32 val; u32 val;
/* /*
* If aie_timer is enabled, we should get the normal alarm time. * Before RTC device is registered, it will check to see if there is an
* alarm already set in RTC hardware, and we always read the normal
* alarm at this time.
*
* Or if aie_timer is enabled, we should get the normal alarm time.
* Otherwise we should get auxiliary alarm time. * Otherwise we should get auxiliary alarm time.
*/ */
if (rtc->rtc && rtc->rtc->aie_timer.enabled == 0) if (rtc->rtc && rtc->rtc->registered && rtc->rtc->aie_timer.enabled == 0)
return sprd_rtc_read_aux_alarm(dev, alrm); return sprd_rtc_read_aux_alarm(dev, alrm);
ret = sprd_rtc_get_secs(rtc, SPRD_RTC_ALARM, &secs); ret = sprd_rtc_get_secs(rtc, SPRD_RTC_ALARM, &secs);
...@@ -575,6 +567,32 @@ static int sprd_rtc_check_power_down(struct sprd_rtc *rtc) ...@@ -575,6 +567,32 @@ static int sprd_rtc_check_power_down(struct sprd_rtc *rtc)
return 0; return 0;
} }
static int sprd_rtc_check_alarm_int(struct sprd_rtc *rtc)
{
u32 val;
int ret;
ret = regmap_read(rtc->regmap, rtc->base + SPRD_RTC_SPG_VALUE, &val);
if (ret)
return ret;
/*
* The SPRD_RTC_INT_EN register is not put in always-power-on region
* supplied by VDDRTC, so we should check if we need enable the alarm
* interrupt when system booting.
*
* If we have set SPRD_RTC_POWEROFF_ALM_FLAG which is saved in
* always-power-on region, that means we have set one alarm last time,
* so we should enable the alarm interrupt to help RTC core to see if
* there is an alarm already set in RTC hardware.
*/
if (!(val & SPRD_RTC_POWEROFF_ALM_FLAG))
return 0;
return regmap_update_bits(rtc->regmap, rtc->base + SPRD_RTC_INT_EN,
SPRD_RTC_ALARM_EN, SPRD_RTC_ALARM_EN);
}
static int sprd_rtc_probe(struct platform_device *pdev) static int sprd_rtc_probe(struct platform_device *pdev)
{ {
struct device_node *node = pdev->dev.of_node; struct device_node *node = pdev->dev.of_node;
...@@ -608,10 +626,10 @@ static int sprd_rtc_probe(struct platform_device *pdev) ...@@ -608,10 +626,10 @@ static int sprd_rtc_probe(struct platform_device *pdev)
rtc->dev = &pdev->dev; rtc->dev = &pdev->dev;
platform_set_drvdata(pdev, rtc); platform_set_drvdata(pdev, rtc);
/* clear all RTC interrupts and disable all RTC interrupts */ /* check if we need set the alarm interrupt */
ret = sprd_rtc_disable_ints(rtc); ret = sprd_rtc_check_alarm_int(rtc);
if (ret) { if (ret) {
dev_err(&pdev->dev, "failed to disable RTC interrupts\n"); dev_err(&pdev->dev, "failed to check RTC alarm interrupt\n");
return ret; return ret;
} }
...@@ -631,16 +649,18 @@ static int sprd_rtc_probe(struct platform_device *pdev) ...@@ -631,16 +649,18 @@ static int sprd_rtc_probe(struct platform_device *pdev)
return ret; return ret;
} }
device_init_wakeup(&pdev->dev, 1);
rtc->rtc->ops = &sprd_rtc_ops; rtc->rtc->ops = &sprd_rtc_ops;
rtc->rtc->range_min = 0; rtc->rtc->range_min = 0;
rtc->rtc->range_max = 5662310399LL; rtc->rtc->range_max = 5662310399LL;
ret = rtc_register_device(rtc->rtc); ret = rtc_register_device(rtc->rtc);
if (ret) { if (ret) {
dev_err(&pdev->dev, "failed to register rtc device\n"); dev_err(&pdev->dev, "failed to register rtc device\n");
device_init_wakeup(&pdev->dev, 0);
return ret; return ret;
} }
device_init_wakeup(&pdev->dev, 1);
return 0; return 0;
} }
......
...@@ -199,8 +199,7 @@ static void __init sun6i_rtc_clk_init(struct device_node *node) ...@@ -199,8 +199,7 @@ static void __init sun6i_rtc_clk_init(struct device_node *node)
if (!rtc) if (!rtc)
return; return;
clk_data = kzalloc(sizeof(*clk_data) + (sizeof(*clk_data->hws) * 2), clk_data = kzalloc(struct_size(clk_data, hws, 2), GFP_KERNEL);
GFP_KERNEL);
if (!clk_data) { if (!clk_data) {
kfree(rtc); kfree(rtc);
return; return;
......
...@@ -338,8 +338,8 @@ int rtc_add_groups(struct rtc_device *rtc, const struct attribute_group **grps) ...@@ -338,8 +338,8 @@ int rtc_add_groups(struct rtc_device *rtc, const struct attribute_group **grps)
new_cnt = old_cnt + add_cnt + 1; new_cnt = old_cnt + add_cnt + 1;
groups = devm_kcalloc(&rtc->dev, new_cnt, sizeof(*groups), GFP_KERNEL); groups = devm_kcalloc(&rtc->dev, new_cnt, sizeof(*groups), GFP_KERNEL);
if (IS_ERR_OR_NULL(groups)) if (!groups)
return PTR_ERR(groups); return -ENOMEM;
memcpy(groups, rtc->dev.groups, old_cnt * sizeof(*groups)); memcpy(groups, rtc->dev.groups, old_cnt * sizeof(*groups));
memcpy(groups + old_cnt, grps, add_cnt * sizeof(*groups)); memcpy(groups + old_cnt, grps, add_cnt * sizeof(*groups));
groups[old_cnt + add_cnt] = NULL; groups[old_cnt + add_cnt] = NULL;
......
...@@ -322,9 +322,13 @@ static int __init tegra_rtc_probe(struct platform_device *pdev) ...@@ -322,9 +322,13 @@ static int __init tegra_rtc_probe(struct platform_device *pdev)
if (IS_ERR(info->rtc_base)) if (IS_ERR(info->rtc_base))
return PTR_ERR(info->rtc_base); return PTR_ERR(info->rtc_base);
info->tegra_rtc_irq = platform_get_irq(pdev, 0); ret = platform_get_irq(pdev, 0);
if (info->tegra_rtc_irq <= 0) if (ret <= 0) {
return -EBUSY; dev_err(&pdev->dev, "failed to get platform IRQ: %d\n", ret);
return ret;
}
info->tegra_rtc_irq = ret;
info->clk = devm_clk_get(&pdev->dev, NULL); info->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(info->clk)) if (IS_ERR(info->clk))
......
// SPDX-License-Identifier: GPL-2.0
/* /*
* An RTC test device/driver * An RTC test device/driver
* Copyright (C) 2005 Tower Technologies * Copyright (C) 2005 Tower Technologies
* Author: Alessandro Zummo <a.zummo@towertech.it> * Author: Alessandro Zummo <a.zummo@towertech.it>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/ */
#include <linux/module.h> #include <linux/module.h>
...@@ -197,7 +194,7 @@ static void __exit test_exit(void) ...@@ -197,7 +194,7 @@ static void __exit test_exit(void)
MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>"); MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
MODULE_DESCRIPTION("RTC test driver/device"); MODULE_DESCRIPTION("RTC test driver/device");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL v2");
module_init(test_init); module_init(test_init);
module_exit(test_exit); module_exit(test_exit);
...@@ -253,9 +253,7 @@ static int __init tx4939_rtc_probe(struct platform_device *pdev) ...@@ -253,9 +253,7 @@ static int __init tx4939_rtc_probe(struct platform_device *pdev)
struct resource *res; struct resource *res;
int irq, ret; int irq, ret;
struct nvmem_config nvmem_cfg = { struct nvmem_config nvmem_cfg = {
.name = "rv8803_nvram", .name = "tx4939_nvram",
.word_size = 4,
.stride = 4,
.size = TX4939_RTC_REG_RAMSIZE, .size = TX4939_RTC_REG_RAMSIZE,
.reg_read = tx4939_nvram_read, .reg_read = tx4939_nvram_read,
.reg_write = tx4939_nvram_write, .reg_write = tx4939_nvram_write,
......
...@@ -136,8 +136,7 @@ static int vr41xx_rtc_set_time(struct device *dev, struct rtc_time *time) ...@@ -136,8 +136,7 @@ static int vr41xx_rtc_set_time(struct device *dev, struct rtc_time *time)
time64_t epoch_sec, current_sec; time64_t epoch_sec, current_sec;
epoch_sec = mktime64(epoch, 1, 1, 0, 0, 0); epoch_sec = mktime64(epoch, 1, 1, 0, 0, 0);
current_sec = mktime64(time->tm_year + 1900, time->tm_mon + 1, time->tm_mday, current_sec = rtc_tm_to_time64(time);
time->tm_hour, time->tm_min, time->tm_sec);
write_elapsed_second(current_sec - epoch_sec); write_elapsed_second(current_sec - epoch_sec);
...@@ -158,7 +157,7 @@ static int vr41xx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *wkalrm) ...@@ -158,7 +157,7 @@ static int vr41xx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
spin_unlock_irq(&rtc_lock); spin_unlock_irq(&rtc_lock);
rtc_time_to_tm((high << 17) | (mid << 1) | (low >> 15), time); rtc_time64_to_tm((high << 17) | (mid << 1) | (low >> 15), time);
return 0; return 0;
} }
...@@ -166,10 +165,8 @@ static int vr41xx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *wkalrm) ...@@ -166,10 +165,8 @@ static int vr41xx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
static int vr41xx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *wkalrm) static int vr41xx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
{ {
time64_t alarm_sec; time64_t alarm_sec;
struct rtc_time *time = &wkalrm->time;
alarm_sec = mktime64(time->tm_year + 1900, time->tm_mon + 1, time->tm_mday, alarm_sec = rtc_tm_to_time64(&wkalrm->time);
time->tm_hour, time->tm_min, time->tm_sec);
spin_lock_irq(&rtc_lock); spin_lock_irq(&rtc_lock);
......
...@@ -167,17 +167,12 @@ struct rtc_device { ...@@ -167,17 +167,12 @@ struct rtc_device {
#define RTC_TIMESTAMP_BEGIN_2000 946684800LL /* 2000-01-01 00:00:00 */ #define RTC_TIMESTAMP_BEGIN_2000 946684800LL /* 2000-01-01 00:00:00 */
#define RTC_TIMESTAMP_END_2099 4102444799LL /* 2099-12-31 23:59:59 */ #define RTC_TIMESTAMP_END_2099 4102444799LL /* 2099-12-31 23:59:59 */
extern struct rtc_device *rtc_device_register(const char *name,
struct device *dev,
const struct rtc_class_ops *ops,
struct module *owner);
extern struct rtc_device *devm_rtc_device_register(struct device *dev, extern struct rtc_device *devm_rtc_device_register(struct device *dev,
const char *name, const char *name,
const struct rtc_class_ops *ops, const struct rtc_class_ops *ops,
struct module *owner); struct module *owner);
struct rtc_device *devm_rtc_allocate_device(struct device *dev); struct rtc_device *devm_rtc_allocate_device(struct device *dev);
int __rtc_register_device(struct module *owner, struct rtc_device *rtc); int __rtc_register_device(struct module *owner, struct rtc_device *rtc);
extern void rtc_device_unregister(struct rtc_device *rtc);
extern void devm_rtc_device_unregister(struct device *dev, extern void devm_rtc_device_unregister(struct device *dev,
struct rtc_device *rtc); struct rtc_device *rtc);
...@@ -277,4 +272,20 @@ static inline int rtc_nvmem_register(struct rtc_device *rtc, ...@@ -277,4 +272,20 @@ static inline int rtc_nvmem_register(struct rtc_device *rtc,
static inline void rtc_nvmem_unregister(struct rtc_device *rtc) {} static inline void rtc_nvmem_unregister(struct rtc_device *rtc) {}
#endif #endif
#ifdef CONFIG_RTC_INTF_SYSFS
int rtc_add_group(struct rtc_device *rtc, const struct attribute_group *grp);
int rtc_add_groups(struct rtc_device *rtc, const struct attribute_group **grps);
#else
static inline
int rtc_add_group(struct rtc_device *rtc, const struct attribute_group *grp)
{
return 0;
}
static inline
int rtc_add_groups(struct rtc_device *rtc, const struct attribute_group **grps)
{
return 0;
}
#endif
#endif /* _LINUX_RTC_H_ */ #endif /* _LINUX_RTC_H_ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment