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
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQIcBAABCAAGBQJV7ARpAAoJEKbNnwlvZCyzo40P/09fca3C9HBEI5hgJO7PmQX8
 +3wkacMjEi58yMTzWoDCFh2H1Vvajm1d6bJ6H//5/3h/KPKrjIsCTFlMfuv8gfbe
 xFoeXPMdiojjPxFjbjnpM+0GD9SKTIjwpP4d8HgoUDwGRJ6dxaTOVuJXRmVGcmas
 e4Ih6hDy2YBiRXLzLHSvSNcTJDGznwMvEEg1AfqUjAtNm4BUzhUnvq0CYlSdwMzy
 xK6w0LmOr67l2QpjiQNCvIn04OWdDQ35f0GcRHYEY66cZPkvPp3OCC/UbeChU6uK
 He/v1n+QdBTbkKYeYmNnBSr42KPTLONNaOFXf79PpAz/WtiYxLxJDbf8DYW9gGQj
 mC3rMNWXf4rEFHkHYH4KvbvxplYd6/pCByMFJa76pKtcE2FG7pVAQZgLaLGemct4
 q0MW73n7yBR1wDlTHqqKu1pAnz1CW3Eui96mDJJptG3CtNqe9a8G48Yzy5OuYAcI
 wxBWCbxeT2z+EuePOBGlQvPreyqyTjHXL87NqMEDrzFrdQd02rn90xqIPlCbcr/P
 qyRwIrDGFyV8PX9I4ewrtt9WfgttayHgZ4juaSi9F479oT6006z6vArrTg2Q/saA
 b0X+hG8oLGSZuSobASjjCtjTE+jYhr+4hzGuHJw0ky0CzLQOqf1APMKDwLN4m5Pz
 Ex+JKalozL+LElGMCS3q
 =cKuu
 -----END PGP SIGNATURE-----

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
  ...
This commit is contained in:
Linus Torvalds 2015-09-08 15:46:31 -07:00
Родитель 12f03ee606 5f1b2f7764
Коммит c19176154b
82 изменённых файлов: 1763 добавлений и 940 удалений

Просмотреть файл

@ -0,0 +1,21 @@
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:
Optional properties:
- system-power-controller: whether the rtc is controlling the system power
through pmic_power_en
- clocks: Any internal or external clocks feeding in to rtc
- clock-names: Corresponding names of the clocks
Example:
@ -26,4 +28,6 @@ rtc@1c23000 {
19>;
interrupt-parent = <&intc>;
system-power-controller;
clocks = <&clk_32k_rtc>, <&clk_32768_ck>;
clock-names = "ext-clk", "int-clk";
};

Просмотреть файл

@ -0,0 +1,25 @@
* 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 @@
interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH
GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "rtc";
clocks = <&clk_32768_ck>;
clock-names = "int-clk";
status = "disabled";
};

Просмотреть файл

@ -112,6 +112,13 @@
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 {
compatible = "simple-audio-card";
simple-audio-card,name = "AM437x-GP-EVM";
@ -941,3 +948,9 @@
tx-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 @@
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 {
@ -394,6 +401,8 @@
};
&rtc {
clocks = <&clk_32k_rtc>, <&clk_32768_ck>;
clock-names = "ext-clk", "int-clk";
status = "okay";
};

Просмотреть файл

@ -24,6 +24,13 @@
display0 = &lcd0;
};
/* fixed 32k external oscillator clock */
clk_32k_rtc: clk_32k_rtc {
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <32768>;
};
backlight {
compatible = "pwm-backlight";
pwms = <&ecap0 0 50000 PWM_POLARITY_INVERTED>;
@ -697,6 +704,8 @@
};
&rtc {
clocks = <&clk_32k_rtc>, <&clk_32768_ck>;
clock-names = "ext-clk", "int-clk";
status = "okay";
};

Просмотреть файл

@ -157,7 +157,7 @@ CONFIG_LEDS_TRIGGERS=y
CONFIG_LEDS_TRIGGER_HEARTBEAT=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_V3020=y
CONFIG_RTC_DRV_SA1100=y
CONFIG_RTC_DRV_PXA=y
CONFIG_EXT2_FS=y
CONFIG_EXT3_FS=y
CONFIG_INOTIFY=y

Просмотреть файл

@ -157,7 +157,7 @@ CONFIG_LEDS_TRIGGERS=y
CONFIG_LEDS_TRIGGER_HEARTBEAT=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_V3020=y
CONFIG_RTC_DRV_SA1100=y
CONFIG_RTC_DRV_PXA=y
CONFIG_EXT2_FS=y
CONFIG_EXT3_FS=y
CONFIG_INOTIFY=y

Просмотреть файл

@ -150,7 +150,7 @@ CONFIG_LEDS_TRIGGERS=y
CONFIG_LEDS_TRIGGER_BACKLIGHT=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_DEBUG=y
CONFIG_RTC_DRV_SA1100=y
CONFIG_RTC_DRV_PXA=y
CONFIG_EXT2_FS=y
CONFIG_INOTIFY=y
CONFIG_MSDOS_FS=m

Просмотреть файл

@ -67,7 +67,7 @@ CONFIG_MMC=y
CONFIG_MMC_DEBUG=y
CONFIG_MMC_PXA=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_SA1100=y
CONFIG_RTC_DRV_PXA=y
CONFIG_EXT2_FS=y
CONFIG_EXT3_FS=y
# CONFIG_DNOTIFY is not set

Просмотреть файл

@ -82,7 +82,7 @@ CONFIG_MMC=y
CONFIG_MMC_PXA=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_PCF8563=m
CONFIG_RTC_DRV_SA1100=m
CONFIG_RTC_DRV_PXA=m
CONFIG_EXT2_FS=m
CONFIG_EXT3_FS=m
# CONFIG_DNOTIFY is not set

Просмотреть файл

@ -177,7 +177,7 @@ CONFIG_NEW_LEDS=y
CONFIG_RTC_CLASS=y
# CONFIG_RTC_HCTOSYS is not set
CONFIG_RTC_DRV_PCF8583=m
CONFIG_RTC_DRV_SA1100=y
CONFIG_RTC_DRV_PXA=y
CONFIG_EXT2_FS=y
CONFIG_EXT2_FS_XATTR=y
CONFIG_EXT2_FS_POSIX_ACL=y

Просмотреть файл

@ -1,23 +0,0 @@
#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 = {
.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 = {
.name = "sa1100-rtc",
.id = -1,
.num_resources = ARRAY_SIZE(sa1100_rtc_resources),
.resource = sa1100_rtc_resources,
.num_resources = ARRAY_SIZE(pxa_rtc_resources),
.resource = pxa_rtc_resources,
};
static struct resource pxa_ac97_resources[] = {

Просмотреть файл

@ -282,7 +282,6 @@ static struct platform_device *devices[] __initdata = {
&pxa_device_asoc_ssp2,
&pxa_device_asoc_ssp3,
&pxa_device_asoc_platform,
&sa1100_device_rtc,
&pxa_device_rtc,
&pxa27x_device_ssp1,
&pxa27x_device_ssp2,

Просмотреть файл

@ -394,7 +394,6 @@ static struct platform_device *devices[] __initdata = {
&pxa_device_asoc_ssp3,
&pxa_device_asoc_ssp4,
&pxa_device_asoc_platform,
&sa1100_device_rtc,
&pxa_device_rtc,
&pxa3xx_device_ssp1,
&pxa3xx_device_ssp2,

Просмотреть файл

@ -857,40 +857,6 @@
#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
*

Просмотреть файл

@ -945,11 +945,11 @@ config RTC_DRV_DA9055
will be called rtc-da9055
config RTC_DRV_DA9063
tristate "Dialog Semiconductor DA9063 RTC"
depends on MFD_DA9063
tristate "Dialog Semiconductor DA9063/DA9062 RTC"
depends on MFD_DA9063 || MFD_DA9062
help
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
will be called "rtc-da9063".
@ -1116,6 +1116,13 @@ config RTC_DRV_OPAL
This driver can also be built as a module. If so, the module
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"
config RTC_DRV_DAVINCI
@ -1306,11 +1313,13 @@ config RTC_DRV_GENERIC
just say Y.
config RTC_DRV_PXA
tristate "PXA27x/PXA3xx"
depends on ARCH_PXA
help
If you say Y here you will get access to the real time clock
built into your PXA27x or PXA3xx CPU.
tristate "PXA27x/PXA3xx"
depends on ARCH_PXA
select RTC_DRV_SA1100
help
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
series (RDxR, RYxR) instead of legacy RCNR, RTAR.
@ -1456,6 +1465,18 @@ config RTC_DRV_JZ4740
This driver can also be buillt as a module. If so, the module
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
depends on ARCH_LPC32XX
tristate "NXP LPC32XX RTC"

Просмотреть файл

@ -74,6 +74,7 @@ obj-$(CONFIG_RTC_DRV_ISL12057) += rtc-isl12057.o
obj-$(CONFIG_RTC_DRV_ISL1208) += rtc-isl1208.o
obj-$(CONFIG_RTC_DRV_JZ4740) += rtc-jz4740.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_LOONGSON1) += rtc-ls1x.o
obj-$(CONFIG_RTC_DRV_M41T80) += rtc-m41t80.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_X1205) += rtc-x1205.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,
rtc->max_user_freq = 64;
rtc->dev.parent = dev;
rtc->dev.class = rtc_class;
rtc->dev.groups = rtc_get_dev_attribute_groups();
rtc->dev.release = rtc_device_release;
mutex_init(&rtc->ops_lock);
@ -234,12 +235,12 @@ struct rtc_device *rtc_device_register(const char *name, struct device *dev,
err = device_register(&rtc->dev);
if (err) {
/* This will free both memory and the ID */
put_device(&rtc->dev);
goto exit_kfree;
goto exit;
}
rtc_dev_add_device(rtc);
rtc_sysfs_add_device(rtc);
rtc_proc_add_device(rtc);
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,
return rtc;
exit_kfree:
kfree(rtc);
exit_ida:
ida_simple_remove(&rtc_ida, id);
@ -268,19 +266,17 @@ EXPORT_SYMBOL_GPL(rtc_device_register);
*/
void rtc_device_unregister(struct rtc_device *rtc)
{
if (get_device(&rtc->dev) != NULL) {
mutex_lock(&rtc->ops_lock);
/* remove innards of this RTC, then disable it, before
* letting any rtc_class_open() users access it again
*/
rtc_sysfs_del_device(rtc);
rtc_dev_del_device(rtc);
rtc_proc_del_device(rtc);
device_unregister(&rtc->dev);
rtc->ops = NULL;
mutex_unlock(&rtc->ops_lock);
put_device(&rtc->dev);
}
mutex_lock(&rtc->ops_lock);
/*
* Remove innards of this RTC, then disable it, before
* letting any rtc_class_open() users access it again
*/
rtc_dev_del_device(rtc);
rtc_proc_del_device(rtc);
device_del(&rtc->dev);
rtc->ops = NULL;
mutex_unlock(&rtc->ops_lock);
put_device(&rtc->dev);
}
EXPORT_SYMBOL_GPL(rtc_device_unregister);
@ -363,7 +359,6 @@ static int __init rtc_init(void)
}
rtc_class->pm = RTC_CLASS_DEV_PM_OPS;
rtc_dev_init();
rtc_sysfs_init(rtc_class);
return 0;
}

Просмотреть файл

@ -564,7 +564,7 @@ enum hrtimer_restart rtc_pie_update_irq(struct hrtimer *timer)
void rtc_update_irq(struct rtc_device *rtc,
unsigned long num, unsigned long events)
{
if (unlikely(IS_ERR_OR_NULL(rtc)))
if (IS_ERR_OR_NULL(rtc))
return;
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);
static int pm80x_rtc_probe(struct platform_device *pdev)
{
struct pm80x_chip *chip = dev_get_drvdata(pdev->dev.parent);
struct pm80x_platform_data *pm80x_pdata =
dev_get_platdata(pdev->dev.parent);
struct pm80x_rtc_pdata *pdata = NULL;
struct pm80x_rtc_pdata *pdata = dev_get_platdata(&pdev->dev);
struct pm80x_rtc_info *info;
struct device_node *node = pdev->dev.of_node;
struct rtc_time tm;
unsigned long ticks = 0;
int ret;
pdata = dev_get_platdata(&pdev->dev);
if (pdata == NULL)
dev_warn(&pdev->dev, "No platform data!\n");
if (!pdata && !node) {
dev_err(&pdev->dev,
"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 =
devm_kzalloc(&pdev->dev, sizeof(struct pm80x_rtc_info), GFP_KERNEL);
@ -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,
PM800_RTC1_USE_XO);
if (pm80x_pdata) {
pdata = pm80x_pdata->rtc;
if (pdata)
info->rtc_dev->dev.platform_data = &pdata->rtc_wakeup;
}
/* remember whether this power up is caused by PMIC RTC or not */
info->rtc_dev->dev.platform_data = &pdata->rtc_wakeup;
device_init_wakeup(&pdev->dev, 1);

Просмотреть файл

@ -1009,6 +1009,7 @@ static const struct of_device_id abb5zes3_dt_match[] = {
{ .compatible = "abracon,abb5zes3" },
{ },
};
MODULE_DEVICE_TABLE(of, abb5zes3_dt_match);
#endif
static const struct i2c_device_id abb5zes3_id[] = {
@ -1020,7 +1021,6 @@ MODULE_DEVICE_TABLE(i2c, abb5zes3_id);
static struct i2c_driver abb5zes3_driver = {
.driver = {
.name = DRV_NAME,
.owner = THIS_MODULE,
.pm = &abb5zes3_rtc_pm_ops,
.of_match_table = of_match_ptr(abb5zes3_dt_match),
},

Просмотреть файл

@ -445,7 +445,9 @@ static const struct rtc_class_ops ab8540_rtc_ops = {
static const struct platform_device_id ab85xx_rtc_ids[] = {
{ "ab8500-rtc", (kernel_ulong_t)&ab8500_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)
{

Просмотреть файл

@ -28,7 +28,7 @@
#define ABX8XX_REG_WD 0x07
#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_REG_CFG_KEY 0x1f

Просмотреть файл

@ -40,13 +40,6 @@ struct armada38x_rtc {
void __iomem *regs;
void __iomem *regs_soc;
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;
};
@ -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)
{
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);
/*
* 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)
if ((time_check - time) > 1)
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);
@ -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);
int ret = 0;
unsigned long time;
unsigned long time, flags;
ret = rtc_tm_to_time(tm, &time);
if (ret)
goto out;
/*
* Setting the RTC time not always succeeds. According to the
* errata we need to first write on the status register and
* then wait for 100ms before writing to the time register to be
* sure that the data will be taken into account.
* According to errata FE-3124064, Write to RTC TIME register
* may fail. As a workaround, after writing to RTC TIME
* register, issue a dummy write of 0x0 twice to RTC Status
* register.
*/
mutex_lock(&rtc->mutex_time);
rtc_delayed_write(0, rtc, RTC_STATUS);
msleep(100);
spin_lock_irqsave(&rtc->lock, flags);
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:
return ret;
@ -229,7 +222,6 @@ static __init int armada38x_rtc_probe(struct platform_device *pdev)
return -ENOMEM;
spin_lock_init(&rtc->lock);
mutex_init(&rtc->mutex_time);
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rtc");
rtc->regs = devm_ioremap_resource(&pdev->dev, res);
@ -303,6 +295,7 @@ static const struct of_device_id armada38x_rtc_of_match_table[] = {
{ .compatible = "marvell,armada-380-rtc", },
{}
};
MODULE_DEVICE_TABLE(of, armada38x_rtc_of_match_table);
#endif
static struct platform_driver armada38x_rtc_driver = {

Просмотреть файл

@ -45,7 +45,7 @@ static void as3722_time_to_reg(u8 *rbuff, struct rtc_time *tm)
rbuff[1] = bin2bcd(tm->tm_min);
rbuff[2] = bin2bcd(tm->tm_hour);
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));
}
@ -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_hour = bcd2bin(rbuff[2] & 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);
return;
}

Просмотреть файл

@ -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/interrupt.h>
#include <linux/spinlock.h>
#include <linux/ioctl.h>
#include <linux/clk.h>
#include <linux/completion.h>
#include <linux/interrupt.h>
#include <linux/ioctl.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.h>
#include <linux/platform_device.h>
#include <linux/rtc.h>
#include <linux/spinlock.h>
#include <linux/suspend.h>
#include <linux/time.h>
#include <linux/uaccess.h>
#include "rtc-at91rm9200.h"
@ -59,6 +60,7 @@ static bool suspended;
static DEFINE_SPINLOCK(suspended_lock);
static unsigned long cached_events;
static u32 at91_rtc_imr;
static struct clk *sclk;
static void at91_rtc_write_ier(u32 mask)
{
@ -407,6 +409,16 @@ static int __init at91_rtc_probe(struct platform_device *pdev)
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_MR, 0); /* 24 hour mode */
@ -420,7 +432,7 @@ static int __init at91_rtc_probe(struct platform_device *pdev)
"at91_rtc", pdev);
if (ret) {
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
@ -431,8 +443,10 @@ static int __init at91_rtc_probe(struct platform_device *pdev)
rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
&at91_rtc_ops, THIS_MODULE);
if (IS_ERR(rtc))
return PTR_ERR(rtc);
if (IS_ERR(rtc)) {
ret = PTR_ERR(rtc);
goto err_clk;
}
platform_set_drvdata(pdev, rtc);
/* 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)
dev_info(&pdev->dev, "AT91 Real Time Clock driver.\n");
return 0;
err_clk:
clk_disable_unprepare(sclk);
return ret;
}
/*
@ -454,6 +473,8 @@ static int __exit at91_rtc_remove(struct platform_device *pdev)
AT91_RTC_SECEV | AT91_RTC_TIMEV |
AT91_RTC_CALEV);
clk_disable_unprepare(sclk);
return 0;
}

Просмотреть файл

@ -11,20 +11,20 @@
* 2 of the License, or (at your option) any later version.
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/time.h>
#include <linux/rtc.h>
#include <linux/clk.h>
#include <linux/interrupt.h>
#include <linux/ioctl.h>
#include <linux/slab.h>
#include <linux/platform_data/atmel.h>
#include <linux/io.h>
#include <linux/kernel.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/rtc.h>
#include <linux/slab.h>
#include <linux/suspend.h>
#include <linux/clk.h>
#include <linux/time.h>
/*
* This driver uses two configurable hardware resources that live in the
@ -425,18 +425,19 @@ static int at91_rtc_probe(struct platform_device *pdev)
if (IS_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);
if (ret) {
dev_err(&pdev->dev, "Could not enable slow clock\n");
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);
/* unless RTT is counting at 1 Hz, re-initialize it */
@ -451,8 +452,10 @@ static int at91_rtc_probe(struct platform_device *pdev)
rtc->rtcdev = devm_rtc_device_register(&pdev->dev, pdev->name,
&at91_rtc_ops, THIS_MODULE);
if (IS_ERR(rtc->rtcdev))
return PTR_ERR(rtc->rtcdev);
if (IS_ERR(rtc->rtcdev)) {
ret = PTR_ERR(rtc->rtcdev);
goto err_clk;
}
/* register irq handler after we know what name we'll use */
ret = devm_request_irq(&pdev->dev, rtc->irq, at91_rtc_interrupt,
@ -460,7 +463,7 @@ static int at91_rtc_probe(struct platform_device *pdev)
dev_name(&rtc->rtcdev->dev), rtc);
if (ret) {
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
@ -474,6 +477,11 @@ static int at91_rtc_probe(struct platform_device *pdev)
dev_name(&rtc->rtcdev->dev));
return 0;
err_clk:
clk_disable_unprepare(rtc->sclk);
return ret;
}
/*
@ -487,8 +495,7 @@ static int at91_rtc_remove(struct platform_device *pdev)
/* disable all interrupts */
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;
}

Просмотреть файл

@ -361,7 +361,7 @@ static int bfin_rtc_probe(struct platform_device *pdev)
/* Register our RTC with the RTC framework */
rtc->rtc_dev = devm_rtc_device_register(dev, pdev->name, &bfin_rtc_ops,
THIS_MODULE);
if (unlikely(IS_ERR(rtc->rtc_dev)))
if (IS_ERR(rtc->rtc_dev))
return PTR_ERR(rtc->rtc_dev);
/* Grab the IRQ and init the hardware */

Просмотреть файл

@ -212,7 +212,7 @@ static int bq32k_probe(struct i2c_client *client,
if (error)
return error;
if (client && client->dev.of_node)
if (client->dev.of_node)
trickle_charger_of_init(dev, client->dev.of_node);
rtc = devm_rtc_device_register(&client->dev, bq32k_driver.driver.name,
@ -234,7 +234,6 @@ MODULE_DEVICE_TABLE(i2c, bq32k_id);
static struct i2c_driver bq32k_driver = {
.driver = {
.name = "bq32k",
.owner = THIS_MODULE,
},
.probe = bq32k_probe,
.id_table = bq32k_id,

Просмотреть файл

@ -41,7 +41,6 @@
#include <linux/pm.h>
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/dmi.h>
/* this is for "generic access to PC-style RTC" using CMOS_READ/CMOS_WRITE */
#include <asm-generic/rtc.h>
@ -51,6 +50,7 @@ struct cmos_rtc {
struct device *dev;
int irq;
struct resource *iomem;
time64_t alarm_expires;
void (*wake_on)(struct device *);
void (*wake_off)(struct device *);
@ -377,53 +377,11 @@ static int cmos_set_alarm(struct device *dev, struct rtc_wkalrm *t)
spin_unlock_irq(&rtc_lock);
cmos->alarm_expires = rtc_tm_to_time64(&t->time);
return 0;
}
/*
* 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;
}
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)
{
struct cmos_rtc *cmos = dev_get_drvdata(dev);
@ -432,9 +390,6 @@ static int cmos_alarm_irq_enable(struct device *dev, unsigned int enabled)
if (!is_valid_irq(cmos->irq))
return -EINVAL;
if (alarm_disable_quirk)
return 0;
spin_lock_irqsave(&rtc_lock, flags);
if (enabled)
@ -512,13 +467,6 @@ cmos_nvram_read(struct file *filp, struct kobject *kobj,
{
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;
spin_lock_irq(&rtc_lock);
for (retval = 0; count; count--, off++, retval++) {
@ -543,12 +491,6 @@ cmos_nvram_write(struct file *filp, struct kobject *kobj,
int retval;
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
* checksum on part of the NVRAM data. That's currently ignored
@ -860,6 +802,51 @@ static void __exit cmos_do_remove(struct device *dev)
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
static int cmos_suspend(struct device *dev)
@ -1094,8 +1081,12 @@ static void cmos_pnp_shutdown(struct pnp_dev *pnp)
struct device *dev = &pnp->dev;
struct cmos_rtc *cmos = dev_get_drvdata(dev);
if (system_state == SYSTEM_POWER_OFF && !cmos_poweroff(dev))
return;
if (system_state == SYSTEM_POWER_OFF) {
int retval = cmos_poweroff(dev);
if (cmos_aie_poweroff(dev) < 0 && !retval)
return;
}
cmos_do_shutdown(cmos->irq);
}
@ -1200,8 +1191,12 @@ static void cmos_platform_shutdown(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct cmos_rtc *cmos = dev_get_drvdata(dev);
if (system_state == SYSTEM_POWER_OFF && !cmos_poweroff(dev))
return;
if (system_state == SYSTEM_POWER_OFF) {
int retval = cmos_poweroff(dev);
if (cmos_aie_poweroff(dev) < 0 && !retval)
return;
}
cmos_do_shutdown(cmos->irq);
}
@ -1243,8 +1238,6 @@ static int __init cmos_init(void)
platform_driver_registered = true;
}
dmi_check_system(rtc_quirks);
if (retval == 0)
return 0;

Просмотреть файл

@ -263,6 +263,7 @@ static const struct of_device_id coh901331_dt_match[] = {
{ .compatible = "stericsson,coh901331" },
{},
};
MODULE_DEVICE_TABLE(of, coh901331_dt_match);
static struct platform_driver coh901331_driver = {
.driver = {

Просмотреть файл

@ -48,23 +48,10 @@ static inline void rtc_proc_del_device(struct rtc_device *rtc)
#endif
#ifdef CONFIG_RTC_INTF_SYSFS
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);
const struct attribute_group **rtc_get_dev_attribute_groups(void);
#else
static inline void rtc_sysfs_init(struct class *rtc)
static inline const struct attribute_group **rtc_get_dev_attribute_groups(void)
{
return NULL;
}
static inline void rtc_sysfs_add_device(struct rtc_device *rtc)
{
}
static inline void rtc_sysfs_del_device(struct rtc_device *rtc)
{
}
#endif

Просмотреть файл

@ -12,15 +12,18 @@
* 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/module.h>
#include <linux/init.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/regmap.h>
#include <linux/rtc.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/core.h>
@ -29,99 +32,231 @@
#define YEARS_FROM_DA9063(year) ((year) + 100)
#define MONTHS_FROM_DA9063(month) ((month) - 1)
#define RTC_ALARM_DATA_LEN (DA9063_AD_REG_ALARM_Y - DA9063_AD_REG_ALARM_MI + 1)
#define RTC_DATA_LEN (DA9063_REG_COUNT_Y - DA9063_REG_COUNT_S + 1)
#define RTC_SEC 0
#define RTC_MIN 1
#define RTC_HOUR 2
#define RTC_DAY 3
#define RTC_MONTH 4
#define RTC_YEAR 5
struct da9063_rtc {
struct rtc_device *rtc_dev;
struct da9063 *hw;
struct rtc_time alarm_time;
bool rtc_sync;
int alarm_year;
int alarm_start;
int alarm_len;
int data_start;
enum {
RTC_SEC = 0,
RTC_MIN = 1,
RTC_HOUR = 2,
RTC_DAY = 3,
RTC_MONTH = 4,
RTC_YEAR = 5,
RTC_DATA_LEN
};
static void da9063_data_to_tm(u8 *data, struct rtc_time *tm)
struct da9063_compatible_rtc_regmap {
/* REGS */
int rtc_enable_reg;
int rtc_enable_32k_crystal_reg;
int rtc_alarm_secs_reg;
int rtc_alarm_year_reg;
int rtc_count_secs_reg;
int rtc_count_year_reg;
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,
struct da9063_compatible_rtc *rtc)
{
tm->tm_sec = data[RTC_SEC] & DA9063_COUNT_SEC_MASK;
tm->tm_min = data[RTC_MIN] & DA9063_COUNT_MIN_MASK;
tm->tm_hour = data[RTC_HOUR] & DA9063_COUNT_HOUR_MASK;
tm->tm_mday = data[RTC_DAY] & DA9063_COUNT_DAY_MASK;
const struct da9063_compatible_rtc_regmap *config = rtc->config;
tm->tm_sec = data[RTC_SEC] & config->rtc_count_sec_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] &
DA9063_COUNT_MONTH_MASK);
config->rtc_count_month_mask);
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;
data[RTC_SEC] |= tm->tm_sec & DA9063_COUNT_SEC_MASK;
const struct da9063_compatible_rtc_regmap *config = rtc->config;
data[RTC_MIN] &= ~DA9063_COUNT_MIN_MASK;
data[RTC_MIN] |= tm->tm_min & DA9063_COUNT_MIN_MASK;
data[RTC_SEC] &= ~config->rtc_count_sec_mask;
data[RTC_SEC] |= tm->tm_sec & config->rtc_count_sec_mask;
data[RTC_HOUR] &= ~DA9063_COUNT_HOUR_MASK;
data[RTC_HOUR] |= tm->tm_hour & DA9063_COUNT_HOUR_MASK;
data[RTC_MIN] &= ~config->rtc_count_min_mask;
data[RTC_MIN] |= tm->tm_min & config->rtc_count_min_mask;
data[RTC_DAY] &= ~DA9063_COUNT_DAY_MASK;
data[RTC_DAY] |= tm->tm_mday & DA9063_COUNT_DAY_MASK;
data[RTC_HOUR] &= ~config->rtc_count_hour_mask;
data[RTC_HOUR] |= tm->tm_hour & config->rtc_count_hour_mask;
data[RTC_MONTH] &= ~DA9063_COUNT_MONTH_MASK;
data[RTC_DAY] &= ~config->rtc_count_day_mask;
data[RTC_DAY] |= tm->tm_mday & config->rtc_count_day_mask;
data[RTC_MONTH] &= ~config->rtc_count_month_mask;
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) &
DA9063_COUNT_YEAR_MASK;
config->rtc_count_year_mask;
}
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,
DA9063_ALARM_ON, 0);
return regmap_update_bits(rtc->regmap,
config->rtc_alarm_year_reg,
config->rtc_alarm_on_mask,
0);
}
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,
DA9063_ALARM_ON, DA9063_ALARM_ON);
return regmap_update_bits(rtc->regmap,
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)
{
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 al_secs;
u8 data[RTC_DATA_LEN];
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);
if (ret < 0) {
dev_err(dev, "Failed to read RTC time data: %d\n", 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");
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(&rtc->alarm_time, &al_secs);
@ -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)
{
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];
int ret;
da9063_tm_to_data(tm, data);
ret = regmap_bulk_write(rtc->hw->regmap, DA9063_REG_COUNT_S,
da9063_tm_to_data(tm, data, rtc);
ret = regmap_bulk_write(rtc->regmap,
config->rtc_count_secs_reg,
data, RTC_DATA_LEN);
if (ret < 0)
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)
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];
int ret;
unsigned int val;
data[RTC_SEC] = 0;
ret = regmap_bulk_read(rtc->hw->regmap, rtc->alarm_start,
&data[rtc->data_start], rtc->alarm_len);
ret = regmap_bulk_read(rtc->regmap,
config->rtc_alarm_secs_reg,
&data[config->rtc_data_start],
config->rtc_alarm_len);
if (ret < 0)
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)
return ret;
if (val & (DA9063_E_ALARM))
if (val & config->rtc_event_alarm_mask)
alrm->pending = 1;
else
alrm->pending = 0;
@ -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)
{
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];
int ret;
da9063_tm_to_data(&alrm->time, data);
da9063_tm_to_data(&alrm->time, data, rtc);
ret = da9063_rtc_stop_alarm(dev);
if (ret < 0) {
@ -193,14 +336,16 @@ static int da9063_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
return ret;
}
ret = regmap_bulk_write(rtc->hw->regmap, rtc->alarm_start,
&data[rtc->data_start], rtc->alarm_len);
ret = regmap_bulk_write(rtc->regmap,
config->rtc_alarm_secs_reg,
&data[config->rtc_data_start],
config->rtc_alarm_len);
if (ret < 0) {
dev_err(dev, "Failed to write alarm: %d\n", ret);
return ret;
}
da9063_data_to_tm(data, &rtc->alarm_time);
da9063_data_to_tm(data, &rtc->alarm_time, rtc);
if (alrm->enabled) {
ret = da9063_rtc_start_alarm(dev);
@ -213,7 +358,8 @@ static int da9063_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
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)
return da9063_rtc_start_alarm(dev);
@ -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)
{
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,
DA9063_ALARM_ON, 0);
regmap_update_bits(rtc->regmap,
config->rtc_alarm_year_reg,
config->rtc_alarm_on_mask,
0);
rtc->rtc_sync = true;
rtc_update_irq(rtc->rtc_dev, 1, RTC_IRQF | RTC_AF);
@ -244,72 +393,92 @@ static const struct rtc_class_ops da9063_rtc_ops = {
static int da9063_rtc_probe(struct platform_device *pdev)
{
struct da9063 *da9063 = dev_get_drvdata(pdev->dev.parent);
struct da9063_rtc *rtc;
struct da9063_compatible_rtc *rtc;
const struct da9063_compatible_rtc_regmap *config;
const struct of_device_id *match;
int irq_alarm;
u8 data[RTC_DATA_LEN];
int ret;
ret = regmap_update_bits(da9063->regmap, DA9063_REG_CONTROL_E,
DA9063_RTC_EN, DA9063_RTC_EN);
if (ret < 0) {
dev_err(&pdev->dev, "Failed to enable RTC\n");
goto err;
}
if (!pdev->dev.of_node)
return -ENXIO;
ret = regmap_update_bits(da9063->regmap, DA9063_REG_EN_32K,
DA9063_CRYSTAL, DA9063_CRYSTAL);
if (ret < 0) {
dev_err(&pdev->dev, "Failed to run 32kHz oscillator\n");
goto err;
}
match = of_match_node(da9063_compatible_reg_id_table,
pdev->dev.of_node);
rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL);
if (!rtc)
return -ENOMEM;
if (da9063->variant_code == PMIC_DA9063_AD) {
rtc->alarm_year = DA9063_AD_REG_ALARM_Y;
rtc->alarm_start = DA9063_AD_REG_ALARM_MI;
rtc->alarm_len = RTC_ALARM_DATA_LEN;
rtc->data_start = RTC_MIN;
} else {
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;
rtc->config = match->data;
if (of_device_is_compatible(pdev->dev.of_node, "dlg,da9063-rtc")) {
struct da9063 *chip = dev_get_drvdata(pdev->dev.parent);
if (chip->variant_code == PMIC_DA9063_AD)
rtc->config = &da9063_ad_regs;
}
ret = regmap_update_bits(da9063->regmap, rtc->alarm_start,
DA9063_ALARM_STATUS_TICK | DA9063_ALARM_STATUS_ALARM,
0);
rtc->regmap = dev_get_regmap(pdev->dev.parent, NULL);
if (!rtc->regmap) {
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) {
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);
if (ret < 0) {
dev_err(&pdev->dev, "Failed to access RTC alarm register\n");
goto err;
return ret;
}
ret = regmap_update_bits(da9063->regmap, rtc->alarm_year,
DA9063_TICK_ON, 0);
ret = regmap_update_bits(rtc->regmap,
config->rtc_alarm_year_reg,
config->rtc_tick_on_mask,
0);
if (ret < 0) {
dev_err(&pdev->dev, "Failed to disable TICKs\n");
goto err;
return ret;
}
data[RTC_SEC] = 0;
ret = regmap_bulk_read(da9063->regmap, rtc->alarm_start,
&data[rtc->data_start], rtc->alarm_len);
ret = regmap_bulk_read(rtc->regmap,
config->rtc_alarm_secs_reg,
&data[config->rtc_data_start],
config->rtc_alarm_len);
if (ret < 0) {
dev_err(&pdev->dev, "Failed to read initial alarm data: %d\n",
ret);
goto err;
return ret;
}
platform_set_drvdata(pdev, rtc);
@ -322,18 +491,16 @@ static int da9063_rtc_probe(struct platform_device *pdev)
if (ret) {
dev_err(&pdev->dev, "Failed to request ALARM IRQ %d: %d\n",
irq_alarm, ret);
goto err;
return ret;
}
rtc->hw = da9063;
rtc->rtc_dev = devm_rtc_device_register(&pdev->dev, DA9063_DRVNAME_RTC,
&da9063_rtc_ops, THIS_MODULE);
if (IS_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;
err:
return ret;
}
@ -341,6 +508,7 @@ static struct platform_driver da9063_rtc_driver = {
.probe = da9063_rtc_probe,
.driver = {
.name = DA9063_DRVNAME_RTC,
.of_match_table = da9063_compatible_reg_id_table,
},
};

Просмотреть файл

@ -477,6 +477,7 @@ void rtc_dev_prepare(struct rtc_device *rtc)
cdev_init(&rtc->char_dev, &rtc_dev_fops);
rtc->char_dev.owner = rtc->owner;
rtc->char_dev.kobj.parent = &rtc->dev.kobj;
}
void rtc_dev_add_device(struct rtc_device *rtc)

Просмотреть файл

@ -538,15 +538,6 @@ ds1305_nvram_read(struct file *filp, struct kobject *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;
msg_init(&m, x, &addr, count, NULL, buf);
@ -569,15 +560,6 @@ ds1305_nvram_write(struct file *filp, struct kobject *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;
msg_init(&m, x, &addr, count, buf, NULL);

Просмотреть файл

@ -11,14 +11,17 @@
* published by the Free Software Foundation.
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/string.h>
#include <linux/rtc.h>
#include <linux/bcd.h>
#include <linux/i2c.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/string.h>
/*
* We can't determine type by probing, but if we expect pre-Linux code
@ -114,7 +117,7 @@ struct ds1307 {
#define HAS_ALARM 1 /* bit 1 == irq claimed */
struct i2c_client *client;
struct rtc_device *rtc;
struct work_struct work;
int wakeirq;
s32 (*read_block_data)(const struct i2c_client *client, u8 command,
u8 length, u8 *values);
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,
/*----------------------------------------------------------------------*/
/*
* 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
* one (with a "seconds" field). For ds1337 we expect nINTA is our alarm
* 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;
struct mutex *lock;
struct i2c_client *client = dev_id;
struct ds1307 *ds1307 = i2c_get_clientdata(client);
struct mutex *lock = &ds1307->rtc->ops_lock;
int stat, control;
ds1307 = container_of(work, struct ds1307, work);
client = ds1307->client;
lock = &ds1307->rtc->ops_lock;
mutex_lock(lock);
stat = i2c_smbus_read_byte_data(client, DS1337_REG_STATUS);
if (stat < 0)
@ -352,18 +345,8 @@ static void ds1307_work(struct work_struct *work)
}
out:
if (test_bit(HAS_ALARM, &ds1307->flags))
enable_irq(client->irq);
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;
}
@ -634,13 +617,14 @@ static const struct rtc_class_ops ds13xx_rtc_ops = {
MCP794XX_BIT_ALMX_C1 | \
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 = ds1307->client;
struct i2c_client *client = dev_id;
struct ds1307 *ds1307 = i2c_get_clientdata(client);
struct mutex *lock = &ds1307->rtc->ops_lock;
int reg, ret;
mutex_lock(&ds1307->rtc->ops_lock);
mutex_lock(lock);
/* Check and clear alarm 0 interrupt flag. */
reg = i2c_smbus_read_byte_data(client, MCP794XX_REG_ALARM0_CTRL);
@ -665,9 +649,9 @@ static void mcp794xx_work(struct work_struct *work)
rtc_update_irq(ds1307->rtc, 1, RTC_AF | RTC_IRQF);
out:
if (test_bit(HAS_ALARM, &ds1307->flags))
enable_irq(client->irq);
mutex_unlock(&ds1307->rtc->ops_lock);
mutex_unlock(lock);
return IRQ_HANDLED;
}
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,
client = kobj_to_i2c_client(kobj);
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,
count, buf);
if (result < 0)
@ -824,13 +801,6 @@ ds1307_nvram_write(struct file *filp, struct kobject *kobj,
client = kobj_to_i2c_client(kobj);
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,
count, buf);
if (result < 0) {
@ -896,6 +866,8 @@ static int ds1307_probe(struct i2c_client *client,
bool want_irq = false;
unsigned char *buf;
struct ds1307_platform_data *pdata = dev_get_platdata(&client->dev);
irq_handler_t irq_handler = ds1307_irq;
static const int bbsqi_bitpos[] = {
[ds_1337] = 0,
[ds_1339] = DS1339_BIT_BBSQI,
@ -962,8 +934,6 @@ static int ds1307_probe(struct i2c_client *client,
* running on Vbackup (BBSQI/BBSQW)
*/
if (ds1307->client->irq > 0 && chip->alarm) {
INIT_WORK(&ds1307->work, ds1307_work);
ds1307->regs[0] |= DS1337_BIT_INTCN
| bbsqi_bitpos[ds1307->type];
ds1307->regs[0] &= ~(DS1337_BIT_A2IE | DS1337_BIT_A1IE);
@ -1053,7 +1023,7 @@ static int ds1307_probe(struct i2c_client *client,
case mcp794xx:
rtc_ops = &mcp794xx_rtc_ops;
if (ds1307->client->irq > 0 && chip->alarm) {
INIT_WORK(&ds1307->work, mcp794xx_work);
irq_handler = mcp794xx_irq;
want_irq = true;
}
break;
@ -1176,18 +1146,43 @@ read_rtc:
}
if (want_irq) {
err = request_irq(client->irq, ds1307_irq, IRQF_SHARED,
ds1307->rtc->name, client);
struct device_node *node = client->dev.of_node;
err = devm_request_threaded_irq(&client->dev,
client->irq, NULL, irq_handler,
IRQF_SHARED | IRQF_ONESHOT,
ds1307->rtc->name, client);
if (err) {
client->irq = 0;
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);
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;
err = dev_pm_set_dedicated_wake_irq(&client->dev,
ds1307->wakeirq);
if (err) {
dev_err(&client->dev, "unable to setup wakeIRQ %d!\n",
err);
goto exit;
}
}
no_irq:
if (chip->nvram_size) {
ds1307->nvram = devm_kzalloc(&client->dev,
@ -1231,10 +1226,8 @@ static int ds1307_remove(struct i2c_client *client)
{
struct ds1307 *ds1307 = i2c_get_clientdata(client);
if (test_and_clear_bit(HAS_ALARM, &ds1307->flags)) {
free_irq(client->irq, client);
cancel_work_sync(&ds1307->work);
}
if (ds1307->wakeirq)
dev_pm_clear_wake_irq(&client->dev);
if (test_and_clear_bit(HAS_NVRAM, &ds1307->flags))
sysfs_remove_bin_file(&client->dev.kobj, ds1307->nvram);
@ -1245,7 +1238,6 @@ static int ds1307_remove(struct i2c_client *client)
static struct i2c_driver ds1307_driver = {
.driver = {
.name = "rtc-ds1307",
.owner = THIS_MODULE,
},
.probe = ds1307_probe,
.remove = ds1307_remove,

Просмотреть файл

@ -162,12 +162,6 @@ static ssize_t ds1343_nvram_write(struct file *filp, struct kobject *kobj,
struct device *dev = kobj_to_dev(kobj);
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;
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,
struct device *dev = kobj_to_dev(kobj);
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;
ret = regmap_bulk_read(priv->map, address, buf, count);

Просмотреть файл

@ -664,8 +664,6 @@ static int ds1374_remove(struct i2c_client *client)
{
struct ds1374 *ds1374 = i2c_get_clientdata(client);
#ifdef CONFIG_RTC_DRV_DS1374_WDT
int res;
misc_deregister(&ds1374_miscdev);
ds1374_miscdev.parent = NULL;
unregister_reboot_notifier(&ds1374_wdt_notifier);
@ -688,7 +686,7 @@ static int ds1374_suspend(struct device *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);
return 0;
}
@ -697,7 +695,7 @@ static int ds1374_resume(struct device *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);
return 0;
}
@ -708,7 +706,6 @@ static SIMPLE_DEV_PM_OPS(ds1374_pm, ds1374_suspend, ds1374_resume);
static struct i2c_driver ds1374_driver = {
.driver = {
.name = "rtc-ds1374",
.owner = THIS_MODULE,
.pm = &ds1374_pm,
},
.probe = ds1374_probe,

Просмотреть файл

@ -64,7 +64,7 @@ enum ds1511reg {
#define DS1511_KIE 0x04
#define DS1511_WDE 0x02
#define DS1511_WDS 0x01
#define DS1511_RAM_MAX 0xff
#define DS1511_RAM_MAX 0x100
#define RTC_CMD DS1511_CONTROL_B
#define RTC_CMD1 DS1511_CONTROL_A
@ -159,7 +159,7 @@ ds1511_wdog_set(unsigned long deciseconds)
/*
* 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
@ -407,26 +407,10 @@ ds1511_nvram_read(struct file *filp, struct kobject *kobj,
{
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);
for (count = 0; size > 0; count++, size--)
for (count = 0; count < size; count++)
*buf++ = rtc_read(DS1511_RAMDATA);
if (count > 1)
rtc_write((rtc_read(RTC_CMD) & ~DS1511_BME), RTC_CMD);
return count;
}
@ -437,26 +421,10 @@ ds1511_nvram_write(struct file *filp, struct kobject *kobj,
{
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);
for (count = 0; size > 0; count++, size--)
for (count = 0; count < size; count++)
rtc_write(*buf++, DS1511_RAMDATA);
if (count > 1)
rtc_write((rtc_read(RTC_CMD) & ~DS1511_BME), RTC_CMD);
return count;
}
@ -490,7 +458,7 @@ static int ds1511_rtc_probe(struct platform_device *pdev)
/*
* turn on the clock and the crystal, etc.
*/
rtc_write(0, RTC_CMD);
rtc_write(DS1511_BME, RTC_CMD);
rtc_write(0, RTC_CMD1);
/*
* clear the wdog counter

Просмотреть файл

@ -245,7 +245,7 @@ static ssize_t ds1553_nvram_read(struct file *filp, struct kobject *kobj,
void __iomem *ioaddr = pdata->ioaddr;
ssize_t count;
for (count = 0; size > 0 && pos < RTC_OFFSET; count++, size--)
for (count = 0; count < size; count++)
*buf++ = readb(ioaddr + pos++);
return count;
}
@ -260,7 +260,7 @@ static ssize_t ds1553_nvram_write(struct file *filp, struct kobject *kobj,
void __iomem *ioaddr = pdata->ioaddr;
ssize_t count;
for (count = 0; size > 0 && pos < RTC_OFFSET; count++, size--)
for (count = 0; count < size; count++)
writeb(*buf++, ioaddr + pos++);
return count;
}

Просмотреть файл

@ -2145,27 +2145,7 @@ static struct platform_driver ds1685_rtc_driver = {
.probe = ds1685_rtc_probe,
.remove = ds1685_rtc_remove,
};
/**
* 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);
module_platform_driver(ds1685_rtc_driver);
/* ----------------------------------------------------------------------- */

Просмотреть файл

@ -134,7 +134,7 @@ static ssize_t ds1742_nvram_read(struct file *filp, struct kobject *kobj,
void __iomem *ioaddr = pdata->ioaddr_nvram;
ssize_t count;
for (count = 0; size > 0 && pos < pdata->size_nvram; count++, size--)
for (count = 0; count < size; count++)
*buf++ = readb(ioaddr + pos++);
return count;
}
@ -149,7 +149,7 @@ static ssize_t ds1742_nvram_write(struct file *filp, struct kobject *kobj,
void __iomem *ioaddr = pdata->ioaddr_nvram;
ssize_t count;
for (count = 0; size > 0 && pos < pdata->size_nvram; count++, size--)
for (count = 0; count < size; count++)
writeb(*buf++, ioaddr + pos++);
return count;
}

Просмотреть файл

@ -443,7 +443,7 @@ static int ds3232_remove(struct i2c_client *client)
{
struct ds3232 *ds3232 = i2c_get_clientdata(client);
if (client->irq >= 0) {
if (client->irq > 0) {
mutex_lock(&ds3232->mutex);
ds3232->exiting = 1;
mutex_unlock(&ds3232->mutex);
@ -463,7 +463,10 @@ static int ds3232_suspend(struct device *dev)
if (device_can_wakeup(dev)) {
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;
@ -500,7 +503,6 @@ MODULE_DEVICE_TABLE(i2c, ds3232_id);
static struct i2c_driver ds3232_driver = {
.driver = {
.name = "rtc-ds3232",
.owner = THIS_MODULE,
.pm = &ds3232_pm_ops,
},
.probe = ds3232_probe,

Просмотреть файл

@ -523,7 +523,6 @@ exit_free:
static struct i2c_driver fm3130_driver = {
.driver = {
.name = "rtc-fm3130",
.owner = THIS_MODULE,
},
.probe = fm3130_probe,
.id_table = fm3130_id,

Просмотреть файл

@ -148,10 +148,7 @@ static int gemini_rtc_probe(struct platform_device *pdev)
rtc->rtc_dev = rtc_device_register(pdev->name, dev,
&gemini_rtc_ops, THIS_MODULE);
if (likely(IS_ERR(rtc->rtc_dev)))
return PTR_ERR(rtc->rtc_dev);
return 0;
return PTR_ERR_OR_ZERO(rtc->rtc_dev);
}
static int gemini_rtc_remove(struct platform_device *pdev)

Просмотреть файл

@ -599,7 +599,6 @@ MODULE_DEVICE_TABLE(of, hym8563_dt_idtable);
static struct i2c_driver hym8563_driver = {
.driver = {
.name = "rtc-hym8563",
.owner = THIS_MODULE,
.pm = &hym8563_pm_ops,
.of_match_table = hym8563_dt_idtable,
},

Просмотреть файл

@ -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_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
/* The clock can give out invalid datetime, but we cannot return
* -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;
return rtc_valid_tm(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[] = {
{ .compatible = "isil,isl12022" },
{ },
};
MODULE_DEVICE_TABLE(of, isl12022_dt_match);
#endif
static const struct i2c_device_id isl12022_id[] = {

Просмотреть файл

@ -648,6 +648,7 @@ static const struct of_device_id isl12057_dt_match[] = {
{ .compatible = "isil,isl12057" },
{ },
};
MODULE_DEVICE_TABLE(of, isl12057_dt_match);
#endif
static const struct i2c_device_id isl12057_id[] = {
@ -659,7 +660,6 @@ MODULE_DEVICE_TABLE(i2c, isl12057_id);
static struct i2c_driver isl12057_driver = {
.driver = {
.name = DRV_NAME,
.owner = THIS_MODULE,
.pm = &isl12057_rtc_pm_ops,
.of_match_table = of_match_ptr(isl12057_dt_match),
},

310
drivers/rtc/rtc-lpc24xx.c Normal file
Просмотреть файл

@ -0,0 +1,310 @@
/*
* 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,
ssize_t cnt = 0;
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);
spin_unlock_irqrestore(&m48t59->lock, flags);
}
spin_unlock_irqrestore(&m48t59->lock, flags);
return cnt;
}
@ -365,11 +366,12 @@ static ssize_t m48t59_nvram_write(struct file *filp, struct kobject *kobj,
ssize_t cnt = 0;
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);
spin_unlock_irqrestore(&m48t59->lock, flags);
}
spin_unlock_irqrestore(&m48t59->lock, flags);
return cnt;
}

Просмотреть файл

@ -521,6 +521,7 @@ static const struct platform_device_id rtc_id[] = {
{ "max8997-rtc", 0 },
{},
};
MODULE_DEVICE_TABLE(platform, rtc_id);
static struct platform_driver max8997_rtc_driver = {
.driver = {

Просмотреть файл

@ -312,6 +312,7 @@ static const struct of_device_id moxart_rtc_match[] = {
{ .compatible = "moxa,moxart-rtc" },
{ },
};
MODULE_DEVICE_TABLE(of, moxart_rtc_match);
static struct platform_driver moxart_rtc_driver = {
.probe = moxart_rtc_probe,

Просмотреть файл

@ -406,6 +406,7 @@ static const struct of_device_id mpc5121_rtc_match[] = {
{ .compatible = "fsl,mpc5200-rtc", },
{},
};
MODULE_DEVICE_TABLE(of, mpc5121_rtc_match);
#endif
static struct platform_driver mpc5121_rtc_driver = {

Просмотреть файл

@ -373,15 +373,42 @@ static int mtk_rtc_remove(struct platform_device *pdev)
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[] = {
{ .compatible = "mediatek,mt6397-rtc", },
{ }
};
MODULE_DEVICE_TABLE(of, mt6397_rtc_of_match);
static struct platform_driver mtk_rtc_driver = {
.driver = {
.name = "mt6397-rtc",
.of_match_table = mt6397_rtc_of_match,
.pm = &mt6397_pm_ops,
},
.probe = mtk_rtc_probe,
.remove = mtk_rtc_remove,

Просмотреть файл

@ -324,6 +324,7 @@ static const struct of_device_id rtc_mv_of_match_table[] = {
{ .compatible = "marvell,orion-rtc", },
{}
};
MODULE_DEVICE_TABLE(of, rtc_mv_of_match_table);
#endif
static struct platform_driver mv_rtc_driver = {

Просмотреть файл

@ -25,6 +25,7 @@
#include <linux/of_device.h>
#include <linux/pm_runtime.h>
#include <linux/io.h>
#include <linux/clk.h>
/*
* The OMAP RTC is a year/month/day/hours/minutes/seconds BCD clock
@ -107,6 +108,7 @@
/* OMAP_RTC_OSC_REG bit fields: */
#define OMAP_RTC_OSC_32KCLK_EN BIT(6)
#define OMAP_RTC_OSC_SEL_32KCLK_SRC BIT(3)
/* OMAP_RTC_IRQWAKEEN bit fields: */
#define OMAP_RTC_IRQWAKEEN_ALARM_WAKEEN BIT(1)
@ -132,10 +134,12 @@ struct omap_rtc_device_type {
struct omap_rtc {
struct rtc_device *rtc;
void __iomem *base;
struct clk *clk;
int irq_alarm;
int irq_timer;
u8 interrupts_reg;
bool is_pmic_controller;
bool has_ext_clk;
const struct omap_rtc_device_type *type;
};
@ -553,6 +557,15 @@ static int omap_rtc_probe(struct platform_device *pdev)
if (rtc->irq_alarm <= 0)
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);
rtc->base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(rtc->base))
@ -627,6 +640,16 @@ static int omap_rtc_probe(struct platform_device *pdev)
if (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);
device_init_wakeup(&pdev->dev, true);
@ -672,6 +695,7 @@ err:
static int __exit omap_rtc_remove(struct platform_device *pdev)
{
struct omap_rtc *rtc = platform_get_drvdata(pdev);
u8 reg;
if (pm_power_off == omap_rtc_power_off &&
omap_rtc_power_off_rtc == rtc) {
@ -681,10 +705,19 @@ static int __exit omap_rtc_remove(struct platform_device *pdev)
device_init_wakeup(&pdev->dev, 0);
if (!IS_ERR(rtc->clk))
clk_disable_unprepare(rtc->clk);
rtc->type->unlock(rtc);
/* leave rtc running, but disable irqs */
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);
/* Disable the clock/module */

Просмотреть файл

@ -190,11 +190,9 @@ exit:
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,
.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)
@ -202,8 +200,11 @@ static int opal_rtc_probe(struct platform_device *pdev)
struct rtc_device *rtc;
if (pdev->dev.of_node && of_get_property(pdev->dev.of_node, "has-tpo",
NULL))
NULL)) {
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,
THIS_MODULE);
@ -236,7 +237,6 @@ static struct platform_driver opal_rtc_driver = {
.id_table = opal_rtc_driver_ids,
.driver = {
.name = DRVNAME,
.owner = THIS_MODULE,
.of_match_table = opal_rtc_match,
},
};

Просмотреть файл

@ -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_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
/* the clock can give out invalid datetime, but we cannot return
* -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;
return rtc_valid_tm(tm);
}
static int pcf2123_rtc_set_time(struct device *dev, struct rtc_time *tm)

Просмотреть файл

@ -33,11 +33,14 @@
#define PCF2127_REG_MO (0x08)
#define PCF2127_REG_YR (0x09)
#define PCF2127_OSF BIT(7) /* Oscillator Fail flag */
static struct i2c_driver pcf2127_driver;
struct pcf2127 {
struct rtc_device *rtc;
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)
if (buf[PCF2127_REG_CTRL3] & 0x04) {
pcf2127->voltage_low = 1;
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,
@ -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_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
/* the clock can give out invalid datetime, but we cannot return
* -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;
return rtc_valid_tm(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];
int i = 0, err;
@ -112,7 +121,7 @@ static int pcf2127_set_datetime(struct i2c_client *client, struct rtc_time *tm)
buf[i++] = PCF2127_REG_SC;
/* 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_hour);
buf[i++] = bin2bcd(tm->tm_mday);
@ -132,6 +141,9 @@ static int pcf2127_set_datetime(struct i2c_client *client, struct rtc_time *tm)
return -EIO;
}
/* clear OSF flag in client data */
pcf2127->oscillator_failed = 0;
return 0;
}
@ -144,7 +156,9 @@ static int pcf2127_rtc_ioctl(struct device *dev,
switch (cmd) {
case RTC_VL_READ:
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,
sizeof(int)))
@ -217,7 +231,6 @@ MODULE_DEVICE_TABLE(of, pcf2127_of_match);
static struct i2c_driver pcf2127_driver = {
.driver = {
.name = "rtc-pcf2127",
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(pcf2127_of_match),
},
.probe = pcf2127_probe,

Просмотреть файл

@ -189,7 +189,6 @@ MODULE_DEVICE_TABLE(of, pcf85063_of_match);
static struct i2c_driver pcf85063_driver = {
.driver = {
.name = "rtc-pcf85063",
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(pcf85063_of_match),
},
.probe = pcf85063_probe,

Просмотреть файл

@ -334,7 +334,6 @@ MODULE_DEVICE_TABLE(of, pcf8523_of_match);
static struct i2c_driver pcf8523_driver = {
.driver = {
.name = DRIVER_NAME,
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(pcf8523_of_match),
},
.probe = pcf8523_probe,

Просмотреть файл

@ -483,7 +483,6 @@ MODULE_DEVICE_TABLE(of, pcf8563_of_match);
static struct i2c_driver pcf8563_driver = {
.driver = {
.name = "rtc-pcf8563",
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(pcf8563_of_match),
},
.probe = pcf8563_probe,

Просмотреть файл

@ -309,7 +309,6 @@ MODULE_DEVICE_TABLE(i2c, pcf8583_id);
static struct i2c_driver pcf8583_driver = {
.driver = {
.name = "pcf8583",
.owner = THIS_MODULE,
},
.probe = pcf8583_probe,
.id_table = pcf8583_id,

Просмотреть файл

@ -476,6 +476,6 @@ static struct 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_LICENSE("GPL");

Просмотреть файл

@ -32,6 +32,8 @@
#include <mach/hardware.h>
#include "rtc-sa1100.h"
#define RTC_DEF_DIVIDER (32768 - 1)
#define RTC_DEF_TRIM 0
#define MAXFREQ_PERIODIC 1000
@ -86,10 +88,9 @@
__raw_writel((value), (pxa_rtc)->base + (reg))
struct pxa_rtc {
struct sa1100_rtc sa1100_rtc;
struct resource *ress;
void __iomem *base;
int irq_1Hz;
int irq_Alrm;
struct rtc_device *rtc;
spinlock_t lock; /* Protects this structure */
};
@ -184,25 +185,25 @@ static int pxa_rtc_open(struct device *dev)
struct pxa_rtc *pxa_rtc = dev_get_drvdata(dev);
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);
if (ret < 0) {
dev_err(dev, "can't get irq %i, err %d\n", pxa_rtc->irq_1Hz,
ret);
dev_err(dev, "can't get irq %i, err %d\n",
pxa_rtc->sa1100_rtc.irq_1hz, ret);
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);
if (ret < 0) {
dev_err(dev, "can't get irq %i, err %d\n", pxa_rtc->irq_Alrm,
ret);
dev_err(dev, "can't get irq %i, err %d\n",
pxa_rtc->sa1100_rtc.irq_alarm, ret);
goto err_irq_Alrm;
}
return 0;
err_irq_Alrm:
free_irq(pxa_rtc->irq_1Hz, dev);
free_irq(pxa_rtc->sa1100_rtc.irq_1hz, dev);
err_irq_1Hz:
return ret;
}
@ -215,8 +216,8 @@ static void pxa_rtc_release(struct device *dev)
rtsr_clear_bits(pxa_rtc, RTSR_PIALE | RTSR_RDALE1 | RTSR_HZE);
spin_unlock_irq(&pxa_rtc->lock);
free_irq(pxa_rtc->irq_Alrm, dev);
free_irq(pxa_rtc->irq_1Hz, dev);
free_irq(pxa_rtc->sa1100_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)
@ -320,12 +321,13 @@ static int __init pxa_rtc_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct pxa_rtc *pxa_rtc;
struct sa1100_rtc *sa1100_rtc;
int ret;
u32 rttr;
pxa_rtc = devm_kzalloc(dev, sizeof(*pxa_rtc), GFP_KERNEL);
if (!pxa_rtc)
return -ENOMEM;
sa1100_rtc = &pxa_rtc->sa1100_rtc;
spin_lock_init(&pxa_rtc->lock);
platform_set_drvdata(pdev, pxa_rtc);
@ -336,13 +338,13 @@ static int __init pxa_rtc_probe(struct platform_device *pdev)
return -ENXIO;
}
pxa_rtc->irq_1Hz = platform_get_irq(pdev, 0);
if (pxa_rtc->irq_1Hz < 0) {
sa1100_rtc->irq_1hz = platform_get_irq(pdev, 0);
if (sa1100_rtc->irq_1hz < 0) {
dev_err(dev, "No 1Hz IRQ resource defined\n");
return -ENXIO;
}
pxa_rtc->irq_Alrm = platform_get_irq(pdev, 1);
if (pxa_rtc->irq_Alrm < 0) {
sa1100_rtc->irq_alarm = platform_get_irq(pdev, 1);
if (sa1100_rtc->irq_alarm < 0) {
dev_err(dev, "No alarm IRQ resource defined\n");
return -ENXIO;
}
@ -354,15 +356,14 @@ static int __init pxa_rtc_probe(struct platform_device *pdev)
return -ENOMEM;
}
/*
* If the clock divider is uninitialized then reset it to the
* default value to get the 1Hz clock.
*/
if (rtc_readl(pxa_rtc, RTTR) == 0) {
rttr = RTC_DEF_DIVIDER + (RTC_DEF_TRIM << 16);
rtc_writel(pxa_rtc, RTTR, rttr);
dev_warn(dev, "warning: initializing default clock"
" divider/trim value\n");
sa1100_rtc->rcnr = pxa_rtc->base + 0x0;
sa1100_rtc->rtsr = pxa_rtc->base + 0x8;
sa1100_rtc->rtar = pxa_rtc->base + 0x4;
sa1100_rtc->rttr = pxa_rtc->base + 0xc;
ret = sa1100_rtc_init(pdev, sa1100_rtc);
if (!ret) {
dev_err(dev, "Unable to init SA1100 RTC sub-device\n");
return ret;
}
rtsr_clear_bits(pxa_rtc, RTSR_PIALE | RTSR_RDALE1 | RTSR_HZE);
@ -402,7 +403,7 @@ static int pxa_rtc_suspend(struct device *dev)
struct pxa_rtc *pxa_rtc = dev_get_drvdata(dev);
if (device_may_wakeup(dev))
enable_irq_wake(pxa_rtc->irq_Alrm);
enable_irq_wake(pxa_rtc->sa1100_rtc.irq_alarm);
return 0;
}
@ -411,7 +412,7 @@ static int pxa_rtc_resume(struct device *dev)
struct pxa_rtc *pxa_rtc = dev_get_drvdata(dev);
if (device_may_wakeup(dev))
disable_irq_wake(pxa_rtc->irq_Alrm);
disable_irq_wake(pxa_rtc->sa1100_rtc.irq_alarm);
return 0;
}
#endif

Просмотреть файл

@ -170,7 +170,7 @@ static ssize_t rp5c01_nvram_read(struct file *filp, struct kobject *kobj,
spin_lock_irq(&priv->lock);
for (count = 0; size > 0 && pos < RP5C01_MODE; count++, size--) {
for (count = 0; count < size; count++) {
u8 data;
rp5c01_write(priv,
@ -200,7 +200,7 @@ static ssize_t rp5c01_nvram_write(struct file *filp, struct kobject *kobj,
spin_lock_irq(&priv->lock);
for (count = 0; size > 0 && pos < RP5C01_MODE; count++, size--) {
for (count = 0; count < size; count++) {
u8 data = *buf++;
rp5c01_write(priv,

Просмотреть файл

@ -18,13 +18,11 @@
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*/
#include <linux/bcd.h>
#include <linux/bitops.h>
#include <linux/i2c.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/bcd.h>
#include <linux/i2c.h>
#include <linux/list.h>
#include <linux/rtc.h>
/* Register definitions */
@ -48,17 +46,17 @@
#define RX8025_BIT_CTRL1_CT (7 << 0)
/* 1 Hz periodic level irq */
#define RX8025_BIT_CTRL1_CT_1HZ 4
#define RX8025_BIT_CTRL1_TEST (1 << 3)
#define RX8025_BIT_CTRL1_1224 (1 << 5)
#define RX8025_BIT_CTRL1_DALE (1 << 6)
#define RX8025_BIT_CTRL1_WALE (1 << 7)
#define RX8025_BIT_CTRL1_TEST BIT(3)
#define RX8025_BIT_CTRL1_1224 BIT(5)
#define RX8025_BIT_CTRL1_DALE BIT(6)
#define RX8025_BIT_CTRL1_WALE BIT(7)
#define RX8025_BIT_CTRL2_DAFG (1 << 0)
#define RX8025_BIT_CTRL2_WAFG (1 << 1)
#define RX8025_BIT_CTRL2_CTFG (1 << 2)
#define RX8025_BIT_CTRL2_PON (1 << 4)
#define RX8025_BIT_CTRL2_XST (1 << 5)
#define RX8025_BIT_CTRL2_VDET (1 << 6)
#define RX8025_BIT_CTRL2_DAFG BIT(0)
#define RX8025_BIT_CTRL2_WAFG BIT(1)
#define RX8025_BIT_CTRL2_CTFG BIT(2)
#define RX8025_BIT_CTRL2_PON BIT(4)
#define RX8025_BIT_CTRL2_XST BIT(5)
#define RX8025_BIT_CTRL2_VDET BIT(6)
/* Clock precision adjustment */
#define RX8025_ADJ_RESOLUTION 3050 /* in ppb */
@ -74,84 +72,84 @@ MODULE_DEVICE_TABLE(i2c, rx8025_id);
struct rx8025_data {
struct i2c_client *client;
struct rtc_device *rtc;
struct work_struct work;
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);
if (ret < 0) {
dev_err(&client->dev, "Unable to read register #%d\n", number);
return ret;
}
*value = ret;
return 0;
return i2c_smbus_read_byte_data(client, number << 4);
}
static int rx8025_read_regs(struct i2c_client *client,
int number, u8 length, u8 *values)
static int rx8025_read_regs(const struct i2c_client *client,
u8 number, u8 length, u8 *values)
{
int ret = i2c_smbus_read_i2c_block_data(client, (number << 4) | 0x08,
length, values);
if (ret != length) {
dev_err(&client->dev, "Unable to read registers #%d..#%d\n",
number, number + length - 1);
int ret = i2c_smbus_read_i2c_block_data(client, number << 4, length,
values);
if (ret != length)
return ret < 0 ? ret : -EIO;
return 0;
}
static s32 rx8025_write_reg(const struct i2c_client *client, u8 number,
u8 value)
{
return i2c_smbus_write_byte_data(client, number << 4, value);
}
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_check_validity(struct device *dev)
{
struct rx8025_data *rx8025 = dev_get_drvdata(dev);
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 (!(ctrl2 & RX8025_BIT_CTRL2_XST)) {
dev_warn(dev, "crystal stopped, date is invalid\n");
return -EINVAL;
}
return 0;
}
static int rx8025_write_reg(struct i2c_client *client, int number, u8 value)
static int rx8025_reset_validity(struct i2c_client *client)
{
int ret = i2c_smbus_write_byte_data(client, number << 4, value);
int ctrl2 = rx8025_read_reg(client, RX8025_REG_CTRL2);
if (ret)
dev_err(&client->dev, "Unable to write register #%d\n",
number);
if (ctrl2 < 0)
return ctrl2;
return ret;
ctrl2 &= ~(RX8025_BIT_CTRL2_PON | RX8025_BIT_CTRL2_VDET);
return rx8025_write_reg(client, RX8025_REG_CTRL2,
ctrl2 | RX8025_BIT_CTRL2_XST);
}
static int rx8025_write_regs(struct i2c_client *client,
int number, u8 length, u8 *values)
{
int ret = i2c_smbus_write_i2c_block_data(client, (number << 4) | 0x08,
length, values);
if (ret)
dev_err(&client->dev, "Unable to write registers #%d..#%d\n",
number, number + length - 1);
return ret;
}
static irqreturn_t rx8025_irq(int irq, void *dev_id)
static irqreturn_t rx8025_handle_irq(int irq, void *dev_id)
{
struct i2c_client *client = dev_id;
struct rx8025_data *rx8025 = i2c_get_clientdata(client);
int status;
disable_irq_nosync(irq);
schedule_work(&rx8025->work);
return IRQ_HANDLED;
}
static void rx8025_work(struct work_struct *work)
{
struct rx8025_data *rx8025 = container_of(work, struct rx8025_data,
work);
struct i2c_client *client = rx8025->client;
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;
if (!(status & RX8025_BIT_CTRL2_XST))
@ -161,9 +159,7 @@ static void rx8025_work(struct work_struct *work)
if (status & RX8025_BIT_CTRL2_CTFG) {
/* periodic */
status &= ~RX8025_BIT_CTRL2_CTFG;
local_irq_disable();
rtc_update_irq(rx8025->rtc, 1, RTC_PF | RTC_IRQF);
local_irq_enable();
}
if (status & RX8025_BIT_CTRL2_DAFG) {
@ -172,20 +168,11 @@ static void rx8025_work(struct work_struct *work)
if (rx8025_write_reg(client, RX8025_REG_CTRL1,
rx8025->ctrl1 & ~RX8025_BIT_CTRL1_DALE))
goto out;
local_irq_disable();
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:
if (!rx8025->exiting)
enable_irq(client->irq);
mutex_unlock(lock);
return IRQ_HANDLED;
}
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];
int err;
err = rx8025_check_validity(dev);
if (err)
return err;
err = rx8025_read_regs(rx8025->client, RX8025_REG_SEC, 7, date);
if (err)
return err;
@ -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_mon = bcd2bin(date[RX8025_REG_MONTH] & 0x1f) - 1;
dt->tm_year = bcd2bin(date[RX8025_REG_YEAR]);
if (dt->tm_year < 70)
dt->tm_year += 100;
dt->tm_year = bcd2bin(date[RX8025_REG_YEAR]) + 100;
dev_dbg(dev, "%s: date %ds %dm %dh %dmd %dm %dy\n", __func__,
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)
{
struct rx8025_data *rx8025 = dev_get_drvdata(dev);
u8 date[7];
int ret;
/*
* BUG: The HW assumes every year that is a multiple of 4 to be a leap
* year. Next time this is wrong is 2100, which will not be a leap
* year.
*/
if ((dt->tm_year < 100) || (dt->tm_year > 199))
return -EINVAL;
/*
* 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)
date[RX8025_REG_WDAY] = bin2bcd(dt->tm_wday);
date[RX8025_REG_MDAY] = bin2bcd(dt->tm_mday);
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,
"%s: write 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
__func__,
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);
u8 ctrl[2], ctrl2;
@ -275,38 +265,18 @@ static int rx8025_init_client(struct i2c_client *client, int *need_reset)
/* Keep test bit zero ! */
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)) {
dev_warn(&client->dev, "Alarm was detected\n");
need_clear = 1;
}
if (!(ctrl[1] & RX8025_BIT_CTRL2_CTFG))
if (ctrl[1] & RX8025_BIT_CTRL2_CTFG)
need_clear = 1;
if (*need_reset || need_clear) {
ctrl2 = ctrl[0];
ctrl2 &= ~(RX8025_BIT_CTRL2_PON | RX8025_BIT_CTRL2_VDET |
RX8025_BIT_CTRL2_CTFG | RX8025_BIT_CTRL2_WAFG |
if (need_clear) {
ctrl2 = ctrl[1];
ctrl2 &= ~(RX8025_BIT_CTRL2_CTFG | RX8025_BIT_CTRL2_WAFG |
RX8025_BIT_CTRL2_DAFG);
ctrl2 |= RX8025_BIT_CTRL2_XST;
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)
{
struct rx8025_data *rx8025 = dev_get_drvdata(dev);
struct i2c_client *client = rx8025->client;
u8 ctrl2, ald[2];
int err;
u8 ald[2];
int ctrl2, err;
if (client->irq <= 0)
return -EINVAL;
@ -329,9 +299,9 @@ static int rx8025_read_alarm(struct device *dev, struct rtc_wkalrm *t)
if (err)
return err;
err = rx8025_read_reg(client, RX8025_REG_CTRL2, &ctrl2);
if (err)
return err;
ctrl2 = rx8025_read_reg(client, RX8025_REG_CTRL2);
if (ctrl2 < 0)
return ctrl2;
dev_dbg(dev, "%s: read alarm 0x%02x 0x%02x ctrl2 %02x\n",
__func__, ald[0], ald[1], ctrl2);
@ -452,12 +422,11 @@ static struct rtc_class_ops rx8025_rtc_ops = {
static int rx8025_get_clock_adjust(struct device *dev, int *adj)
{
struct i2c_client *client = to_i2c_client(dev);
u8 digoff;
int err;
int digoff;
err = rx8025_read_reg(client, RX8025_REG_DIGOFF, &digoff);
if (err)
return err;
digoff = rx8025_read_reg(client, RX8025_REG_DIGOFF);
if (digoff < 0)
return digoff;
*adj = digoff >= 64 ? digoff - 128 : digoff;
if (*adj > 0)
@ -539,88 +508,53 @@ static int rx8025_probe(struct i2c_client *client,
{
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
struct rx8025_data *rx8025;
int err, need_reset = 0;
int err = 0;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA
| I2C_FUNC_SMBUS_I2C_BLOCK)) {
dev_err(&adapter->dev,
"doesn't support required functionality\n");
err = -EIO;
goto errout;
return -EIO;
}
rx8025 = devm_kzalloc(&client->dev, sizeof(*rx8025), GFP_KERNEL);
if (!rx8025) {
err = -ENOMEM;
goto errout;
return -ENOMEM;
}
rx8025->client = client;
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)
goto errout;
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);
}
return err;
rx8025->rtc = devm_rtc_device_register(&client->dev, client->name,
&rx8025_rtc_ops, THIS_MODULE);
if (IS_ERR(rx8025->rtc)) {
err = PTR_ERR(rx8025->rtc);
dev_err(&client->dev, "unable to register the class device\n");
goto errout;
return PTR_ERR(rx8025->rtc);
}
if (client->irq > 0) {
dev_info(&client->dev, "IRQ %d supplied\n", client->irq);
err = request_irq(client->irq, rx8025_irq,
0, "rx8025", client);
err = devm_request_threaded_irq(&client->dev, client->irq, NULL,
rx8025_handle_irq, 0, "rx8025",
client);
if (err) {
dev_err(&client->dev, "unable to request IRQ\n");
goto errout;
dev_err(&client->dev, "unable to request IRQ, alarms disabled\n");
client->irq = 0;
}
}
rx8025->rtc->irq_freq = 1;
rx8025->rtc->max_user_freq = 1;
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;
}
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);
return 0;
}
@ -628,7 +562,6 @@ static int rx8025_remove(struct i2c_client *client)
static struct i2c_driver rx8025_driver = {
.driver = {
.name = "rtc-rx8025",
.owner = THIS_MODULE,
},
.probe = rx8025_probe,
.remove = rx8025_remove,

Просмотреть файл

@ -315,7 +315,6 @@ MODULE_DEVICE_TABLE(i2c, rx8581_id);
static struct i2c_driver rx8581_driver = {
.driver = {
.name = "rtc-rx8581",
.owner = THIS_MODULE,
},
.probe = rx8581_probe,
.id_table = rx8581_id,

Просмотреть файл

@ -39,6 +39,7 @@ struct s3c_rtc {
void __iomem *base;
struct clk *rtc_clk;
struct clk *rtc_src_clk;
bool clk_disabled;
struct s3c_rtc_data *data;
@ -71,9 +72,12 @@ static void s3c_rtc_enable_clk(struct s3c_rtc *info)
unsigned long irq_flags;
spin_lock_irqsave(&info->alarm_clk_lock, irq_flags);
clk_enable(info->rtc_clk);
if (info->data->needs_src_clk)
clk_enable(info->rtc_src_clk);
if (info->clk_disabled) {
clk_enable(info->rtc_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);
}
@ -82,9 +86,12 @@ static void s3c_rtc_disable_clk(struct s3c_rtc *info)
unsigned long irq_flags;
spin_lock_irqsave(&info->alarm_clk_lock, irq_flags);
if (info->data->needs_src_clk)
clk_disable(info->rtc_src_clk);
clk_disable(info->rtc_clk);
if (!info->clk_disabled) {
if (info->data->needs_src_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);
}
@ -128,6 +135,11 @@ static int s3c_rtc_setaie(struct device *dev, unsigned int enabled)
s3c_rtc_disable_clk(info);
if (enabled)
s3c_rtc_enable_clk(info);
else
s3c_rtc_disable_clk(info);
return 0;
}
@ -410,8 +422,9 @@ static int s3c_rtc_remove(struct platform_device *pdev)
s3c_rtc_setaie(info->dev, 0);
if (info->data->needs_src_clk)
clk_unprepare(info->rtc_src_clk);
clk_unprepare(info->rtc_clk);
info->rtc_clk = NULL;
return 0;
}
@ -482,6 +495,7 @@ static int s3c_rtc_probe(struct platform_device *pdev)
if (IS_ERR(info->rtc_src_clk)) {
dev_err(&pdev->dev,
"failed to find rtc source clock\n");
clk_disable_unprepare(info->rtc_clk);
return PTR_ERR(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)
case S2MPS13X:
data[0] = (0 << BCD_EN_SHIFT) | (1 << MODEL24_SHIFT);
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;
default:
@ -797,6 +807,7 @@ static const struct platform_device_id s5m_rtc_id[] = {
{ "s2mps14-rtc", S2MPS14X },
{ },
};
MODULE_DEVICE_TABLE(platform, s5m_rtc_id);
static struct platform_driver s5m_rtc_driver = {
.driver = {

Просмотреть файл

@ -35,24 +35,17 @@
#include <linux/bitops.h>
#include <linux/io.h>
#include <mach/hardware.h>
#include <mach/irqs.h>
#define RTSR_HZE BIT(3) /* HZ interrupt enable */
#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 <mach/regs-rtc.h>
#endif
#include "rtc-sa1100.h"
#define RTC_DEF_DIVIDER (32768 - 1)
#define RTC_DEF_TRIM 0
#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)
{
@ -63,16 +56,16 @@ static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id)
spin_lock(&info->lock);
rtsr = RTSR;
rtsr = readl_relaxed(info->rtsr);
/* clear interrupt sources */
RTSR = 0;
writel_relaxed(0, info->rtsr);
/* Fix for a nasty initialization problem the in SA11xx RTSR register.
* See also the comments in sa1100_rtc_probe(). */
if (rtsr & (RTSR_ALE | RTSR_HZE)) {
/* This is the original code, before there was the if test
* above. This code does not clear interrupts that were not
* enabled. */
RTSR = (RTSR_AL | RTSR_HZ) & (rtsr >> 2);
writel_relaxed((RTSR_AL | RTSR_HZ) & (rtsr >> 2), info->rtsr);
} else {
/* For some reason, it is possible to enter this routine
* without interruptions enabled, it has been tested with
@ -81,13 +74,13 @@ static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id)
* This situation leads to an infinite "loop" of interrupt
* routine calling and as a result the processor seems to
* 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 */
if (rtsr & RTSR_AL)
rtsr &= ~RTSR_ALE;
RTSR = rtsr & (RTSR_ALE | RTSR_HZE);
writel_relaxed(rtsr & (RTSR_ALE | RTSR_HZE), info->rtsr);
/* update irq data & counter */
if (rtsr & RTSR_AL)
@ -135,7 +128,7 @@ static void sa1100_rtc_release(struct device *dev)
struct sa1100_rtc *info = dev_get_drvdata(dev);
spin_lock_irq(&info->lock);
RTSR = 0;
writel_relaxed(0, info->rtsr);
spin_unlock_irq(&info->lock);
free_irq(info->irq_alarm, 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)
{
u32 rtsr;
struct sa1100_rtc *info = dev_get_drvdata(dev);
spin_lock_irq(&info->lock);
rtsr = readl_relaxed(info->rtsr);
if (enabled)
RTSR |= RTSR_ALE;
rtsr |= RTSR_ALE;
else
RTSR &= ~RTSR_ALE;
rtsr &= ~RTSR_ALE;
writel_relaxed(rtsr, info->rtsr);
spin_unlock_irq(&info->lock);
return 0;
}
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;
}
static int sa1100_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
struct sa1100_rtc *info = dev_get_drvdata(dev);
unsigned long time;
int ret;
ret = rtc_tm_to_time(tm, &time);
if (ret == 0)
RCNR = time;
writel_relaxed(time, info->rcnr);
return ret;
}
static int sa1100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
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->pending = (rtsr & RTSR_AL) ? 1 : 0;
return 0;
@ -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);
if (ret != 0)
goto out;
RTSR = RTSR & (RTSR_HZE|RTSR_ALE|RTSR_AL);
RTAR = time;
writel_relaxed(readl_relaxed(info->rtsr) &
(RTSR_HZE | RTSR_ALE | RTSR_AL), info->rtsr);
writel_relaxed(time, info->rtar);
if (alrm->enabled)
RTSR |= RTSR_ALE;
writel_relaxed(readl_relaxed(info->rtsr) | RTSR_ALE, info->rtsr);
else
RTSR &= ~RTSR_ALE;
writel_relaxed(readl_relaxed(info->rtsr) & ~RTSR_ALE, info->rtsr);
out:
spin_unlock_irq(&info->lock);
@ -206,8 +207,10 @@ out:
static int sa1100_rtc_proc(struct device *dev, struct seq_file *seq)
{
seq_printf(seq, "trim/divider\t\t: 0x%08x\n", (u32) RTTR);
seq_printf(seq, "RTSR\t\t\t: 0x%08x\n", (u32)RTSR);
struct sa1100_rtc *info = dev_get_drvdata(dev);
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;
}
@ -223,29 +226,18 @@ static const struct rtc_class_ops sa1100_rtc_ops = {
.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 sa1100_rtc *info;
int irq_1hz, irq_alarm, ret = 0;
int ret;
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;
spin_lock_init(&info->lock);
info = devm_kzalloc(&pdev->dev, sizeof(struct sa1100_rtc), GFP_KERNEL);
if (!info)
return -ENOMEM;
info->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(info->clk)) {
dev_err(&pdev->dev, "failed to find rtc clock source\n");
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);
if (ret)
@ -257,22 +249,19 @@ static int sa1100_rtc_probe(struct platform_device *pdev)
* If the clock divider is uninitialized then reset it to the
* default value to get the 1Hz clock.
*/
if (RTTR == 0) {
RTTR = RTC_DEF_DIVIDER + (RTC_DEF_TRIM << 16);
if (readl_relaxed(info->rttr) == 0) {
writel_relaxed(RTC_DEF_DIVIDER + (RTC_DEF_TRIM << 16), info->rttr);
dev_warn(&pdev->dev, "warning: "
"initializing default clock divider/trim value\n");
/* 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,
THIS_MODULE);
if (IS_ERR(rtc)) {
ret = PTR_ERR(rtc);
goto err_dev;
clk_disable_unprepare(info->clk);
return PTR_ERR(rtc);
}
info->rtc = rtc;
@ -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
* the corresponding bits in RTSR. */
RTSR = RTSR_AL | RTSR_HZ;
writel_relaxed(RTSR_AL | RTSR_HZ, info->rtsr);
return 0;
err_dev:
clk_disable_unprepare(info->clk);
return ret;
}
EXPORT_SYMBOL_GPL(sa1100_rtc_init);
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)

23
drivers/rtc/rtc-sa1100.h Normal file
Просмотреть файл

@ -0,0 +1,23 @@
#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 @@
#include <linux/slab.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/regmap.h>
#include <linux/rtc/sirfsoc_rtciobrg.h>
@ -48,12 +49,27 @@ struct sirfsoc_rtc_drv {
/* Overflow for every 8 years extra time */
u32 overflow_rtc;
spinlock_t lock;
struct regmap *regmap;
#ifdef CONFIG_PM
u32 saved_counter;
u32 saved_overflow_rtc;
#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,
struct rtc_wkalrm *alrm)
{
@ -64,9 +80,9 @@ static int sirfsoc_rtc_read_alarm(struct device *dev,
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));
/*
@ -82,8 +98,7 @@ static int sirfsoc_rtc_read_alarm(struct device *dev,
rtc_time_to_tm(rtcdrv->overflow_rtc
<< (BITS_PER_LONG - RTC_SHIFT)
| rtc_alarm >> RTC_SHIFT, &(alrm->time));
if (sirfsoc_rtc_iobrg_readl(
rtcdrv->rtc_base + RTC_STATUS) & SIRFSOC_RTC_AL0E)
if (sirfsoc_rtc_readl(rtcdrv, RTC_STATUS) & SIRFSOC_RTC_AL0E)
alrm->enabled = 1;
spin_unlock_irq(&rtcdrv->lock);
@ -103,8 +118,7 @@ static int sirfsoc_rtc_set_alarm(struct device *dev,
spin_lock_irq(&rtcdrv->lock);
rtc_status_reg = sirfsoc_rtc_iobrg_readl(
rtcdrv->rtc_base + RTC_STATUS);
rtc_status_reg = sirfsoc_rtc_readl(rtcdrv, RTC_STATUS);
if (rtc_status_reg & SIRFSOC_RTC_AL0E) {
/*
* An ongoing alarm in progress - ingore it and not
@ -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");
}
sirfsoc_rtc_iobrg_writel(
rtc_alarm << RTC_SHIFT, rtcdrv->rtc_base + RTC_ALARM0);
sirfsoc_rtc_writel(rtcdrv, RTC_ALARM0, rtc_alarm << RTC_SHIFT);
rtc_status_reg &= ~0x07; /* mask out the lower status bits */
/*
* 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,
rtc_status_reg |= SIRFSOC_RTC_AL0;
/* enable the RTC alarm interrupt */
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);
} else {
@ -135,8 +147,7 @@ static int sirfsoc_rtc_set_alarm(struct device *dev,
*/
spin_lock_irq(&rtcdrv->lock);
rtc_status_reg = sirfsoc_rtc_iobrg_readl(
rtcdrv->rtc_base + RTC_STATUS);
rtc_status_reg = sirfsoc_rtc_readl(rtcdrv, RTC_STATUS);
if (rtc_status_reg & SIRFSOC_RTC_AL0E) {
/* clear the RTC status register's alarm bit */
rtc_status_reg &= ~0x07;
@ -145,8 +156,8 @@ static int sirfsoc_rtc_set_alarm(struct device *dev,
/* Clear the Alarm enable bit */
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);
@ -167,9 +178,9 @@ static int sirfsoc_rtc_read_time(struct device *dev,
* fail, read several times to make sure get stable value.
*/
do {
tmp_rtc = sirfsoc_rtc_iobrg_readl(rtcdrv->rtc_base + RTC_CN);
tmp_rtc = sirfsoc_rtc_readl(rtcdrv, RTC_CN);
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) |
tmp_rtc >> RTC_SHIFT, tm);
@ -187,10 +198,8 @@ static int sirfsoc_rtc_set_time(struct device *dev,
rtcdrv->overflow_rtc = rtc_time >> (BITS_PER_LONG - RTC_SHIFT);
sirfsoc_rtc_iobrg_writel(rtcdrv->overflow_rtc,
rtcdrv->rtc_base + RTC_SW_VALUE);
sirfsoc_rtc_iobrg_writel(
rtc_time << RTC_SHIFT, rtcdrv->rtc_base + RTC_CN);
sirfsoc_rtc_writel(rtcdrv, RTC_SW_VALUE, rtcdrv->overflow_rtc);
sirfsoc_rtc_writel(rtcdrv, RTC_CN, rtc_time << RTC_SHIFT);
return 0;
}
@ -222,14 +231,13 @@ static int sirfsoc_rtc_alarm_irq_enable(struct device *dev,
spin_lock_irq(&rtcdrv->lock);
rtc_status_reg = sirfsoc_rtc_iobrg_readl(
rtcdrv->rtc_base + RTC_STATUS);
rtc_status_reg = sirfsoc_rtc_readl(rtcdrv, RTC_STATUS);
if (enabled)
rtc_status_reg |= SIRFSOC_RTC_AL0E;
else
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);
@ -254,7 +262,7 @@ static irqreturn_t sirfsoc_rtc_irq_handler(int irq, void *pdata)
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
* and it expired NOW
* So this is being used as an ASSERT
@ -270,7 +278,8 @@ static irqreturn_t sirfsoc_rtc_irq_handler(int irq, void *pdata)
/* Clear the Alarm enable bit */
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);
@ -287,6 +296,13 @@ static const struct of_device_id sirfsoc_rtc_of_match[] = {
{ .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);
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 */
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
* We are using 32K RTC crystal (32768 / RTC_HZ / 2) -1
* If 16HZ, therefore RTC_DIV = 1023;
*/
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 */
sirfsoc_rtc_iobrg_writel(SIRFSOC_RTC_CLK,
rtcdrv->rtc_base + RTC_CLOCK_SWITCH);
sirfsoc_rtc_writel(rtcdrv, RTC_CLOCK_SWITCH, SIRFSOC_RTC_CLK);
/* 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 */
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 */
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,
&sirfsoc_rtc_ops, THIS_MODULE);
@ -372,10 +396,10 @@ static int sirfsoc_rtc_suspend(struct device *dev)
{
struct sirfsoc_rtc_drv *rtcdrv = dev_get_drvdata(dev);
rtcdrv->overflow_rtc =
sirfsoc_rtc_iobrg_readl(rtcdrv->rtc_base + RTC_SW_VALUE);
sirfsoc_rtc_readl(rtcdrv, RTC_SW_VALUE);
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;
if (device_may_wakeup(dev) && !enable_irq_wake(rtcdrv->irq))
rtcdrv->irq_wake = 1;
@ -392,12 +416,10 @@ static int sirfsoc_rtc_resume(struct device *dev)
* if resume from snapshot and the rtc power is lost,
* restroe the rtc settings
*/
if (SIRFSOC_RTC_CLK != sirfsoc_rtc_iobrg_readl(
rtcdrv->rtc_base + RTC_CLOCK_SWITCH)) {
if (SIRFSOC_RTC_CLK != sirfsoc_rtc_readl(rtcdrv, RTC_CLOCK_SWITCH)) {
u32 rtc_div;
/* 0x3 -> RTC_CLK */
sirfsoc_rtc_iobrg_writel(SIRFSOC_RTC_CLK,
rtcdrv->rtc_base + RTC_CLOCK_SWITCH);
sirfsoc_rtc_writel(rtcdrv, RTC_CLOCK_SWITCH, SIRFSOC_RTC_CLK);
/*
* Set SYS_RTC counter in RTC_HZ HZ Units
* We are using 32K RTC crystal (32768 / RTC_HZ / 2) -1
@ -405,13 +427,13 @@ static int sirfsoc_rtc_resume(struct device *dev)
*/
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 */
sirfsoc_rtc_iobrg_writel(0x0, rtcdrv->rtc_base + RTC_ALARM0);
sirfsoc_rtc_writel(rtcdrv, RTC_ALARM0, 0x0);
/* 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;
@ -419,15 +441,14 @@ static int sirfsoc_rtc_resume(struct device *dev)
* if current counter is small than previous,
* 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)
rtcdrv->overflow_rtc++;
/*
*PWRC Value Be Changed When Suspend, Restore Overflow
* In Memory To Register
*/
sirfsoc_rtc_iobrg_writel(rtcdrv->overflow_rtc,
rtcdrv->rtc_base + RTC_SW_VALUE);
sirfsoc_rtc_writel(rtcdrv, RTC_SW_VALUE, rtcdrv->overflow_rtc);
if (device_may_wakeup(dev) && rtcdrv->irq_wake) {
disable_irq_wake(rtcdrv->irq);

Просмотреть файл

@ -254,7 +254,7 @@ static ssize_t stk17ta8_nvram_read(struct file *filp, struct kobject *kobj,
void __iomem *ioaddr = pdata->ioaddr;
ssize_t count;
for (count = 0; size > 0 && pos < RTC_OFFSET; count++, size--)
for (count = 0; count < size; count++)
*buf++ = readb(ioaddr + pos++);
return count;
}
@ -269,7 +269,7 @@ static ssize_t stk17ta8_nvram_write(struct file *filp, struct kobject *kobj,
void __iomem *ioaddr = pdata->ioaddr;
ssize_t count;
for (count = 0; size > 0 && pos < RTC_OFFSET; count++, size--)
for (count = 0; count < size; count++)
writeb(*buf++, ioaddr + pos++);
return count;
}

Просмотреть файл

@ -122,20 +122,8 @@ hctosys_show(struct device *dev, struct device_attribute *attr, char *buf)
}
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
rtc_sysfs_show_wakealarm(struct device *dev, struct device_attribute *attr,
char *buf)
wakealarm_show(struct device *dev, struct device_attribute *attr, char *buf)
{
ssize_t retval;
unsigned long alarm;
@ -159,7 +147,7 @@ rtc_sysfs_show_wakealarm(struct device *dev, struct device_attribute *attr,
}
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)
{
ssize_t retval;
@ -221,45 +209,57 @@ rtc_sysfs_set_wakealarm(struct device *dev, struct device_attribute *attr,
retval = rtc_set_alarm(rtc, &alm);
return (retval < 0) ? retval : n;
}
static DEVICE_ATTR(wakealarm, S_IRUGO | S_IWUSR,
rtc_sysfs_show_wakealarm, rtc_sysfs_set_wakealarm);
static DEVICE_ATTR_RW(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)
* 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.
* (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))
return 0;
return false;
return rtc->ops->set_alarm != NULL;
}
void rtc_sysfs_add_device(struct rtc_device *rtc)
static umode_t rtc_attr_is_visible(struct kobject *kobj,
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 (!rtc_does_wakealarm(rtc))
return;
if (attr == &dev_attr_wakealarm.attr)
if (!rtc_does_wakealarm(rtc))
mode = 0;
err = device_create_file(&rtc->dev, &dev_attr_wakealarm);
if (err)
dev_err(rtc->dev.parent,
"failed to create alarm attribute, %d\n", err);
return mode;
}
void rtc_sysfs_del_device(struct rtc_device *rtc)
{
/* REVISIT did we add it successfully? */
if (rtc_does_wakealarm(rtc))
device_remove_file(&rtc->dev, &dev_attr_wakealarm);
}
static struct attribute_group rtc_attr_group = {
.is_visible = rtc_attr_is_visible,
.attrs = rtc_attrs,
};
void __init rtc_sysfs_init(struct class *rtc_class)
static const struct attribute_group *rtc_attr_groups[] = {
&rtc_attr_group,
NULL
};
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,
ssize_t count;
spin_lock_irq(&pdata->lock);
for (count = 0; size > 0 && pos < TX4939_RTC_REG_RAMSIZE;
count++, size--) {
for (count = 0; count < size; count++) {
__raw_writel(pos++, &rtcreg->adr);
*buf++ = __raw_readl(&rtcreg->dat);
}
@ -218,8 +217,7 @@ static ssize_t tx4939_rtc_nvram_write(struct file *filp, struct kobject *kobj,
ssize_t count;
spin_lock_irq(&pdata->lock);
for (count = 0; size > 0 && pos < TX4939_RTC_REG_RAMSIZE;
count++, size--) {
for (count = 0; count < size; count++) {
__raw_writel(pos++, &rtcreg->adr);
__raw_writel(*buf++, &rtcreg->dat);
}

Просмотреть файл

@ -271,6 +271,7 @@ static const struct of_device_id wmt_dt_ids[] = {
{ .compatible = "via,vt8500-rtc", },
{}
};
MODULE_DEVICE_TABLE(of, wmt_dt_ids);
static struct platform_driver vt8500_rtc_driver = {
.probe = vt8500_rtc_probe,

279
drivers/rtc/rtc-zynqmp.c Normal file
Просмотреть файл

@ -0,0 +1,279 @@
/*
* 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 @@
#include <linux/rtc.h>
#include <linux/bcd.h>
#include <linux/delay.h>
#ifdef CONFIG_ACPI
#include <linux/acpi.h>
#endif
#define RTC_PIE 0x40 /* periodic interrupt enable */
#define RTC_AIE 0x20 /* alarm interrupt enable */
@ -46,6 +49,7 @@ static inline unsigned int __get_rtc_time(struct rtc_time *time)
{
unsigned char ctrl;
unsigned long flags;
unsigned char century = 0;
#ifdef CONFIG_MACH_DECSTATION
unsigned int real_year;
@ -78,6 +82,11 @@ static inline unsigned int __get_rtc_time(struct rtc_time *time)
time->tm_year = CMOS_READ(RTC_YEAR);
#ifdef CONFIG_MACH_DECSTATION
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
ctrl = CMOS_READ(RTC_CONTROL);
spin_unlock_irqrestore(&rtc_lock, flags);
@ -90,12 +99,16 @@ static inline unsigned int __get_rtc_time(struct rtc_time *time)
time->tm_mday = bcd2bin(time->tm_mday);
time->tm_mon = bcd2bin(time->tm_mon);
time->tm_year = bcd2bin(time->tm_year);
century = bcd2bin(century);
}
#ifdef CONFIG_MACH_DECSTATION
time->tm_year += real_year - 72;
#endif
if (century)
time->tm_year += (century - 19) * 100;
/*
* Account for differences between how the RTC uses the values
* and how they are defined in a struct rtc_time;
@ -122,6 +135,7 @@ static inline int __set_rtc_time(struct rtc_time *time)
#ifdef CONFIG_MACH_DECSTATION
unsigned int real_yrs, leap_yr;
#endif
unsigned char century = 0;
yrs = time->tm_year;
mon = time->tm_mon + 1; /* tm_mon starts at zero */
@ -150,6 +164,15 @@ static inline int __set_rtc_time(struct rtc_time *time)
yrs = 73;
}
#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
* whether the chip is in binary mode or not.
*/
@ -169,6 +192,7 @@ static inline int __set_rtc_time(struct rtc_time *time)
day = bin2bcd(day);
mon = bin2bcd(mon);
yrs = bin2bcd(yrs);
century = bin2bcd(century);
}
save_control = CMOS_READ(RTC_CONTROL);
@ -185,6 +209,11 @@ static inline int __set_rtc_time(struct rtc_time *time)
CMOS_WRITE(hrs, RTC_HOURS);
CMOS_WRITE(min, RTC_MINUTES);
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_freq_select, RTC_FREQ_SELECT);