Commit c1917615 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull RTC updates from Alexandre Belloni:
 "Core:
   - use is_visible() to control sysfs attributes
   - switch wakealarm attribute to DEVICE_ATTR_RW
   - make rtc_does_wakealarm() return boolean
   - properly manage lifetime of dev and cdev in rtc device
   - remove unnecessary device_get() in rtc_device_unregister
   - fix double free in rtc_register_device() error path

  New drivers:
   - NXP LPC24xx
   - Xilinx Zynq MP
   - Dialog DA9062

  Subsystem wide cleanups:
   - fix drivers that consider 0 as a valid IRQ in client->irq
   - Drop (un)likely before IS_ERR(_OR_NULL)
   - drop the remaining owner assignment for i2c_driver and
     platform_driver
   - module autoload fixes

  Drivers:
   - 88pm80x: add device tree support
   - abx80x: fix RTC write bit
   - ab8500: Add a sentinel to ab85xx_rtc_ids[]
   - armada38x: Align RTC set time procedure with the official errata
   - as3722: correct month value
   - at91sam9: cleanups
   - at91rm9200: get and use slow clock and cleanups
   - bq32k: remove redundant check
   - cmos: century support, proper fix for the spurious wakeup
   - ds1307: cleanups and wakeup irq support
   - ds1374: Remove unused variable
   - ds1685: Use module_platform_driver
   - ds3232: fix WARNING trace in resume function
   - gemini: fix ptr_ret.cocci warnings
   - mt6397: implement suspend/resume
   - omap: support internal and external clock enabling
   - opal: Enable alarms only when opal supports tpo
   - pcf2127: use OFS flag to detect unreliable date and warn the user
   - pl031: fix typo for author email
   - rx8025: huge cleanup and fixes
   - sa1100/pxa: share common code
   - s5m: fix to update ctrl register
   - s3c: fix clocks and wakeup, cleanup
   - sirfsoc: use regmap
   - nvram_read()/nvram_write() functions for cmos, ds1305, ds1307,
     ds1343, ds1511, ds1553, ds1742, m48t59, rp5c01, stk17ta8, tx4939
   - use rtc_valid_tm() error code when reading date/time instead of 0
     for isl12022, pcf2123, pcf2127"

* tag 'rtc-v4.3' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux: (90 commits)
  rtc: abx80x: fix RTC write bit
  rtc: ab8500: Add a sentinel to ab85xx_rtc_ids[]
  rtc: ds1374: Remove unused variable
  rtc: Fix module autoload for OF platform drivers
  rtc: Fix module autoload for rtc-{ab8500,max8997,s5m} drivers
  rtc: omap: Add external clock enabling support
  rtc: omap: Add internal clock enabling support
  ARM: dts: AM437x: Add the internal and external clock nodes for rtc
  rtc: s5m: fix to update ctrl register
  rtc: add xilinx zynqmp rtc driver
  devicetree: bindings: rtc: add bindings for xilinx zynqmp rtc
  rtc: as3722: correct month value
  ARM: config: Switch PXA27x platforms to use PXA RTC driver
  ARM: mmp: remove unused RTC register definitions
  ARM: sa1100: remove unused RTC register definitions
  rtc: sa1100/pxa: convert to run-time register mapping
  ARM: pxa: add memory resource to SA1100 RTC device
  rtc: pxa: convert to use shared sa1100 functions
  rtc: sa1100: prepare to share sa1100_rtc_ops
  rtc: ds3232: fix WARNING trace in resume function
  ...
parents 12f03ee6 5f1b2f77
NXP LPC1788 real-time clock
The LPC1788 RTC provides calendar and clock functionality
together with periodic tick and alarm interrupt support.
Required properties:
- compatible : must contain "nxp,lpc1788-rtc"
- reg : Specifies base physical address and size of the registers.
- interrupts : A single interrupt specifier.
- clocks : Must contain clock specifiers for rtc and register clock
- clock-names : Must contain "rtc" and "reg"
See ../clocks/clock-bindings.txt for details.
Example:
rtc: rtc@40046000 {
compatible = "nxp,lpc1788-rtc";
reg = <0x40046000 0x1000>;
interrupts = <47>;
clocks = <&creg_clk 0>, <&ccu1 CLK_CPU_BUS>;
clock-names = "rtc", "reg";
};
...@@ -16,6 +16,8 @@ Required properties: ...@@ -16,6 +16,8 @@ Required properties:
Optional properties: Optional properties:
- system-power-controller: whether the rtc is controlling the system power - system-power-controller: whether the rtc is controlling the system power
through pmic_power_en through pmic_power_en
- clocks: Any internal or external clocks feeding in to rtc
- clock-names: Corresponding names of the clocks
Example: Example:
...@@ -26,4 +28,6 @@ rtc@1c23000 { ...@@ -26,4 +28,6 @@ rtc@1c23000 {
19>; 19>;
interrupt-parent = <&intc>; interrupt-parent = <&intc>;
system-power-controller; system-power-controller;
clocks = <&clk_32k_rtc>, <&clk_32768_ck>;
clock-names = "ext-clk", "int-clk";
}; };
* Xilinx Zynq Ultrascale+ MPSoC Real Time Clock
RTC controller for the Xilinx Zynq MPSoC Real Time Clock
Separate IRQ lines for seconds and alarm
Required properties:
- compatible: Should be "xlnx,zynqmp-rtc"
- reg: Physical base address of the controller and length
of memory mapped region.
- interrupts: IRQ lines for the RTC.
- interrupt-names: interrupt line names eg. "sec" "alarm"
Optional:
- calibration: calibration value for 1 sec period which will
be programmed directly to calibration register
Example:
rtc: rtc@ffa60000 {
compatible = "xlnx,zynqmp-rtc";
reg = <0x0 0xffa60000 0x100>;
interrupt-parent = <&gic>;
interrupts = <0 26 4>, <0 27 4>;
interrupt-names = "alarm", "sec";
calibration = <0x198233>;
};
...@@ -358,6 +358,8 @@ rtc: rtc@44e3e000 { ...@@ -358,6 +358,8 @@ rtc: rtc@44e3e000 {
interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH
GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>; GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "rtc"; ti,hwmods = "rtc";
clocks = <&clk_32768_ck>;
clock-names = "int-clk";
status = "disabled"; status = "disabled";
}; };
......
...@@ -112,6 +112,13 @@ refclk: oscillator { ...@@ -112,6 +112,13 @@ refclk: oscillator {
clock-frequency = <12000000>; clock-frequency = <12000000>;
}; };
/* fixed 32k external oscillator clock */
clk_32k_rtc: clk_32k_rtc {
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <32768>;
};
sound0: sound@0 { sound0: sound@0 {
compatible = "simple-audio-card"; compatible = "simple-audio-card";
simple-audio-card,name = "AM437x-GP-EVM"; simple-audio-card,name = "AM437x-GP-EVM";
...@@ -941,3 +948,9 @@ &mcasp1 { ...@@ -941,3 +948,9 @@ &mcasp1 {
tx-num-evt = <32>; tx-num-evt = <32>;
rx-num-evt = <32>; rx-num-evt = <32>;
}; };
&rtc {
clocks = <&clk_32k_rtc>, <&clk_32768_ck>;
clock-names = "ext-clk", "int-clk";
status = "okay";
};
...@@ -110,6 +110,13 @@ switch@0 { ...@@ -110,6 +110,13 @@ switch@0 {
gpios = <&gpio4 2 GPIO_ACTIVE_LOW>; gpios = <&gpio4 2 GPIO_ACTIVE_LOW>;
}; };
}; };
/* fixed 32k external oscillator clock */
clk_32k_rtc: clk_32k_rtc {
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <32768>;
};
}; };
&am43xx_pinmux { &am43xx_pinmux {
...@@ -394,6 +401,8 @@ &cpsw_emac0 { ...@@ -394,6 +401,8 @@ &cpsw_emac0 {
}; };
&rtc { &rtc {
clocks = <&clk_32k_rtc>, <&clk_32768_ck>;
clock-names = "ext-clk", "int-clk";
status = "okay"; status = "okay";
}; };
......
...@@ -24,6 +24,13 @@ aliases { ...@@ -24,6 +24,13 @@ aliases {
display0 = &lcd0; display0 = &lcd0;
}; };
/* fixed 32k external oscillator clock */
clk_32k_rtc: clk_32k_rtc {
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <32768>;
};
backlight { backlight {
compatible = "pwm-backlight"; compatible = "pwm-backlight";
pwms = <&ecap0 0 50000 PWM_POLARITY_INVERTED>; pwms = <&ecap0 0 50000 PWM_POLARITY_INVERTED>;
...@@ -697,6 +704,8 @@ dpi_out: endpoint@0 { ...@@ -697,6 +704,8 @@ dpi_out: endpoint@0 {
}; };
&rtc { &rtc {
clocks = <&clk_32k_rtc>, <&clk_32768_ck>;
clock-names = "ext-clk", "int-clk";
status = "okay"; status = "okay";
}; };
......
...@@ -157,7 +157,7 @@ CONFIG_LEDS_TRIGGERS=y ...@@ -157,7 +157,7 @@ CONFIG_LEDS_TRIGGERS=y
CONFIG_LEDS_TRIGGER_HEARTBEAT=y CONFIG_LEDS_TRIGGER_HEARTBEAT=y
CONFIG_RTC_CLASS=y CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_V3020=y CONFIG_RTC_DRV_V3020=y
CONFIG_RTC_DRV_SA1100=y CONFIG_RTC_DRV_PXA=y
CONFIG_EXT2_FS=y CONFIG_EXT2_FS=y
CONFIG_EXT3_FS=y CONFIG_EXT3_FS=y
CONFIG_INOTIFY=y CONFIG_INOTIFY=y
......
...@@ -157,7 +157,7 @@ CONFIG_LEDS_TRIGGERS=y ...@@ -157,7 +157,7 @@ CONFIG_LEDS_TRIGGERS=y
CONFIG_LEDS_TRIGGER_HEARTBEAT=y CONFIG_LEDS_TRIGGER_HEARTBEAT=y
CONFIG_RTC_CLASS=y CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_V3020=y CONFIG_RTC_DRV_V3020=y
CONFIG_RTC_DRV_SA1100=y CONFIG_RTC_DRV_PXA=y
CONFIG_EXT2_FS=y CONFIG_EXT2_FS=y
CONFIG_EXT3_FS=y CONFIG_EXT3_FS=y
CONFIG_INOTIFY=y CONFIG_INOTIFY=y
......
...@@ -150,7 +150,7 @@ CONFIG_LEDS_TRIGGERS=y ...@@ -150,7 +150,7 @@ CONFIG_LEDS_TRIGGERS=y
CONFIG_LEDS_TRIGGER_BACKLIGHT=y CONFIG_LEDS_TRIGGER_BACKLIGHT=y
CONFIG_RTC_CLASS=y CONFIG_RTC_CLASS=y
CONFIG_RTC_DEBUG=y CONFIG_RTC_DEBUG=y
CONFIG_RTC_DRV_SA1100=y CONFIG_RTC_DRV_PXA=y
CONFIG_EXT2_FS=y CONFIG_EXT2_FS=y
CONFIG_INOTIFY=y CONFIG_INOTIFY=y
CONFIG_MSDOS_FS=m CONFIG_MSDOS_FS=m
......
...@@ -67,7 +67,7 @@ CONFIG_MMC=y ...@@ -67,7 +67,7 @@ CONFIG_MMC=y
CONFIG_MMC_DEBUG=y CONFIG_MMC_DEBUG=y
CONFIG_MMC_PXA=y CONFIG_MMC_PXA=y
CONFIG_RTC_CLASS=y CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_SA1100=y CONFIG_RTC_DRV_PXA=y
CONFIG_EXT2_FS=y CONFIG_EXT2_FS=y
CONFIG_EXT3_FS=y CONFIG_EXT3_FS=y
# CONFIG_DNOTIFY is not set # CONFIG_DNOTIFY is not set
......
...@@ -82,7 +82,7 @@ CONFIG_MMC=y ...@@ -82,7 +82,7 @@ CONFIG_MMC=y
CONFIG_MMC_PXA=y CONFIG_MMC_PXA=y
CONFIG_RTC_CLASS=y CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_PCF8563=m CONFIG_RTC_DRV_PCF8563=m
CONFIG_RTC_DRV_SA1100=m CONFIG_RTC_DRV_PXA=m
CONFIG_EXT2_FS=m CONFIG_EXT2_FS=m
CONFIG_EXT3_FS=m CONFIG_EXT3_FS=m
# CONFIG_DNOTIFY is not set # CONFIG_DNOTIFY is not set
......
...@@ -177,7 +177,7 @@ CONFIG_NEW_LEDS=y ...@@ -177,7 +177,7 @@ CONFIG_NEW_LEDS=y
CONFIG_RTC_CLASS=y CONFIG_RTC_CLASS=y
# CONFIG_RTC_HCTOSYS is not set # CONFIG_RTC_HCTOSYS is not set
CONFIG_RTC_DRV_PCF8583=m CONFIG_RTC_DRV_PCF8583=m
CONFIG_RTC_DRV_SA1100=y CONFIG_RTC_DRV_PXA=y
CONFIG_EXT2_FS=y CONFIG_EXT2_FS=y
CONFIG_EXT2_FS_XATTR=y CONFIG_EXT2_FS_XATTR=y
CONFIG_EXT2_FS_POSIX_ACL=y CONFIG_EXT2_FS_POSIX_ACL=y
......
#ifndef __ASM_MACH_REGS_RTC_H
#define __ASM_MACH_REGS_RTC_H
#include <mach/addr-map.h>
#define RTC_VIRT_BASE (APB_VIRT_BASE + 0x10000)
#define RTC_REG(x) (*((volatile u32 __iomem *)(RTC_VIRT_BASE + (x))))
/*
* Real Time Clock
*/
#define RCNR RTC_REG(0x00) /* RTC Count Register */
#define RTAR RTC_REG(0x04) /* RTC Alarm Register */
#define RTSR RTC_REG(0x08) /* RTC Status Register */
#define RTTR RTC_REG(0x0C) /* RTC Timer Trim Register */
#define RTSR_HZE (1 << 3) /* HZ interrupt enable */
#define RTSR_ALE (1 << 2) /* RTC alarm interrupt enable */
#define RTSR_HZ (1 << 1) /* HZ rising-edge detected */
#define RTSR_AL (1 << 0) /* RTC alarm detected */
#endif /* __ASM_MACH_REGS_RTC_H */
...@@ -440,25 +440,11 @@ struct platform_device pxa_device_rtc = { ...@@ -440,25 +440,11 @@ struct platform_device pxa_device_rtc = {
.resource = pxa_rtc_resources, .resource = pxa_rtc_resources,
}; };
static struct resource sa1100_rtc_resources[] = {
{
.start = IRQ_RTC1Hz,
.end = IRQ_RTC1Hz,
.name = "rtc 1Hz",
.flags = IORESOURCE_IRQ,
}, {
.start = IRQ_RTCAlrm,
.end = IRQ_RTCAlrm,
.name = "rtc alarm",
.flags = IORESOURCE_IRQ,
},
};
struct platform_device sa1100_device_rtc = { struct platform_device sa1100_device_rtc = {
.name = "sa1100-rtc", .name = "sa1100-rtc",
.id = -1, .id = -1,
.num_resources = ARRAY_SIZE(sa1100_rtc_resources), .num_resources = ARRAY_SIZE(pxa_rtc_resources),
.resource = sa1100_rtc_resources, .resource = pxa_rtc_resources,
}; };
static struct resource pxa_ac97_resources[] = { static struct resource pxa_ac97_resources[] = {
......
...@@ -282,7 +282,6 @@ static struct platform_device *devices[] __initdata = { ...@@ -282,7 +282,6 @@ static struct platform_device *devices[] __initdata = {
&pxa_device_asoc_ssp2, &pxa_device_asoc_ssp2,
&pxa_device_asoc_ssp3, &pxa_device_asoc_ssp3,
&pxa_device_asoc_platform, &pxa_device_asoc_platform,
&sa1100_device_rtc,
&pxa_device_rtc, &pxa_device_rtc,
&pxa27x_device_ssp1, &pxa27x_device_ssp1,
&pxa27x_device_ssp2, &pxa27x_device_ssp2,
......
...@@ -394,7 +394,6 @@ static struct platform_device *devices[] __initdata = { ...@@ -394,7 +394,6 @@ static struct platform_device *devices[] __initdata = {
&pxa_device_asoc_ssp3, &pxa_device_asoc_ssp3,
&pxa_device_asoc_ssp4, &pxa_device_asoc_ssp4,
&pxa_device_asoc_platform, &pxa_device_asoc_platform,
&sa1100_device_rtc,
&pxa_device_rtc, &pxa_device_rtc,
&pxa3xx_device_ssp1, &pxa3xx_device_ssp1,
&pxa3xx_device_ssp2, &pxa3xx_device_ssp2,
......
...@@ -857,40 +857,6 @@ ...@@ -857,40 +857,6 @@
#define OIER_E3 OIER_E (3) /* match interrupt Enable 3 */ #define OIER_E3 OIER_E (3) /* match interrupt Enable 3 */
/*
* Real-Time Clock (RTC) control registers
*
* Registers
* RTAR Real-Time Clock (RTC) Alarm Register (read/write).
* RCNR Real-Time Clock (RTC) CouNt Register (read/write).
* RTTR Real-Time Clock (RTC) Trim Register (read/write).
* RTSR Real-Time Clock (RTC) Status Register (read/write).
*
* Clocks
* frtx, Trtx Frequency, period of the real-time clock crystal
* (32.768 kHz nominal).
* frtc, Trtc Frequency, period of the real-time clock counter
* (1 Hz nominal).
*/
#define RTAR __REG(0x90010000) /* RTC Alarm Reg. */
#define RCNR __REG(0x90010004) /* RTC CouNt Reg. */
#define RTTR __REG(0x90010008) /* RTC Trim Reg. */
#define RTSR __REG(0x90010010) /* RTC Status Reg. */
#define RTTR_C Fld (16, 0) /* clock divider Count - 1 */
#define RTTR_D Fld (10, 16) /* trim Delete count */
/* frtc = (1023*(C + 1) - D)*frtx/ */
/* (1023*(C + 1)^2) */
/* Trtc = (1023*(C + 1)^2)*Trtx/ */
/* (1023*(C + 1) - D) */
#define RTSR_AL 0x00000001 /* ALarm detected */
#define RTSR_HZ 0x00000002 /* 1 Hz clock detected */
#define RTSR_ALE 0x00000004 /* ALarm interrupt Enable */
#define RTSR_HZE 0x00000008 /* 1 Hz clock interrupt Enable */
/* /*
* Power Manager (PM) control registers * Power Manager (PM) control registers
* *
......
...@@ -945,11 +945,11 @@ config RTC_DRV_DA9055 ...@@ -945,11 +945,11 @@ config RTC_DRV_DA9055
will be called rtc-da9055 will be called rtc-da9055
config RTC_DRV_DA9063 config RTC_DRV_DA9063
tristate "Dialog Semiconductor DA9063 RTC" tristate "Dialog Semiconductor DA9063/DA9062 RTC"
depends on MFD_DA9063 depends on MFD_DA9063 || MFD_DA9062
help help
If you say yes here you will get support for the RTC subsystem If you say yes here you will get support for the RTC subsystem
of the Dialog Semiconductor DA9063. for the Dialog Semiconductor PMIC chips DA9063 and DA9062.
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called "rtc-da9063". will be called "rtc-da9063".
...@@ -1116,6 +1116,13 @@ config RTC_DRV_OPAL ...@@ -1116,6 +1116,13 @@ config RTC_DRV_OPAL
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called rtc-opal. will be called rtc-opal.
config RTC_DRV_ZYNQMP
tristate "Xilinx Zynq Ultrascale+ MPSoC RTC"
depends on OF
help
If you say yes here you get support for the RTC controller found on
Xilinx Zynq Ultrascale+ MPSoC.
comment "on-CPU RTC drivers" comment "on-CPU RTC drivers"
config RTC_DRV_DAVINCI config RTC_DRV_DAVINCI
...@@ -1306,11 +1313,13 @@ config RTC_DRV_GENERIC ...@@ -1306,11 +1313,13 @@ config RTC_DRV_GENERIC
just say Y. just say Y.
config RTC_DRV_PXA config RTC_DRV_PXA
tristate "PXA27x/PXA3xx" tristate "PXA27x/PXA3xx"
depends on ARCH_PXA depends on ARCH_PXA
help select RTC_DRV_SA1100
If you say Y here you will get access to the real time clock help
built into your PXA27x or PXA3xx CPU. If you say Y here you will get access to the real time clock
built into your PXA27x or PXA3xx CPU. This RTC is actually 2 RTCs
consisting of an SA1100 compatible RTC and the extended PXA RTC.
This RTC driver uses PXA RTC registers available since pxa27x This RTC driver uses PXA RTC registers available since pxa27x
series (RDxR, RYxR) instead of legacy RCNR, RTAR. series (RDxR, RYxR) instead of legacy RCNR, RTAR.
...@@ -1456,6 +1465,18 @@ config RTC_DRV_JZ4740 ...@@ -1456,6 +1465,18 @@ config RTC_DRV_JZ4740
This driver can also be buillt as a module. If so, the module This driver can also be buillt as a module. If so, the module
will be called rtc-jz4740. will be called rtc-jz4740.
config RTC_DRV_LPC24XX
tristate "NXP RTC for LPC178x/18xx/408x/43xx"
depends on ARCH_LPC18XX || COMPILE_TEST
depends on OF && HAS_IOMEM
help
This enables support for the NXP RTC found which can be found on
NXP LPC178x/18xx/408x/43xx devices.
If you have one of the devices above enable this driver to use
the hardware RTC. This driver can also be buillt as a module. If
so, the module will be called rtc-lpc24xx.
config RTC_DRV_LPC32XX config RTC_DRV_LPC32XX
depends on ARCH_LPC32XX depends on ARCH_LPC32XX
tristate "NXP LPC32XX RTC" tristate "NXP LPC32XX RTC"
......
...@@ -74,6 +74,7 @@ obj-$(CONFIG_RTC_DRV_ISL12057) += rtc-isl12057.o ...@@ -74,6 +74,7 @@ obj-$(CONFIG_RTC_DRV_ISL12057) += rtc-isl12057.o
obj-$(CONFIG_RTC_DRV_ISL1208) += rtc-isl1208.o obj-$(CONFIG_RTC_DRV_ISL1208) += rtc-isl1208.o
obj-$(CONFIG_RTC_DRV_JZ4740) += rtc-jz4740.o obj-$(CONFIG_RTC_DRV_JZ4740) += rtc-jz4740.o
obj-$(CONFIG_RTC_DRV_LP8788) += rtc-lp8788.o obj-$(CONFIG_RTC_DRV_LP8788) += rtc-lp8788.o
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_LOONGSON1) += rtc-ls1x.o
obj-$(CONFIG_RTC_DRV_M41T80) += rtc-m41t80.o obj-$(CONFIG_RTC_DRV_M41T80) += rtc-m41t80.o
...@@ -158,3 +159,4 @@ obj-$(CONFIG_RTC_DRV_WM831X) += rtc-wm831x.o ...@@ -158,3 +159,4 @@ 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
...@@ -202,6 +202,7 @@ struct rtc_device *rtc_device_register(const char *name, struct device *dev, ...@@ -202,6 +202,7 @@ struct rtc_device *rtc_device_register(const char *name, struct device *dev,
rtc->max_user_freq = 64; rtc->max_user_freq = 64;
rtc->dev.parent = dev; rtc->dev.parent = dev;
rtc->dev.class = rtc_class; rtc->dev.class = rtc_class;
rtc->dev.groups = rtc_get_dev_attribute_groups();
rtc->dev.release = rtc_device_release; rtc->dev.release = rtc_device_release;
mutex_init(&rtc->ops_lock); mutex_init(&rtc->ops_lock);
...@@ -234,12 +235,12 @@ struct rtc_device *rtc_device_register(const char *name, struct device *dev, ...@@ -234,12 +235,12 @@ struct rtc_device *rtc_device_register(const char *name, struct device *dev,
err = device_register(&rtc->dev); err = device_register(&rtc->dev);
if (err) { if (err) {
/* This will free both memory and the ID */
put_device(&rtc->dev); put_device(&rtc->dev);
goto exit_kfree; goto exit;
} }
rtc_dev_add_device(rtc); rtc_dev_add_device(rtc);
rtc_sysfs_add_device(rtc);
rtc_proc_add_device(rtc); rtc_proc_add_device(rtc);
dev_info(dev, "rtc core: registered %s as %s\n", dev_info(dev, "rtc core: registered %s as %s\n",
...@@ -247,9 +248,6 @@ struct rtc_device *rtc_device_register(const char *name, struct device *dev, ...@@ -247,9 +248,6 @@ struct rtc_device *rtc_device_register(const char *name, struct device *dev,
return rtc; return rtc;
exit_kfree:
kfree(rtc);
exit_ida: exit_ida:
ida_simple_remove(&rtc_ida, id); ida_simple_remove(&rtc_ida, id);
...@@ -268,19 +266,17 @@ EXPORT_SYMBOL_GPL(rtc_device_register); ...@@ -268,19 +266,17 @@ EXPORT_SYMBOL_GPL(rtc_device_register);
*/ */
void rtc_device_unregister(struct rtc_device *rtc) void rtc_device_unregister(struct rtc_device *rtc)
{ {
if (get_device(&rtc->dev) != NULL) { mutex_lock(&rtc->ops_lock);
mutex_lock(&rtc->ops_lock); /*
/* remove innards of this RTC, then disable it, before * Remove innards of this RTC, then disable it, before
* letting any rtc_class_open() users access it again * letting any rtc_class_open() users access it again
*/ */
rtc_sysfs_del_device(rtc); rtc_dev_del_device(rtc);
rtc_dev_del_device(rtc); rtc_proc_del_device(rtc);
rtc_proc_del_device(rtc); device_del(&rtc->dev);
device_unregister(&rtc->dev); rtc->ops = NULL;
rtc->ops = NULL; mutex_unlock(&rtc->ops_lock);
mutex_unlock(&rtc->ops_lock); put_device(&rtc->dev);
put_device(&rtc->dev);
}
} }
EXPORT_SYMBOL_GPL(rtc_device_unregister); EXPORT_SYMBOL_GPL(rtc_device_unregister);
...@@ -363,7 +359,6 @@ static int __init rtc_init(void) ...@@ -363,7 +359,6 @@ static int __init rtc_init(void)
} }
rtc_class->pm = RTC_CLASS_DEV_PM_OPS; rtc_class->pm = RTC_CLASS_DEV_PM_OPS;
rtc_dev_init(); rtc_dev_init();
rtc_sysfs_init(rtc_class);
return 0; return 0;
} }
......
...@@ -564,7 +564,7 @@ enum hrtimer_restart rtc_pie_update_irq(struct hrtimer *timer) ...@@ -564,7 +564,7 @@ enum hrtimer_restart rtc_pie_update_irq(struct hrtimer *timer)
void rtc_update_irq(struct rtc_device *rtc, void rtc_update_irq(struct rtc_device *rtc,
unsigned long num, unsigned long events) unsigned long num, unsigned long events)
{ {
if (unlikely(IS_ERR_OR_NULL(rtc))) if (IS_ERR_OR_NULL(rtc))
return; return;
pm_stay_awake(rtc->dev.parent); pm_stay_awake(rtc->dev.parent);
......
...@@ -251,17 +251,26 @@ static SIMPLE_DEV_PM_OPS(pm80x_rtc_pm_ops, pm80x_rtc_suspend, pm80x_rtc_resume); ...@@ -251,17 +251,26 @@ static SIMPLE_DEV_PM_OPS(pm80x_rtc_pm_ops, pm80x_rtc_suspend, pm80x_rtc_resume);
static int pm80x_rtc_probe(struct platform_device *pdev) static int pm80x_rtc_probe(struct platform_device *pdev)
{ {
struct pm80x_chip *chip = dev_get_drvdata(pdev->dev.parent); struct pm80x_chip *chip = dev_get_drvdata(pdev->dev.parent);
struct pm80x_platform_data *pm80x_pdata = struct pm80x_rtc_pdata *pdata = dev_get_platdata(&pdev->dev);
dev_get_platdata(pdev->dev.parent);
struct pm80x_rtc_pdata *pdata = NULL;
struct pm80x_rtc_info *info; struct pm80x_rtc_info *info;
struct device_node *node = pdev->dev.of_node;
struct rtc_time tm; struct rtc_time tm;
unsigned long ticks = 0; unsigned long ticks = 0;
int ret; int ret;
pdata = dev_get_platdata(&pdev->dev); if (!pdata && !node) {
if (pdata == NULL) dev_err(&pdev->dev,
dev_warn(&pdev->dev, "No platform data!\n"); "pm80x-rtc requires platform data or of_node\n");
return -EINVAL;
}
if (!pdata) {
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata) {
dev_err(&pdev->dev, "failed to allocate memory\n");
return -ENOMEM;
}
}
info = info =
devm_kzalloc(&pdev->dev, sizeof(struct pm80x_rtc_info), GFP_KERNEL); devm_kzalloc(&pdev->dev, sizeof(struct pm80x_rtc_info), GFP_KERNEL);
...@@ -327,11 +336,8 @@ static int pm80x_rtc_probe(struct platform_device *pdev) ...@@ -327,11 +336,8 @@ static int pm80x_rtc_probe(struct platform_device *pdev)
regmap_update_bits(info->map, PM800_RTC_CONTROL, PM800_RTC1_USE_XO, regmap_update_bits(info->map, PM800_RTC_CONTROL, PM800_RTC1_USE_XO,
PM800_RTC1_USE_XO); PM800_RTC1_USE_XO);
if (pm80x_pdata) { /* remember whether this power up is caused by PMIC RTC or not */
pdata = pm80x_pdata->rtc; info->rtc_dev->dev.platform_data = &pdata->rtc_wakeup;
if (pdata)
info->rtc_dev->dev.platform_data = &pdata->rtc_wakeup;
}
device_init_wakeup(&pdev->dev, 1); device_init_wakeup(&pdev->dev, 1);
......
...@@ -1009,6 +1009,7 @@ static const struct of_device_id abb5zes3_dt_match[] = { ...@@ -1009,6 +1009,7 @@ static const struct of_device_id abb5zes3_dt_match[] = {
{ .compatible = "abracon,abb5zes3" }, { .compatible = "abracon,abb5zes3" },
{ }, { },
}; };
MODULE_DEVICE_TABLE(of, abb5zes3_dt_match);
#endif #endif
static const struct i2c_device_id abb5zes3_id[] = { static const struct i2c_device_id abb5zes3_id[] = {
...@@ -1020,7 +1021,6 @@ MODULE_DEVICE_TABLE(i2c, abb5zes3_id); ...@@ -1020,7 +1021,6 @@ MODULE_DEVICE_TABLE(i2c, abb5zes3_id);
static struct i2c_driver abb5zes3_driver = { static struct i2c_driver abb5zes3_driver = {
.driver = { .driver = {
.name = DRV_NAME, .name = DRV_NAME,
.owner = THIS_MODULE,
.pm = &abb5zes3_rtc_pm_ops, .pm = &abb5zes3_rtc_pm_ops,
.of_match_table = of_match_ptr(abb5zes3_dt_match), .of_match_table = of_match_ptr(abb5zes3_dt_match),
}, },
......
...@@ -445,7 +445,9 @@ static const struct rtc_class_ops ab8540_rtc_ops = { ...@@ -445,7 +445,9 @@ static const struct rtc_class_ops ab8540_rtc_ops = {
static const struct platform_device_id ab85xx_rtc_ids[] = { static const struct platform_device_id ab85xx_rtc_ids[] = {
{ "ab8500-rtc", (kernel_ulong_t)&ab8500_rtc_ops, }, { "ab8500-rtc", (kernel_ulong_t)&ab8500_rtc_ops, },
{ "ab8540-rtc", (kernel_ulong_t)&ab8540_rtc_ops, }, { "ab8540-rtc", (kernel_ulong_t)&ab8540_rtc_ops, },
{ /* sentinel */ }
}; };
MODULE_DEVICE_TABLE(platform, ab85xx_rtc_ids);
static int ab8500_rtc_probe(struct platform_device *pdev) static int ab8500_rtc_probe(struct platform_device *pdev)
{ {
......
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
#define ABX8XX_REG_WD 0x07 #define ABX8XX_REG_WD 0x07
#define ABX8XX_REG_CTRL1 0x10 #define ABX8XX_REG_CTRL1 0x10
#define ABX8XX_CTRL_WRITE BIT(1) #define ABX8XX_CTRL_WRITE BIT(0)
#define ABX8XX_CTRL_12_24 BIT(6) #define ABX8XX_CTRL_12_24 BIT(6)
#define ABX8XX_REG_CFG_KEY 0x1f #define ABX8XX_REG_CFG_KEY 0x1f
......
...@@ -40,13 +40,6 @@ struct armada38x_rtc { ...@@ -40,13 +40,6 @@ struct armada38x_rtc {
void __iomem *regs; void __iomem *regs;
void __iomem *regs_soc; void __iomem *regs_soc;
spinlock_t lock; spinlock_t lock;
/*
* While setting the time, the RTC TIME register should not be
* accessed. Setting the RTC time involves sleeping during
* 100ms, so a mutex instead of a spinlock is used to protect
* it
*/
struct mutex mutex_time;
int irq; int irq;
}; };
...@@ -64,9 +57,9 @@ static void rtc_delayed_write(u32 val, struct armada38x_rtc *rtc, int offset) ...@@ -64,9 +57,9 @@ static void rtc_delayed_write(u32 val, struct armada38x_rtc *rtc, int offset)
static int armada38x_rtc_read_time(struct device *dev, struct rtc_time *tm) static int armada38x_rtc_read_time(struct device *dev, struct rtc_time *tm)
{ {
struct armada38x_rtc *rtc = dev_get_drvdata(dev); struct armada38x_rtc *rtc = dev_get_drvdata(dev);
unsigned long time, time_check; unsigned long time, time_check, flags;
mutex_lock(&rtc->mutex_time); spin_lock_irqsave(&rtc->lock, flags);
time = readl(rtc->regs + RTC_TIME); time = readl(rtc->regs + RTC_TIME);
/* /*
* WA for failing time set attempts. As stated in HW ERRATA if * WA for failing time set attempts. As stated in HW ERRATA if
...@@ -77,7 +70,7 @@ static int armada38x_rtc_read_time(struct device *dev, struct rtc_time *tm) ...@@ -77,7 +70,7 @@ static int armada38x_rtc_read_time(struct device *dev, struct rtc_time *tm)
if ((time_check - time) > 1) if ((time_check - time) > 1)
time_check = readl(rtc->regs + RTC_TIME); time_check = readl(rtc->regs + RTC_TIME);
mutex_unlock(&rtc->mutex_time); spin_unlock_irqrestore(&rtc->lock, flags);
rtc_time_to_tm(time_check, tm); rtc_time_to_tm(time_check, tm);
...@@ -88,23 +81,23 @@ static int armada38x_rtc_set_time(struct device *dev, struct rtc_time *tm) ...@@ -88,23 +81,23 @@ 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; int ret = 0;
unsigned long time; unsigned long time, flags;
ret = rtc_tm_to_time(tm, &time); ret = rtc_tm_to_time(tm, &time);
if (ret) if (ret)
goto out; goto out;
/* /*
* Setting the RTC time not always succeeds. According to the * According to errata FE-3124064, Write to RTC TIME register
* errata we need to first write on the status register and * may fail. As a workaround, after writing to RTC TIME
* then wait for 100ms before writing to the time register to be * register, issue a dummy write of 0x0 twice to RTC Status
* sure that the data will be taken into account. * register.
*/ */
mutex_lock(&rtc->mutex_time); spin_lock_irqsave(&rtc->lock, flags);
rtc_delayed_write(0, rtc, RTC_STATUS);
msleep(100);
rtc_delayed_write(time, rtc, RTC_TIME); rtc_delayed_write(time, rtc, RTC_TIME);
mutex_unlock(&rtc->mutex_time); rtc_delayed_write(0, rtc, RTC_STATUS);
rtc_delayed_write(0, rtc, RTC_STATUS);
spin_unlock_irqrestore(&rtc->lock, flags);
out: out:
return ret; return ret;
...@@ -229,7 +222,6 @@ static __init int armada38x_rtc_probe(struct platform_device *pdev) ...@@ -229,7 +222,6 @@ static __init int armada38x_rtc_probe(struct platform_device *pdev)
return -ENOMEM; return -ENOMEM;
spin_lock_init(&rtc->lock); spin_lock_init(&rtc->lock);
mutex_init(&rtc->mutex_time);
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rtc"); res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rtc");
rtc->regs = devm_ioremap_resource(&pdev->dev, res); rtc->regs = devm_ioremap_resource(&pdev->dev, res);
...@@ -303,6 +295,7 @@ static const struct of_device_id armada38x_rtc_of_match_table[] = { ...@@ -303,6 +295,7 @@ static const struct of_device_id armada38x_rtc_of_match_table[] = {
{ .compatible = "marvell,armada-380-rtc", }, { .compatible = "marvell,armada-380-rtc", },
{} {}
}; };
MODULE_DEVICE_TABLE(of, armada38x_rtc_of_match_table);
#endif #endif
static struct platform_driver armada38x_rtc_driver = { static struct platform_driver armada38x_rtc_driver = {
......
...@@ -45,7 +45,7 @@ static void as3722_time_to_reg(u8 *rbuff, struct rtc_time *tm) ...@@ -45,7 +45,7 @@ static void as3722_time_to_reg(u8 *rbuff, struct rtc_time *tm)
rbuff[1] = bin2bcd(tm->tm_min); rbuff[1] = bin2bcd(tm->tm_min);
rbuff[2] = bin2bcd(tm->tm_hour); rbuff[2] = bin2bcd(tm->tm_hour);
rbuff[3] = bin2bcd(tm->tm_mday); rbuff[3] = bin2bcd(tm->tm_mday);
rbuff[4] = bin2bcd(tm->tm_mon); rbuff[4] = bin2bcd(tm->tm_mon + 1);
rbuff[5] = bin2bcd(tm->tm_year - (AS3722_RTC_START_YEAR - 1900)); rbuff[5] = bin2bcd(tm->tm_year - (AS3722_RTC_START_YEAR - 1900));
} }
...@@ -55,7 +55,7 @@ static void as3722_reg_to_time(u8 *rbuff, struct rtc_time *tm) ...@@ -55,7 +55,7 @@ static void as3722_reg_to_time(u8 *rbuff, struct rtc_time *tm)
tm->tm_min = bcd2bin(rbuff[1] & 0x7F); tm->tm_min = bcd2bin(rbuff[1] & 0x7F);
tm->tm_hour = bcd2bin(rbuff[2] & 0x3F); tm->tm_hour = bcd2bin(rbuff[2] & 0x3F);
tm->tm_mday = bcd2bin(rbuff[3] & 0x3F); tm->tm_mday = bcd2bin(rbuff[3] & 0x3F);
tm->tm_mon = bcd2bin(rbuff[4] & 0x1F); tm->tm_mon = bcd2bin(rbuff[4] & 0x1F) - 1;
tm->tm_year = (AS3722_RTC_START_YEAR - 1900) + bcd2bin(rbuff[5] & 0x7F); tm->tm_year = (AS3722_RTC_START_YEAR - 1900) + bcd2bin(rbuff[5] & 0x7F);
return; return;
} }
......
...@@ -18,20 +18,21 @@ ...@@ -18,20 +18,21 @@
* *
*/ */
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/time.h>
#include <linux/rtc.h>
#include <linux/bcd.h> #include <linux/bcd.h>
#include <linux/clk.h>
#include <linux/completion.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/spinlock.h>
#include <linux/ioctl.h> #include <linux/ioctl.h>
#include <linux/completion.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/of.h> #include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of_device.h> #include <linux/of_device.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/rtc.h>
#include <linux/spinlock.h>
#include <linux/suspend.h> #include <linux/suspend.h>
#include <linux/time.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include "rtc-at91rm9200.h" #include "rtc-at91rm9200.h"
...@@ -59,6 +60,7 @@ static bool suspended; ...@@ -59,6 +60,7 @@ static bool suspended;
static DEFINE_SPINLOCK(suspended_lock); static DEFINE_SPINLOCK(suspended_lock);
static unsigned long cached_events; static unsigned long cached_events;
static u32 at91_rtc_imr; static u32 at91_rtc_imr;
static struct clk *sclk;
static void at91_rtc_write_ier(u32 mask) static void at91_rtc_write_ier(u32 mask)
{ {
...@@ -407,6 +409,16 @@ static int __init at91_rtc_probe(struct platform_device *pdev) ...@@ -407,6 +409,16 @@ static int __init at91_rtc_probe(struct platform_device *pdev)
return -ENOMEM; return -ENOMEM;
} }
sclk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(sclk))
return PTR_ERR(sclk);
ret = clk_prepare_enable(sclk);
if (ret) {
dev_err(&pdev->dev, "Could not enable slow clock\n");
return ret;
}
at91_rtc_write(AT91_RTC_CR, 0); at91_rtc_write(AT91_RTC_CR, 0);
at91_rtc_write(AT91_RTC_MR, 0); /* 24 hour mode */ at91_rtc_write(AT91_RTC_MR, 0); /* 24 hour mode */
...@@ -420,7 +432,7 @@ static int __init at91_rtc_probe(struct platform_device *pdev) ...@@ -420,7 +432,7 @@ static int __init at91_rtc_probe(struct platform_device *pdev)
"at91_rtc", pdev); "at91_rtc", pdev);
if (ret) { if (ret) {
dev_err(&pdev->dev, "IRQ %d already in use.\n", irq); dev_err(&pdev->dev, "IRQ %d already in use.\n", irq);
return ret; goto err_clk;
} }
/* cpu init code should really have flagged this device as /* cpu init code should really have flagged this device as
...@@ -431,8 +443,10 @@ static int __init at91_rtc_probe(struct platform_device *pdev) ...@@ -431,8 +443,10 @@ static int __init at91_rtc_probe(struct platform_device *pdev)
rtc = devm_rtc_device_register(&pdev->dev, pdev->name, rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
&at91_rtc_ops, THIS_MODULE); &at91_rtc_ops, THIS_MODULE);
if (IS_ERR(rtc)) if (IS_ERR(rtc)) {
return PTR_ERR(rtc); ret = PTR_ERR(rtc);
goto err_clk;
}
platform_set_drvdata(pdev, rtc); platform_set_drvdata(pdev, rtc);
/* enable SECEV interrupt in order to initialize at91_rtc_upd_rdy /* enable SECEV interrupt in order to initialize at91_rtc_upd_rdy
...@@ -442,6 +456,11 @@ static int __init at91_rtc_probe(struct platform_device *pdev) ...@@ -442,6 +456,11 @@ static int __init at91_rtc_probe(struct platform_device *pdev)
dev_info(&pdev->dev, "AT91 Real Time Clock driver.\n"); dev_info(&pdev->dev, "AT91 Real Time Clock driver.\n");
return 0; return 0;
err_clk:
clk_disable_unprepare(sclk);
return ret;
} }
/* /*
...@@ -454,6 +473,8 @@ static int __exit at91_rtc_remove(struct platform_device *pdev) ...@@ -454,6 +473,8 @@ static int __exit at91_rtc_remove(struct platform_device *pdev)
AT91_RTC_SECEV | AT91_RTC_TIMEV | AT91_RTC_SECEV | AT91_RTC_TIMEV |
AT91_RTC_CALEV); AT91_RTC_CALEV);
clk_disable_unprepare(sclk);
return 0; return 0;
} }
......
...@@ -11,20 +11,20 @@ ...@@ -11,20 +11,20 @@
* 2 of the License, or (at your option) any later version. * 2 of the License, or (at your option) any later version.
*/ */
#include <linux/module.h> #include <linux/clk.h>
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/time.h>
#include <linux/rtc.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/ioctl.h> #include <linux/ioctl.h>
#include <linux/slab.h>
#include <linux/platform_data/atmel.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/kernel.h>
#include <linux/mfd/syscon.h> #include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/regmap.h> #include <linux/regmap.h>
#include <linux/rtc.h>
#include <linux/slab.h>
#include <linux/suspend.h> #include <linux/suspend.h>
#include <linux/clk.h> #include <linux/time.h>
/* /*
* This driver uses two configurable hardware resources that live in the * This driver uses two configurable hardware resources that live in the
...@@ -425,18 +425,19 @@ static int at91_rtc_probe(struct platform_device *pdev) ...@@ -425,18 +425,19 @@ static int at91_rtc_probe(struct platform_device *pdev)
if (IS_ERR(rtc->sclk)) if (IS_ERR(rtc->sclk))
return PTR_ERR(rtc->sclk); return PTR_ERR(rtc->sclk);
sclk_rate = clk_get_rate(rtc->sclk);
if (!sclk_rate || sclk_rate > AT91_RTT_RTPRES) {
dev_err(&pdev->dev, "Invalid slow clock rate\n");
return -EINVAL;
}
ret = clk_prepare_enable(rtc->sclk); ret = clk_prepare_enable(rtc->sclk);
if (ret) { if (ret) {
dev_err(&pdev->dev, "Could not enable slow clock\n"); dev_err(&pdev->dev, "Could not enable slow clock\n");
return ret; return ret;
} }
sclk_rate = clk_get_rate(rtc->sclk);
if (!sclk_rate || sclk_rate > AT91_RTT_RTPRES) {
dev_err(&pdev->dev, "Invalid slow clock rate\n");
ret = -EINVAL;
goto err_clk;
}
mr = rtt_readl(rtc, MR); mr = rtt_readl(rtc, MR);
/* unless RTT is counting at 1 Hz, re-initialize it */ /* unless RTT is counting at 1 Hz, re-initialize it */
...@@ -451,8 +452,10 @@ static int at91_rtc_probe(struct platform_device *pdev) ...@@ -451,8 +452,10 @@ static int at91_rtc_probe(struct platform_device *pdev)
rtc->rtcdev = devm_rtc_device_register(&pdev->dev, pdev->name, rtc->rtcdev = devm_rtc_device_register(&pdev->dev, pdev->name,
&at91_rtc_ops, THIS_MODULE); &at91_rtc_ops, THIS_MODULE);
if (IS_ERR(rtc->rtcdev)) if (IS_ERR(rtc->rtcdev)) {
return PTR_ERR(rtc->rtcdev); ret = PTR_ERR(rtc->rtcdev);
goto err_clk;
}
/* register irq handler after we know what name we'll use */ /* register irq handler after we know what name we'll use */
ret = devm_request_irq(&pdev->dev, rtc->irq, at91_rtc_interrupt, ret = devm_request_irq(&pdev->dev, rtc->irq, at91_rtc_interrupt,
...@@ -460,7 +463,7 @@ static int at91_rtc_probe(struct platform_device *pdev) ...@@ -460,7 +463,7 @@ static int at91_rtc_probe(struct platform_device *pdev)
dev_name(&rtc->rtcdev->dev), rtc); dev_name(&rtc->rtcdev->dev), rtc);
if (ret) { if (ret) {
dev_dbg(&pdev->dev, "can't share IRQ %d?\n", rtc->irq); dev_dbg(&pdev->dev, "can't share IRQ %d?\n", rtc->irq);
return ret; goto err_clk;
} }
/* NOTE: sam9260 rev A silicon has a ROM bug which resets the /* NOTE: sam9260 rev A silicon has a ROM bug which resets the
...@@ -474,6 +477,11 @@ static int at91_rtc_probe(struct platform_device *pdev) ...@@ -474,6 +477,11 @@ static int at91_rtc_probe(struct platform_device *pdev)
dev_name(&rtc->rtcdev->dev)); dev_name(&rtc->rtcdev->dev));
return 0; return 0;
err_clk:
clk_disable_unprepare(rtc->sclk);
return ret;
} }
/* /*
...@@ -487,8 +495,7 @@ static int at91_rtc_remove(struct platform_device *pdev) ...@@ -487,8 +495,7 @@ static int at91_rtc_remove(struct platform_device *pdev)
/* disable all interrupts */ /* disable all interrupts */
rtt_writel(rtc, MR, mr & ~(AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN)); rtt_writel(rtc, MR, mr & ~(AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN));
if (!IS_ERR(rtc->sclk)) clk_disable_unprepare(rtc->sclk);
clk_disable_unprepare(rtc->sclk);
return 0; return 0;
} }
......
...@@ -361,7 +361,7 @@ static int bfin_rtc_probe(struct platform_device *pdev) ...@@ -361,7 +361,7 @@ static int bfin_rtc_probe(struct platform_device *pdev)
/* Register our RTC with the RTC framework */ /* Register our RTC with the RTC framework */
rtc->rtc_dev = devm_rtc_device_register(dev, pdev->name, &bfin_rtc_ops, rtc->rtc_dev = devm_rtc_device_register(dev, pdev->name, &bfin_rtc_ops,
THIS_MODULE); THIS_MODULE);
if (unlikely(IS_ERR(rtc->rtc_dev))) if (IS_ERR(rtc->rtc_dev))
return PTR_ERR(rtc->rtc_dev); return PTR_ERR(rtc->rtc_dev);
/* Grab the IRQ and init the hardware */ /* Grab the IRQ and init the hardware */
......
...@@ -212,7 +212,7 @@ static int bq32k_probe(struct i2c_client *client, ...@@ -212,7 +212,7 @@ static int bq32k_probe(struct i2c_client *client,
if (error) if (error)
return error; return error;
if (client && client->dev.of_node) if (client->dev.of_node)
trickle_charger_of_init(dev, client->dev.of_node); trickle_charger_of_init(dev, client->dev.of_node);
rtc = devm_rtc_device_register(&client->dev, bq32k_driver.driver.name, rtc = devm_rtc_device_register(&client->dev, bq32k_driver.driver.name,
...@@ -234,7 +234,6 @@ MODULE_DEVICE_TABLE(i2c, bq32k_id); ...@@ -234,7 +234,6 @@ MODULE_DEVICE_TABLE(i2c, bq32k_id);
static struct i2c_driver bq32k_driver = { static struct i2c_driver bq32k_driver = {
.driver = { .driver = {
.name = "bq32k", .name = "bq32k",
.owner = THIS_MODULE,
}, },
.probe = bq32k_probe, .probe = bq32k_probe,
.id_table = bq32k_id, .id_table = bq32k_id,
......
...@@ -41,7 +41,6 @@ ...@@ -41,7 +41,6 @@
#include <linux/pm.h> #include <linux/pm.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_platform.h> #include <linux/of_platform.h>
#include <linux/dmi.h>
/* 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 <asm-generic/rtc.h> #include <asm-generic/rtc.h>
...@@ -51,6 +50,7 @@ struct cmos_rtc { ...@@ -51,6 +50,7 @@ struct cmos_rtc {
struct device *dev; struct device *dev;
int irq; int irq;
struct resource *iomem; struct resource *iomem;
time64_t alarm_expires;
void (*wake_on)(struct device *); void (*wake_on)(struct device *);
void (*wake_off)(struct device *); void (*wake_off)(struct device *);
...@@ -377,53 +377,11 @@ static int cmos_set_alarm(struct device *dev, struct rtc_wkalrm *t) ...@@ -377,53 +377,11 @@ static int cmos_set_alarm(struct device *dev, struct rtc_wkalrm *t)
spin_unlock_irq(&rtc_lock); spin_unlock_irq(&rtc_lock);
return 0; cmos->alarm_expires = rtc_tm_to_time64(&t->time);
}
/*
* Do not disable RTC alarm on shutdown - workaround for b0rked BIOSes.
*/
static bool alarm_disable_quirk;
static int __init set_alarm_disable_quirk(const struct dmi_system_id *id)
{
alarm_disable_quirk = true;
pr_info("BIOS has alarm-disable quirk - RTC alarms disabled\n");
return 0; return 0;
} }
static const struct dmi_system_id rtc_quirks[] __initconst = {
/* https://bugzilla.novell.com/show_bug.cgi?id=805740 */
{
.callback = set_alarm_disable_quirk,
.ident = "IBM Truman",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
DMI_MATCH(DMI_PRODUCT_NAME, "4852570"),
},
},
/* https://bugzilla.novell.com/show_bug.cgi?id=812592 */
{
.callback = set_alarm_disable_quirk,
.ident = "Gigabyte GA-990XA-UD3",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR,
"Gigabyte Technology Co., Ltd."),
DMI_MATCH(DMI_PRODUCT_NAME, "GA-990XA-UD3"),
},
},
/* http://permalink.gmane.org/gmane.linux.kernel/1604474 */
{
.callback = set_alarm_disable_quirk,
.ident = "Toshiba Satellite L300",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
DMI_MATCH(DMI_PRODUCT_NAME, "Satellite L300"),
},
},
{}
};
static int cmos_alarm_irq_enable(struct device *dev, unsigned int enabled) static int cmos_alarm_irq_enable(struct device *dev, unsigned int enabled)
{ {
struct cmos_rtc *cmos = dev_get_drvdata(dev); struct cmos_rtc *cmos = dev_get_drvdata(dev);
...@@ -432,9 +390,6 @@ static int cmos_alarm_irq_enable(struct device *dev, unsigned int enabled) ...@@ -432,9 +390,6 @@ static int cmos_alarm_irq_enable(struct device *dev, unsigned int enabled)
if (!is_valid_irq(cmos->irq)) if (!is_valid_irq(cmos->irq))
return -EINVAL; return -EINVAL;
if (alarm_disable_quirk)
return 0;
spin_lock_irqsave(&rtc_lock, flags); spin_lock_irqsave(&rtc_lock, flags);
if (enabled) if (enabled)
...@@ -512,13 +467,6 @@ cmos_nvram_read(struct file *filp, struct kobject *kobj, ...@@ -512,13 +467,6 @@ cmos_nvram_read(struct file *filp, struct kobject *kobj,
{ {
int retval; int retval;
if (unlikely(off >= attr->size))
return 0;
if (unlikely(off < 0))
return -EINVAL;
if ((off + count) > attr->size)
count = attr->size - off;
off += NVRAM_OFFSET; off += NVRAM_OFFSET;
spin_lock_irq(&rtc_lock); spin_lock_irq(&rtc_lock);
for (retval = 0; count; count--, off++, retval++) { for (retval = 0; count; count--, off++, retval++) {
...@@ -543,12 +491,6 @@ cmos_nvram_write(struct file *filp, struct kobject *kobj, ...@@ -543,12 +491,6 @@ cmos_nvram_write(struct file *filp, struct kobject *kobj,
int retval; int retval;
cmos = dev_get_drvdata(container_of(kobj, struct device, kobj)); cmos = dev_get_drvdata(container_of(kobj, struct device, kobj));
if (unlikely(off >= attr->size))
return -EFBIG;
if (unlikely(off < 0))
return -EINVAL;
if ((off + count) > attr->size)
count = attr->size - off;
/* NOTE: on at least PCs and Ataris, the boot firmware uses a /* NOTE: on at least PCs and Ataris, the boot firmware uses a
* checksum on part of the NVRAM data. That's currently ignored * checksum on part of the NVRAM data. That's currently ignored
...@@ -860,6 +802,51 @@ static void __exit cmos_do_remove(struct device *dev) ...@@ -860,6 +802,51 @@ static void __exit cmos_do_remove(struct device *dev)
cmos->dev = NULL; cmos->dev = NULL;
} }
static int cmos_aie_poweroff(struct device *dev)
{
struct cmos_rtc *cmos = dev_get_drvdata(dev);
struct rtc_time now;
time64_t t_now;
int retval = 0;
unsigned char rtc_control;
if (!cmos->alarm_expires)
return -EINVAL;
spin_lock_irq(&rtc_lock);
rtc_control = CMOS_READ(RTC_CONTROL);
spin_unlock_irq(&rtc_lock);
/* We only care about the situation where AIE is disabled. */
if (rtc_control & RTC_AIE)
return -EBUSY;
cmos_read_time(dev, &now);
t_now = rtc_tm_to_time64(&now);
/*
* When enabling "RTC wake-up" in BIOS setup, the machine reboots
* automatically right after shutdown on some buggy boxes.
* This automatic rebooting issue won't happen when the alarm
* time is larger than now+1 seconds.
*
* If the alarm time is equal to now+1 seconds, the issue can be
* prevented by cancelling the alarm.
*/
if (cmos->alarm_expires == t_now + 1) {
struct rtc_wkalrm alarm;
/* Cancel the AIE timer by configuring the past time. */
rtc_time64_to_tm(t_now - 1, &alarm.time);
alarm.enabled = 0;
retval = cmos_set_alarm(dev, &alarm);
} else if (cmos->alarm_expires > t_now + 1) {
retval = -EBUSY;
}
return retval;
}
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int cmos_suspend(struct device *dev) static int cmos_suspend(struct device *dev)
...@@ -1094,8 +1081,12 @@ static void cmos_pnp_shutdown(struct pnp_dev *pnp) ...@@ -1094,8 +1081,12 @@ static void cmos_pnp_shutdown(struct pnp_dev *pnp)
struct device *dev = &pnp->dev; struct device *dev = &pnp->dev;
struct cmos_rtc *cmos = dev_get_drvdata(dev); struct cmos_rtc *cmos = dev_get_drvdata(dev);
if (system_state == SYSTEM_POWER_OFF && !cmos_poweroff(dev)) if (system_state == SYSTEM_POWER_OFF) {
return; int retval = cmos_poweroff(dev);
if (cmos_aie_poweroff(dev) < 0 && !retval)
return;
}
cmos_do_shutdown(cmos->irq); cmos_do_shutdown(cmos->irq);
} }
...@@ -1200,8 +1191,12 @@ static void cmos_platform_shutdown(struct platform_device *pdev) ...@@ -1200,8 +1191,12 @@ static void cmos_platform_shutdown(struct platform_device *pdev)
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct cmos_rtc *cmos = dev_get_drvdata(dev); struct cmos_rtc *cmos = dev_get_drvdata(dev);
if (system_state == SYSTEM_POWER_OFF && !cmos_poweroff(dev)) if (system_state == SYSTEM_POWER_OFF) {
return; int retval = cmos_poweroff(dev);
if (cmos_aie_poweroff(dev) < 0 && !retval)
return;
}
cmos_do_shutdown(cmos->irq); cmos_do_shutdown(cmos->irq);
} }
...@@ -1243,8 +1238,6 @@ static int __init cmos_init(void) ...@@ -1243,8 +1238,6 @@ static int __init cmos_init(void)
platform_driver_registered = true; platform_driver_registered = true;
} }
dmi_check_system(rtc_quirks);
if (retval == 0) if (retval == 0)
return 0; return 0;
......
...@@ -263,6 +263,7 @@ static const struct of_device_id coh901331_dt_match[] = { ...@@ -263,6 +263,7 @@ static const struct of_device_id coh901331_dt_match[] = {
{ .compatible = "stericsson,coh901331" }, { .compatible = "stericsson,coh901331" },
{}, {},
}; };
MODULE_DEVICE_TABLE(of, coh901331_dt_match);
static struct platform_driver coh901331_driver = { static struct platform_driver coh901331_driver = {
.driver = { .driver = {
......
...@@ -48,23 +48,10 @@ static inline void rtc_proc_del_device(struct rtc_device *rtc) ...@@ -48,23 +48,10 @@ static inline void rtc_proc_del_device(struct rtc_device *rtc)
#endif #endif
#ifdef CONFIG_RTC_INTF_SYSFS #ifdef CONFIG_RTC_INTF_SYSFS
const struct attribute_group **rtc_get_dev_attribute_groups(void);
extern void __init rtc_sysfs_init(struct class *);
extern void rtc_sysfs_add_device(struct rtc_device *rtc);
extern void rtc_sysfs_del_device(struct rtc_device *rtc);
#else #else
static inline const struct attribute_group **rtc_get_dev_attribute_groups(void)
static inline void rtc_sysfs_init(struct class *rtc)
{
}
static inline void rtc_sysfs_add_device(struct rtc_device *rtc)
{ {
return NULL;
} }
static inline void rtc_sysfs_del_device(struct rtc_device *rtc)
{
}
#endif #endif
...@@ -12,15 +12,18 @@ ...@@ -12,15 +12,18 @@
* Library General Public License for more details. * Library General Public License for more details.
*/ */
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/init.h> #include <linux/of.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/interrupt.h> #include <linux/regmap.h>
#include <linux/rtc.h> #include <linux/rtc.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/delay.h>
#include <linux/regmap.h> #include <linux/mfd/da9062/registers.h>
#include <linux/mfd/da9063/registers.h> #include <linux/mfd/da9063/registers.h>
#include <linux/mfd/da9063/core.h> #include <linux/mfd/da9063/core.h>
...@@ -29,99 +32,231 @@ ...@@ -29,99 +32,231 @@
#define YEARS_FROM_DA9063(year) ((year) + 100) #define YEARS_FROM_DA9063(year) ((year) + 100)
#define MONTHS_FROM_DA9063(month) ((month) - 1) #define MONTHS_FROM_DA9063(month) ((month) - 1)
#define RTC_ALARM_DATA_LEN (DA9063_AD_REG_ALARM_Y - DA9063_AD_REG_ALARM_MI + 1) enum {
RTC_SEC = 0,
#define RTC_DATA_LEN (DA9063_REG_COUNT_Y - DA9063_REG_COUNT_S + 1) RTC_MIN = 1,
#define RTC_SEC 0 RTC_HOUR = 2,
#define RTC_MIN 1 RTC_DAY = 3,
#define RTC_HOUR 2 RTC_MONTH = 4,
#define RTC_DAY 3 RTC_YEAR = 5,
#define RTC_MONTH 4 RTC_DATA_LEN
#define RTC_YEAR 5 };
struct da9063_rtc { struct da9063_compatible_rtc_regmap {
struct rtc_device *rtc_dev; /* REGS */
struct da9063 *hw; int rtc_enable_reg;
struct rtc_time alarm_time; int rtc_enable_32k_crystal_reg;
bool rtc_sync; int rtc_alarm_secs_reg;
int alarm_year; int rtc_alarm_year_reg;
int alarm_start; int rtc_count_secs_reg;
int alarm_len; int rtc_count_year_reg;
int data_start; int rtc_event_reg;
/* MASKS */
int rtc_enable_mask;
int rtc_crystal_mask;
int rtc_event_alarm_mask;
int rtc_alarm_on_mask;
int rtc_alarm_status_mask;
int rtc_tick_on_mask;
int rtc_ready_to_read_mask;
int rtc_count_sec_mask;
int rtc_count_min_mask;
int rtc_count_hour_mask;
int rtc_count_day_mask;
int rtc_count_month_mask;
int rtc_count_year_mask;
/* ALARM CONFIG */
int rtc_data_start;
int rtc_alarm_len;
};
struct da9063_compatible_rtc {
struct rtc_device *rtc_dev;
struct rtc_time alarm_time;
struct regmap *regmap;
const struct da9063_compatible_rtc_regmap *config;
bool rtc_sync;
};
static const struct da9063_compatible_rtc_regmap da9063_ad_regs = {
/* REGS */
.rtc_enable_reg = DA9063_REG_CONTROL_E,
.rtc_alarm_secs_reg = DA9063_AD_REG_ALARM_MI,
.rtc_alarm_year_reg = DA9063_AD_REG_ALARM_Y,
.rtc_count_secs_reg = DA9063_REG_COUNT_S,
.rtc_count_year_reg = DA9063_REG_COUNT_Y,
.rtc_event_reg = DA9063_REG_EVENT_A,
/* MASKS */
.rtc_enable_mask = DA9063_RTC_EN,
.rtc_crystal_mask = DA9063_CRYSTAL,
.rtc_enable_32k_crystal_reg = DA9063_REG_EN_32K,
.rtc_event_alarm_mask = DA9063_E_ALARM,
.rtc_alarm_on_mask = DA9063_ALARM_ON,
.rtc_alarm_status_mask = DA9063_ALARM_STATUS_ALARM |
DA9063_ALARM_STATUS_TICK,
.rtc_tick_on_mask = DA9063_TICK_ON,
.rtc_ready_to_read_mask = DA9063_RTC_READ,
.rtc_count_sec_mask = DA9063_COUNT_SEC_MASK,
.rtc_count_min_mask = DA9063_COUNT_MIN_MASK,
.rtc_count_hour_mask = DA9063_COUNT_HOUR_MASK,
.rtc_count_day_mask = DA9063_COUNT_DAY_MASK,
.rtc_count_month_mask = DA9063_COUNT_MONTH_MASK,
.rtc_count_year_mask = DA9063_COUNT_YEAR_MASK,
/* ALARM CONFIG */
.rtc_data_start = RTC_MIN,
.rtc_alarm_len = RTC_DATA_LEN - 1,
};
static const struct da9063_compatible_rtc_regmap da9063_bb_regs = {
/* REGS */
.rtc_enable_reg = DA9063_REG_CONTROL_E,
.rtc_alarm_secs_reg = DA9063_BB_REG_ALARM_S,
.rtc_alarm_year_reg = DA9063_BB_REG_ALARM_Y,
.rtc_count_secs_reg = DA9063_REG_COUNT_S,
.rtc_count_year_reg = DA9063_REG_COUNT_Y,
.rtc_event_reg = DA9063_REG_EVENT_A,
/* MASKS */
.rtc_enable_mask = DA9063_RTC_EN,
.rtc_crystal_mask = DA9063_CRYSTAL,
.rtc_enable_32k_crystal_reg = DA9063_REG_EN_32K,
.rtc_event_alarm_mask = DA9063_E_ALARM,
.rtc_alarm_on_mask = DA9063_ALARM_ON,
.rtc_alarm_status_mask = DA9063_ALARM_STATUS_ALARM |
DA9063_ALARM_STATUS_TICK,
.rtc_tick_on_mask = DA9063_TICK_ON,
.rtc_ready_to_read_mask = DA9063_RTC_READ,
.rtc_count_sec_mask = DA9063_COUNT_SEC_MASK,
.rtc_count_min_mask = DA9063_COUNT_MIN_MASK,
.rtc_count_hour_mask = DA9063_COUNT_HOUR_MASK,
.rtc_count_day_mask = DA9063_COUNT_DAY_MASK,
.rtc_count_month_mask = DA9063_COUNT_MONTH_MASK,
.rtc_count_year_mask = DA9063_COUNT_YEAR_MASK,
/* ALARM CONFIG */
.rtc_data_start = RTC_SEC,
.rtc_alarm_len = RTC_DATA_LEN,
};
static const struct da9063_compatible_rtc_regmap da9062_aa_regs = {
/* REGS */
.rtc_enable_reg = DA9062AA_CONTROL_E,
.rtc_alarm_secs_reg = DA9062AA_ALARM_S,
.rtc_alarm_year_reg = DA9062AA_ALARM_Y,
.rtc_count_secs_reg = DA9062AA_COUNT_S,
.rtc_count_year_reg = DA9062AA_COUNT_Y,
.rtc_event_reg = DA9062AA_EVENT_A,
/* MASKS */
.rtc_enable_mask = DA9062AA_RTC_EN_MASK,
.rtc_crystal_mask = DA9062AA_CRYSTAL_MASK,
.rtc_enable_32k_crystal_reg = DA9062AA_EN_32K,
.rtc_event_alarm_mask = DA9062AA_M_ALARM_MASK,
.rtc_alarm_on_mask = DA9062AA_ALARM_ON_MASK,
.rtc_alarm_status_mask = (0x02 << 6),
.rtc_tick_on_mask = DA9062AA_TICK_ON_MASK,
.rtc_ready_to_read_mask = DA9062AA_RTC_READ_MASK,
.rtc_count_sec_mask = DA9062AA_COUNT_SEC_MASK,
.rtc_count_min_mask = DA9062AA_COUNT_MIN_MASK,
.rtc_count_hour_mask = DA9062AA_COUNT_HOUR_MASK,
.rtc_count_day_mask = DA9062AA_COUNT_DAY_MASK,
.rtc_count_month_mask = DA9062AA_COUNT_MONTH_MASK,
.rtc_count_year_mask = DA9062AA_COUNT_YEAR_MASK,
/* ALARM CONFIG */
.rtc_data_start = RTC_SEC,
.rtc_alarm_len = RTC_DATA_LEN,
};
static const struct of_device_id da9063_compatible_reg_id_table[] = {
{ .compatible = "dlg,da9063-rtc", .data = &da9063_bb_regs },
{ .compatible = "dlg,da9062-rtc", .data = &da9062_aa_regs },
{ },
}; };
MODULE_DEVICE_TABLE(of, da9063_compatible_reg_id_table);
static void da9063_data_to_tm(u8 *data, struct rtc_time *tm) static void da9063_data_to_tm(u8 *data, struct rtc_time *tm,
struct da9063_compatible_rtc *rtc)
{ {
tm->tm_sec = data[RTC_SEC] & DA9063_COUNT_SEC_MASK; const struct da9063_compatible_rtc_regmap *config = rtc->config;
tm->tm_min = data[RTC_MIN] & DA9063_COUNT_MIN_MASK;
tm->tm_hour = data[RTC_HOUR] & DA9063_COUNT_HOUR_MASK; tm->tm_sec = data[RTC_SEC] & config->rtc_count_sec_mask;
tm->tm_mday = data[RTC_DAY] & DA9063_COUNT_DAY_MASK; tm->tm_min = data[RTC_MIN] & config->rtc_count_min_mask;
tm->tm_hour = data[RTC_HOUR] & config->rtc_count_hour_mask;
tm->tm_mday = data[RTC_DAY] & config->rtc_count_day_mask;
tm->tm_mon = MONTHS_FROM_DA9063(data[RTC_MONTH] & tm->tm_mon = MONTHS_FROM_DA9063(data[RTC_MONTH] &
DA9063_COUNT_MONTH_MASK); config->rtc_count_month_mask);
tm->tm_year = YEARS_FROM_DA9063(data[RTC_YEAR] & tm->tm_year = YEARS_FROM_DA9063(data[RTC_YEAR] &
DA9063_COUNT_YEAR_MASK); config->rtc_count_year_mask);
} }
static void da9063_tm_to_data(struct rtc_time *tm, u8 *data) static void da9063_tm_to_data(struct rtc_time *tm, u8 *data,
struct da9063_compatible_rtc *rtc)
{ {
data[RTC_SEC] &= ~DA9063_COUNT_SEC_MASK; const struct da9063_compatible_rtc_regmap *config = rtc->config;
data[RTC_SEC] |= tm->tm_sec & DA9063_COUNT_SEC_MASK;
data[RTC_SEC] &= ~config->rtc_count_sec_mask;
data[RTC_SEC] |= tm->tm_sec & config->rtc_count_sec_mask;
data[RTC_MIN] &= ~DA9063_COUNT_MIN_MASK; data[RTC_MIN] &= ~config->rtc_count_min_mask;
data[RTC_MIN] |= tm->tm_min & DA9063_COUNT_MIN_MASK; data[RTC_MIN] |= tm->tm_min & config->rtc_count_min_mask;
data[RTC_HOUR] &= ~DA9063_COUNT_HOUR_MASK; data[RTC_HOUR] &= ~config->rtc_count_hour_mask;
data[RTC_HOUR] |= tm->tm_hour & DA9063_COUNT_HOUR_MASK; data[RTC_HOUR] |= tm->tm_hour & config->rtc_count_hour_mask;
data[RTC_DAY] &= ~DA9063_COUNT_DAY_MASK; data[RTC_DAY] &= ~config->rtc_count_day_mask;
data[RTC_DAY] |= tm->tm_mday & DA9063_COUNT_DAY_MASK; data[RTC_DAY] |= tm->tm_mday & config->rtc_count_day_mask;
data[RTC_MONTH] &= ~DA9063_COUNT_MONTH_MASK; data[RTC_MONTH] &= ~config->rtc_count_month_mask;
data[RTC_MONTH] |= MONTHS_TO_DA9063(tm->tm_mon) & data[RTC_MONTH] |= MONTHS_TO_DA9063(tm->tm_mon) &
DA9063_COUNT_MONTH_MASK; config->rtc_count_month_mask;
data[RTC_YEAR] &= ~DA9063_COUNT_YEAR_MASK; data[RTC_YEAR] &= ~config->rtc_count_year_mask;
data[RTC_YEAR] |= YEARS_TO_DA9063(tm->tm_year) & data[RTC_YEAR] |= YEARS_TO_DA9063(tm->tm_year) &
DA9063_COUNT_YEAR_MASK; config->rtc_count_year_mask;
} }
static int da9063_rtc_stop_alarm(struct device *dev) static int da9063_rtc_stop_alarm(struct device *dev)
{ {
struct da9063_rtc *rtc = dev_get_drvdata(dev); struct da9063_compatible_rtc *rtc = dev_get_drvdata(dev);
const struct da9063_compatible_rtc_regmap *config = rtc->config;
return regmap_update_bits(rtc->hw->regmap, rtc->alarm_year, return regmap_update_bits(rtc->regmap,
DA9063_ALARM_ON, 0); config->rtc_alarm_year_reg,
config->rtc_alarm_on_mask,
0);
} }
static int da9063_rtc_start_alarm(struct device *dev) static int da9063_rtc_start_alarm(struct device *dev)
{ {
struct da9063_rtc *rtc = dev_get_drvdata(dev); struct da9063_compatible_rtc *rtc = dev_get_drvdata(dev);
const struct da9063_compatible_rtc_regmap *config = rtc->config;
return regmap_update_bits(rtc->hw->regmap, rtc->alarm_year, return regmap_update_bits(rtc->regmap,
DA9063_ALARM_ON, DA9063_ALARM_ON); config->rtc_alarm_year_reg,
config->rtc_alarm_on_mask,
config->rtc_alarm_on_mask);
} }
static int da9063_rtc_read_time(struct device *dev, struct rtc_time *tm) static int da9063_rtc_read_time(struct device *dev, struct rtc_time *tm)
{ {
struct da9063_rtc *rtc = dev_get_drvdata(dev); struct da9063_compatible_rtc *rtc = dev_get_drvdata(dev);
const struct da9063_compatible_rtc_regmap *config = rtc->config;
unsigned long tm_secs; unsigned long tm_secs;
unsigned long al_secs; unsigned long al_secs;
u8 data[RTC_DATA_LEN]; u8 data[RTC_DATA_LEN];
int ret; int ret;
ret = regmap_bulk_read(rtc->hw->regmap, DA9063_REG_COUNT_S, ret = regmap_bulk_read(rtc->regmap,
config->rtc_count_secs_reg,
data, RTC_DATA_LEN); data, RTC_DATA_LEN);
if (ret < 0) { if (ret < 0) {
dev_err(dev, "Failed to read RTC time data: %d\n", ret); dev_err(dev, "Failed to read RTC time data: %d\n", ret);
return ret; return ret;
} }
if (!(data[RTC_SEC] & DA9063_RTC_READ)) { if (!(data[RTC_SEC] & config->rtc_ready_to_read_mask)) {
dev_dbg(dev, "RTC not yet ready to be read by the host\n"); dev_dbg(dev, "RTC not yet ready to be read by the host\n");
return -EINVAL; return -EINVAL;
} }
da9063_data_to_tm(data, tm); da9063_data_to_tm(data, tm, rtc);
rtc_tm_to_time(tm, &tm_secs); rtc_tm_to_time(tm, &tm_secs);
rtc_tm_to_time(&rtc->alarm_time, &al_secs); rtc_tm_to_time(&rtc->alarm_time, &al_secs);
...@@ -137,12 +272,14 @@ static int da9063_rtc_read_time(struct device *dev, struct rtc_time *tm) ...@@ -137,12 +272,14 @@ static int da9063_rtc_read_time(struct device *dev, struct rtc_time *tm)
static int da9063_rtc_set_time(struct device *dev, struct rtc_time *tm) static int da9063_rtc_set_time(struct device *dev, struct rtc_time *tm)
{ {
struct da9063_rtc *rtc = dev_get_drvdata(dev); struct da9063_compatible_rtc *rtc = dev_get_drvdata(dev);
const struct da9063_compatible_rtc_regmap *config = rtc->config;
u8 data[RTC_DATA_LEN]; u8 data[RTC_DATA_LEN];
int ret; int ret;
da9063_tm_to_data(tm, data); da9063_tm_to_data(tm, data, rtc);
ret = regmap_bulk_write(rtc->hw->regmap, DA9063_REG_COUNT_S, ret = regmap_bulk_write(rtc->regmap,
config->rtc_count_secs_reg,
data, RTC_DATA_LEN); data, RTC_DATA_LEN);
if (ret < 0) if (ret < 0)
dev_err(dev, "Failed to set RTC time data: %d\n", ret); dev_err(dev, "Failed to set RTC time data: %d\n", ret);
...@@ -152,26 +289,31 @@ static int da9063_rtc_set_time(struct device *dev, struct rtc_time *tm) ...@@ -152,26 +289,31 @@ static int da9063_rtc_set_time(struct device *dev, struct rtc_time *tm)
static int da9063_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) static int da9063_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{ {
struct da9063_rtc *rtc = dev_get_drvdata(dev); struct da9063_compatible_rtc *rtc = dev_get_drvdata(dev);
const struct da9063_compatible_rtc_regmap *config = rtc->config;
u8 data[RTC_DATA_LEN]; u8 data[RTC_DATA_LEN];
int ret; int ret;
unsigned int val; unsigned int val;
data[RTC_SEC] = 0; data[RTC_SEC] = 0;
ret = regmap_bulk_read(rtc->hw->regmap, rtc->alarm_start, ret = regmap_bulk_read(rtc->regmap,
&data[rtc->data_start], rtc->alarm_len); config->rtc_alarm_secs_reg,
&data[config->rtc_data_start],
config->rtc_alarm_len);
if (ret < 0) if (ret < 0)
return ret; return ret;
da9063_data_to_tm(data, &alrm->time); da9063_data_to_tm(data, &alrm->time, rtc);
alrm->enabled = !!(data[RTC_YEAR] & DA9063_ALARM_ON); alrm->enabled = !!(data[RTC_YEAR] & config->rtc_alarm_on_mask);
ret = regmap_read(rtc->hw->regmap, DA9063_REG_EVENT_A, &val); ret = regmap_read(rtc->regmap,
config->rtc_event_reg,
&val);
if (ret < 0) if (ret < 0)
return ret; return ret;
if (val & (DA9063_E_ALARM)) if (val & config->rtc_event_alarm_mask)
alrm->pending = 1; alrm->pending = 1;
else else
alrm->pending = 0; alrm->pending = 0;
...@@ -181,11 +323,12 @@ static int da9063_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) ...@@ -181,11 +323,12 @@ static int da9063_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
static int da9063_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) static int da9063_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{ {
struct da9063_rtc *rtc = dev_get_drvdata(dev); struct da9063_compatible_rtc *rtc = dev_get_drvdata(dev);
const struct da9063_compatible_rtc_regmap *config = rtc->config;
u8 data[RTC_DATA_LEN]; u8 data[RTC_DATA_LEN];
int ret; int ret;
da9063_tm_to_data(&alrm->time, data); da9063_tm_to_data(&alrm->time, data, rtc);
ret = da9063_rtc_stop_alarm(dev); ret = da9063_rtc_stop_alarm(dev);
if (ret < 0) { if (ret < 0) {
...@@ -193,14 +336,16 @@ static int da9063_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) ...@@ -193,14 +336,16 @@ static int da9063_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
return ret; return ret;
} }
ret = regmap_bulk_write(rtc->hw->regmap, rtc->alarm_start, ret = regmap_bulk_write(rtc->regmap,
&data[rtc->data_start], rtc->alarm_len); config->rtc_alarm_secs_reg,
&data[config->rtc_data_start],
config->rtc_alarm_len);
if (ret < 0) { if (ret < 0) {
dev_err(dev, "Failed to write alarm: %d\n", ret); dev_err(dev, "Failed to write alarm: %d\n", ret);
return ret; return ret;
} }
da9063_data_to_tm(data, &rtc->alarm_time); da9063_data_to_tm(data, &rtc->alarm_time, rtc);
if (alrm->enabled) { if (alrm->enabled) {
ret = da9063_rtc_start_alarm(dev); ret = da9063_rtc_start_alarm(dev);
...@@ -213,7 +358,8 @@ static int da9063_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) ...@@ -213,7 +358,8 @@ static int da9063_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
return ret; return ret;
} }
static int da9063_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) static int da9063_rtc_alarm_irq_enable(struct device *dev,
unsigned int enabled)
{ {
if (enabled) if (enabled)
return da9063_rtc_start_alarm(dev); return da9063_rtc_start_alarm(dev);
...@@ -223,10 +369,13 @@ static int da9063_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) ...@@ -223,10 +369,13 @@ static int da9063_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
static irqreturn_t da9063_alarm_event(int irq, void *data) static irqreturn_t da9063_alarm_event(int irq, void *data)
{ {
struct da9063_rtc *rtc = data; struct da9063_compatible_rtc *rtc = data;
const struct da9063_compatible_rtc_regmap *config = rtc->config;
regmap_update_bits(rtc->hw->regmap, rtc->alarm_year, regmap_update_bits(rtc->regmap,
DA9063_ALARM_ON, 0); config->rtc_alarm_year_reg,
config->rtc_alarm_on_mask,
0);
rtc->rtc_sync = true; rtc->rtc_sync = true;
rtc_update_irq(rtc->rtc_dev, 1, RTC_IRQF | RTC_AF); rtc_update_irq(rtc->rtc_dev, 1, RTC_IRQF | RTC_AF);
...@@ -244,72 +393,92 @@ static const struct rtc_class_ops da9063_rtc_ops = { ...@@ -244,72 +393,92 @@ static const struct rtc_class_ops da9063_rtc_ops = {
static int da9063_rtc_probe(struct platform_device *pdev) static int da9063_rtc_probe(struct platform_device *pdev)
{ {
struct da9063 *da9063 = dev_get_drvdata(pdev->dev.parent); struct da9063_compatible_rtc *rtc;
struct da9063_rtc *rtc; const struct da9063_compatible_rtc_regmap *config;
const struct of_device_id *match;
int irq_alarm; int irq_alarm;
u8 data[RTC_DATA_LEN]; u8 data[RTC_DATA_LEN];
int ret; int ret;
ret = regmap_update_bits(da9063->regmap, DA9063_REG_CONTROL_E, if (!pdev->dev.of_node)
DA9063_RTC_EN, DA9063_RTC_EN); return -ENXIO;
if (ret < 0) {
dev_err(&pdev->dev, "Failed to enable RTC\n");
goto err;
}
ret = regmap_update_bits(da9063->regmap, DA9063_REG_EN_32K, match = of_match_node(da9063_compatible_reg_id_table,
DA9063_CRYSTAL, DA9063_CRYSTAL); pdev->dev.of_node);
if (ret < 0) {
dev_err(&pdev->dev, "Failed to run 32kHz oscillator\n");
goto err;
}
rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL); rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL);
if (!rtc) if (!rtc)
return -ENOMEM; return -ENOMEM;
if (da9063->variant_code == PMIC_DA9063_AD) { rtc->config = match->data;
rtc->alarm_year = DA9063_AD_REG_ALARM_Y; if (of_device_is_compatible(pdev->dev.of_node, "dlg,da9063-rtc")) {
rtc->alarm_start = DA9063_AD_REG_ALARM_MI; struct da9063 *chip = dev_get_drvdata(pdev->dev.parent);
rtc->alarm_len = RTC_ALARM_DATA_LEN;
rtc->data_start = RTC_MIN; if (chip->variant_code == PMIC_DA9063_AD)
} else { rtc->config = &da9063_ad_regs;
rtc->alarm_year = DA9063_BB_REG_ALARM_Y;
rtc->alarm_start = DA9063_BB_REG_ALARM_S;
rtc->alarm_len = RTC_DATA_LEN;
rtc->data_start = RTC_SEC;
} }
ret = regmap_update_bits(da9063->regmap, rtc->alarm_start, rtc->regmap = dev_get_regmap(pdev->dev.parent, NULL);
DA9063_ALARM_STATUS_TICK | DA9063_ALARM_STATUS_ALARM, if (!rtc->regmap) {
0); dev_warn(&pdev->dev, "Parent regmap unavailable.\n");
return -ENXIO;
}
config = rtc->config;
ret = regmap_update_bits(rtc->regmap,
config->rtc_enable_reg,
config->rtc_enable_mask,
config->rtc_enable_mask);
if (ret < 0) {
dev_err(&pdev->dev, "Failed to enable RTC\n");
return ret;
}
ret = regmap_update_bits(rtc->regmap,
config->rtc_enable_32k_crystal_reg,
config->rtc_crystal_mask,
config->rtc_crystal_mask);
if (ret < 0) {
dev_err(&pdev->dev, "Failed to run 32kHz oscillator\n");
return ret;
}
ret = regmap_update_bits(rtc->regmap,
config->rtc_alarm_secs_reg,
config->rtc_alarm_status_mask,
0);
if (ret < 0) { if (ret < 0) {
dev_err(&pdev->dev, "Failed to access RTC alarm register\n"); dev_err(&pdev->dev, "Failed to access RTC alarm register\n");
goto err; return ret;
} }
ret = regmap_update_bits(da9063->regmap, rtc->alarm_start, ret = regmap_update_bits(rtc->regmap,
config->rtc_alarm_secs_reg,
DA9063_ALARM_STATUS_ALARM, DA9063_ALARM_STATUS_ALARM,
DA9063_ALARM_STATUS_ALARM); DA9063_ALARM_STATUS_ALARM);
if (ret < 0) { if (ret < 0) {
dev_err(&pdev->dev, "Failed to access RTC alarm register\n"); dev_err(&pdev->dev, "Failed to access RTC alarm register\n");
goto err; return ret;
} }
ret = regmap_update_bits(da9063->regmap, rtc->alarm_year, ret = regmap_update_bits(rtc->regmap,
DA9063_TICK_ON, 0); config->rtc_alarm_year_reg,
config->rtc_tick_on_mask,
0);
if (ret < 0) { if (ret < 0) {
dev_err(&pdev->dev, "Failed to disable TICKs\n"); dev_err(&pdev->dev, "Failed to disable TICKs\n");
goto err; return ret;
} }
data[RTC_SEC] = 0; data[RTC_SEC] = 0;
ret = regmap_bulk_read(da9063->regmap, rtc->alarm_start, ret = regmap_bulk_read(rtc->regmap,
&data[rtc->data_start], rtc->alarm_len); config->rtc_alarm_secs_reg,
&data[config->rtc_data_start],
config->rtc_alarm_len);
if (ret < 0) { if (ret < 0) {
dev_err(&pdev->dev, "Failed to read initial alarm data: %d\n", dev_err(&pdev->dev, "Failed to read initial alarm data: %d\n",
ret); ret);
goto err; return ret;
} }
platform_set_drvdata(pdev, rtc); platform_set_drvdata(pdev, rtc);
...@@ -322,18 +491,16 @@ static int da9063_rtc_probe(struct platform_device *pdev) ...@@ -322,18 +491,16 @@ static int da9063_rtc_probe(struct platform_device *pdev)
if (ret) { if (ret) {
dev_err(&pdev->dev, "Failed to request ALARM IRQ %d: %d\n", dev_err(&pdev->dev, "Failed to request ALARM IRQ %d: %d\n",
irq_alarm, ret); irq_alarm, ret);
goto err; return ret;
} }
rtc->hw = da9063;
rtc->rtc_dev = devm_rtc_device_register(&pdev->dev, DA9063_DRVNAME_RTC, rtc->rtc_dev = devm_rtc_device_register(&pdev->dev, DA9063_DRVNAME_RTC,
&da9063_rtc_ops, THIS_MODULE); &da9063_rtc_ops, THIS_MODULE);
if (IS_ERR(rtc->rtc_dev)) if (IS_ERR(rtc->rtc_dev))
return PTR_ERR(rtc->rtc_dev); return PTR_ERR(rtc->rtc_dev);
da9063_data_to_tm(data, &rtc->alarm_time); da9063_data_to_tm(data, &rtc->alarm_time, rtc);
rtc->rtc_sync = false; rtc->rtc_sync = false;
err:
return ret; return ret;
} }
...@@ -341,6 +508,7 @@ static struct platform_driver da9063_rtc_driver = { ...@@ -341,6 +508,7 @@ static struct platform_driver da9063_rtc_driver = {
.probe = da9063_rtc_probe, .probe = da9063_rtc_probe,
.driver = { .driver = {
.name = DA9063_DRVNAME_RTC, .name = DA9063_DRVNAME_RTC,
.of_match_table = da9063_compatible_reg_id_table,
}, },
}; };
......
...@@ -477,6 +477,7 @@ void rtc_dev_prepare(struct rtc_device *rtc) ...@@ -477,6 +477,7 @@ void rtc_dev_prepare(struct rtc_device *rtc)
cdev_init(&rtc->char_dev, &rtc_dev_fops); cdev_init(&rtc->char_dev, &rtc_dev_fops);
rtc->char_dev.owner = rtc->owner; rtc->char_dev.owner = rtc->owner;
rtc->char_dev.kobj.parent = &rtc->dev.kobj;
} }
void rtc_dev_add_device(struct rtc_device *rtc) void rtc_dev_add_device(struct rtc_device *rtc)
......
...@@ -538,15 +538,6 @@ ds1305_nvram_read(struct file *filp, struct kobject *kobj, ...@@ -538,15 +538,6 @@ ds1305_nvram_read(struct file *filp, struct kobject *kobj,
spi = container_of(kobj, struct spi_device, dev.kobj); spi = container_of(kobj, struct spi_device, dev.kobj);
if (unlikely(off >= DS1305_NVRAM_LEN))
return 0;
if (count >= DS1305_NVRAM_LEN)
count = DS1305_NVRAM_LEN;
if ((off + count) > DS1305_NVRAM_LEN)
count = DS1305_NVRAM_LEN - off;
if (unlikely(!count))
return count;
addr = DS1305_NVRAM + off; addr = DS1305_NVRAM + off;
msg_init(&m, x, &addr, count, NULL, buf); msg_init(&m, x, &addr, count, NULL, buf);
...@@ -569,15 +560,6 @@ ds1305_nvram_write(struct file *filp, struct kobject *kobj, ...@@ -569,15 +560,6 @@ ds1305_nvram_write(struct file *filp, struct kobject *kobj,
spi = container_of(kobj, struct spi_device, dev.kobj); spi = container_of(kobj, struct spi_device, dev.kobj);
if (unlikely(off >= DS1305_NVRAM_LEN))
return -EFBIG;
if (count >= DS1305_NVRAM_LEN)
count = DS1305_NVRAM_LEN;
if ((off + count) > DS1305_NVRAM_LEN)
count = DS1305_NVRAM_LEN - off;
if (unlikely(!count))
return count;
addr = (DS1305_WRITE | DS1305_NVRAM) + off; addr = (DS1305_WRITE | DS1305_NVRAM) + off;
msg_init(&m, x, &addr, count, buf, NULL); msg_init(&m, x, &addr, count, buf, NULL);
......
...@@ -11,14 +11,17 @@ ...@@ -11,14 +11,17 @@
* published by the Free Software Foundation. * published by the Free Software Foundation.
*/ */
#include <linux/module.h> #include <linux/bcd.h>
#include <linux/i2c.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/of_irq.h>
#include <linux/pm_wakeirq.h>
#include <linux/rtc/ds1307.h>
#include <linux/rtc.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/rtc.h>
#include <linux/bcd.h>
#include <linux/rtc/ds1307.h>
/* /*
* We can't determine type by probing, but if we expect pre-Linux code * We can't determine type by probing, but if we expect pre-Linux code
...@@ -114,7 +117,7 @@ struct ds1307 { ...@@ -114,7 +117,7 @@ struct ds1307 {
#define HAS_ALARM 1 /* bit 1 == irq claimed */ #define HAS_ALARM 1 /* bit 1 == irq claimed */
struct i2c_client *client; struct i2c_client *client;
struct rtc_device *rtc; struct rtc_device *rtc;
struct work_struct work; int wakeirq;
s32 (*read_block_data)(const struct i2c_client *client, u8 command, s32 (*read_block_data)(const struct i2c_client *client, u8 command,
u8 length, u8 *values); u8 length, u8 *values);
s32 (*write_block_data)(const struct i2c_client *client, u8 command, s32 (*write_block_data)(const struct i2c_client *client, u8 command,
...@@ -311,27 +314,17 @@ static s32 ds1307_native_smbus_read_block_data(const struct i2c_client *client, ...@@ -311,27 +314,17 @@ static s32 ds1307_native_smbus_read_block_data(const struct i2c_client *client,
/*----------------------------------------------------------------------*/ /*----------------------------------------------------------------------*/
/* /*
* The IRQ logic includes a "real" handler running in IRQ context just
* long enough to schedule this workqueue entry. We need a task context
* to talk to the RTC, since I2C I/O calls require that; and disable the
* IRQ until we clear its status on the chip, so that this handler can
* work with any type of triggering (not just falling edge).
*
* The ds1337 and ds1339 both have two alarms, but we only use the first * The ds1337 and ds1339 both have two alarms, but we only use the first
* one (with a "seconds" field). For ds1337 we expect nINTA is our alarm * one (with a "seconds" field). For ds1337 we expect nINTA is our alarm
* signal; ds1339 chips have only one alarm signal. * signal; ds1339 chips have only one alarm signal.
*/ */
static void ds1307_work(struct work_struct *work) static irqreturn_t ds1307_irq(int irq, void *dev_id)
{ {
struct ds1307 *ds1307; struct i2c_client *client = dev_id;
struct i2c_client *client; struct ds1307 *ds1307 = i2c_get_clientdata(client);
struct mutex *lock; struct mutex *lock = &ds1307->rtc->ops_lock;
int stat, control; int stat, control;
ds1307 = container_of(work, struct ds1307, work);
client = ds1307->client;
lock = &ds1307->rtc->ops_lock;
mutex_lock(lock); mutex_lock(lock);
stat = i2c_smbus_read_byte_data(client, DS1337_REG_STATUS); stat = i2c_smbus_read_byte_data(client, DS1337_REG_STATUS);
if (stat < 0) if (stat < 0)
...@@ -352,18 +345,8 @@ static void ds1307_work(struct work_struct *work) ...@@ -352,18 +345,8 @@ static void ds1307_work(struct work_struct *work)
} }
out: out:
if (test_bit(HAS_ALARM, &ds1307->flags))
enable_irq(client->irq);
mutex_unlock(lock); mutex_unlock(lock);
}
static irqreturn_t ds1307_irq(int irq, void *dev_id)
{
struct i2c_client *client = dev_id;
struct ds1307 *ds1307 = i2c_get_clientdata(client);
disable_irq_nosync(irq);
schedule_work(&ds1307->work);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -634,13 +617,14 @@ static const struct rtc_class_ops ds13xx_rtc_ops = { ...@@ -634,13 +617,14 @@ static const struct rtc_class_ops ds13xx_rtc_ops = {
MCP794XX_BIT_ALMX_C1 | \ MCP794XX_BIT_ALMX_C1 | \
MCP794XX_BIT_ALMX_C2) MCP794XX_BIT_ALMX_C2)
static void mcp794xx_work(struct work_struct *work) static irqreturn_t mcp794xx_irq(int irq, void *dev_id)
{ {
struct ds1307 *ds1307 = container_of(work, struct ds1307, work); struct i2c_client *client = dev_id;
struct i2c_client *client = ds1307->client; struct ds1307 *ds1307 = i2c_get_clientdata(client);
struct mutex *lock = &ds1307->rtc->ops_lock;
int reg, ret; int reg, ret;
mutex_lock(&ds1307->rtc->ops_lock); mutex_lock(lock);
/* Check and clear alarm 0 interrupt flag. */ /* Check and clear alarm 0 interrupt flag. */
reg = i2c_smbus_read_byte_data(client, MCP794XX_REG_ALARM0_CTRL); reg = i2c_smbus_read_byte_data(client, MCP794XX_REG_ALARM0_CTRL);
...@@ -665,9 +649,9 @@ static void mcp794xx_work(struct work_struct *work) ...@@ -665,9 +649,9 @@ static void mcp794xx_work(struct work_struct *work)
rtc_update_irq(ds1307->rtc, 1, RTC_AF | RTC_IRQF); rtc_update_irq(ds1307->rtc, 1, RTC_AF | RTC_IRQF);
out: out:
if (test_bit(HAS_ALARM, &ds1307->flags)) mutex_unlock(lock);
enable_irq(client->irq);
mutex_unlock(&ds1307->rtc->ops_lock); return IRQ_HANDLED;
} }
static int mcp794xx_read_alarm(struct device *dev, struct rtc_wkalrm *t) static int mcp794xx_read_alarm(struct device *dev, struct rtc_wkalrm *t)
...@@ -798,13 +782,6 @@ ds1307_nvram_read(struct file *filp, struct kobject *kobj, ...@@ -798,13 +782,6 @@ ds1307_nvram_read(struct file *filp, struct kobject *kobj,
client = kobj_to_i2c_client(kobj); client = kobj_to_i2c_client(kobj);
ds1307 = i2c_get_clientdata(client); ds1307 = i2c_get_clientdata(client);
if (unlikely(off >= ds1307->nvram->size))
return 0;
if ((off + count) > ds1307->nvram->size)
count = ds1307->nvram->size - off;
if (unlikely(!count))
return count;
result = ds1307->read_block_data(client, ds1307->nvram_offset + off, result = ds1307->read_block_data(client, ds1307->nvram_offset + off,
count, buf); count, buf);
if (result < 0) if (result < 0)
...@@ -824,13 +801,6 @@ ds1307_nvram_write(struct file *filp, struct kobject *kobj, ...@@ -824,13 +801,6 @@ ds1307_nvram_write(struct file *filp, struct kobject *kobj,
client = kobj_to_i2c_client(kobj); client = kobj_to_i2c_client(kobj);
ds1307 = i2c_get_clientdata(client); ds1307 = i2c_get_clientdata(client);
if (unlikely(off >= ds1307->nvram->size))
return -EFBIG;
if ((off + count) > ds1307->nvram->size)
count = ds1307->nvram->size - off;
if (unlikely(!count))
return count;
result = ds1307->write_block_data(client, ds1307->nvram_offset + off, result = ds1307->write_block_data(client, ds1307->nvram_offset + off,
count, buf); count, buf);
if (result < 0) { if (result < 0) {
...@@ -896,6 +866,8 @@ static int ds1307_probe(struct i2c_client *client, ...@@ -896,6 +866,8 @@ static int ds1307_probe(struct i2c_client *client,
bool want_irq = false; bool want_irq = false;
unsigned char *buf; unsigned char *buf;
struct ds1307_platform_data *pdata = dev_get_platdata(&client->dev); struct ds1307_platform_data *pdata = dev_get_platdata(&client->dev);
irq_handler_t irq_handler = ds1307_irq;
static const int bbsqi_bitpos[] = { static const int bbsqi_bitpos[] = {
[ds_1337] = 0, [ds_1337] = 0,
[ds_1339] = DS1339_BIT_BBSQI, [ds_1339] = DS1339_BIT_BBSQI,
...@@ -962,8 +934,6 @@ static int ds1307_probe(struct i2c_client *client, ...@@ -962,8 +934,6 @@ static int ds1307_probe(struct i2c_client *client,
* running on Vbackup (BBSQI/BBSQW) * running on Vbackup (BBSQI/BBSQW)
*/ */
if (ds1307->client->irq > 0 && chip->alarm) { if (ds1307->client->irq > 0 && chip->alarm) {
INIT_WORK(&ds1307->work, ds1307_work);
ds1307->regs[0] |= DS1337_BIT_INTCN ds1307->regs[0] |= DS1337_BIT_INTCN
| bbsqi_bitpos[ds1307->type]; | bbsqi_bitpos[ds1307->type];
ds1307->regs[0] &= ~(DS1337_BIT_A2IE | DS1337_BIT_A1IE); ds1307->regs[0] &= ~(DS1337_BIT_A2IE | DS1337_BIT_A1IE);
...@@ -1053,7 +1023,7 @@ static int ds1307_probe(struct i2c_client *client, ...@@ -1053,7 +1023,7 @@ static int ds1307_probe(struct i2c_client *client,
case mcp794xx: case mcp794xx:
rtc_ops = &mcp794xx_rtc_ops; rtc_ops = &mcp794xx_rtc_ops;
if (ds1307->client->irq > 0 && chip->alarm) { if (ds1307->client->irq > 0 && chip->alarm) {
INIT_WORK(&ds1307->work, mcp794xx_work); irq_handler = mcp794xx_irq;
want_irq = true; want_irq = true;
} }
break; break;
...@@ -1176,18 +1146,43 @@ static int ds1307_probe(struct i2c_client *client, ...@@ -1176,18 +1146,43 @@ static int ds1307_probe(struct i2c_client *client,
} }
if (want_irq) { if (want_irq) {
err = request_irq(client->irq, ds1307_irq, IRQF_SHARED, struct device_node *node = client->dev.of_node;
ds1307->rtc->name, client);
err = devm_request_threaded_irq(&client->dev,
client->irq, NULL, irq_handler,
IRQF_SHARED | IRQF_ONESHOT,
ds1307->rtc->name, client);
if (err) { if (err) {
client->irq = 0; client->irq = 0;
dev_err(&client->dev, "unable to request IRQ!\n"); dev_err(&client->dev, "unable to request IRQ!\n");
} else { goto no_irq;
}
set_bit(HAS_ALARM, &ds1307->flags);
dev_dbg(&client->dev, "got IRQ %d\n", client->irq);
/* Currently supported by OF code only! */
if (!node)
goto no_irq;
err = of_irq_get(node, 1);
if (err <= 0) {
if (err == -EPROBE_DEFER)
goto exit;
goto no_irq;
}
ds1307->wakeirq = err;
set_bit(HAS_ALARM, &ds1307->flags); err = dev_pm_set_dedicated_wake_irq(&client->dev,
dev_dbg(&client->dev, "got IRQ %d\n", client->irq); ds1307->wakeirq);
if (err) {
dev_err(&client->dev, "unable to setup wakeIRQ %d!\n",
err);
goto exit;
} }
} }
no_irq:
if (chip->nvram_size) { if (chip->nvram_size) {
ds1307->nvram = devm_kzalloc(&client->dev, ds1307->nvram = devm_kzalloc(&client->dev,
...@@ -1231,10 +1226,8 @@ static int ds1307_remove(struct i2c_client *client) ...@@ -1231,10 +1226,8 @@ static int ds1307_remove(struct i2c_client *client)
{ {
struct ds1307 *ds1307 = i2c_get_clientdata(client); struct ds1307 *ds1307 = i2c_get_clientdata(client);
if (test_and_clear_bit(HAS_ALARM, &ds1307->flags)) { if (ds1307->wakeirq)
free_irq(client->irq, client); dev_pm_clear_wake_irq(&client->dev);
cancel_work_sync(&ds1307->work);
}
if (test_and_clear_bit(HAS_NVRAM, &ds1307->flags)) if (test_and_clear_bit(HAS_NVRAM, &ds1307->flags))
sysfs_remove_bin_file(&client->dev.kobj, ds1307->nvram); sysfs_remove_bin_file(&client->dev.kobj, ds1307->nvram);
...@@ -1245,7 +1238,6 @@ static int ds1307_remove(struct i2c_client *client) ...@@ -1245,7 +1238,6 @@ static int ds1307_remove(struct i2c_client *client)
static struct i2c_driver ds1307_driver = { static struct i2c_driver ds1307_driver = {
.driver = { .driver = {
.name = "rtc-ds1307", .name = "rtc-ds1307",
.owner = THIS_MODULE,
}, },
.probe = ds1307_probe, .probe = ds1307_probe,
.remove = ds1307_remove, .remove = ds1307_remove,
......
...@@ -162,12 +162,6 @@ static ssize_t ds1343_nvram_write(struct file *filp, struct kobject *kobj, ...@@ -162,12 +162,6 @@ static ssize_t ds1343_nvram_write(struct file *filp, struct kobject *kobj,
struct device *dev = kobj_to_dev(kobj); struct device *dev = kobj_to_dev(kobj);
struct ds1343_priv *priv = dev_get_drvdata(dev); struct ds1343_priv *priv = dev_get_drvdata(dev);
if (unlikely(!count))
return count;
if ((count + off) > DS1343_NVRAM_LEN)
count = DS1343_NVRAM_LEN - off;
address = DS1343_NVRAM + off; address = DS1343_NVRAM + off;
ret = regmap_bulk_write(priv->map, address, buf, count); ret = regmap_bulk_write(priv->map, address, buf, count);
...@@ -187,12 +181,6 @@ static ssize_t ds1343_nvram_read(struct file *filp, struct kobject *kobj, ...@@ -187,12 +181,6 @@ static ssize_t ds1343_nvram_read(struct file *filp, struct kobject *kobj,
struct device *dev = kobj_to_dev(kobj); struct device *dev = kobj_to_dev(kobj);
struct ds1343_priv *priv = dev_get_drvdata(dev); struct ds1343_priv *priv = dev_get_drvdata(dev);
if (unlikely(!count))
return count;
if ((count + off) > DS1343_NVRAM_LEN)
count = DS1343_NVRAM_LEN - off;
address = DS1343_NVRAM + off; address = DS1343_NVRAM + off;
ret = regmap_bulk_read(priv->map, address, buf, count); ret = regmap_bulk_read(priv->map, address, buf, count);
......
...@@ -664,8 +664,6 @@ static int ds1374_remove(struct i2c_client *client) ...@@ -664,8 +664,6 @@ static int ds1374_remove(struct i2c_client *client)
{ {
struct ds1374 *ds1374 = i2c_get_clientdata(client); struct ds1374 *ds1374 = i2c_get_clientdata(client);
#ifdef CONFIG_RTC_DRV_DS1374_WDT #ifdef CONFIG_RTC_DRV_DS1374_WDT
int res;
misc_deregister(&ds1374_miscdev); misc_deregister(&ds1374_miscdev);
ds1374_miscdev.parent = NULL; ds1374_miscdev.parent = NULL;
unregister_reboot_notifier(&ds1374_wdt_notifier); unregister_reboot_notifier(&ds1374_wdt_notifier);
...@@ -688,7 +686,7 @@ static int ds1374_suspend(struct device *dev) ...@@ -688,7 +686,7 @@ static int ds1374_suspend(struct device *dev)
{ {
struct i2c_client *client = to_i2c_client(dev); struct i2c_client *client = to_i2c_client(dev);
if (client->irq >= 0 && device_may_wakeup(&client->dev)) if (client->irq > 0 && device_may_wakeup(&client->dev))
enable_irq_wake(client->irq); enable_irq_wake(client->irq);
return 0; return 0;
} }
...@@ -697,7 +695,7 @@ static int ds1374_resume(struct device *dev) ...@@ -697,7 +695,7 @@ static int ds1374_resume(struct device *dev)
{ {
struct i2c_client *client = to_i2c_client(dev); struct i2c_client *client = to_i2c_client(dev);
if (client->irq >= 0 && device_may_wakeup(&client->dev)) if (client->irq > 0 && device_may_wakeup(&client->dev))
disable_irq_wake(client->irq); disable_irq_wake(client->irq);
return 0; return 0;
} }
...@@ -708,7 +706,6 @@ static SIMPLE_DEV_PM_OPS(ds1374_pm, ds1374_suspend, ds1374_resume); ...@@ -708,7 +706,6 @@ static SIMPLE_DEV_PM_OPS(ds1374_pm, ds1374_suspend, ds1374_resume);
static struct i2c_driver ds1374_driver = { static struct i2c_driver ds1374_driver = {
.driver = { .driver = {
.name = "rtc-ds1374", .name = "rtc-ds1374",
.owner = THIS_MODULE,
.pm = &ds1374_pm, .pm = &ds1374_pm,
}, },
.probe = ds1374_probe, .probe = ds1374_probe,
......
...@@ -64,7 +64,7 @@ enum ds1511reg { ...@@ -64,7 +64,7 @@ enum ds1511reg {
#define DS1511_KIE 0x04 #define DS1511_KIE 0x04
#define DS1511_WDE 0x02 #define DS1511_WDE 0x02
#define DS1511_WDS 0x01 #define DS1511_WDS 0x01
#define DS1511_RAM_MAX 0xff #define DS1511_RAM_MAX 0x100
#define RTC_CMD DS1511_CONTROL_B #define RTC_CMD DS1511_CONTROL_B
#define RTC_CMD1 DS1511_CONTROL_A #define RTC_CMD1 DS1511_CONTROL_A
...@@ -159,7 +159,7 @@ ds1511_wdog_set(unsigned long deciseconds) ...@@ -159,7 +159,7 @@ ds1511_wdog_set(unsigned long deciseconds)
/* /*
* set wdog enable and wdog 'steering' bit to issue a reset * set wdog enable and wdog 'steering' bit to issue a reset
*/ */
rtc_write(DS1511_WDE | DS1511_WDS, RTC_CMD); rtc_write(rtc_read(RTC_CMD) | DS1511_WDE | DS1511_WDS, RTC_CMD);
} }
void void
...@@ -407,26 +407,10 @@ ds1511_nvram_read(struct file *filp, struct kobject *kobj, ...@@ -407,26 +407,10 @@ ds1511_nvram_read(struct file *filp, struct kobject *kobj,
{ {
ssize_t count; ssize_t count;
/*
* if count is more than one, turn on "burst" mode
* turn it off when you're done
*/
if (size > 1)
rtc_write((rtc_read(RTC_CMD) | DS1511_BME), RTC_CMD);
if (pos > DS1511_RAM_MAX)
pos = DS1511_RAM_MAX;
if (size + pos > DS1511_RAM_MAX + 1)
size = DS1511_RAM_MAX - pos + 1;
rtc_write(pos, DS1511_RAMADDR_LSB); rtc_write(pos, DS1511_RAMADDR_LSB);
for (count = 0; size > 0; count++, size--) for (count = 0; count < size; count++)
*buf++ = rtc_read(DS1511_RAMDATA); *buf++ = rtc_read(DS1511_RAMDATA);
if (count > 1)
rtc_write((rtc_read(RTC_CMD) & ~DS1511_BME), RTC_CMD);
return count; return count;
} }
...@@ -437,26 +421,10 @@ ds1511_nvram_write(struct file *filp, struct kobject *kobj, ...@@ -437,26 +421,10 @@ ds1511_nvram_write(struct file *filp, struct kobject *kobj,
{ {
ssize_t count; ssize_t count;
/*
* if count is more than one, turn on "burst" mode
* turn it off when you're done
*/
if (size > 1)
rtc_write((rtc_read(RTC_CMD) | DS1511_BME), RTC_CMD);
if (pos > DS1511_RAM_MAX)
pos = DS1511_RAM_MAX;
if (size + pos > DS1511_RAM_MAX + 1)
size = DS1511_RAM_MAX - pos + 1;
rtc_write(pos, DS1511_RAMADDR_LSB); rtc_write(pos, DS1511_RAMADDR_LSB);
for (count = 0; size > 0; count++, size--) for (count = 0; count < size; count++)
rtc_write(*buf++, DS1511_RAMDATA); rtc_write(*buf++, DS1511_RAMDATA);
if (count > 1)
rtc_write((rtc_read(RTC_CMD) & ~DS1511_BME), RTC_CMD);
return count; return count;
} }
...@@ -490,7 +458,7 @@ static int ds1511_rtc_probe(struct platform_device *pdev) ...@@ -490,7 +458,7 @@ static int ds1511_rtc_probe(struct platform_device *pdev)
/* /*
* turn on the clock and the crystal, etc. * turn on the clock and the crystal, etc.
*/ */
rtc_write(0, RTC_CMD); rtc_write(DS1511_BME, RTC_CMD);
rtc_write(0, RTC_CMD1); rtc_write(0, RTC_CMD1);
/* /*
* clear the wdog counter * clear the wdog counter
......
...@@ -245,7 +245,7 @@ static ssize_t ds1553_nvram_read(struct file *filp, struct kobject *kobj, ...@@ -245,7 +245,7 @@ static ssize_t ds1553_nvram_read(struct file *filp, struct kobject *kobj,
void __iomem *ioaddr = pdata->ioaddr; void __iomem *ioaddr = pdata->ioaddr;
ssize_t count; ssize_t count;
for (count = 0; size > 0 && pos < RTC_OFFSET; count++, size--) for (count = 0; count < size; count++)
*buf++ = readb(ioaddr + pos++); *buf++ = readb(ioaddr + pos++);
return count; return count;
} }
...@@ -260,7 +260,7 @@ static ssize_t ds1553_nvram_write(struct file *filp, struct kobject *kobj, ...@@ -260,7 +260,7 @@ static ssize_t ds1553_nvram_write(struct file *filp, struct kobject *kobj,
void __iomem *ioaddr = pdata->ioaddr; void __iomem *ioaddr = pdata->ioaddr;
ssize_t count; ssize_t count;
for (count = 0; size > 0 && pos < RTC_OFFSET; count++, size--) for (count = 0; count < size; count++)
writeb(*buf++, ioaddr + pos++); writeb(*buf++, ioaddr + pos++);
return count; return count;
} }
......
...@@ -2145,27 +2145,7 @@ static struct platform_driver ds1685_rtc_driver = { ...@@ -2145,27 +2145,7 @@ static struct platform_driver ds1685_rtc_driver = {
.probe = ds1685_rtc_probe, .probe = ds1685_rtc_probe,
.remove = ds1685_rtc_remove, .remove = ds1685_rtc_remove,
}; };
module_platform_driver(ds1685_rtc_driver);
/**
* ds1685_rtc_init - rtc module init.
*/
static int __init
ds1685_rtc_init(void)
{
return platform_driver_register(&ds1685_rtc_driver);
}
/**
* ds1685_rtc_exit - rtc module exit.
*/
static void __exit
ds1685_rtc_exit(void)
{
platform_driver_unregister(&ds1685_rtc_driver);
}
module_init(ds1685_rtc_init);
module_exit(ds1685_rtc_exit);
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
......
...@@ -134,7 +134,7 @@ static ssize_t ds1742_nvram_read(struct file *filp, struct kobject *kobj, ...@@ -134,7 +134,7 @@ static ssize_t ds1742_nvram_read(struct file *filp, struct kobject *kobj,
void __iomem *ioaddr = pdata->ioaddr_nvram; void __iomem *ioaddr = pdata->ioaddr_nvram;
ssize_t count; ssize_t count;
for (count = 0; size > 0 && pos < pdata->size_nvram; count++, size--) for (count = 0; count < size; count++)
*buf++ = readb(ioaddr + pos++); *buf++ = readb(ioaddr + pos++);
return count; return count;
} }
...@@ -149,7 +149,7 @@ static ssize_t ds1742_nvram_write(struct file *filp, struct kobject *kobj, ...@@ -149,7 +149,7 @@ static ssize_t ds1742_nvram_write(struct file *filp, struct kobject *kobj,
void __iomem *ioaddr = pdata->ioaddr_nvram; void __iomem *ioaddr = pdata->ioaddr_nvram;
ssize_t count; ssize_t count;
for (count = 0; size > 0 && pos < pdata->size_nvram; count++, size--) for (count = 0; count < size; count++)
writeb(*buf++, ioaddr + pos++); writeb(*buf++, ioaddr + pos++);
return count; return count;
} }
......
...@@ -443,7 +443,7 @@ static int ds3232_remove(struct i2c_client *client) ...@@ -443,7 +443,7 @@ static int ds3232_remove(struct i2c_client *client)
{ {
struct ds3232 *ds3232 = i2c_get_clientdata(client); struct ds3232 *ds3232 = i2c_get_clientdata(client);
if (client->irq >= 0) { if (client->irq > 0) {
mutex_lock(&ds3232->mutex); mutex_lock(&ds3232->mutex);
ds3232->exiting = 1; ds3232->exiting = 1;
mutex_unlock(&ds3232->mutex); mutex_unlock(&ds3232->mutex);
...@@ -463,7 +463,10 @@ static int ds3232_suspend(struct device *dev) ...@@ -463,7 +463,10 @@ static int ds3232_suspend(struct device *dev)
if (device_can_wakeup(dev)) { if (device_can_wakeup(dev)) {
ds3232->suspended = true; ds3232->suspended = true;
irq_set_irq_wake(client->irq, 1); if (irq_set_irq_wake(client->irq, 1)) {
dev_warn_once(dev, "Cannot set wakeup source\n");
ds3232->suspended = false;
}
} }
return 0; return 0;
...@@ -500,7 +503,6 @@ MODULE_DEVICE_TABLE(i2c, ds3232_id); ...@@ -500,7 +503,6 @@ MODULE_DEVICE_TABLE(i2c, ds3232_id);
static struct i2c_driver ds3232_driver = { static struct i2c_driver ds3232_driver = {
.driver = { .driver = {
.name = "rtc-ds3232", .name = "rtc-ds3232",
.owner = THIS_MODULE,
.pm = &ds3232_pm_ops, .pm = &ds3232_pm_ops,
}, },
.probe = ds3232_probe, .probe = ds3232_probe,
......
...@@ -523,7 +523,6 @@ static int fm3130_probe(struct i2c_client *client, ...@@ -523,7 +523,6 @@ static int fm3130_probe(struct i2c_client *client,
static struct i2c_driver fm3130_driver = { static struct i2c_driver fm3130_driver = {
.driver = { .driver = {
.name = "rtc-fm3130", .name = "rtc-fm3130",
.owner = THIS_MODULE,
}, },
.probe = fm3130_probe, .probe = fm3130_probe,
.id_table = fm3130_id, .id_table = fm3130_id,
......
...@@ -148,10 +148,7 @@ static int gemini_rtc_probe(struct platform_device *pdev) ...@@ -148,10 +148,7 @@ static int gemini_rtc_probe(struct platform_device *pdev)
rtc->rtc_dev = rtc_device_register(pdev->name, dev, rtc->rtc_dev = rtc_device_register(pdev->name, dev,
&gemini_rtc_ops, THIS_MODULE); &gemini_rtc_ops, THIS_MODULE);
if (likely(IS_ERR(rtc->rtc_dev))) return PTR_ERR_OR_ZERO(rtc->rtc_dev);
return PTR_ERR(rtc->rtc_dev);
return 0;
} }
static int gemini_rtc_remove(struct platform_device *pdev) static int gemini_rtc_remove(struct platform_device *pdev)
......
...@@ -599,7 +599,6 @@ MODULE_DEVICE_TABLE(of, hym8563_dt_idtable); ...@@ -599,7 +599,6 @@ MODULE_DEVICE_TABLE(of, hym8563_dt_idtable);
static struct i2c_driver hym8563_driver = { static struct i2c_driver hym8563_driver = {
.driver = { .driver = {
.name = "rtc-hym8563", .name = "rtc-hym8563",
.owner = THIS_MODULE,
.pm = &hym8563_pm_ops, .pm = &hym8563_pm_ops,
.of_match_table = hym8563_dt_idtable, .of_match_table = hym8563_dt_idtable,
}, },
......
...@@ -151,12 +151,7 @@ static int isl12022_get_datetime(struct i2c_client *client, struct rtc_time *tm) ...@@ -151,12 +151,7 @@ static int isl12022_get_datetime(struct i2c_client *client, struct rtc_time *tm)
tm->tm_sec, tm->tm_min, tm->tm_hour, tm->tm_sec, tm->tm_min, tm->tm_hour,
tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
/* The clock can give out invalid datetime, but we cannot return return rtc_valid_tm(tm);
* -EINVAL otherwise hwclock will refuse to set the time on bootup. */
if (rtc_valid_tm(tm) < 0)
dev_err(&client->dev, "retrieved date and time is invalid.\n");
return 0;
} }
static int isl12022_set_datetime(struct i2c_client *client, struct rtc_time *tm) static int isl12022_set_datetime(struct i2c_client *client, struct rtc_time *tm)
...@@ -279,6 +274,7 @@ static const struct of_device_id isl12022_dt_match[] = { ...@@ -279,6 +274,7 @@ static const struct of_device_id isl12022_dt_match[] = {
{ .compatible = "isil,isl12022" }, { .compatible = "isil,isl12022" },
{ }, { },
}; };
MODULE_DEVICE_TABLE(of, isl12022_dt_match);
#endif #endif
static const struct i2c_device_id isl12022_id[] = { static const struct i2c_device_id isl12022_id[] = {
......
...@@ -648,6 +648,7 @@ static const struct of_device_id isl12057_dt_match[] = { ...@@ -648,6 +648,7 @@ static const struct of_device_id isl12057_dt_match[] = {
{ .compatible = "isil,isl12057" }, { .compatible = "isil,isl12057" },
{ }, { },
}; };
MODULE_DEVICE_TABLE(of, isl12057_dt_match);
#endif #endif
static const struct i2c_device_id isl12057_id[] = { static const struct i2c_device_id isl12057_id[] = {
...@@ -659,7 +660,6 @@ MODULE_DEVICE_TABLE(i2c, isl12057_id); ...@@ -659,7 +660,6 @@ MODULE_DEVICE_TABLE(i2c, isl12057_id);
static struct i2c_driver isl12057_driver = { static struct i2c_driver isl12057_driver = {
.driver = { .driver = {
.name = DRV_NAME, .name = DRV_NAME,
.owner = THIS_MODULE,
.pm = &isl12057_rtc_pm_ops, .pm = &isl12057_rtc_pm_ops,
.of_match_table = of_match_ptr(isl12057_dt_match), .of_match_table = of_match_ptr(isl12057_dt_match),
}, },
......
/*
* RTC driver for NXP LPC178x/18xx/43xx Real-Time Clock (RTC)
*
* Copyright (C) 2011 NXP Semiconductors
* Copyright (C) 2015 Joachim Eastwood <manabian@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
*/
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/rtc.h>
/* LPC24xx RTC register offsets and bits */
#define LPC24XX_ILR 0x00
#define LPC24XX_RTCCIF BIT(0)
#define LPC24XX_RTCALF BIT(1)
#define LPC24XX_CTC 0x04
#define LPC24XX_CCR 0x08
#define LPC24XX_CLKEN BIT(0)
#define LPC178X_CCALEN BIT(4)
#define LPC24XX_CIIR 0x0c
#define LPC24XX_AMR 0x10
#define LPC24XX_ALARM_DISABLE 0xff
#define LPC24XX_CTIME0 0x14
#define LPC24XX_CTIME1 0x18
#define LPC24XX_CTIME2 0x1c
#define LPC24XX_SEC 0x20
#define LPC24XX_MIN 0x24
#define LPC24XX_HOUR 0x28
#define LPC24XX_DOM 0x2c
#define LPC24XX_DOW 0x30
#define LPC24XX_DOY 0x34
#define LPC24XX_MONTH 0x38
#define LPC24XX_YEAR 0x3c
#define LPC24XX_ALSEC 0x60
#define LPC24XX_ALMIN 0x64
#define LPC24XX_ALHOUR 0x68
#define LPC24XX_ALDOM 0x6c
#define LPC24XX_ALDOW 0x70
#define LPC24XX_ALDOY 0x74
#define LPC24XX_ALMON 0x78
#define LPC24XX_ALYEAR 0x7c
/* Macros to read fields in consolidated time (CT) registers */
#define CT0_SECS(x) (((x) >> 0) & 0x3f)
#define CT0_MINS(x) (((x) >> 8) & 0x3f)
#define CT0_HOURS(x) (((x) >> 16) & 0x1f)
#define CT0_DOW(x) (((x) >> 24) & 0x07)
#define CT1_DOM(x) (((x) >> 0) & 0x1f)
#define CT1_MONTH(x) (((x) >> 8) & 0x0f)
#define CT1_YEAR(x) (((x) >> 16) & 0xfff)
#define CT2_DOY(x) (((x) >> 0) & 0xfff)
#define rtc_readl(dev, reg) readl((dev)->rtc_base + (reg))
#define rtc_writel(dev, reg, val) writel((val), (dev)->rtc_base + (reg))
struct lpc24xx_rtc {
void __iomem *rtc_base;
struct rtc_device *rtc;
struct clk *clk_rtc;
struct clk *clk_reg;
};
static int lpc24xx_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
struct lpc24xx_rtc *rtc = dev_get_drvdata(dev);
/* Disable RTC during update */
rtc_writel(rtc, LPC24XX_CCR, LPC178X_CCALEN);
rtc_writel(rtc, LPC24XX_SEC, tm->tm_sec);
rtc_writel(rtc, LPC24XX_MIN, tm->tm_min);
rtc_writel(rtc, LPC24XX_HOUR, tm->tm_hour);
rtc_writel(rtc, LPC24XX_DOW, tm->tm_wday);
rtc_writel(rtc, LPC24XX_DOM, tm->tm_mday);
rtc_writel(rtc, LPC24XX_DOY, tm->tm_yday);
rtc_writel(rtc, LPC24XX_MONTH, tm->tm_mon);
rtc_writel(rtc, LPC24XX_YEAR, tm->tm_year);
rtc_writel(rtc, LPC24XX_CCR, LPC24XX_CLKEN | LPC178X_CCALEN);
return 0;
}
static int lpc24xx_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
struct lpc24xx_rtc *rtc = dev_get_drvdata(dev);
u32 ct0, ct1, ct2;
ct0 = rtc_readl(rtc, LPC24XX_CTIME0);
ct1 = rtc_readl(rtc, LPC24XX_CTIME1);
ct2 = rtc_readl(rtc, LPC24XX_CTIME2);
tm->tm_sec = CT0_SECS(ct0);
tm->tm_min = CT0_MINS(ct0);
tm->tm_hour = CT0_HOURS(ct0);
tm->tm_wday = CT0_DOW(ct0);
tm->tm_mon = CT1_MONTH(ct1);
tm->tm_mday = CT1_DOM(ct1);
tm->tm_year = CT1_YEAR(ct1);
tm->tm_yday = CT2_DOY(ct2);
return rtc_valid_tm(tm);
}
static int lpc24xx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
{
struct lpc24xx_rtc *rtc = dev_get_drvdata(dev);
struct rtc_time *tm = &wkalrm->time;
tm->tm_sec = rtc_readl(rtc, LPC24XX_ALSEC);
tm->tm_min = rtc_readl(rtc, LPC24XX_ALMIN);
tm->tm_hour = rtc_readl(rtc, LPC24XX_ALHOUR);
tm->tm_mday = rtc_readl(rtc, LPC24XX_ALDOM);
tm->tm_wday = rtc_readl(rtc, LPC24XX_ALDOW);
tm->tm_yday = rtc_readl(rtc, LPC24XX_ALDOY);
tm->tm_mon = rtc_readl(rtc, LPC24XX_ALMON);
tm->tm_year = rtc_readl(rtc, LPC24XX_ALYEAR);
wkalrm->enabled = rtc_readl(rtc, LPC24XX_AMR) == 0;
wkalrm->pending = !!(rtc_readl(rtc, LPC24XX_ILR) & LPC24XX_RTCCIF);
return rtc_valid_tm(&wkalrm->time);
}
static int lpc24xx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
{
struct lpc24xx_rtc *rtc = dev_get_drvdata(dev);
struct rtc_time *tm = &wkalrm->time;
/* Disable alarm irq during update */
rtc_writel(rtc, LPC24XX_AMR, LPC24XX_ALARM_DISABLE);
rtc_writel(rtc, LPC24XX_ALSEC, tm->tm_sec);
rtc_writel(rtc, LPC24XX_ALMIN, tm->tm_min);
rtc_writel(rtc, LPC24XX_ALHOUR, tm->tm_hour);
rtc_writel(rtc, LPC24XX_ALDOM, tm->tm_mday);
rtc_writel(rtc, LPC24XX_ALDOW, tm->tm_wday);
rtc_writel(rtc, LPC24XX_ALDOY, tm->tm_yday);
rtc_writel(rtc, LPC24XX_ALMON, tm->tm_mon);
rtc_writel(rtc, LPC24XX_ALYEAR, tm->tm_year);
if (wkalrm->enabled)
rtc_writel(rtc, LPC24XX_AMR, 0);
return 0;
}
static int lpc24xx_rtc_alarm_irq_enable(struct device *dev, unsigned int enable)
{
struct lpc24xx_rtc *rtc = dev_get_drvdata(dev);
if (enable)
rtc_writel(rtc, LPC24XX_AMR, 0);
else
rtc_writel(rtc, LPC24XX_AMR, LPC24XX_ALARM_DISABLE);
return 0;
}
static irqreturn_t lpc24xx_rtc_interrupt(int irq, void *data)
{
unsigned long events = RTC_IRQF;
struct lpc24xx_rtc *rtc = data;
u32 rtc_iir;
/* Check interrupt cause */
rtc_iir = rtc_readl(rtc, LPC24XX_ILR);
if (rtc_iir & LPC24XX_RTCALF) {
events |= RTC_AF;
rtc_writel(rtc, LPC24XX_AMR, LPC24XX_ALARM_DISABLE);
}
/* Clear interrupt status and report event */
rtc_writel(rtc, LPC24XX_ILR, rtc_iir);
rtc_update_irq(rtc->rtc, 1, events);
return IRQ_HANDLED;
}
static const struct rtc_class_ops lpc24xx_rtc_ops = {
.read_time = lpc24xx_rtc_read_time,
.set_time = lpc24xx_rtc_set_time,
.read_alarm = lpc24xx_rtc_read_alarm,
.set_alarm = lpc24xx_rtc_set_alarm,
.alarm_irq_enable = lpc24xx_rtc_alarm_irq_enable,
};
static int lpc24xx_rtc_probe(struct platform_device *pdev)
{
struct lpc24xx_rtc *rtc;
struct resource *res;
int irq, ret;
rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL);
if (!rtc)
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
rtc->rtc_base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(rtc->rtc_base))
return PTR_ERR(rtc->rtc_base);
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_warn(&pdev->dev, "can't get interrupt resource\n");
return irq;
}
rtc->clk_rtc = devm_clk_get(&pdev->dev, "rtc");
if (IS_ERR(rtc->clk_rtc)) {
dev_err(&pdev->dev, "error getting rtc clock\n");
return PTR_ERR(rtc->clk_rtc);
}
rtc->clk_reg = devm_clk_get(&pdev->dev, "reg");
if (IS_ERR(rtc->clk_reg)) {
dev_err(&pdev->dev, "error getting reg clock\n");
return PTR_ERR(rtc->clk_reg);
}
ret = clk_prepare_enable(rtc->clk_rtc);
if (ret) {
dev_err(&pdev->dev, "unable to enable rtc clock\n");
return ret;
}
ret = clk_prepare_enable(rtc->clk_reg);
if (ret) {
dev_err(&pdev->dev, "unable to enable reg clock\n");
goto disable_rtc_clk;
}
platform_set_drvdata(pdev, rtc);
/* Clear any pending interrupts */
rtc_writel(rtc, LPC24XX_ILR, LPC24XX_RTCCIF | LPC24XX_RTCALF);
/* Enable RTC count */
rtc_writel(rtc, LPC24XX_CCR, LPC24XX_CLKEN | LPC178X_CCALEN);
ret = devm_request_irq(&pdev->dev, irq, lpc24xx_rtc_interrupt, 0,
pdev->name, rtc);
if (ret < 0) {
dev_warn(&pdev->dev, "can't request interrupt\n");
goto disable_clks;
}
rtc->rtc = devm_rtc_device_register(&pdev->dev, "lpc24xx-rtc",
&lpc24xx_rtc_ops, THIS_MODULE);
if (IS_ERR(rtc->rtc)) {
dev_err(&pdev->dev, "can't register rtc device\n");
ret = PTR_ERR(rtc->rtc);
goto disable_clks;
}
return 0;
disable_clks:
clk_disable_unprepare(rtc->clk_reg);
disable_rtc_clk:
clk_disable_unprepare(rtc->clk_rtc);
return ret;
}
static int lpc24xx_rtc_remove(struct platform_device *pdev)
{
struct lpc24xx_rtc *rtc = platform_get_drvdata(pdev);
/* Ensure all interrupt sources are masked */
rtc_writel(rtc, LPC24XX_AMR, LPC24XX_ALARM_DISABLE);
rtc_writel(rtc, LPC24XX_CIIR, 0);
rtc_writel(rtc, LPC24XX_CCR, LPC178X_CCALEN);
clk_disable_unprepare(rtc->clk_rtc);
clk_disable_unprepare(rtc->clk_reg);
return 0;
}
static const struct of_device_id lpc24xx_rtc_match[] = {
{ .compatible = "nxp,lpc1788-rtc" },
{ }
};
MODULE_DEVICE_TABLE(of, lpc24xx_rtc_match);
static struct platform_driver lpc24xx_rtc_driver = {
.probe = lpc24xx_rtc_probe,
.remove = lpc24xx_rtc_remove,
.driver = {
.name = "lpc24xx-rtc",
.of_match_table = lpc24xx_rtc_match,
},
};
module_platform_driver(lpc24xx_rtc_driver);
MODULE_AUTHOR("Kevin Wells <wellsk40@gmail.com>");
MODULE_DESCRIPTION("RTC driver for the LPC178x/18xx/408x/43xx SoCs");
MODULE_LICENSE("GPL");
...@@ -345,11 +345,12 @@ static ssize_t m48t59_nvram_read(struct file *filp, struct kobject *kobj, ...@@ -345,11 +345,12 @@ static ssize_t m48t59_nvram_read(struct file *filp, struct kobject *kobj,
ssize_t cnt = 0; ssize_t cnt = 0;
unsigned long flags; unsigned long flags;
for (; size > 0 && pos < pdata->offset; cnt++, size--) { spin_lock_irqsave(&m48t59->lock, flags);
spin_lock_irqsave(&m48t59->lock, flags);
for (; cnt < size; cnt++)
*buf++ = M48T59_READ(cnt); *buf++ = M48T59_READ(cnt);
spin_unlock_irqrestore(&m48t59->lock, flags);
} spin_unlock_irqrestore(&m48t59->lock, flags);
return cnt; return cnt;
} }
...@@ -365,11 +366,12 @@ static ssize_t m48t59_nvram_write(struct file *filp, struct kobject *kobj, ...@@ -365,11 +366,12 @@ static ssize_t m48t59_nvram_write(struct file *filp, struct kobject *kobj,
ssize_t cnt = 0; ssize_t cnt = 0;
unsigned long flags; unsigned long flags;
for (; size > 0 && pos < pdata->offset; cnt++, size--) { spin_lock_irqsave(&m48t59->lock, flags);
spin_lock_irqsave(&m48t59->lock, flags);
for (; cnt < size; cnt++)
M48T59_WRITE(*buf++, cnt); M48T59_WRITE(*buf++, cnt);
spin_unlock_irqrestore(&m48t59->lock, flags);
} spin_unlock_irqrestore(&m48t59->lock, flags);
return cnt; return cnt;
} }
......
...@@ -521,6 +521,7 @@ static const struct platform_device_id rtc_id[] = { ...@@ -521,6 +521,7 @@ static const struct platform_device_id rtc_id[] = {
{ "max8997-rtc", 0 }, { "max8997-rtc", 0 },
{}, {},
}; };
MODULE_DEVICE_TABLE(platform, rtc_id);
static struct platform_driver max8997_rtc_driver = { static struct platform_driver max8997_rtc_driver = {
.driver = { .driver = {
......
...@@ -312,6 +312,7 @@ static const struct of_device_id moxart_rtc_match[] = { ...@@ -312,6 +312,7 @@ static const struct of_device_id moxart_rtc_match[] = {
{ .compatible = "moxa,moxart-rtc" }, { .compatible = "moxa,moxart-rtc" },
{ }, { },
}; };
MODULE_DEVICE_TABLE(of, moxart_rtc_match);
static struct platform_driver moxart_rtc_driver = { static struct platform_driver moxart_rtc_driver = {
.probe = moxart_rtc_probe, .probe = moxart_rtc_probe,
......
...@@ -406,6 +406,7 @@ static const struct of_device_id mpc5121_rtc_match[] = { ...@@ -406,6 +406,7 @@ static const struct of_device_id mpc5121_rtc_match[] = {
{ .compatible = "fsl,mpc5200-rtc", }, { .compatible = "fsl,mpc5200-rtc", },
{}, {},
}; };
MODULE_DEVICE_TABLE(of, mpc5121_rtc_match);
#endif #endif
static struct platform_driver mpc5121_rtc_driver = { static struct platform_driver mpc5121_rtc_driver = {
......
...@@ -373,15 +373,42 @@ static int mtk_rtc_remove(struct platform_device *pdev) ...@@ -373,15 +373,42 @@ static int mtk_rtc_remove(struct platform_device *pdev)
return 0; return 0;
} }
#ifdef CONFIG_PM_SLEEP
static int mt6397_rtc_suspend(struct device *dev)
{
struct mt6397_rtc *rtc = dev_get_drvdata(dev);
if (device_may_wakeup(dev))
enable_irq_wake(rtc->irq);
return 0;
}
static int mt6397_rtc_resume(struct device *dev)
{
struct mt6397_rtc *rtc = dev_get_drvdata(dev);
if (device_may_wakeup(dev))
disable_irq_wake(rtc->irq);
return 0;
}
#endif
static SIMPLE_DEV_PM_OPS(mt6397_pm_ops, mt6397_rtc_suspend,
mt6397_rtc_resume);
static const struct of_device_id mt6397_rtc_of_match[] = { static const struct of_device_id mt6397_rtc_of_match[] = {
{ .compatible = "mediatek,mt6397-rtc", }, { .compatible = "mediatek,mt6397-rtc", },
{ } { }
}; };
MODULE_DEVICE_TABLE(of, mt6397_rtc_of_match);
static struct platform_driver mtk_rtc_driver = { static struct platform_driver mtk_rtc_driver = {
.driver = { .driver = {
.name = "mt6397-rtc", .name = "mt6397-rtc",
.of_match_table = mt6397_rtc_of_match, .of_match_table = mt6397_rtc_of_match,
.pm = &mt6397_pm_ops,
}, },
.probe = mtk_rtc_probe, .probe = mtk_rtc_probe,
.remove = mtk_rtc_remove, .remove = mtk_rtc_remove,
......
...@@ -324,6 +324,7 @@ static const struct of_device_id rtc_mv_of_match_table[] = { ...@@ -324,6 +324,7 @@ static const struct of_device_id rtc_mv_of_match_table[] = {
{ .compatible = "marvell,orion-rtc", }, { .compatible = "marvell,orion-rtc", },
{} {}
}; };
MODULE_DEVICE_TABLE(of, rtc_mv_of_match_table);
#endif #endif
static struct platform_driver mv_rtc_driver = { static struct platform_driver mv_rtc_driver = {
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include <linux/of_device.h> #include <linux/of_device.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/clk.h>
/* /*
* The OMAP RTC is a year/month/day/hours/minutes/seconds BCD clock * The OMAP RTC is a year/month/day/hours/minutes/seconds BCD clock
...@@ -107,6 +108,7 @@ ...@@ -107,6 +108,7 @@
/* OMAP_RTC_OSC_REG bit fields: */ /* OMAP_RTC_OSC_REG bit fields: */
#define OMAP_RTC_OSC_32KCLK_EN BIT(6) #define OMAP_RTC_OSC_32KCLK_EN BIT(6)
#define OMAP_RTC_OSC_SEL_32KCLK_SRC BIT(3)
/* OMAP_RTC_IRQWAKEEN bit fields: */ /* OMAP_RTC_IRQWAKEEN bit fields: */
#define OMAP_RTC_IRQWAKEEN_ALARM_WAKEEN BIT(1) #define OMAP_RTC_IRQWAKEEN_ALARM_WAKEEN BIT(1)
...@@ -132,10 +134,12 @@ struct omap_rtc_device_type { ...@@ -132,10 +134,12 @@ struct omap_rtc_device_type {
struct omap_rtc { struct omap_rtc {
struct rtc_device *rtc; struct rtc_device *rtc;
void __iomem *base; void __iomem *base;
struct clk *clk;
int irq_alarm; int irq_alarm;
int irq_timer; int irq_timer;
u8 interrupts_reg; u8 interrupts_reg;
bool is_pmic_controller; bool is_pmic_controller;
bool has_ext_clk;
const struct omap_rtc_device_type *type; const struct omap_rtc_device_type *type;
}; };
...@@ -553,6 +557,15 @@ static int omap_rtc_probe(struct platform_device *pdev) ...@@ -553,6 +557,15 @@ static int omap_rtc_probe(struct platform_device *pdev)
if (rtc->irq_alarm <= 0) if (rtc->irq_alarm <= 0)
return -ENOENT; return -ENOENT;
rtc->clk = devm_clk_get(&pdev->dev, "ext-clk");
if (!IS_ERR(rtc->clk))
rtc->has_ext_clk = true;
else
rtc->clk = devm_clk_get(&pdev->dev, "int-clk");
if (!IS_ERR(rtc->clk))
clk_prepare_enable(rtc->clk);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
rtc->base = devm_ioremap_resource(&pdev->dev, res); rtc->base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(rtc->base)) if (IS_ERR(rtc->base))
...@@ -627,6 +640,16 @@ static int omap_rtc_probe(struct platform_device *pdev) ...@@ -627,6 +640,16 @@ static int omap_rtc_probe(struct platform_device *pdev)
if (reg != new_ctrl) if (reg != new_ctrl)
rtc_write(rtc, OMAP_RTC_CTRL_REG, new_ctrl); rtc_write(rtc, OMAP_RTC_CTRL_REG, new_ctrl);
/*
* If we have the external clock then switch to it so we can keep
* ticking across suspend.
*/
if (rtc->has_ext_clk) {
reg = rtc_read(rtc, OMAP_RTC_OSC_REG);
rtc_write(rtc, OMAP_RTC_OSC_REG,
reg | OMAP_RTC_OSC_SEL_32KCLK_SRC);
}
rtc->type->lock(rtc); rtc->type->lock(rtc);
device_init_wakeup(&pdev->dev, true); device_init_wakeup(&pdev->dev, true);
...@@ -672,6 +695,7 @@ static int omap_rtc_probe(struct platform_device *pdev) ...@@ -672,6 +695,7 @@ static int omap_rtc_probe(struct platform_device *pdev)
static int __exit omap_rtc_remove(struct platform_device *pdev) static int __exit omap_rtc_remove(struct platform_device *pdev)
{ {
struct omap_rtc *rtc = platform_get_drvdata(pdev); struct omap_rtc *rtc = platform_get_drvdata(pdev);
u8 reg;
if (pm_power_off == omap_rtc_power_off && if (pm_power_off == omap_rtc_power_off &&
omap_rtc_power_off_rtc == rtc) { omap_rtc_power_off_rtc == rtc) {
...@@ -681,10 +705,19 @@ static int __exit omap_rtc_remove(struct platform_device *pdev) ...@@ -681,10 +705,19 @@ static int __exit omap_rtc_remove(struct platform_device *pdev)
device_init_wakeup(&pdev->dev, 0); device_init_wakeup(&pdev->dev, 0);
if (!IS_ERR(rtc->clk))
clk_disable_unprepare(rtc->clk);
rtc->type->unlock(rtc); rtc->type->unlock(rtc);
/* leave rtc running, but disable irqs */ /* leave rtc running, but disable irqs */
rtc_write(rtc, OMAP_RTC_INTERRUPTS_REG, 0); rtc_write(rtc, OMAP_RTC_INTERRUPTS_REG, 0);
if (rtc->has_ext_clk) {
reg = rtc_read(rtc, OMAP_RTC_OSC_REG);
reg &= ~OMAP_RTC_OSC_SEL_32KCLK_SRC;
rtc_write(rtc, OMAP_RTC_OSC_REG, reg);
}
rtc->type->lock(rtc); rtc->type->lock(rtc);
/* Disable the clock/module */ /* Disable the clock/module */
......
...@@ -190,11 +190,9 @@ static int opal_set_tpo_time(struct device *dev, struct rtc_wkalrm *alarm) ...@@ -190,11 +190,9 @@ static int opal_set_tpo_time(struct device *dev, struct rtc_wkalrm *alarm)
return rc; return rc;
} }
static const struct rtc_class_ops opal_rtc_ops = { static struct rtc_class_ops opal_rtc_ops = {
.read_time = opal_get_rtc_time, .read_time = opal_get_rtc_time,
.set_time = opal_set_rtc_time, .set_time = opal_set_rtc_time,
.read_alarm = opal_get_tpo_time,
.set_alarm = opal_set_tpo_time,
}; };
static int opal_rtc_probe(struct platform_device *pdev) static int opal_rtc_probe(struct platform_device *pdev)
...@@ -202,8 +200,11 @@ static int opal_rtc_probe(struct platform_device *pdev) ...@@ -202,8 +200,11 @@ static int opal_rtc_probe(struct platform_device *pdev)
struct rtc_device *rtc; struct rtc_device *rtc;
if (pdev->dev.of_node && of_get_property(pdev->dev.of_node, "has-tpo", if (pdev->dev.of_node && of_get_property(pdev->dev.of_node, "has-tpo",
NULL)) NULL)) {
device_set_wakeup_capable(&pdev->dev, true); device_set_wakeup_capable(&pdev->dev, true);
opal_rtc_ops.read_alarm = opal_get_tpo_time;
opal_rtc_ops.set_alarm = opal_set_tpo_time;
}
rtc = devm_rtc_device_register(&pdev->dev, DRVNAME, &opal_rtc_ops, rtc = devm_rtc_device_register(&pdev->dev, DRVNAME, &opal_rtc_ops,
THIS_MODULE); THIS_MODULE);
...@@ -236,7 +237,6 @@ static struct platform_driver opal_rtc_driver = { ...@@ -236,7 +237,6 @@ static struct platform_driver opal_rtc_driver = {
.id_table = opal_rtc_driver_ids, .id_table = opal_rtc_driver_ids,
.driver = { .driver = {
.name = DRVNAME, .name = DRVNAME,
.owner = THIS_MODULE,
.of_match_table = opal_rtc_match, .of_match_table = opal_rtc_match,
}, },
}; };
......
...@@ -165,13 +165,7 @@ static int pcf2123_rtc_read_time(struct device *dev, struct rtc_time *tm) ...@@ -165,13 +165,7 @@ static int pcf2123_rtc_read_time(struct device *dev, struct rtc_time *tm)
tm->tm_sec, tm->tm_min, tm->tm_hour, tm->tm_sec, tm->tm_min, tm->tm_hour,
tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
/* the clock can give out invalid datetime, but we cannot return return rtc_valid_tm(tm);
* -EINVAL otherwise hwclock will refuse to set the time on bootup.
*/
if (rtc_valid_tm(tm) < 0)
dev_err(dev, "retrieved date/time is not valid.\n");
return 0;
} }
static int pcf2123_rtc_set_time(struct device *dev, struct rtc_time *tm) static int pcf2123_rtc_set_time(struct device *dev, struct rtc_time *tm)
......
...@@ -33,11 +33,14 @@ ...@@ -33,11 +33,14 @@
#define PCF2127_REG_MO (0x08) #define PCF2127_REG_MO (0x08)
#define PCF2127_REG_YR (0x09) #define PCF2127_REG_YR (0x09)
#define PCF2127_OSF BIT(7) /* Oscillator Fail flag */
static struct i2c_driver pcf2127_driver; static struct i2c_driver pcf2127_driver;
struct pcf2127 { struct pcf2127 {
struct rtc_device *rtc; struct rtc_device *rtc;
int voltage_low; /* indicates if a low_voltage was detected */ int voltage_low; /* indicates if a low_voltage was detected */
int oscillator_failed; /* OSF was detected and date is unreliable */
}; };
/* /*
...@@ -59,7 +62,18 @@ static int pcf2127_get_datetime(struct i2c_client *client, struct rtc_time *tm) ...@@ -59,7 +62,18 @@ static int pcf2127_get_datetime(struct i2c_client *client, struct rtc_time *tm)
if (buf[PCF2127_REG_CTRL3] & 0x04) { if (buf[PCF2127_REG_CTRL3] & 0x04) {
pcf2127->voltage_low = 1; pcf2127->voltage_low = 1;
dev_info(&client->dev, dev_info(&client->dev,
"low voltage detected, date/time is not reliable.\n"); "low voltage detected, check/replace RTC battery.\n");
}
if (buf[PCF2127_REG_SC] & PCF2127_OSF) {
/*
* no need clear the flag here,
* it will be cleared once the new date is saved
*/
pcf2127->oscillator_failed = 1;
dev_warn(&client->dev,
"oscillator stop detected, date/time is not reliable\n");
return -EINVAL;
} }
dev_dbg(&client->dev, dev_dbg(&client->dev,
...@@ -88,17 +102,12 @@ static int pcf2127_get_datetime(struct i2c_client *client, struct rtc_time *tm) ...@@ -88,17 +102,12 @@ static int pcf2127_get_datetime(struct i2c_client *client, struct rtc_time *tm)
tm->tm_sec, tm->tm_min, tm->tm_hour, tm->tm_sec, tm->tm_min, tm->tm_hour,
tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
/* the clock can give out invalid datetime, but we cannot return return rtc_valid_tm(tm);
* -EINVAL otherwise hwclock will refuse to set the time on bootup.
*/
if (rtc_valid_tm(tm) < 0)
dev_err(&client->dev, "retrieved date/time is not valid.\n");
return 0;
} }
static int pcf2127_set_datetime(struct i2c_client *client, struct rtc_time *tm) static int pcf2127_set_datetime(struct i2c_client *client, struct rtc_time *tm)
{ {
struct pcf2127 *pcf2127 = i2c_get_clientdata(client);
unsigned char buf[8]; unsigned char buf[8];
int i = 0, err; int i = 0, err;
...@@ -112,7 +121,7 @@ static int pcf2127_set_datetime(struct i2c_client *client, struct rtc_time *tm) ...@@ -112,7 +121,7 @@ static int pcf2127_set_datetime(struct i2c_client *client, struct rtc_time *tm)
buf[i++] = PCF2127_REG_SC; buf[i++] = PCF2127_REG_SC;
/* hours, minutes and seconds */ /* hours, minutes and seconds */
buf[i++] = bin2bcd(tm->tm_sec); buf[i++] = bin2bcd(tm->tm_sec); /* this will also clear OSF flag */
buf[i++] = bin2bcd(tm->tm_min); buf[i++] = bin2bcd(tm->tm_min);
buf[i++] = bin2bcd(tm->tm_hour); buf[i++] = bin2bcd(tm->tm_hour);
buf[i++] = bin2bcd(tm->tm_mday); buf[i++] = bin2bcd(tm->tm_mday);
...@@ -132,6 +141,9 @@ static int pcf2127_set_datetime(struct i2c_client *client, struct rtc_time *tm) ...@@ -132,6 +141,9 @@ static int pcf2127_set_datetime(struct i2c_client *client, struct rtc_time *tm)
return -EIO; return -EIO;
} }
/* clear OSF flag in client data */
pcf2127->oscillator_failed = 0;
return 0; return 0;
} }
...@@ -144,7 +156,9 @@ static int pcf2127_rtc_ioctl(struct device *dev, ...@@ -144,7 +156,9 @@ static int pcf2127_rtc_ioctl(struct device *dev,
switch (cmd) { switch (cmd) {
case RTC_VL_READ: case RTC_VL_READ:
if (pcf2127->voltage_low) if (pcf2127->voltage_low)
dev_info(dev, "low voltage detected, date/time is not reliable.\n"); dev_info(dev, "low voltage detected, check/replace battery\n");
if (pcf2127->oscillator_failed)
dev_info(dev, "oscillator stop detected, date/time is not reliable\n");
if (copy_to_user((void __user *)arg, &pcf2127->voltage_low, if (copy_to_user((void __user *)arg, &pcf2127->voltage_low,
sizeof(int))) sizeof(int)))
...@@ -217,7 +231,6 @@ MODULE_DEVICE_TABLE(of, pcf2127_of_match); ...@@ -217,7 +231,6 @@ MODULE_DEVICE_TABLE(of, pcf2127_of_match);
static struct i2c_driver pcf2127_driver = { static struct i2c_driver pcf2127_driver = {
.driver = { .driver = {
.name = "rtc-pcf2127", .name = "rtc-pcf2127",
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(pcf2127_of_match), .of_match_table = of_match_ptr(pcf2127_of_match),
}, },
.probe = pcf2127_probe, .probe = pcf2127_probe,
......
...@@ -189,7 +189,6 @@ MODULE_DEVICE_TABLE(of, pcf85063_of_match); ...@@ -189,7 +189,6 @@ MODULE_DEVICE_TABLE(of, pcf85063_of_match);
static struct i2c_driver pcf85063_driver = { static struct i2c_driver pcf85063_driver = {
.driver = { .driver = {
.name = "rtc-pcf85063", .name = "rtc-pcf85063",
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(pcf85063_of_match), .of_match_table = of_match_ptr(pcf85063_of_match),
}, },
.probe = pcf85063_probe, .probe = pcf85063_probe,
......
...@@ -334,7 +334,6 @@ MODULE_DEVICE_TABLE(of, pcf8523_of_match); ...@@ -334,7 +334,6 @@ MODULE_DEVICE_TABLE(of, pcf8523_of_match);
static struct i2c_driver pcf8523_driver = { static struct i2c_driver pcf8523_driver = {
.driver = { .driver = {
.name = DRIVER_NAME, .name = DRIVER_NAME,
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(pcf8523_of_match), .of_match_table = of_match_ptr(pcf8523_of_match),
}, },
.probe = pcf8523_probe, .probe = pcf8523_probe,
......
...@@ -483,7 +483,6 @@ MODULE_DEVICE_TABLE(of, pcf8563_of_match); ...@@ -483,7 +483,6 @@ MODULE_DEVICE_TABLE(of, pcf8563_of_match);
static struct i2c_driver pcf8563_driver = { static struct i2c_driver pcf8563_driver = {
.driver = { .driver = {
.name = "rtc-pcf8563", .name = "rtc-pcf8563",
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(pcf8563_of_match), .of_match_table = of_match_ptr(pcf8563_of_match),
}, },
.probe = pcf8563_probe, .probe = pcf8563_probe,
......
...@@ -309,7 +309,6 @@ MODULE_DEVICE_TABLE(i2c, pcf8583_id); ...@@ -309,7 +309,6 @@ MODULE_DEVICE_TABLE(i2c, pcf8583_id);
static struct i2c_driver pcf8583_driver = { static struct i2c_driver pcf8583_driver = {
.driver = { .driver = {
.name = "pcf8583", .name = "pcf8583",
.owner = THIS_MODULE,
}, },
.probe = pcf8583_probe, .probe = pcf8583_probe,
.id_table = pcf8583_id, .id_table = pcf8583_id,
......
...@@ -476,6 +476,6 @@ static struct amba_driver pl031_driver = { ...@@ -476,6 +476,6 @@ static struct amba_driver pl031_driver = {
module_amba_driver(pl031_driver); module_amba_driver(pl031_driver);
MODULE_AUTHOR("Deepak Saxena <dsaxena@plexity.net"); MODULE_AUTHOR("Deepak Saxena <dsaxena@plexity.net>");
MODULE_DESCRIPTION("ARM AMBA PL031 RTC Driver"); MODULE_DESCRIPTION("ARM AMBA PL031 RTC Driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -32,6 +32,8 @@ ...@@ -32,6 +32,8 @@
#include <mach/hardware.h> #include <mach/hardware.h>
#include "rtc-sa1100.h"
#define RTC_DEF_DIVIDER (32768 - 1) #define RTC_DEF_DIVIDER (32768 - 1)
#define RTC_DEF_TRIM 0 #define RTC_DEF_TRIM 0
#define MAXFREQ_PERIODIC 1000 #define MAXFREQ_PERIODIC 1000
...@@ -86,10 +88,9 @@ ...@@ -86,10 +88,9 @@
__raw_writel((value), (pxa_rtc)->base + (reg)) __raw_writel((value), (pxa_rtc)->base + (reg))
struct pxa_rtc { struct pxa_rtc {
struct sa1100_rtc sa1100_rtc;
struct resource *ress; struct resource *ress;
void __iomem *base; void __iomem *base;
int irq_1Hz;
int irq_Alrm;
struct rtc_device *rtc; struct rtc_device *rtc;
spinlock_t lock; /* Protects this structure */ spinlock_t lock; /* Protects this structure */
}; };
...@@ -184,25 +185,25 @@ static int pxa_rtc_open(struct device *dev) ...@@ -184,25 +185,25 @@ static int pxa_rtc_open(struct device *dev)
struct pxa_rtc *pxa_rtc = dev_get_drvdata(dev); struct pxa_rtc *pxa_rtc = dev_get_drvdata(dev);
int ret; int ret;
ret = request_irq(pxa_rtc->irq_1Hz, pxa_rtc_irq, 0, ret = request_irq(pxa_rtc->sa1100_rtc.irq_1hz, pxa_rtc_irq, 0,
"rtc 1Hz", dev); "rtc 1Hz", dev);
if (ret < 0) { if (ret < 0) {
dev_err(dev, "can't get irq %i, err %d\n", pxa_rtc->irq_1Hz, dev_err(dev, "can't get irq %i, err %d\n",
ret); pxa_rtc->sa1100_rtc.irq_1hz, ret);
goto err_irq_1Hz; goto err_irq_1Hz;
} }
ret = request_irq(pxa_rtc->irq_Alrm, pxa_rtc_irq, 0, ret = request_irq(pxa_rtc->sa1100_rtc.irq_alarm, pxa_rtc_irq, 0,
"rtc Alrm", dev); "rtc Alrm", dev);
if (ret < 0) { if (ret < 0) {
dev_err(dev, "can't get irq %i, err %d\n", pxa_rtc->irq_Alrm, dev_err(dev, "can't get irq %i, err %d\n",
ret); pxa_rtc->sa1100_rtc.irq_alarm, ret);
goto err_irq_Alrm; goto err_irq_Alrm;
} }
return 0; return 0;
err_irq_Alrm: err_irq_Alrm:
free_irq(pxa_rtc->irq_1Hz, dev); free_irq(pxa_rtc->sa1100_rtc.irq_1hz, dev);
err_irq_1Hz: err_irq_1Hz:
return ret; return ret;
} }
...@@ -215,8 +216,8 @@ static void pxa_rtc_release(struct device *dev) ...@@ -215,8 +216,8 @@ static void pxa_rtc_release(struct device *dev)
rtsr_clear_bits(pxa_rtc, RTSR_PIALE | RTSR_RDALE1 | RTSR_HZE); rtsr_clear_bits(pxa_rtc, RTSR_PIALE | RTSR_RDALE1 | RTSR_HZE);
spin_unlock_irq(&pxa_rtc->lock); spin_unlock_irq(&pxa_rtc->lock);
free_irq(pxa_rtc->irq_Alrm, dev); free_irq(pxa_rtc->sa1100_rtc.irq_1hz, dev);
free_irq(pxa_rtc->irq_1Hz, dev); free_irq(pxa_rtc->sa1100_rtc.irq_alarm, dev);
} }
static int pxa_alarm_irq_enable(struct device *dev, unsigned int enabled) static int pxa_alarm_irq_enable(struct device *dev, unsigned int enabled)
...@@ -320,12 +321,13 @@ static int __init pxa_rtc_probe(struct platform_device *pdev) ...@@ -320,12 +321,13 @@ static int __init pxa_rtc_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct pxa_rtc *pxa_rtc; struct pxa_rtc *pxa_rtc;
struct sa1100_rtc *sa1100_rtc;
int ret; int ret;
u32 rttr;
pxa_rtc = devm_kzalloc(dev, sizeof(*pxa_rtc), GFP_KERNEL); pxa_rtc = devm_kzalloc(dev, sizeof(*pxa_rtc), GFP_KERNEL);
if (!pxa_rtc) if (!pxa_rtc)
return -ENOMEM; return -ENOMEM;
sa1100_rtc = &pxa_rtc->sa1100_rtc;
spin_lock_init(&pxa_rtc->lock); spin_lock_init(&pxa_rtc->lock);
platform_set_drvdata(pdev, pxa_rtc); platform_set_drvdata(pdev, pxa_rtc);
...@@ -336,13 +338,13 @@ static int __init pxa_rtc_probe(struct platform_device *pdev) ...@@ -336,13 +338,13 @@ static int __init pxa_rtc_probe(struct platform_device *pdev)
return -ENXIO; return -ENXIO;
} }
pxa_rtc->irq_1Hz = platform_get_irq(pdev, 0); sa1100_rtc->irq_1hz = platform_get_irq(pdev, 0);
if (pxa_rtc->irq_1Hz < 0) { if (sa1100_rtc->irq_1hz < 0) {
dev_err(dev, "No 1Hz IRQ resource defined\n"); dev_err(dev, "No 1Hz IRQ resource defined\n");
return -ENXIO; return -ENXIO;
} }
pxa_rtc->irq_Alrm = platform_get_irq(pdev, 1); sa1100_rtc->irq_alarm = platform_get_irq(pdev, 1);
if (pxa_rtc->irq_Alrm < 0) { if (sa1100_rtc->irq_alarm < 0) {
dev_err(dev, "No alarm IRQ resource defined\n"); dev_err(dev, "No alarm IRQ resource defined\n");
return -ENXIO; return -ENXIO;
} }
...@@ -354,15 +356,14 @@ static int __init pxa_rtc_probe(struct platform_device *pdev) ...@@ -354,15 +356,14 @@ static int __init pxa_rtc_probe(struct platform_device *pdev)
return -ENOMEM; return -ENOMEM;
} }
/* sa1100_rtc->rcnr = pxa_rtc->base + 0x0;
* If the clock divider is uninitialized then reset it to the sa1100_rtc->rtsr = pxa_rtc->base + 0x8;
* default value to get the 1Hz clock. sa1100_rtc->rtar = pxa_rtc->base + 0x4;
*/ sa1100_rtc->rttr = pxa_rtc->base + 0xc;
if (rtc_readl(pxa_rtc, RTTR) == 0) { ret = sa1100_rtc_init(pdev, sa1100_rtc);
rttr = RTC_DEF_DIVIDER + (RTC_DEF_TRIM << 16); if (!ret) {
rtc_writel(pxa_rtc, RTTR, rttr); dev_err(dev, "Unable to init SA1100 RTC sub-device\n");
dev_warn(dev, "warning: initializing default clock" return ret;
" divider/trim value\n");
} }
rtsr_clear_bits(pxa_rtc, RTSR_PIALE | RTSR_RDALE1 | RTSR_HZE); rtsr_clear_bits(pxa_rtc, RTSR_PIALE | RTSR_RDALE1 | RTSR_HZE);
...@@ -402,7 +403,7 @@ static int pxa_rtc_suspend(struct device *dev) ...@@ -402,7 +403,7 @@ static int pxa_rtc_suspend(struct device *dev)
struct pxa_rtc *pxa_rtc = dev_get_drvdata(dev); struct pxa_rtc *pxa_rtc = dev_get_drvdata(dev);
if (device_may_wakeup(dev)) if (device_may_wakeup(dev))
enable_irq_wake(pxa_rtc->irq_Alrm); enable_irq_wake(pxa_rtc->sa1100_rtc.irq_alarm);
return 0; return 0;
} }
...@@ -411,7 +412,7 @@ static int pxa_rtc_resume(struct device *dev) ...@@ -411,7 +412,7 @@ static int pxa_rtc_resume(struct device *dev)
struct pxa_rtc *pxa_rtc = dev_get_drvdata(dev); struct pxa_rtc *pxa_rtc = dev_get_drvdata(dev);
if (device_may_wakeup(dev)) if (device_may_wakeup(dev))
disable_irq_wake(pxa_rtc->irq_Alrm); disable_irq_wake(pxa_rtc->sa1100_rtc.irq_alarm);
return 0; return 0;
} }
#endif #endif
......
...@@ -170,7 +170,7 @@ static ssize_t rp5c01_nvram_read(struct file *filp, struct kobject *kobj, ...@@ -170,7 +170,7 @@ static ssize_t rp5c01_nvram_read(struct file *filp, struct kobject *kobj,
spin_lock_irq(&priv->lock); spin_lock_irq(&priv->lock);
for (count = 0; size > 0 && pos < RP5C01_MODE; count++, size--) { for (count = 0; count < size; count++) {
u8 data; u8 data;
rp5c01_write(priv, rp5c01_write(priv,
...@@ -200,7 +200,7 @@ static ssize_t rp5c01_nvram_write(struct file *filp, struct kobject *kobj, ...@@ -200,7 +200,7 @@ static ssize_t rp5c01_nvram_write(struct file *filp, struct kobject *kobj,
spin_lock_irq(&priv->lock); spin_lock_irq(&priv->lock);
for (count = 0; size > 0 && pos < RP5C01_MODE; count++, size--) { for (count = 0; count < size; count++) {
u8 data = *buf++; u8 data = *buf++;
rp5c01_write(priv, rp5c01_write(priv,
......
...@@ -18,13 +18,11 @@ ...@@ -18,13 +18,11 @@
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation. * version 2 as published by the Free Software Foundation.
*/ */
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/bcd.h> #include <linux/bcd.h>
#include <linux/bitops.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/list.h> #include <linux/kernel.h>
#include <linux/module.h>
#include <linux/rtc.h> #include <linux/rtc.h>
/* Register definitions */ /* Register definitions */
...@@ -48,17 +46,17 @@ ...@@ -48,17 +46,17 @@
#define RX8025_BIT_CTRL1_CT (7 << 0) #define RX8025_BIT_CTRL1_CT (7 << 0)
/* 1 Hz periodic level irq */ /* 1 Hz periodic level irq */
#define RX8025_BIT_CTRL1_CT_1HZ 4 #define RX8025_BIT_CTRL1_CT_1HZ 4
#define RX8025_BIT_CTRL1_TEST (1 << 3) #define RX8025_BIT_CTRL1_TEST BIT(3)
#define RX8025_BIT_CTRL1_1224 (1 << 5) #define RX8025_BIT_CTRL1_1224 BIT(5)
#define RX8025_BIT_CTRL1_DALE (1 << 6) #define RX8025_BIT_CTRL1_DALE BIT(6)
#define RX8025_BIT_CTRL1_WALE (1 << 7) #define RX8025_BIT_CTRL1_WALE BIT(7)
#define RX8025_BIT_CTRL2_DAFG (1 << 0) #define RX8025_BIT_CTRL2_DAFG BIT(0)
#define RX8025_BIT_CTRL2_WAFG (1 << 1) #define RX8025_BIT_CTRL2_WAFG BIT(1)
#define RX8025_BIT_CTRL2_CTFG (1 << 2) #define RX8025_BIT_CTRL2_CTFG BIT(2)
#define RX8025_BIT_CTRL2_PON (1 << 4) #define RX8025_BIT_CTRL2_PON BIT(4)
#define RX8025_BIT_CTRL2_XST (1 << 5) #define RX8025_BIT_CTRL2_XST BIT(5)
#define RX8025_BIT_CTRL2_VDET (1 << 6) #define RX8025_BIT_CTRL2_VDET BIT(6)
/* Clock precision adjustment */ /* Clock precision adjustment */
#define RX8025_ADJ_RESOLUTION 3050 /* in ppb */ #define RX8025_ADJ_RESOLUTION 3050 /* in ppb */
...@@ -74,84 +72,84 @@ MODULE_DEVICE_TABLE(i2c, rx8025_id); ...@@ -74,84 +72,84 @@ MODULE_DEVICE_TABLE(i2c, rx8025_id);
struct rx8025_data { struct rx8025_data {
struct i2c_client *client; struct i2c_client *client;
struct rtc_device *rtc; struct rtc_device *rtc;
struct work_struct work;
u8 ctrl1; u8 ctrl1;
unsigned exiting:1;
}; };
static int rx8025_read_reg(struct i2c_client *client, int number, u8 *value) static s32 rx8025_read_reg(const struct i2c_client *client, u8 number)
{ {
int ret = i2c_smbus_read_byte_data(client, (number << 4) | 0x08); return i2c_smbus_read_byte_data(client, number << 4);
if (ret < 0) {
dev_err(&client->dev, "Unable to read register #%d\n", number);
return ret;
}
*value = ret;
return 0;
} }
static int rx8025_read_regs(struct i2c_client *client, static int rx8025_read_regs(const struct i2c_client *client,
int number, u8 length, u8 *values) u8 number, u8 length, u8 *values)
{ {
int ret = i2c_smbus_read_i2c_block_data(client, (number << 4) | 0x08, int ret = i2c_smbus_read_i2c_block_data(client, number << 4, length,
length, values); values);
if (ret != length)
if (ret != length) {
dev_err(&client->dev, "Unable to read registers #%d..#%d\n",
number, number + length - 1);
return ret < 0 ? ret : -EIO; return ret < 0 ? ret : -EIO;
}
return 0; return 0;
} }
static int rx8025_write_reg(struct i2c_client *client, int number, u8 value) static s32 rx8025_write_reg(const struct i2c_client *client, u8 number,
u8 value)
{ {
int ret = i2c_smbus_write_byte_data(client, number << 4, value); return i2c_smbus_write_byte_data(client, number << 4, value);
}
if (ret)
dev_err(&client->dev, "Unable to write register #%d\n",
number);
return ret; static s32 rx8025_write_regs(const struct i2c_client *client,
u8 number, u8 length, const u8 *values)
{
return i2c_smbus_write_i2c_block_data(client, number << 4,
length, values);
} }
static int rx8025_write_regs(struct i2c_client *client, static int rx8025_check_validity(struct device *dev)
int number, u8 length, u8 *values)
{ {
int ret = i2c_smbus_write_i2c_block_data(client, (number << 4) | 0x08, struct rx8025_data *rx8025 = dev_get_drvdata(dev);
length, values); int ctrl2;
ctrl2 = rx8025_read_reg(rx8025->client, RX8025_REG_CTRL2);
if (ctrl2 < 0)
return ctrl2;
if (ctrl2 & RX8025_BIT_CTRL2_VDET)
dev_warn(dev, "power voltage drop detected\n");
if (ctrl2 & RX8025_BIT_CTRL2_PON) {
dev_warn(dev, "power-on reset detected, date is invalid\n");
return -EINVAL;
}
if (ret) if (!(ctrl2 & RX8025_BIT_CTRL2_XST)) {
dev_err(&client->dev, "Unable to write registers #%d..#%d\n", dev_warn(dev, "crystal stopped, date is invalid\n");
number, number + length - 1); return -EINVAL;
}
return ret; return 0;
} }
static irqreturn_t rx8025_irq(int irq, void *dev_id) static int rx8025_reset_validity(struct i2c_client *client)
{ {
struct i2c_client *client = dev_id; int ctrl2 = rx8025_read_reg(client, RX8025_REG_CTRL2);
struct rx8025_data *rx8025 = i2c_get_clientdata(client);
disable_irq_nosync(irq); if (ctrl2 < 0)
schedule_work(&rx8025->work); return ctrl2;
return IRQ_HANDLED;
ctrl2 &= ~(RX8025_BIT_CTRL2_PON | RX8025_BIT_CTRL2_VDET);
return rx8025_write_reg(client, RX8025_REG_CTRL2,
ctrl2 | RX8025_BIT_CTRL2_XST);
} }
static void rx8025_work(struct work_struct *work) static irqreturn_t rx8025_handle_irq(int irq, void *dev_id)
{ {
struct rx8025_data *rx8025 = container_of(work, struct rx8025_data, struct i2c_client *client = dev_id;
work); struct rx8025_data *rx8025 = i2c_get_clientdata(client);
struct i2c_client *client = rx8025->client; int status;
struct mutex *lock = &rx8025->rtc->ops_lock;
u8 status;
mutex_lock(lock);
if (rx8025_read_reg(client, RX8025_REG_CTRL2, &status)) status = rx8025_read_reg(client, RX8025_REG_CTRL2);
if (status < 0)
goto out; goto out;
if (!(status & RX8025_BIT_CTRL2_XST)) if (!(status & RX8025_BIT_CTRL2_XST))
...@@ -161,9 +159,7 @@ static void rx8025_work(struct work_struct *work) ...@@ -161,9 +159,7 @@ static void rx8025_work(struct work_struct *work)
if (status & RX8025_BIT_CTRL2_CTFG) { if (status & RX8025_BIT_CTRL2_CTFG) {
/* periodic */ /* periodic */
status &= ~RX8025_BIT_CTRL2_CTFG; status &= ~RX8025_BIT_CTRL2_CTFG;
local_irq_disable();
rtc_update_irq(rx8025->rtc, 1, RTC_PF | RTC_IRQF); rtc_update_irq(rx8025->rtc, 1, RTC_PF | RTC_IRQF);
local_irq_enable();
} }
if (status & RX8025_BIT_CTRL2_DAFG) { if (status & RX8025_BIT_CTRL2_DAFG) {
...@@ -172,20 +168,11 @@ static void rx8025_work(struct work_struct *work) ...@@ -172,20 +168,11 @@ static void rx8025_work(struct work_struct *work)
if (rx8025_write_reg(client, RX8025_REG_CTRL1, if (rx8025_write_reg(client, RX8025_REG_CTRL1,
rx8025->ctrl1 & ~RX8025_BIT_CTRL1_DALE)) rx8025->ctrl1 & ~RX8025_BIT_CTRL1_DALE))
goto out; goto out;
local_irq_disable();
rtc_update_irq(rx8025->rtc, 1, RTC_AF | RTC_IRQF); rtc_update_irq(rx8025->rtc, 1, RTC_AF | RTC_IRQF);
local_irq_enable();
} }
/* acknowledge IRQ */
rx8025_write_reg(client, RX8025_REG_CTRL2,
status | RX8025_BIT_CTRL2_XST);
out: out:
if (!rx8025->exiting) return IRQ_HANDLED;
enable_irq(client->irq);
mutex_unlock(lock);
} }
static int rx8025_get_time(struct device *dev, struct rtc_time *dt) static int rx8025_get_time(struct device *dev, struct rtc_time *dt)
...@@ -194,6 +181,10 @@ static int rx8025_get_time(struct device *dev, struct rtc_time *dt) ...@@ -194,6 +181,10 @@ static int rx8025_get_time(struct device *dev, struct rtc_time *dt)
u8 date[7]; u8 date[7];
int err; int err;
err = rx8025_check_validity(dev);
if (err)
return err;
err = rx8025_read_regs(rx8025->client, RX8025_REG_SEC, 7, date); err = rx8025_read_regs(rx8025->client, RX8025_REG_SEC, 7, date);
if (err) if (err)
return err; return err;
...@@ -213,10 +204,7 @@ static int rx8025_get_time(struct device *dev, struct rtc_time *dt) ...@@ -213,10 +204,7 @@ static int rx8025_get_time(struct device *dev, struct rtc_time *dt)
dt->tm_mday = bcd2bin(date[RX8025_REG_MDAY] & 0x3f); dt->tm_mday = bcd2bin(date[RX8025_REG_MDAY] & 0x3f);
dt->tm_mon = bcd2bin(date[RX8025_REG_MONTH] & 0x1f) - 1; dt->tm_mon = bcd2bin(date[RX8025_REG_MONTH] & 0x1f) - 1;
dt->tm_year = bcd2bin(date[RX8025_REG_YEAR]); dt->tm_year = bcd2bin(date[RX8025_REG_YEAR]) + 100;
if (dt->tm_year < 70)
dt->tm_year += 100;
dev_dbg(dev, "%s: date %ds %dm %dh %dmd %dm %dy\n", __func__, dev_dbg(dev, "%s: date %ds %dm %dh %dmd %dm %dy\n", __func__,
dt->tm_sec, dt->tm_min, dt->tm_hour, dt->tm_sec, dt->tm_min, dt->tm_hour,
...@@ -229,12 +217,10 @@ static int rx8025_set_time(struct device *dev, struct rtc_time *dt) ...@@ -229,12 +217,10 @@ static int rx8025_set_time(struct device *dev, struct rtc_time *dt)
{ {
struct rx8025_data *rx8025 = dev_get_drvdata(dev); struct rx8025_data *rx8025 = dev_get_drvdata(dev);
u8 date[7]; u8 date[7];
int ret;
/* if ((dt->tm_year < 100) || (dt->tm_year > 199))
* BUG: The HW assumes every year that is a multiple of 4 to be a leap return -EINVAL;
* year. Next time this is wrong is 2100, which will not be a leap
* year.
*/
/* /*
* Here the read-only bits are written as "0". I'm not sure if that * Here the read-only bits are written as "0". I'm not sure if that
...@@ -251,17 +237,21 @@ static int rx8025_set_time(struct device *dev, struct rtc_time *dt) ...@@ -251,17 +237,21 @@ static int rx8025_set_time(struct device *dev, struct rtc_time *dt)
date[RX8025_REG_WDAY] = bin2bcd(dt->tm_wday); date[RX8025_REG_WDAY] = bin2bcd(dt->tm_wday);
date[RX8025_REG_MDAY] = bin2bcd(dt->tm_mday); date[RX8025_REG_MDAY] = bin2bcd(dt->tm_mday);
date[RX8025_REG_MONTH] = bin2bcd(dt->tm_mon + 1); date[RX8025_REG_MONTH] = bin2bcd(dt->tm_mon + 1);
date[RX8025_REG_YEAR] = bin2bcd(dt->tm_year % 100); date[RX8025_REG_YEAR] = bin2bcd(dt->tm_year - 100);
dev_dbg(dev, dev_dbg(dev,
"%s: write 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n", "%s: write 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
__func__, __func__,
date[0], date[1], date[2], date[3], date[4], date[5], date[6]); date[0], date[1], date[2], date[3], date[4], date[5], date[6]);
return rx8025_write_regs(rx8025->client, RX8025_REG_SEC, 7, date); ret = rx8025_write_regs(rx8025->client, RX8025_REG_SEC, 7, date);
if (ret < 0)
return ret;
return rx8025_reset_validity(rx8025->client);
} }
static int rx8025_init_client(struct i2c_client *client, int *need_reset) static int rx8025_init_client(struct i2c_client *client)
{ {
struct rx8025_data *rx8025 = i2c_get_clientdata(client); struct rx8025_data *rx8025 = i2c_get_clientdata(client);
u8 ctrl[2], ctrl2; u8 ctrl[2], ctrl2;
...@@ -275,38 +265,18 @@ static int rx8025_init_client(struct i2c_client *client, int *need_reset) ...@@ -275,38 +265,18 @@ static int rx8025_init_client(struct i2c_client *client, int *need_reset)
/* Keep test bit zero ! */ /* Keep test bit zero ! */
rx8025->ctrl1 = ctrl[0] & ~RX8025_BIT_CTRL1_TEST; rx8025->ctrl1 = ctrl[0] & ~RX8025_BIT_CTRL1_TEST;
if (ctrl[1] & RX8025_BIT_CTRL2_PON) {
dev_warn(&client->dev, "power-on reset was detected, "
"you may have to readjust the clock\n");
*need_reset = 1;
}
if (ctrl[1] & RX8025_BIT_CTRL2_VDET) {
dev_warn(&client->dev, "a power voltage drop was detected, "
"you may have to readjust the clock\n");
*need_reset = 1;
}
if (!(ctrl[1] & RX8025_BIT_CTRL2_XST)) {
dev_warn(&client->dev, "Oscillation stop was detected,"
"you may have to readjust the clock\n");
*need_reset = 1;
}
if (ctrl[1] & (RX8025_BIT_CTRL2_DAFG | RX8025_BIT_CTRL2_WAFG)) { if (ctrl[1] & (RX8025_BIT_CTRL2_DAFG | RX8025_BIT_CTRL2_WAFG)) {
dev_warn(&client->dev, "Alarm was detected\n"); dev_warn(&client->dev, "Alarm was detected\n");
need_clear = 1; need_clear = 1;
} }
if (!(ctrl[1] & RX8025_BIT_CTRL2_CTFG)) if (ctrl[1] & RX8025_BIT_CTRL2_CTFG)
need_clear = 1; need_clear = 1;
if (*need_reset || need_clear) { if (need_clear) {
ctrl2 = ctrl[0]; ctrl2 = ctrl[1];
ctrl2 &= ~(RX8025_BIT_CTRL2_PON | RX8025_BIT_CTRL2_VDET | ctrl2 &= ~(RX8025_BIT_CTRL2_CTFG | RX8025_BIT_CTRL2_WAFG |
RX8025_BIT_CTRL2_CTFG | RX8025_BIT_CTRL2_WAFG |
RX8025_BIT_CTRL2_DAFG); RX8025_BIT_CTRL2_DAFG);
ctrl2 |= RX8025_BIT_CTRL2_XST;
err = rx8025_write_reg(client, RX8025_REG_CTRL2, ctrl2); err = rx8025_write_reg(client, RX8025_REG_CTRL2, ctrl2);
} }
...@@ -319,8 +289,8 @@ static int rx8025_read_alarm(struct device *dev, struct rtc_wkalrm *t) ...@@ -319,8 +289,8 @@ static int rx8025_read_alarm(struct device *dev, struct rtc_wkalrm *t)
{ {
struct rx8025_data *rx8025 = dev_get_drvdata(dev); struct rx8025_data *rx8025 = dev_get_drvdata(dev);
struct i2c_client *client = rx8025->client; struct i2c_client *client = rx8025->client;
u8 ctrl2, ald[2]; u8 ald[2];
int err; int ctrl2, err;
if (client->irq <= 0) if (client->irq <= 0)
return -EINVAL; return -EINVAL;
...@@ -329,9 +299,9 @@ static int rx8025_read_alarm(struct device *dev, struct rtc_wkalrm *t) ...@@ -329,9 +299,9 @@ static int rx8025_read_alarm(struct device *dev, struct rtc_wkalrm *t)
if (err) if (err)
return err; return err;
err = rx8025_read_reg(client, RX8025_REG_CTRL2, &ctrl2); ctrl2 = rx8025_read_reg(client, RX8025_REG_CTRL2);
if (err) if (ctrl2 < 0)
return err; return ctrl2;
dev_dbg(dev, "%s: read alarm 0x%02x 0x%02x ctrl2 %02x\n", dev_dbg(dev, "%s: read alarm 0x%02x 0x%02x ctrl2 %02x\n",
__func__, ald[0], ald[1], ctrl2); __func__, ald[0], ald[1], ctrl2);
...@@ -452,12 +422,11 @@ static struct rtc_class_ops rx8025_rtc_ops = { ...@@ -452,12 +422,11 @@ static struct rtc_class_ops rx8025_rtc_ops = {
static int rx8025_get_clock_adjust(struct device *dev, int *adj) static int rx8025_get_clock_adjust(struct device *dev, int *adj)
{ {
struct i2c_client *client = to_i2c_client(dev); struct i2c_client *client = to_i2c_client(dev);
u8 digoff; int digoff;
int err;
err = rx8025_read_reg(client, RX8025_REG_DIGOFF, &digoff); digoff = rx8025_read_reg(client, RX8025_REG_DIGOFF);
if (err) if (digoff < 0)
return err; return digoff;
*adj = digoff >= 64 ? digoff - 128 : digoff; *adj = digoff >= 64 ? digoff - 128 : digoff;
if (*adj > 0) if (*adj > 0)
...@@ -539,88 +508,53 @@ static int rx8025_probe(struct i2c_client *client, ...@@ -539,88 +508,53 @@ static int rx8025_probe(struct i2c_client *client,
{ {
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
struct rx8025_data *rx8025; struct rx8025_data *rx8025;
int err, need_reset = 0; int err = 0;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA
| I2C_FUNC_SMBUS_I2C_BLOCK)) { | I2C_FUNC_SMBUS_I2C_BLOCK)) {
dev_err(&adapter->dev, dev_err(&adapter->dev,
"doesn't support required functionality\n"); "doesn't support required functionality\n");
err = -EIO; return -EIO;
goto errout;
} }
rx8025 = devm_kzalloc(&client->dev, sizeof(*rx8025), GFP_KERNEL); rx8025 = devm_kzalloc(&client->dev, sizeof(*rx8025), GFP_KERNEL);
if (!rx8025) { if (!rx8025) {
err = -ENOMEM; return -ENOMEM;
goto errout;
} }
rx8025->client = client; rx8025->client = client;
i2c_set_clientdata(client, rx8025); i2c_set_clientdata(client, rx8025);
INIT_WORK(&rx8025->work, rx8025_work);
err = rx8025_init_client(client, &need_reset); err = rx8025_init_client(client);
if (err) if (err)
goto errout; return err;
if (need_reset) {
struct rtc_time tm;
dev_info(&client->dev,
"bad conditions detected, resetting date\n");
rtc_time_to_tm(0, &tm); /* 1970/1/1 */
rx8025_set_time(&client->dev, &tm);
}
rx8025->rtc = devm_rtc_device_register(&client->dev, client->name, rx8025->rtc = devm_rtc_device_register(&client->dev, client->name,
&rx8025_rtc_ops, THIS_MODULE); &rx8025_rtc_ops, THIS_MODULE);
if (IS_ERR(rx8025->rtc)) { if (IS_ERR(rx8025->rtc)) {
err = PTR_ERR(rx8025->rtc);
dev_err(&client->dev, "unable to register the class device\n"); dev_err(&client->dev, "unable to register the class device\n");
goto errout; return PTR_ERR(rx8025->rtc);
} }
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);
err = request_irq(client->irq, rx8025_irq, err = devm_request_threaded_irq(&client->dev, client->irq, NULL,
0, "rx8025", client); rx8025_handle_irq, 0, "rx8025",
client);
if (err) { if (err) {
dev_err(&client->dev, "unable to request IRQ\n"); dev_err(&client->dev, "unable to request IRQ, alarms disabled\n");
goto errout; client->irq = 0;
} }
} }
rx8025->rtc->irq_freq = 1;
rx8025->rtc->max_user_freq = 1; rx8025->rtc->max_user_freq = 1;
err = rx8025_sysfs_register(&client->dev); err = rx8025_sysfs_register(&client->dev);
if (err)
goto errout_irq;
return 0;
errout_irq:
if (client->irq > 0)
free_irq(client->irq, client);
errout:
dev_err(&adapter->dev, "probing for rx8025 failed\n");
return err; return err;
} }
static int rx8025_remove(struct i2c_client *client) static int rx8025_remove(struct i2c_client *client)
{ {
struct rx8025_data *rx8025 = i2c_get_clientdata(client);
struct mutex *lock = &rx8025->rtc->ops_lock;
if (client->irq > 0) {
mutex_lock(lock);
rx8025->exiting = 1;
mutex_unlock(lock);
free_irq(client->irq, client);
cancel_work_sync(&rx8025->work);
}
rx8025_sysfs_unregister(&client->dev); rx8025_sysfs_unregister(&client->dev);
return 0; return 0;
} }
...@@ -628,7 +562,6 @@ static int rx8025_remove(struct i2c_client *client) ...@@ -628,7 +562,6 @@ static int rx8025_remove(struct i2c_client *client)
static struct i2c_driver rx8025_driver = { static struct i2c_driver rx8025_driver = {
.driver = { .driver = {
.name = "rtc-rx8025", .name = "rtc-rx8025",
.owner = THIS_MODULE,
}, },
.probe = rx8025_probe, .probe = rx8025_probe,
.remove = rx8025_remove, .remove = rx8025_remove,
......
...@@ -315,7 +315,6 @@ MODULE_DEVICE_TABLE(i2c, rx8581_id); ...@@ -315,7 +315,6 @@ MODULE_DEVICE_TABLE(i2c, rx8581_id);
static struct i2c_driver rx8581_driver = { static struct i2c_driver rx8581_driver = {
.driver = { .driver = {
.name = "rtc-rx8581", .name = "rtc-rx8581",
.owner = THIS_MODULE,
}, },
.probe = rx8581_probe, .probe = rx8581_probe,
.id_table = rx8581_id, .id_table = rx8581_id,
......
...@@ -39,6 +39,7 @@ struct s3c_rtc { ...@@ -39,6 +39,7 @@ struct s3c_rtc {
void __iomem *base; void __iomem *base;
struct clk *rtc_clk; struct clk *rtc_clk;
struct clk *rtc_src_clk; struct clk *rtc_src_clk;
bool clk_disabled;
struct s3c_rtc_data *data; struct s3c_rtc_data *data;
...@@ -71,9 +72,12 @@ static void s3c_rtc_enable_clk(struct s3c_rtc *info) ...@@ -71,9 +72,12 @@ static void s3c_rtc_enable_clk(struct s3c_rtc *info)
unsigned long irq_flags; unsigned long irq_flags;
spin_lock_irqsave(&info->alarm_clk_lock, irq_flags); spin_lock_irqsave(&info->alarm_clk_lock, irq_flags);
clk_enable(info->rtc_clk); if (info->clk_disabled) {
if (info->data->needs_src_clk) clk_enable(info->rtc_clk);
clk_enable(info->rtc_src_clk); if (info->data->needs_src_clk)
clk_enable(info->rtc_src_clk);
info->clk_disabled = false;
}
spin_unlock_irqrestore(&info->alarm_clk_lock, irq_flags); spin_unlock_irqrestore(&info->alarm_clk_lock, irq_flags);
} }
...@@ -82,9 +86,12 @@ static void s3c_rtc_disable_clk(struct s3c_rtc *info) ...@@ -82,9 +86,12 @@ static void s3c_rtc_disable_clk(struct s3c_rtc *info)
unsigned long irq_flags; unsigned long irq_flags;
spin_lock_irqsave(&info->alarm_clk_lock, irq_flags); spin_lock_irqsave(&info->alarm_clk_lock, irq_flags);
if (info->data->needs_src_clk) if (!info->clk_disabled) {
clk_disable(info->rtc_src_clk); if (info->data->needs_src_clk)
clk_disable(info->rtc_clk); clk_disable(info->rtc_src_clk);
clk_disable(info->rtc_clk);
info->clk_disabled = true;
}
spin_unlock_irqrestore(&info->alarm_clk_lock, irq_flags); spin_unlock_irqrestore(&info->alarm_clk_lock, irq_flags);
} }
...@@ -128,6 +135,11 @@ static int s3c_rtc_setaie(struct device *dev, unsigned int enabled) ...@@ -128,6 +135,11 @@ static int s3c_rtc_setaie(struct device *dev, unsigned int enabled)
s3c_rtc_disable_clk(info); s3c_rtc_disable_clk(info);
if (enabled)
s3c_rtc_enable_clk(info);
else
s3c_rtc_disable_clk(info);
return 0; return 0;
} }
...@@ -410,8 +422,9 @@ static int s3c_rtc_remove(struct platform_device *pdev) ...@@ -410,8 +422,9 @@ static int s3c_rtc_remove(struct platform_device *pdev)
s3c_rtc_setaie(info->dev, 0); s3c_rtc_setaie(info->dev, 0);
if (info->data->needs_src_clk)
clk_unprepare(info->rtc_src_clk);
clk_unprepare(info->rtc_clk); clk_unprepare(info->rtc_clk);
info->rtc_clk = NULL;
return 0; return 0;
} }
...@@ -482,6 +495,7 @@ static int s3c_rtc_probe(struct platform_device *pdev) ...@@ -482,6 +495,7 @@ static int s3c_rtc_probe(struct platform_device *pdev)
if (IS_ERR(info->rtc_src_clk)) { if (IS_ERR(info->rtc_src_clk)) {
dev_err(&pdev->dev, dev_err(&pdev->dev,
"failed to find rtc source clock\n"); "failed to find rtc source clock\n");
clk_disable_unprepare(info->rtc_clk);
return PTR_ERR(info->rtc_src_clk); return PTR_ERR(info->rtc_src_clk);
} }
clk_prepare_enable(info->rtc_src_clk); clk_prepare_enable(info->rtc_src_clk);
......
...@@ -635,6 +635,16 @@ static int s5m8767_rtc_init_reg(struct s5m_rtc_info *info) ...@@ -635,6 +635,16 @@ static int s5m8767_rtc_init_reg(struct s5m_rtc_info *info)
case S2MPS13X: case S2MPS13X:
data[0] = (0 << BCD_EN_SHIFT) | (1 << MODEL24_SHIFT); data[0] = (0 << BCD_EN_SHIFT) | (1 << MODEL24_SHIFT);
ret = regmap_write(info->regmap, info->regs->ctrl, data[0]); ret = regmap_write(info->regmap, info->regs->ctrl, data[0]);
if (ret < 0)
break;
/*
* Should set WUDR & (RUDR or AUDR) bits to high after writing
* RTC_CTRL register like writing Alarm registers. We can't find
* the description from datasheet but vendor code does that
* really.
*/
ret = s5m8767_rtc_set_alarm_reg(info);
break; break;
default: default:
...@@ -797,6 +807,7 @@ static const struct platform_device_id s5m_rtc_id[] = { ...@@ -797,6 +807,7 @@ static const struct platform_device_id s5m_rtc_id[] = {
{ "s2mps14-rtc", S2MPS14X }, { "s2mps14-rtc", S2MPS14X },
{ }, { },
}; };
MODULE_DEVICE_TABLE(platform, s5m_rtc_id);
static struct platform_driver s5m_rtc_driver = { static struct platform_driver s5m_rtc_driver = {
.driver = { .driver = {
......
...@@ -35,24 +35,17 @@ ...@@ -35,24 +35,17 @@
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/io.h> #include <linux/io.h>
#include <mach/hardware.h> #define RTSR_HZE BIT(3) /* HZ interrupt enable */
#include <mach/irqs.h> #define RTSR_ALE BIT(2) /* RTC alarm interrupt enable */
#define RTSR_HZ BIT(1) /* HZ rising-edge detected */
#define RTSR_AL BIT(0) /* RTC alarm detected */
#if defined(CONFIG_ARCH_PXA) || defined(CONFIG_ARCH_MMP) #include "rtc-sa1100.h"
#include <mach/regs-rtc.h>
#endif
#define RTC_DEF_DIVIDER (32768 - 1) #define RTC_DEF_DIVIDER (32768 - 1)
#define RTC_DEF_TRIM 0 #define RTC_DEF_TRIM 0
#define RTC_FREQ 1024 #define RTC_FREQ 1024
struct sa1100_rtc {
spinlock_t lock;
int irq_1hz;
int irq_alarm;
struct rtc_device *rtc;
struct clk *clk;
};
static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id) static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id)
{ {
...@@ -63,16 +56,16 @@ static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id) ...@@ -63,16 +56,16 @@ static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id)
spin_lock(&info->lock); spin_lock(&info->lock);
rtsr = RTSR; rtsr = readl_relaxed(info->rtsr);
/* clear interrupt sources */ /* clear interrupt sources */
RTSR = 0; writel_relaxed(0, info->rtsr);
/* Fix for a nasty initialization problem the in SA11xx RTSR register. /* Fix for a nasty initialization problem the in SA11xx RTSR register.
* See also the comments in sa1100_rtc_probe(). */ * See also the comments in sa1100_rtc_probe(). */
if (rtsr & (RTSR_ALE | RTSR_HZE)) { if (rtsr & (RTSR_ALE | RTSR_HZE)) {
/* This is the original code, before there was the if test /* This is the original code, before there was the if test
* above. This code does not clear interrupts that were not * above. This code does not clear interrupts that were not
* enabled. */ * enabled. */
RTSR = (RTSR_AL | RTSR_HZ) & (rtsr >> 2); writel_relaxed((RTSR_AL | RTSR_HZ) & (rtsr >> 2), info->rtsr);
} else { } else {
/* For some reason, it is possible to enter this routine /* For some reason, it is possible to enter this routine
* without interruptions enabled, it has been tested with * without interruptions enabled, it has been tested with
...@@ -81,13 +74,13 @@ static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id) ...@@ -81,13 +74,13 @@ static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id)
* This situation leads to an infinite "loop" of interrupt * This situation leads to an infinite "loop" of interrupt
* routine calling and as a result the processor seems to * routine calling and as a result the processor seems to
* lock on its first call to open(). */ * lock on its first call to open(). */
RTSR = RTSR_AL | RTSR_HZ; writel_relaxed(RTSR_AL | RTSR_HZ, info->rtsr);
} }
/* clear alarm interrupt if it has occurred */ /* clear alarm interrupt if it has occurred */
if (rtsr & RTSR_AL) if (rtsr & RTSR_AL)
rtsr &= ~RTSR_ALE; rtsr &= ~RTSR_ALE;
RTSR = rtsr & (RTSR_ALE | RTSR_HZE); writel_relaxed(rtsr & (RTSR_ALE | RTSR_HZE), info->rtsr);
/* update irq data & counter */ /* update irq data & counter */
if (rtsr & RTSR_AL) if (rtsr & RTSR_AL)
...@@ -135,7 +128,7 @@ static void sa1100_rtc_release(struct device *dev) ...@@ -135,7 +128,7 @@ static void sa1100_rtc_release(struct device *dev)
struct sa1100_rtc *info = dev_get_drvdata(dev); struct sa1100_rtc *info = dev_get_drvdata(dev);
spin_lock_irq(&info->lock); spin_lock_irq(&info->lock);
RTSR = 0; writel_relaxed(0, info->rtsr);
spin_unlock_irq(&info->lock); spin_unlock_irq(&info->lock);
free_irq(info->irq_alarm, dev); free_irq(info->irq_alarm, dev);
...@@ -144,39 +137,46 @@ static void sa1100_rtc_release(struct device *dev) ...@@ -144,39 +137,46 @@ static void sa1100_rtc_release(struct device *dev)
static int sa1100_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) static int sa1100_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
{ {
u32 rtsr;
struct sa1100_rtc *info = dev_get_drvdata(dev); struct sa1100_rtc *info = dev_get_drvdata(dev);
spin_lock_irq(&info->lock); spin_lock_irq(&info->lock);
rtsr = readl_relaxed(info->rtsr);
if (enabled) if (enabled)
RTSR |= RTSR_ALE; rtsr |= RTSR_ALE;
else else
RTSR &= ~RTSR_ALE; rtsr &= ~RTSR_ALE;
writel_relaxed(rtsr, info->rtsr);
spin_unlock_irq(&info->lock); spin_unlock_irq(&info->lock);
return 0; return 0;
} }
static int sa1100_rtc_read_time(struct device *dev, struct rtc_time *tm) static int sa1100_rtc_read_time(struct device *dev, struct rtc_time *tm)
{ {
rtc_time_to_tm(RCNR, tm); struct sa1100_rtc *info = dev_get_drvdata(dev);
rtc_time_to_tm(readl_relaxed(info->rcnr), tm);
return 0; return 0;
} }
static int sa1100_rtc_set_time(struct device *dev, struct rtc_time *tm) static int sa1100_rtc_set_time(struct device *dev, struct rtc_time *tm)
{ {
struct sa1100_rtc *info = dev_get_drvdata(dev);
unsigned long time; unsigned long time;
int ret; int ret;
ret = rtc_tm_to_time(tm, &time); ret = rtc_tm_to_time(tm, &time);
if (ret == 0) if (ret == 0)
RCNR = time; writel_relaxed(time, info->rcnr);
return ret; return ret;
} }
static int sa1100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) static int sa1100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{ {
u32 rtsr; u32 rtsr;
struct sa1100_rtc *info = dev_get_drvdata(dev);
rtsr = RTSR; rtsr = readl_relaxed(info->rtsr);
alrm->enabled = (rtsr & RTSR_ALE) ? 1 : 0; alrm->enabled = (rtsr & RTSR_ALE) ? 1 : 0;
alrm->pending = (rtsr & RTSR_AL) ? 1 : 0; alrm->pending = (rtsr & RTSR_AL) ? 1 : 0;
return 0; return 0;
...@@ -192,12 +192,13 @@ static int sa1100_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) ...@@ -192,12 +192,13 @@ static int sa1100_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
ret = rtc_tm_to_time(&alrm->time, &time); ret = rtc_tm_to_time(&alrm->time, &time);
if (ret != 0) if (ret != 0)
goto out; goto out;
RTSR = RTSR & (RTSR_HZE|RTSR_ALE|RTSR_AL); writel_relaxed(readl_relaxed(info->rtsr) &
RTAR = time; (RTSR_HZE | RTSR_ALE | RTSR_AL), info->rtsr);
writel_relaxed(time, info->rtar);
if (alrm->enabled) if (alrm->enabled)
RTSR |= RTSR_ALE; writel_relaxed(readl_relaxed(info->rtsr) | RTSR_ALE, info->rtsr);
else else
RTSR &= ~RTSR_ALE; writel_relaxed(readl_relaxed(info->rtsr) & ~RTSR_ALE, info->rtsr);
out: out:
spin_unlock_irq(&info->lock); spin_unlock_irq(&info->lock);
...@@ -206,8 +207,10 @@ static int sa1100_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) ...@@ -206,8 +207,10 @@ static int sa1100_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
static int sa1100_rtc_proc(struct device *dev, struct seq_file *seq) static int sa1100_rtc_proc(struct device *dev, struct seq_file *seq)
{ {
seq_printf(seq, "trim/divider\t\t: 0x%08x\n", (u32) RTTR); struct sa1100_rtc *info = dev_get_drvdata(dev);
seq_printf(seq, "RTSR\t\t\t: 0x%08x\n", (u32)RTSR);
seq_printf(seq, "trim/divider\t\t: 0x%08x\n", readl_relaxed(info->rttr));
seq_printf(seq, "RTSR\t\t\t: 0x%08x\n", readl_relaxed(info->rtsr));
return 0; return 0;
} }
...@@ -223,29 +226,18 @@ static const struct rtc_class_ops sa1100_rtc_ops = { ...@@ -223,29 +226,18 @@ static const struct rtc_class_ops sa1100_rtc_ops = {
.alarm_irq_enable = sa1100_rtc_alarm_irq_enable, .alarm_irq_enable = sa1100_rtc_alarm_irq_enable,
}; };
static int sa1100_rtc_probe(struct platform_device *pdev) int sa1100_rtc_init(struct platform_device *pdev, struct sa1100_rtc *info)
{ {
struct rtc_device *rtc; struct rtc_device *rtc;
struct sa1100_rtc *info; int ret;
int irq_1hz, irq_alarm, ret = 0;
irq_1hz = platform_get_irq_byname(pdev, "rtc 1Hz"); spin_lock_init(&info->lock);
irq_alarm = platform_get_irq_byname(pdev, "rtc alarm");
if (irq_1hz < 0 || irq_alarm < 0)
return -ENODEV;
info = devm_kzalloc(&pdev->dev, sizeof(struct sa1100_rtc), GFP_KERNEL);
if (!info)
return -ENOMEM;
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)) {
dev_err(&pdev->dev, "failed to find rtc clock source\n"); dev_err(&pdev->dev, "failed to find rtc clock source\n");
return PTR_ERR(info->clk); return PTR_ERR(info->clk);
} }
info->irq_1hz = irq_1hz;
info->irq_alarm = irq_alarm;
spin_lock_init(&info->lock);
platform_set_drvdata(pdev, info);
ret = clk_prepare_enable(info->clk); ret = clk_prepare_enable(info->clk);
if (ret) if (ret)
...@@ -257,22 +249,19 @@ static int sa1100_rtc_probe(struct platform_device *pdev) ...@@ -257,22 +249,19 @@ static int sa1100_rtc_probe(struct platform_device *pdev)
* If the clock divider is uninitialized then reset it to the * If the clock divider is uninitialized then reset it to the
* default value to get the 1Hz clock. * default value to get the 1Hz clock.
*/ */
if (RTTR == 0) { if (readl_relaxed(info->rttr) == 0) {
RTTR = RTC_DEF_DIVIDER + (RTC_DEF_TRIM << 16); writel_relaxed(RTC_DEF_DIVIDER + (RTC_DEF_TRIM << 16), info->rttr);
dev_warn(&pdev->dev, "warning: " dev_warn(&pdev->dev, "warning: "
"initializing default clock divider/trim value\n"); "initializing default clock divider/trim value\n");
/* The current RTC value probably doesn't make sense either */ /* The current RTC value probably doesn't make sense either */
RCNR = 0; writel_relaxed(0, info->rcnr);
} }
device_init_wakeup(&pdev->dev, 1);
rtc = devm_rtc_device_register(&pdev->dev, pdev->name, &sa1100_rtc_ops, rtc = devm_rtc_device_register(&pdev->dev, pdev->name, &sa1100_rtc_ops,
THIS_MODULE); THIS_MODULE);
if (IS_ERR(rtc)) { if (IS_ERR(rtc)) {
ret = PTR_ERR(rtc); clk_disable_unprepare(info->clk);
goto err_dev; return PTR_ERR(rtc);
} }
info->rtc = rtc; info->rtc = rtc;
...@@ -298,12 +287,52 @@ static int sa1100_rtc_probe(struct platform_device *pdev) ...@@ -298,12 +287,52 @@ static int sa1100_rtc_probe(struct platform_device *pdev)
* *
* Notice that clearing bit 1 and 0 is accomplished by writting ONES to * Notice that clearing bit 1 and 0 is accomplished by writting ONES to
* the corresponding bits in RTSR. */ * the corresponding bits in RTSR. */
RTSR = RTSR_AL | RTSR_HZ; writel_relaxed(RTSR_AL | RTSR_HZ, info->rtsr);
return 0; return 0;
err_dev: }
clk_disable_unprepare(info->clk); EXPORT_SYMBOL_GPL(sa1100_rtc_init);
return ret;
static int sa1100_rtc_probe(struct platform_device *pdev)
{
struct sa1100_rtc *info;
struct resource *iores;
void __iomem *base;
int irq_1hz, irq_alarm;
irq_1hz = platform_get_irq_byname(pdev, "rtc 1Hz");
irq_alarm = platform_get_irq_byname(pdev, "rtc alarm");
if (irq_1hz < 0 || irq_alarm < 0)
return -ENODEV;
info = devm_kzalloc(&pdev->dev, sizeof(struct sa1100_rtc), GFP_KERNEL);
if (!info)
return -ENOMEM;
info->irq_1hz = irq_1hz;
info->irq_alarm = irq_alarm;
iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
base = devm_ioremap_resource(&pdev->dev, iores);
if (IS_ERR(base))
return PTR_ERR(base);
if (IS_ENABLED(CONFIG_ARCH_SA1100) ||
of_device_is_compatible(pdev->dev.of_node, "mrvl,sa1100-rtc")) {
info->rcnr = base + 0x04;
info->rtsr = base + 0x10;
info->rtar = base + 0x00;
info->rttr = base + 0x08;
} else {
info->rcnr = base + 0x0;
info->rtsr = base + 0x8;
info->rtar = base + 0x4;
info->rttr = base + 0xc;
}
platform_set_drvdata(pdev, info);
device_init_wakeup(&pdev->dev, 1);
return sa1100_rtc_init(pdev, info);
} }
static int sa1100_rtc_remove(struct platform_device *pdev) static int sa1100_rtc_remove(struct platform_device *pdev)
......
#ifndef __RTC_SA1100_H__
#define __RTC_SA1100_H__
#include <linux/kernel.h>
struct clk;
struct platform_device;
struct sa1100_rtc {
spinlock_t lock;
void __iomem *rcnr;
void __iomem *rtar;
void __iomem *rtsr;
void __iomem *rttr;
int irq_1hz;
int irq_alarm;
struct rtc_device *rtc;
struct clk *clk;
};
int sa1100_rtc_init(struct platform_device *pdev, struct sa1100_rtc *info);
#endif
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/regmap.h>
#include <linux/rtc/sirfsoc_rtciobrg.h> #include <linux/rtc/sirfsoc_rtciobrg.h>
...@@ -48,12 +49,27 @@ struct sirfsoc_rtc_drv { ...@@ -48,12 +49,27 @@ struct sirfsoc_rtc_drv {
/* Overflow for every 8 years extra time */ /* Overflow for every 8 years extra time */
u32 overflow_rtc; u32 overflow_rtc;
spinlock_t lock; spinlock_t lock;
struct regmap *regmap;
#ifdef CONFIG_PM #ifdef CONFIG_PM
u32 saved_counter; u32 saved_counter;
u32 saved_overflow_rtc; u32 saved_overflow_rtc;
#endif #endif
}; };
static u32 sirfsoc_rtc_readl(struct sirfsoc_rtc_drv *rtcdrv, u32 offset)
{
u32 val;
regmap_read(rtcdrv->regmap, rtcdrv->rtc_base + offset, &val);
return val;
}
static void sirfsoc_rtc_writel(struct sirfsoc_rtc_drv *rtcdrv,
u32 offset, u32 val)
{
regmap_write(rtcdrv->regmap, rtcdrv->rtc_base + offset, val);
}
static int sirfsoc_rtc_read_alarm(struct device *dev, static int sirfsoc_rtc_read_alarm(struct device *dev,
struct rtc_wkalrm *alrm) struct rtc_wkalrm *alrm)
{ {
...@@ -64,9 +80,9 @@ static int sirfsoc_rtc_read_alarm(struct device *dev, ...@@ -64,9 +80,9 @@ static int sirfsoc_rtc_read_alarm(struct device *dev,
spin_lock_irq(&rtcdrv->lock); spin_lock_irq(&rtcdrv->lock);
rtc_count = sirfsoc_rtc_iobrg_readl(rtcdrv->rtc_base + RTC_CN); rtc_count = sirfsoc_rtc_readl(rtcdrv, RTC_CN);
rtc_alarm = sirfsoc_rtc_iobrg_readl(rtcdrv->rtc_base + RTC_ALARM0); rtc_alarm = sirfsoc_rtc_readl(rtcdrv, RTC_ALARM0);
memset(alrm, 0, sizeof(struct rtc_wkalrm)); memset(alrm, 0, sizeof(struct rtc_wkalrm));
/* /*
...@@ -82,8 +98,7 @@ static int sirfsoc_rtc_read_alarm(struct device *dev, ...@@ -82,8 +98,7 @@ static int sirfsoc_rtc_read_alarm(struct device *dev,
rtc_time_to_tm(rtcdrv->overflow_rtc rtc_time_to_tm(rtcdrv->overflow_rtc
<< (BITS_PER_LONG - RTC_SHIFT) << (BITS_PER_LONG - RTC_SHIFT)
| rtc_alarm >> RTC_SHIFT, &(alrm->time)); | rtc_alarm >> RTC_SHIFT, &(alrm->time));
if (sirfsoc_rtc_iobrg_readl( if (sirfsoc_rtc_readl(rtcdrv, RTC_STATUS) & SIRFSOC_RTC_AL0E)
rtcdrv->rtc_base + RTC_STATUS) & SIRFSOC_RTC_AL0E)
alrm->enabled = 1; alrm->enabled = 1;
spin_unlock_irq(&rtcdrv->lock); spin_unlock_irq(&rtcdrv->lock);
...@@ -103,8 +118,7 @@ static int sirfsoc_rtc_set_alarm(struct device *dev, ...@@ -103,8 +118,7 @@ static int sirfsoc_rtc_set_alarm(struct device *dev,
spin_lock_irq(&rtcdrv->lock); spin_lock_irq(&rtcdrv->lock);
rtc_status_reg = sirfsoc_rtc_iobrg_readl( rtc_status_reg = sirfsoc_rtc_readl(rtcdrv, RTC_STATUS);
rtcdrv->rtc_base + RTC_STATUS);
if (rtc_status_reg & SIRFSOC_RTC_AL0E) { if (rtc_status_reg & SIRFSOC_RTC_AL0E) {
/* /*
* An ongoing alarm in progress - ingore it and not * An ongoing alarm in progress - ingore it and not
...@@ -113,8 +127,7 @@ static int sirfsoc_rtc_set_alarm(struct device *dev, ...@@ -113,8 +127,7 @@ static int sirfsoc_rtc_set_alarm(struct device *dev,
dev_info(dev, "An old alarm was set, will be replaced by a new one\n"); dev_info(dev, "An old alarm was set, will be replaced by a new one\n");
} }
sirfsoc_rtc_iobrg_writel( sirfsoc_rtc_writel(rtcdrv, RTC_ALARM0, rtc_alarm << RTC_SHIFT);
rtc_alarm << RTC_SHIFT, rtcdrv->rtc_base + RTC_ALARM0);
rtc_status_reg &= ~0x07; /* mask out the lower status bits */ rtc_status_reg &= ~0x07; /* mask out the lower status bits */
/* /*
* This bit RTC_AL sets it as a wake-up source for Sleep Mode * This bit RTC_AL sets it as a wake-up source for Sleep Mode
...@@ -123,8 +136,7 @@ static int sirfsoc_rtc_set_alarm(struct device *dev, ...@@ -123,8 +136,7 @@ static int sirfsoc_rtc_set_alarm(struct device *dev,
rtc_status_reg |= SIRFSOC_RTC_AL0; rtc_status_reg |= SIRFSOC_RTC_AL0;
/* enable the RTC alarm interrupt */ /* enable the RTC alarm interrupt */
rtc_status_reg |= SIRFSOC_RTC_AL0E; rtc_status_reg |= SIRFSOC_RTC_AL0E;
sirfsoc_rtc_iobrg_writel( sirfsoc_rtc_writel(rtcdrv, RTC_STATUS, rtc_status_reg);
rtc_status_reg, rtcdrv->rtc_base + RTC_STATUS);
spin_unlock_irq(&rtcdrv->lock); spin_unlock_irq(&rtcdrv->lock);
} else { } else {
...@@ -135,8 +147,7 @@ static int sirfsoc_rtc_set_alarm(struct device *dev, ...@@ -135,8 +147,7 @@ static int sirfsoc_rtc_set_alarm(struct device *dev,
*/ */
spin_lock_irq(&rtcdrv->lock); spin_lock_irq(&rtcdrv->lock);
rtc_status_reg = sirfsoc_rtc_iobrg_readl( rtc_status_reg = sirfsoc_rtc_readl(rtcdrv, RTC_STATUS);
rtcdrv->rtc_base + RTC_STATUS);
if (rtc_status_reg & SIRFSOC_RTC_AL0E) { if (rtc_status_reg & SIRFSOC_RTC_AL0E) {
/* clear the RTC status register's alarm bit */ /* clear the RTC status register's alarm bit */
rtc_status_reg &= ~0x07; rtc_status_reg &= ~0x07;
...@@ -145,8 +156,8 @@ static int sirfsoc_rtc_set_alarm(struct device *dev, ...@@ -145,8 +156,8 @@ static int sirfsoc_rtc_set_alarm(struct device *dev,
/* Clear the Alarm enable bit */ /* Clear the Alarm enable bit */
rtc_status_reg &= ~(SIRFSOC_RTC_AL0E); rtc_status_reg &= ~(SIRFSOC_RTC_AL0E);
sirfsoc_rtc_iobrg_writel(rtc_status_reg, sirfsoc_rtc_writel(rtcdrv, RTC_STATUS,
rtcdrv->rtc_base + RTC_STATUS); rtc_status_reg);
} }
spin_unlock_irq(&rtcdrv->lock); spin_unlock_irq(&rtcdrv->lock);
...@@ -167,9 +178,9 @@ static int sirfsoc_rtc_read_time(struct device *dev, ...@@ -167,9 +178,9 @@ static int sirfsoc_rtc_read_time(struct device *dev,
* fail, read several times to make sure get stable value. * fail, read several times to make sure get stable value.
*/ */
do { do {
tmp_rtc = sirfsoc_rtc_iobrg_readl(rtcdrv->rtc_base + RTC_CN); tmp_rtc = sirfsoc_rtc_readl(rtcdrv, RTC_CN);
cpu_relax(); cpu_relax();
} while (tmp_rtc != sirfsoc_rtc_iobrg_readl(rtcdrv->rtc_base + RTC_CN)); } while (tmp_rtc != sirfsoc_rtc_readl(rtcdrv, RTC_CN));
rtc_time_to_tm(rtcdrv->overflow_rtc << (BITS_PER_LONG - RTC_SHIFT) | rtc_time_to_tm(rtcdrv->overflow_rtc << (BITS_PER_LONG - RTC_SHIFT) |
tmp_rtc >> RTC_SHIFT, tm); tmp_rtc >> RTC_SHIFT, tm);
...@@ -187,10 +198,8 @@ static int sirfsoc_rtc_set_time(struct device *dev, ...@@ -187,10 +198,8 @@ static int sirfsoc_rtc_set_time(struct device *dev,
rtcdrv->overflow_rtc = rtc_time >> (BITS_PER_LONG - RTC_SHIFT); rtcdrv->overflow_rtc = rtc_time >> (BITS_PER_LONG - RTC_SHIFT);
sirfsoc_rtc_iobrg_writel(rtcdrv->overflow_rtc, sirfsoc_rtc_writel(rtcdrv, RTC_SW_VALUE, rtcdrv->overflow_rtc);
rtcdrv->rtc_base + RTC_SW_VALUE); sirfsoc_rtc_writel(rtcdrv, RTC_CN, rtc_time << RTC_SHIFT);
sirfsoc_rtc_iobrg_writel(
rtc_time << RTC_SHIFT, rtcdrv->rtc_base + RTC_CN);
return 0; return 0;
} }
...@@ -222,14 +231,13 @@ static int sirfsoc_rtc_alarm_irq_enable(struct device *dev, ...@@ -222,14 +231,13 @@ static int sirfsoc_rtc_alarm_irq_enable(struct device *dev,
spin_lock_irq(&rtcdrv->lock); spin_lock_irq(&rtcdrv->lock);
rtc_status_reg = sirfsoc_rtc_iobrg_readl( rtc_status_reg = sirfsoc_rtc_readl(rtcdrv, RTC_STATUS);
rtcdrv->rtc_base + RTC_STATUS);
if (enabled) if (enabled)
rtc_status_reg |= SIRFSOC_RTC_AL0E; rtc_status_reg |= SIRFSOC_RTC_AL0E;
else else
rtc_status_reg &= ~SIRFSOC_RTC_AL0E; rtc_status_reg &= ~SIRFSOC_RTC_AL0E;
sirfsoc_rtc_iobrg_writel(rtc_status_reg, rtcdrv->rtc_base + RTC_STATUS); sirfsoc_rtc_writel(rtcdrv, RTC_STATUS, rtc_status_reg);
spin_unlock_irq(&rtcdrv->lock); spin_unlock_irq(&rtcdrv->lock);
...@@ -254,7 +262,7 @@ static irqreturn_t sirfsoc_rtc_irq_handler(int irq, void *pdata) ...@@ -254,7 +262,7 @@ static irqreturn_t sirfsoc_rtc_irq_handler(int irq, void *pdata)
spin_lock(&rtcdrv->lock); spin_lock(&rtcdrv->lock);
rtc_status_reg = sirfsoc_rtc_iobrg_readl(rtcdrv->rtc_base + RTC_STATUS); rtc_status_reg = sirfsoc_rtc_readl(rtcdrv, RTC_STATUS);
/* this bit will be set ONLY if an alarm was active /* this bit will be set ONLY if an alarm was active
* and it expired NOW * and it expired NOW
* So this is being used as an ASSERT * So this is being used as an ASSERT
...@@ -270,7 +278,8 @@ static irqreturn_t sirfsoc_rtc_irq_handler(int irq, void *pdata) ...@@ -270,7 +278,8 @@ static irqreturn_t sirfsoc_rtc_irq_handler(int irq, void *pdata)
/* Clear the Alarm enable bit */ /* Clear the Alarm enable bit */
rtc_status_reg &= ~(SIRFSOC_RTC_AL0E); rtc_status_reg &= ~(SIRFSOC_RTC_AL0E);
} }
sirfsoc_rtc_iobrg_writel(rtc_status_reg, rtcdrv->rtc_base + RTC_STATUS);
sirfsoc_rtc_writel(rtcdrv, RTC_STATUS, rtc_status_reg);
spin_unlock(&rtcdrv->lock); spin_unlock(&rtcdrv->lock);
...@@ -287,6 +296,13 @@ static const struct of_device_id sirfsoc_rtc_of_match[] = { ...@@ -287,6 +296,13 @@ static const struct of_device_id sirfsoc_rtc_of_match[] = {
{ .compatible = "sirf,prima2-sysrtc"}, { .compatible = "sirf,prima2-sysrtc"},
{}, {},
}; };
const struct regmap_config sysrtc_regmap_config = {
.reg_bits = 32,
.val_bits = 32,
.fast_io = true,
};
MODULE_DEVICE_TABLE(of, sirfsoc_rtc_of_match); MODULE_DEVICE_TABLE(of, sirfsoc_rtc_of_match);
static int sirfsoc_rtc_probe(struct platform_device *pdev) static int sirfsoc_rtc_probe(struct platform_device *pdev)
...@@ -314,27 +330,35 @@ static int sirfsoc_rtc_probe(struct platform_device *pdev) ...@@ -314,27 +330,35 @@ static int sirfsoc_rtc_probe(struct platform_device *pdev)
/* Register rtc alarm as a wakeup source */ /* Register rtc alarm as a wakeup source */
device_init_wakeup(&pdev->dev, 1); device_init_wakeup(&pdev->dev, 1);
rtcdrv->regmap = devm_regmap_init_iobg(&pdev->dev,
&sysrtc_regmap_config);
if (IS_ERR(rtcdrv->regmap)) {
err = PTR_ERR(rtcdrv->regmap);
dev_err(&pdev->dev, "Failed to allocate register map: %d\n",
err);
return err;
}
/* /*
* Set SYS_RTC counter in RTC_HZ HZ Units * Set SYS_RTC counter in RTC_HZ HZ Units
* We are using 32K RTC crystal (32768 / RTC_HZ / 2) -1 * We are using 32K RTC crystal (32768 / RTC_HZ / 2) -1
* If 16HZ, therefore RTC_DIV = 1023; * If 16HZ, therefore RTC_DIV = 1023;
*/ */
rtc_div = ((32768 / RTC_HZ) / 2) - 1; rtc_div = ((32768 / RTC_HZ) / 2) - 1;
sirfsoc_rtc_iobrg_writel(rtc_div, rtcdrv->rtc_base + RTC_DIV); sirfsoc_rtc_writel(rtcdrv, RTC_DIV, rtc_div);
/* 0x3 -> RTC_CLK */ /* 0x3 -> RTC_CLK */
sirfsoc_rtc_iobrg_writel(SIRFSOC_RTC_CLK, sirfsoc_rtc_writel(rtcdrv, RTC_CLOCK_SWITCH, SIRFSOC_RTC_CLK);
rtcdrv->rtc_base + RTC_CLOCK_SWITCH);
/* reset SYS RTC ALARM0 */ /* reset SYS RTC ALARM0 */
sirfsoc_rtc_iobrg_writel(0x0, rtcdrv->rtc_base + RTC_ALARM0); sirfsoc_rtc_writel(rtcdrv, RTC_ALARM0, 0x0);
/* reset SYS RTC ALARM1 */ /* reset SYS RTC ALARM1 */
sirfsoc_rtc_iobrg_writel(0x0, rtcdrv->rtc_base + RTC_ALARM1); sirfsoc_rtc_writel(rtcdrv, RTC_ALARM1, 0x0);
/* Restore RTC Overflow From Register After Command Reboot */ /* Restore RTC Overflow From Register After Command Reboot */
rtcdrv->overflow_rtc = rtcdrv->overflow_rtc =
sirfsoc_rtc_iobrg_readl(rtcdrv->rtc_base + RTC_SW_VALUE); sirfsoc_rtc_readl(rtcdrv, RTC_SW_VALUE);
rtcdrv->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, rtcdrv->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
&sirfsoc_rtc_ops, THIS_MODULE); &sirfsoc_rtc_ops, THIS_MODULE);
...@@ -372,10 +396,10 @@ static int sirfsoc_rtc_suspend(struct device *dev) ...@@ -372,10 +396,10 @@ static int sirfsoc_rtc_suspend(struct device *dev)
{ {
struct sirfsoc_rtc_drv *rtcdrv = dev_get_drvdata(dev); struct sirfsoc_rtc_drv *rtcdrv = dev_get_drvdata(dev);
rtcdrv->overflow_rtc = rtcdrv->overflow_rtc =
sirfsoc_rtc_iobrg_readl(rtcdrv->rtc_base + RTC_SW_VALUE); sirfsoc_rtc_readl(rtcdrv, RTC_SW_VALUE);
rtcdrv->saved_counter = rtcdrv->saved_counter =
sirfsoc_rtc_iobrg_readl(rtcdrv->rtc_base + RTC_CN); sirfsoc_rtc_readl(rtcdrv, RTC_CN);
rtcdrv->saved_overflow_rtc = rtcdrv->overflow_rtc; rtcdrv->saved_overflow_rtc = rtcdrv->overflow_rtc;
if (device_may_wakeup(dev) && !enable_irq_wake(rtcdrv->irq)) if (device_may_wakeup(dev) && !enable_irq_wake(rtcdrv->irq))
rtcdrv->irq_wake = 1; rtcdrv->irq_wake = 1;
...@@ -392,12 +416,10 @@ static int sirfsoc_rtc_resume(struct device *dev) ...@@ -392,12 +416,10 @@ static int sirfsoc_rtc_resume(struct device *dev)
* if resume from snapshot and the rtc power is lost, * if resume from snapshot and the rtc power is lost,
* restroe the rtc settings * restroe the rtc settings
*/ */
if (SIRFSOC_RTC_CLK != sirfsoc_rtc_iobrg_readl( if (SIRFSOC_RTC_CLK != sirfsoc_rtc_readl(rtcdrv, RTC_CLOCK_SWITCH)) {
rtcdrv->rtc_base + RTC_CLOCK_SWITCH)) {
u32 rtc_div; u32 rtc_div;
/* 0x3 -> RTC_CLK */ /* 0x3 -> RTC_CLK */
sirfsoc_rtc_iobrg_writel(SIRFSOC_RTC_CLK, sirfsoc_rtc_writel(rtcdrv, RTC_CLOCK_SWITCH, SIRFSOC_RTC_CLK);
rtcdrv->rtc_base + RTC_CLOCK_SWITCH);
/* /*
* Set SYS_RTC counter in RTC_HZ HZ Units * Set SYS_RTC counter in RTC_HZ HZ Units
* We are using 32K RTC crystal (32768 / RTC_HZ / 2) -1 * We are using 32K RTC crystal (32768 / RTC_HZ / 2) -1
...@@ -405,13 +427,13 @@ static int sirfsoc_rtc_resume(struct device *dev) ...@@ -405,13 +427,13 @@ static int sirfsoc_rtc_resume(struct device *dev)
*/ */
rtc_div = ((32768 / RTC_HZ) / 2) - 1; rtc_div = ((32768 / RTC_HZ) / 2) - 1;
sirfsoc_rtc_iobrg_writel(rtc_div, rtcdrv->rtc_base + RTC_DIV); sirfsoc_rtc_writel(rtcdrv, RTC_DIV, rtc_div);
/* reset SYS RTC ALARM0 */ /* reset SYS RTC ALARM0 */
sirfsoc_rtc_iobrg_writel(0x0, rtcdrv->rtc_base + RTC_ALARM0); sirfsoc_rtc_writel(rtcdrv, RTC_ALARM0, 0x0);
/* reset SYS RTC ALARM1 */ /* reset SYS RTC ALARM1 */
sirfsoc_rtc_iobrg_writel(0x0, rtcdrv->rtc_base + RTC_ALARM1); sirfsoc_rtc_writel(rtcdrv, RTC_ALARM1, 0x0);
} }
rtcdrv->overflow_rtc = rtcdrv->saved_overflow_rtc; rtcdrv->overflow_rtc = rtcdrv->saved_overflow_rtc;
...@@ -419,15 +441,14 @@ static int sirfsoc_rtc_resume(struct device *dev) ...@@ -419,15 +441,14 @@ static int sirfsoc_rtc_resume(struct device *dev)
* if current counter is small than previous, * if current counter is small than previous,
* it means overflow in sleep * it means overflow in sleep
*/ */
tmp = sirfsoc_rtc_iobrg_readl(rtcdrv->rtc_base + RTC_CN); tmp = sirfsoc_rtc_readl(rtcdrv, RTC_CN);
if (tmp <= rtcdrv->saved_counter) if (tmp <= rtcdrv->saved_counter)
rtcdrv->overflow_rtc++; rtcdrv->overflow_rtc++;
/* /*
*PWRC Value Be Changed When Suspend, Restore Overflow *PWRC Value Be Changed When Suspend, Restore Overflow
* In Memory To Register * In Memory To Register
*/ */
sirfsoc_rtc_iobrg_writel(rtcdrv->overflow_rtc, sirfsoc_rtc_writel(rtcdrv, RTC_SW_VALUE, rtcdrv->overflow_rtc);
rtcdrv->rtc_base + RTC_SW_VALUE);
if (device_may_wakeup(dev) && rtcdrv->irq_wake) { if (device_may_wakeup(dev) && rtcdrv->irq_wake) {
disable_irq_wake(rtcdrv->irq); disable_irq_wake(rtcdrv->irq);
......
...@@ -254,7 +254,7 @@ static ssize_t stk17ta8_nvram_read(struct file *filp, struct kobject *kobj, ...@@ -254,7 +254,7 @@ static ssize_t stk17ta8_nvram_read(struct file *filp, struct kobject *kobj,
void __iomem *ioaddr = pdata->ioaddr; void __iomem *ioaddr = pdata->ioaddr;
ssize_t count; ssize_t count;
for (count = 0; size > 0 && pos < RTC_OFFSET; count++, size--) for (count = 0; count < size; count++)
*buf++ = readb(ioaddr + pos++); *buf++ = readb(ioaddr + pos++);
return count; return count;
} }
...@@ -269,7 +269,7 @@ static ssize_t stk17ta8_nvram_write(struct file *filp, struct kobject *kobj, ...@@ -269,7 +269,7 @@ static ssize_t stk17ta8_nvram_write(struct file *filp, struct kobject *kobj,
void __iomem *ioaddr = pdata->ioaddr; void __iomem *ioaddr = pdata->ioaddr;
ssize_t count; ssize_t count;
for (count = 0; size > 0 && pos < RTC_OFFSET; count++, size--) for (count = 0; count < size; count++)
writeb(*buf++, ioaddr + pos++); writeb(*buf++, ioaddr + pos++);
return count; return count;
} }
......
...@@ -122,20 +122,8 @@ hctosys_show(struct device *dev, struct device_attribute *attr, char *buf) ...@@ -122,20 +122,8 @@ hctosys_show(struct device *dev, struct device_attribute *attr, char *buf)
} }
static DEVICE_ATTR_RO(hctosys); static DEVICE_ATTR_RO(hctosys);
static struct attribute *rtc_attrs[] = {
&dev_attr_name.attr,
&dev_attr_date.attr,
&dev_attr_time.attr,
&dev_attr_since_epoch.attr,
&dev_attr_max_user_freq.attr,
&dev_attr_hctosys.attr,
NULL,
};
ATTRIBUTE_GROUPS(rtc);
static ssize_t static ssize_t
rtc_sysfs_show_wakealarm(struct device *dev, struct device_attribute *attr, wakealarm_show(struct device *dev, struct device_attribute *attr, char *buf)
char *buf)
{ {
ssize_t retval; ssize_t retval;
unsigned long alarm; unsigned long alarm;
...@@ -159,7 +147,7 @@ rtc_sysfs_show_wakealarm(struct device *dev, struct device_attribute *attr, ...@@ -159,7 +147,7 @@ rtc_sysfs_show_wakealarm(struct device *dev, struct device_attribute *attr,
} }
static ssize_t static ssize_t
rtc_sysfs_set_wakealarm(struct device *dev, struct device_attribute *attr, wakealarm_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t n) const char *buf, size_t n)
{ {
ssize_t retval; ssize_t retval;
...@@ -221,45 +209,57 @@ rtc_sysfs_set_wakealarm(struct device *dev, struct device_attribute *attr, ...@@ -221,45 +209,57 @@ rtc_sysfs_set_wakealarm(struct device *dev, struct device_attribute *attr,
retval = rtc_set_alarm(rtc, &alm); retval = rtc_set_alarm(rtc, &alm);
return (retval < 0) ? retval : n; return (retval < 0) ? retval : n;
} }
static DEVICE_ATTR(wakealarm, S_IRUGO | S_IWUSR, static DEVICE_ATTR_RW(wakealarm);
rtc_sysfs_show_wakealarm, rtc_sysfs_set_wakealarm);
static struct attribute *rtc_attrs[] = {
&dev_attr_name.attr,
&dev_attr_date.attr,
&dev_attr_time.attr,
&dev_attr_since_epoch.attr,
&dev_attr_max_user_freq.attr,
&dev_attr_hctosys.attr,
&dev_attr_wakealarm.attr,
NULL,
};
/* The reason to trigger an alarm with no process watching it (via sysfs) /* The reason to trigger an alarm with no process watching it (via sysfs)
* is its side effect: waking from a system state like suspend-to-RAM or * is its side effect: waking from a system state like suspend-to-RAM or
* suspend-to-disk. So: no attribute unless that side effect is possible. * suspend-to-disk. So: no attribute unless that side effect is possible.
* (Userspace may disable that mechanism later.) * (Userspace may disable that mechanism later.)
*/ */
static inline int rtc_does_wakealarm(struct rtc_device *rtc) static bool rtc_does_wakealarm(struct rtc_device *rtc)
{ {
if (!device_can_wakeup(rtc->dev.parent)) if (!device_can_wakeup(rtc->dev.parent))
return 0; return false;
return rtc->ops->set_alarm != NULL; return rtc->ops->set_alarm != NULL;
} }
static umode_t rtc_attr_is_visible(struct kobject *kobj,
void rtc_sysfs_add_device(struct rtc_device *rtc) struct attribute *attr, int n)
{ {
int err; struct device *dev = container_of(kobj, struct device, kobj);
struct rtc_device *rtc = to_rtc_device(dev);
umode_t mode = attr->mode;
/* not all RTCs support both alarms and wakeup */ if (attr == &dev_attr_wakealarm.attr)
if (!rtc_does_wakealarm(rtc)) if (!rtc_does_wakealarm(rtc))
return; mode = 0;
err = device_create_file(&rtc->dev, &dev_attr_wakealarm); return mode;
if (err)
dev_err(rtc->dev.parent,
"failed to create alarm attribute, %d\n", err);
} }
void rtc_sysfs_del_device(struct rtc_device *rtc) static struct attribute_group rtc_attr_group = {
{ .is_visible = rtc_attr_is_visible,
/* REVISIT did we add it successfully? */ .attrs = rtc_attrs,
if (rtc_does_wakealarm(rtc)) };
device_remove_file(&rtc->dev, &dev_attr_wakealarm);
} static const struct attribute_group *rtc_attr_groups[] = {
&rtc_attr_group,
NULL
};
void __init rtc_sysfs_init(struct class *rtc_class) const struct attribute_group **rtc_get_dev_attribute_groups(void)
{ {
rtc_class->dev_groups = rtc_groups; return rtc_attr_groups;
} }
...@@ -199,8 +199,7 @@ static ssize_t tx4939_rtc_nvram_read(struct file *filp, struct kobject *kobj, ...@@ -199,8 +199,7 @@ static ssize_t tx4939_rtc_nvram_read(struct file *filp, struct kobject *kobj,
ssize_t count; ssize_t count;
spin_lock_irq(&pdata->lock); spin_lock_irq(&pdata->lock);
for (count = 0; size > 0 && pos < TX4939_RTC_REG_RAMSIZE; for (count = 0; count < size; count++) {
count++, size--) {
__raw_writel(pos++, &rtcreg->adr); __raw_writel(pos++, &rtcreg->adr);
*buf++ = __raw_readl(&rtcreg->dat); *buf++ = __raw_readl(&rtcreg->dat);
} }
...@@ -218,8 +217,7 @@ static ssize_t tx4939_rtc_nvram_write(struct file *filp, struct kobject *kobj, ...@@ -218,8 +217,7 @@ static ssize_t tx4939_rtc_nvram_write(struct file *filp, struct kobject *kobj,
ssize_t count; ssize_t count;
spin_lock_irq(&pdata->lock); spin_lock_irq(&pdata->lock);
for (count = 0; size > 0 && pos < TX4939_RTC_REG_RAMSIZE; for (count = 0; count < size; count++) {
count++, size--) {
__raw_writel(pos++, &rtcreg->adr); __raw_writel(pos++, &rtcreg->adr);
__raw_writel(*buf++, &rtcreg->dat); __raw_writel(*buf++, &rtcreg->dat);
} }
......
...@@ -271,6 +271,7 @@ static const struct of_device_id wmt_dt_ids[] = { ...@@ -271,6 +271,7 @@ static const struct of_device_id wmt_dt_ids[] = {
{ .compatible = "via,vt8500-rtc", }, { .compatible = "via,vt8500-rtc", },
{} {}
}; };
MODULE_DEVICE_TABLE(of, wmt_dt_ids);
static struct platform_driver vt8500_rtc_driver = { static struct platform_driver vt8500_rtc_driver = {
.probe = vt8500_rtc_probe, .probe = vt8500_rtc_probe,
......
/*
* Xilinx Zynq Ultrascale+ MPSoC Real Time Clock Driver
*
* Copyright (C) 2015 Xilinx, Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/rtc.h>
/* RTC Registers */
#define RTC_SET_TM_WR 0x00
#define RTC_SET_TM_RD 0x04
#define RTC_CALIB_WR 0x08
#define RTC_CALIB_RD 0x0C
#define RTC_CUR_TM 0x10
#define RTC_CUR_TICK 0x14
#define RTC_ALRM 0x18
#define RTC_INT_STS 0x20
#define RTC_INT_MASK 0x24
#define RTC_INT_EN 0x28
#define RTC_INT_DIS 0x2C
#define RTC_CTRL 0x40
#define RTC_FR_EN BIT(20)
#define RTC_FR_DATSHIFT 16
#define RTC_TICK_MASK 0xFFFF
#define RTC_INT_SEC BIT(0)
#define RTC_INT_ALRM BIT(1)
#define RTC_OSC_EN BIT(24)
#define RTC_CALIB_DEF 0x198233
#define RTC_CALIB_MASK 0x1FFFFF
#define RTC_SEC_MAX_VAL 0xFFFFFFFF
struct xlnx_rtc_dev {
struct rtc_device *rtc;
void __iomem *reg_base;
int alarm_irq;
int sec_irq;
};
static int xlnx_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
struct xlnx_rtc_dev *xrtcdev = dev_get_drvdata(dev);
unsigned long new_time;
new_time = rtc_tm_to_time64(tm);
if (new_time > RTC_SEC_MAX_VAL)
return -EINVAL;
writel(new_time, xrtcdev->reg_base + RTC_SET_TM_WR);
return 0;
}
static int xlnx_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
struct xlnx_rtc_dev *xrtcdev = dev_get_drvdata(dev);
rtc_time64_to_tm(readl(xrtcdev->reg_base + RTC_CUR_TM), tm);
return rtc_valid_tm(tm);
}
static int xlnx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
struct xlnx_rtc_dev *xrtcdev = dev_get_drvdata(dev);
rtc_time64_to_tm(readl(xrtcdev->reg_base + RTC_ALRM), &alrm->time);
alrm->enabled = readl(xrtcdev->reg_base + RTC_INT_MASK) & RTC_INT_ALRM;
return 0;
}
static int xlnx_rtc_alarm_irq_enable(struct device *dev, u32 enabled)
{
struct xlnx_rtc_dev *xrtcdev = dev_get_drvdata(dev);
if (enabled)
writel(RTC_INT_ALRM, xrtcdev->reg_base + RTC_INT_EN);
else
writel(RTC_INT_ALRM, xrtcdev->reg_base + RTC_INT_DIS);
return 0;
}
static int xlnx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
struct xlnx_rtc_dev *xrtcdev = dev_get_drvdata(dev);
unsigned long alarm_time;
alarm_time = rtc_tm_to_time64(&alrm->time);
if (alarm_time > RTC_SEC_MAX_VAL)
return -EINVAL;
writel((u32)alarm_time, (xrtcdev->reg_base + RTC_ALRM));
xlnx_rtc_alarm_irq_enable(dev, alrm->enabled);
return 0;
}
static void xlnx_init_rtc(struct xlnx_rtc_dev *xrtcdev, u32 calibval)
{
/*
* Based on crystal freq of 33.330 KHz
* set the seconds counter and enable, set fractions counter
* to default value suggested as per design spec
* to correct RTC delay in frequency over period of time.
*/
calibval &= RTC_CALIB_MASK;
writel(calibval, (xrtcdev->reg_base + RTC_CALIB_WR));
}
static const struct rtc_class_ops xlnx_rtc_ops = {
.set_time = xlnx_rtc_set_time,
.read_time = xlnx_rtc_read_time,
.read_alarm = xlnx_rtc_read_alarm,
.set_alarm = xlnx_rtc_set_alarm,
.alarm_irq_enable = xlnx_rtc_alarm_irq_enable,
};
static irqreturn_t xlnx_rtc_interrupt(int irq, void *id)
{
struct xlnx_rtc_dev *xrtcdev = (struct xlnx_rtc_dev *)id;
unsigned int status;
status = readl(xrtcdev->reg_base + RTC_INT_STS);
/* Check if interrupt asserted */
if (!(status & (RTC_INT_SEC | RTC_INT_ALRM)))
return IRQ_NONE;
/* Clear interrupt */
writel(status, xrtcdev->reg_base + RTC_INT_STS);
if (status & RTC_INT_SEC)
rtc_update_irq(xrtcdev->rtc, 1, RTC_IRQF | RTC_UF);
if (status & RTC_INT_ALRM)
rtc_update_irq(xrtcdev->rtc, 1, RTC_IRQF | RTC_AF);
return IRQ_HANDLED;
}
static int xlnx_rtc_probe(struct platform_device *pdev)
{
struct xlnx_rtc_dev *xrtcdev;
struct resource *res;
int ret;
unsigned int calibvalue;
xrtcdev = devm_kzalloc(&pdev->dev, sizeof(*xrtcdev), GFP_KERNEL);
if (!xrtcdev)
return -ENOMEM;
platform_set_drvdata(pdev, xrtcdev);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
xrtcdev->reg_base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(xrtcdev->reg_base))
return PTR_ERR(xrtcdev->reg_base);
xrtcdev->alarm_irq = platform_get_irq_byname(pdev, "alarm");
if (xrtcdev->alarm_irq < 0) {
dev_err(&pdev->dev, "no irq resource\n");
return xrtcdev->alarm_irq;
}
ret = devm_request_irq(&pdev->dev, xrtcdev->alarm_irq,
xlnx_rtc_interrupt, 0,
dev_name(&pdev->dev), xrtcdev);
if (ret) {
dev_err(&pdev->dev, "request irq failed\n");
return ret;
}
xrtcdev->sec_irq = platform_get_irq_byname(pdev, "sec");
if (xrtcdev->sec_irq < 0) {
dev_err(&pdev->dev, "no irq resource\n");
return xrtcdev->sec_irq;
}
ret = devm_request_irq(&pdev->dev, xrtcdev->sec_irq,
xlnx_rtc_interrupt, 0,
dev_name(&pdev->dev), xrtcdev);
if (ret) {
dev_err(&pdev->dev, "request irq failed\n");
return ret;
}
ret = of_property_read_u32(pdev->dev.of_node, "calibration",
&calibvalue);
if (ret)
calibvalue = RTC_CALIB_DEF;
xlnx_init_rtc(xrtcdev, calibvalue);
device_init_wakeup(&pdev->dev, 1);
xrtcdev->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
&xlnx_rtc_ops, THIS_MODULE);
return PTR_ERR_OR_ZERO(xrtcdev->rtc);
}
static int xlnx_rtc_remove(struct platform_device *pdev)
{
xlnx_rtc_alarm_irq_enable(&pdev->dev, 0);
device_init_wakeup(&pdev->dev, 0);
return 0;
}
static int __maybe_unused xlnx_rtc_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct xlnx_rtc_dev *xrtcdev = platform_get_drvdata(pdev);
if (device_may_wakeup(&pdev->dev))
enable_irq_wake(xrtcdev->alarm_irq);
else
xlnx_rtc_alarm_irq_enable(dev, 0);
return 0;
}
static int __maybe_unused xlnx_rtc_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct xlnx_rtc_dev *xrtcdev = platform_get_drvdata(pdev);
if (device_may_wakeup(&pdev->dev))
disable_irq_wake(xrtcdev->alarm_irq);
else
xlnx_rtc_alarm_irq_enable(dev, 1);
return 0;
}
static SIMPLE_DEV_PM_OPS(xlnx_rtc_pm_ops, xlnx_rtc_suspend, xlnx_rtc_resume);
static const struct of_device_id xlnx_rtc_of_match[] = {
{.compatible = "xlnx,zynqmp-rtc" },
{ }
};
MODULE_DEVICE_TABLE(of, xlnx_rtc_of_match);
static struct platform_driver xlnx_rtc_driver = {
.probe = xlnx_rtc_probe,
.remove = xlnx_rtc_remove,
.driver = {
.name = KBUILD_MODNAME,
.pm = &xlnx_rtc_pm_ops,
.of_match_table = xlnx_rtc_of_match,
},
};
module_platform_driver(xlnx_rtc_driver);
MODULE_DESCRIPTION("Xilinx Zynq MPSoC RTC driver");
MODULE_AUTHOR("Xilinx Inc.");
MODULE_LICENSE("GPL v2");
...@@ -16,6 +16,9 @@ ...@@ -16,6 +16,9 @@
#include <linux/rtc.h> #include <linux/rtc.h>
#include <linux/bcd.h> #include <linux/bcd.h>
#include <linux/delay.h> #include <linux/delay.h>
#ifdef CONFIG_ACPI
#include <linux/acpi.h>
#endif
#define RTC_PIE 0x40 /* periodic interrupt enable */ #define RTC_PIE 0x40 /* periodic interrupt enable */
#define RTC_AIE 0x20 /* alarm interrupt enable */ #define RTC_AIE 0x20 /* alarm interrupt enable */
...@@ -46,6 +49,7 @@ static inline unsigned int __get_rtc_time(struct rtc_time *time) ...@@ -46,6 +49,7 @@ static inline unsigned int __get_rtc_time(struct rtc_time *time)
{ {
unsigned char ctrl; unsigned char ctrl;
unsigned long flags; unsigned long flags;
unsigned char century = 0;
#ifdef CONFIG_MACH_DECSTATION #ifdef CONFIG_MACH_DECSTATION
unsigned int real_year; unsigned int real_year;
...@@ -78,6 +82,11 @@ static inline unsigned int __get_rtc_time(struct rtc_time *time) ...@@ -78,6 +82,11 @@ static inline unsigned int __get_rtc_time(struct rtc_time *time)
time->tm_year = CMOS_READ(RTC_YEAR); time->tm_year = CMOS_READ(RTC_YEAR);
#ifdef CONFIG_MACH_DECSTATION #ifdef CONFIG_MACH_DECSTATION
real_year = CMOS_READ(RTC_DEC_YEAR); real_year = CMOS_READ(RTC_DEC_YEAR);
#endif
#ifdef CONFIG_ACPI
if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID &&
acpi_gbl_FADT.century)
century = CMOS_READ(acpi_gbl_FADT.century);
#endif #endif
ctrl = CMOS_READ(RTC_CONTROL); ctrl = CMOS_READ(RTC_CONTROL);
spin_unlock_irqrestore(&rtc_lock, flags); spin_unlock_irqrestore(&rtc_lock, flags);
...@@ -90,12 +99,16 @@ static inline unsigned int __get_rtc_time(struct rtc_time *time) ...@@ -90,12 +99,16 @@ static inline unsigned int __get_rtc_time(struct rtc_time *time)
time->tm_mday = bcd2bin(time->tm_mday); time->tm_mday = bcd2bin(time->tm_mday);
time->tm_mon = bcd2bin(time->tm_mon); time->tm_mon = bcd2bin(time->tm_mon);
time->tm_year = bcd2bin(time->tm_year); time->tm_year = bcd2bin(time->tm_year);
century = bcd2bin(century);
} }
#ifdef CONFIG_MACH_DECSTATION #ifdef CONFIG_MACH_DECSTATION
time->tm_year += real_year - 72; time->tm_year += real_year - 72;
#endif #endif
if (century)
time->tm_year += (century - 19) * 100;
/* /*
* Account for differences between how the RTC uses the values * Account for differences between how the RTC uses the values
* and how they are defined in a struct rtc_time; * and how they are defined in a struct rtc_time;
...@@ -122,6 +135,7 @@ static inline int __set_rtc_time(struct rtc_time *time) ...@@ -122,6 +135,7 @@ static inline int __set_rtc_time(struct rtc_time *time)
#ifdef CONFIG_MACH_DECSTATION #ifdef CONFIG_MACH_DECSTATION
unsigned int real_yrs, leap_yr; unsigned int real_yrs, leap_yr;
#endif #endif
unsigned char century = 0;
yrs = time->tm_year; yrs = time->tm_year;
mon = time->tm_mon + 1; /* tm_mon starts at zero */ mon = time->tm_mon + 1; /* tm_mon starts at zero */
...@@ -150,6 +164,15 @@ static inline int __set_rtc_time(struct rtc_time *time) ...@@ -150,6 +164,15 @@ static inline int __set_rtc_time(struct rtc_time *time)
yrs = 73; yrs = 73;
} }
#endif #endif
#ifdef CONFIG_ACPI
if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID &&
acpi_gbl_FADT.century) {
century = (yrs + 1900) / 100;
yrs %= 100;
}
#endif
/* These limits and adjustments are independent of /* These limits and adjustments are independent of
* whether the chip is in binary mode or not. * whether the chip is in binary mode or not.
*/ */
...@@ -169,6 +192,7 @@ static inline int __set_rtc_time(struct rtc_time *time) ...@@ -169,6 +192,7 @@ static inline int __set_rtc_time(struct rtc_time *time)
day = bin2bcd(day); day = bin2bcd(day);
mon = bin2bcd(mon); mon = bin2bcd(mon);
yrs = bin2bcd(yrs); yrs = bin2bcd(yrs);
century = bin2bcd(century);
} }
save_control = CMOS_READ(RTC_CONTROL); save_control = CMOS_READ(RTC_CONTROL);
...@@ -185,6 +209,11 @@ static inline int __set_rtc_time(struct rtc_time *time) ...@@ -185,6 +209,11 @@ static inline int __set_rtc_time(struct rtc_time *time)
CMOS_WRITE(hrs, RTC_HOURS); CMOS_WRITE(hrs, RTC_HOURS);
CMOS_WRITE(min, RTC_MINUTES); CMOS_WRITE(min, RTC_MINUTES);
CMOS_WRITE(sec, RTC_SECONDS); CMOS_WRITE(sec, RTC_SECONDS);
#ifdef CONFIG_ACPI
if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID &&
acpi_gbl_FADT.century)
CMOS_WRITE(century, acpi_gbl_FADT.century);
#endif
CMOS_WRITE(save_control, RTC_CONTROL); CMOS_WRITE(save_control, RTC_CONTROL);
CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment