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 ...
This commit is contained in:
@@ -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
|
|||||||
|
|
||||||
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
|
|||||||
|
|
||||||
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
|
|||||||
|
|
||||||
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
|
|||||||
|
|
||||||
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
|
|||||||
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
|
|||||||
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
|
|||||||
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
|
|||||||
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
|
|||||||
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
|
|||||||
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
|
|||||||
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)
|
|||||||
*
|
*
|
||||||
* 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 @@ exit:
|
|||||||
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)
|
|||||||
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);
|
|||||||
* 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)
|
|||||||
/**
|
/**
|
||||||
* 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)
|
|||||||
/**
|
/**
|
||||||
* 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 @@
|
|||||||
#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[] = {
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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,
|
|||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
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 @@
|
|||||||
#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 @@
|
|||||||
|
|
||||||
#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 @@
|
|||||||
#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,
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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,
|
|||||||
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;
|
||||||
|
|
||||||
rtc->ops = &abx80x_rtc_ops;
|
priv->rtc = devm_rtc_allocate_device(&client->dev);
|
||||||
|
if (IS_ERR(priv->rtc))
|
||||||
|
return PTR_ERR(priv->rtc);
|
||||||
|
|
||||||
i2c_set_clientdata(client, rtc);
|
priv->rtc->ops = &abx80x_rtc_ops;
|
||||||
|
priv->client = client;
|
||||||
|
|
||||||
|
i2c_set_clientdata(client, priv);
|
||||||
|
|
||||||
|
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,
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
|
|
||||||
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);
|
|||||||
|
|
||||||
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)
|
|||||||
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)
|
|||||||
|
|
||||||
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 @@
|
|||||||
/* 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 @@
|
|||||||
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)
|
|||||||
#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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
}
|
}
|
||||||
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)
|
|||||||
* 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)
|
|||||||
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)
|
|||||||
* 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)
|
|||||||
|
|
||||||
#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 {
|
|||||||
# 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 {
|
|||||||
|
|
||||||
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);
|
|||||||
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 = {
|
|||||||
.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] = {
|
|||||||
.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)
|
|||||||
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)
|
|||||||
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 @@ read_rtc:
|
|||||||
}
|
}
|
||||||
|
|
||||||
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] = {
|
|||||||
"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)
|
|||||||
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)
|
|||||||
"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)
|
|||||||
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 = {
|
|||||||
};
|
};
|
||||||
/* ----------------------------------------------------------------------- */
|
/* ----------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
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,
|
|||||||
#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,
|
|||||||
#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 = {
|
|||||||
.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)
|
|||||||
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)
|
|||||||
/* 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)
|
|||||||
{
|
{
|
||||||
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 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#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,
|
|||||||
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,
|
|||||||
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
|
|||||||
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
|
|||||||
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
|
|||||||
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,
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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 = {
|
|||||||
.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);
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 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,
|
|||||||
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)
|
|||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
{
|
{
|
||||||
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)
|
|||||||
/* 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;
|
|||||||
* 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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
}
|
}
|
||||||
|
|
||||||
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)
|
|||||||
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)
|
|||||||
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 = {
|
|||||||
.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)
|
|||||||
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,
|
|||||||
|
|
||||||
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);
|
|||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
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))
|
||||||
|
@@ -1,11 +1,8 @@
|
|||||||
|
// 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)
|
|||||||
|
|
||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
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 {
|
|||||||
#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,
|
|||||||
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_ */
|
||||||
|
Reference in New Issue
Block a user