Subsystem:
  - The rtc_time_to_tm and rtc_tm_to_time wrappers have finally been removed and
    only the 64bit version remain.
  - hctosys now works with drivers compiled as modules
 
 New driver:
  - MediaTek MT2712 SoC based RTC
 
 Drivers:
  - set range for 88pm860x, au1xxx, cpcap, da9052, davinci, ds1305, ds1374,
    mcp5121, pl030, pl031, pm8xxx, puv3, sa1100, sirfsoc, starfire, sun6i
  - ds1307: DS1388 oscillator failure detection and watchdog support
  - jz4740: JZ4760 support
  - pcf85063: clock out pin support
  - sun6i: external 32k oscillator is now optional, the range is now handled by
    the core, providing a solution for 2034.
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEycoQi/giopmpPgB12wIijOdRNOUFAl6IgdAACgkQ2wIijOdR
 NOVH9Q//evfZmRDQb9Lm8YuSOt+U6lBaCuvRP8H4s7i02jsw0tt1oT6+rGo+1N+k
 pi64+iwPqDj7h+eds06jVur7yWZDNNfCSywlMU8ODGLQcc/hXMTvaIeJtdXG+I+7
 dpIVTs9Artiey2Qb3qZalSMYzrE2rQG6Yuyb/tHx7Pohvje1wKnAE3T64W6sfvir
 zjAwAr/+s9n82mjGtGLapz0onao7dSN4p6b3UIkph9KxPdeHjItd7cRiJuzioysj
 LE8WRUek++uha32PzghK9MoUpRKf8PJtGbsAIRhdwvmwub1Pqs6Uvk5IHQvdiFZx
 af1Qnw/4qUH03HVUuq8VdEkwa8mdthcZ72b8uzUWOqP+uPkeTTlQOGOd1dRECijK
 Qic+SKlEznwgKC9WuDufUQg5i2WjFBnBlA+dCE12/t91SbSlZdYjb53nQLHve1b9
 e4VfyKnS5Ghn/dfizzzSPdcWuPW1rqq2dHTiOvFVqlLn1Fkt1AKaJzGAeCe6PWp4
 AJVqPu+D1eQ/qmvEPXI7dQpCxdI+p6FNJgQvQLMssaq7mpf2fiRoLx23ikFG0v0k
 BeNkNWpLz2ACwHpsOa/RWLwa/FC2+KBHaRWf+As7te63byeDQC8hUEi7F5K78lSS
 yhfZ8SJR04SIIGKjuwAzPmaaIJ0hJT+eaxkFAJU7P5hD7KElsuM=
 =6Veu
 -----END PGP SIGNATURE-----

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

Pull RTC updates from Alexandre Belloni:
 "More cleanup this cycle, with the final goal of removing the
  rtc_time_to_tm and rtc_tm_to_time wrappers. All the drivers that have
  been modified for this now are ready for the end of times (whether it
  happens in 2033, 2038, 2106, 2127 or even 4052). There is also a
  single new driver and the usual fixes and features.

  Summary:

  Subsystem:

   - The rtc_time_to_tm and rtc_tm_to_time wrappers have finally been
     removed and only the 64bit version remain.

   - hctosys now works with drivers compiled as modules

  New driver:

   - MediaTek MT2712 SoC based RTC

  Drivers:

   - set range for 88pm860x, au1xxx, cpcap, da9052, davinci, ds1305,
     ds1374, mcp5121, pl030, pl031, pm8xxx, puv3, sa1100, sirfsoc,
     starfire, sun6i

   - ds1307: DS1388 oscillator failure detection and watchdog support

   - jz4740: JZ4760 support

   - pcf85063: clock out pin support

   - sun6i: external 32k oscillator is now optional, the range is now
     handled by the core, providing a solution for 2034"

* tag 'rtc-5.7' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux: (87 commits)
  rtc: ds1307: check for failed memory allocation on wdt
  rtc: class: remove redundant assignment to variable err
  rtc: remove rtc_time_to_tm and rtc_tm_to_time
  rtc: sun6i: let the core handle rtc range
  rtc: sun6i: switch to rtc_time64_to_tm/rtc_tm_to_time64
  rtc: ds1307: add support for watchdog timer on ds1388
  rtc: da9052: switch to rtc_time64_to_tm/rtc_tm_to_time64
  rtc: da9052: set range
  rtc: da9052: convert to devm_rtc_allocate_device
  rtc: imx-sc: Align imx sc msg structs to 4
  rtc: fsl-ftm-alarm: report alarm to core
  rtc: pcf85063: Add pcf85063 clkout control to common clock framework
  rtc: make definitions in include/uapi/linux/rtc.h actually useful for user space
  rtc: class: avoid unnecessary lookup in hctosys
  dt-bindings: rtc: Convert and update jz4740-rtc doc to YAML
  rtc: jz4740: Rename vendor-specific DT properties
  rtc: jz4740: Add support for JZ4760 SoC
  rtc: class: support hctosys from modular RTC drivers
  rtc: pm8xxx: clear alarm register when alarm is not enabled
  rtc: omap: drop unused dt-bindings header
  ...
This commit is contained in:
Linus Torvalds 2020-04-04 10:38:01 -07:00
Родитель 828907ef25 1821b79d6a
Коммит bdabb68931
42 изменённых файлов: 1192 добавлений и 574 удалений

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

@ -1,37 +0,0 @@
JZ4740 and similar SoCs real-time clock driver
Required properties:
- compatible: One of:
- "ingenic,jz4740-rtc" - for use with the JZ4740 SoC
- "ingenic,jz4780-rtc" - for use with the JZ4780 SoC
- reg: Address range of rtc register set
- interrupts: IRQ number for the alarm interrupt
- clocks: phandle to the "rtc" clock
- clock-names: must be "rtc"
Optional properties:
- system-power-controller: To use this component as the
system power controller
- reset-pin-assert-time-ms: Reset pin low-level assertion
time after wakeup (default 60ms; range 0-125ms if RTC clock
at 32 kHz)
- min-wakeup-pin-assert-time-ms: Minimum wakeup pin assertion
time (default 100ms; range 0-2s if RTC clock at 32 kHz)
Example:
rtc@10003000 {
compatible = "ingenic,jz4740-rtc";
reg = <0x10003000 0x40>;
interrupt-parent = <&intc>;
interrupts = <32>;
clocks = <&rtc_clock>;
clock-names = "rtc";
system-power-controller;
reset-pin-assert-time-ms = <60>;
min-wakeup-pin-assert-time-ms = <100>;
};

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

@ -0,0 +1,83 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/rtc/ingenic,rtc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Ingenic SoCs Real-Time Clock DT bindings
maintainers:
- Paul Cercueil <paul@crapouillou.net>
allOf:
- $ref: rtc.yaml#
properties:
compatible:
oneOf:
- enum:
- ingenic,jz4740-rtc
- ingenic,jz4760-rtc
- items:
- const: ingenic,jz4725b-rtc
- const: ingenic,jz4740-rtc
- items:
- enum:
- ingenic,jz4770-rtc
- ingenic,jz4780-rtc
- const: ingenic,jz4760-rtc
reg:
maxItems: 1
interrupts:
maxItems: 1
clocks:
maxItems: 1
clock-names:
const: rtc
system-power-controller:
description: |
Indicates that the RTC is responsible for powering OFF
the system.
type: boolean
ingenic,reset-pin-assert-time-ms:
minimum: 0
maximum: 125
default: 60
description: |
Reset pin low-level assertion time after wakeup
(assuming RTC clock at 32 kHz)
ingenic,min-wakeup-pin-assert-time-ms:
minimum: 0
maximum: 2000
default: 100
description: |
Minimum wakeup pin assertion time
(assuming RTC clock at 32 kHz)
required:
- compatible
- reg
- interrupts
- clocks
- clock-names
examples:
- |
#include <dt-bindings/clock/jz4740-cgu.h>
rtc_dev: rtc@10003000 {
compatible = "ingenic,jz4740-rtc";
reg = <0x10003000 0x40>;
interrupt-parent = <&intc>;
interrupts = <15>;
clocks = <&cgu JZ4740_CLK_RTC>;
clock-names = "rtc";
};

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

@ -0,0 +1,14 @@
Device-Tree bindings for MediaTek SoC based RTC
Required properties:
- compatible : Should be "mediatek,mt2712-rtc" : for MT2712 SoC
- reg : Specifies base physical address and size of the registers;
- interrupts : Should contain the interrupt for RTC alarm;
Example:
rtc: rtc@10011000 {
compatible = "mediatek,mt2712-rtc";
reg = <0 0x10011000 0 0x1000>;
interrupts = <GIC_SPI 239 IRQ_TYPE_LEVEL_LOW>;
};

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

@ -2015,7 +2015,9 @@ M: Sean Wang <sean.wang@mediatek.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
L: linux-mediatek@lists.infradead.org (moderated for non-subscribers)
S: Maintained
F: Documentation/devicetree/bindings/rtc/rtc-mt2712.txt
F: Documentation/devicetree/bindings/rtc/rtc-mt7622.txt
F: drivers/rtc/rtc-mt2712.c
F: drivers/rtc/rtc-mt6397.c
F: drivers/rtc/rtc-mt7622.c

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

@ -41,9 +41,6 @@ config RTC_HCTOSYS_DEVICE
device should record time in UTC, since the kernel won't do
timezone correction.
The driver for this RTC device must be loaded before late_initcall
functions run, so it must usually be statically linked.
This clock should be battery-backed, so that it reads the correct
time when the system boots from a power-off state. Otherwise, your
system will need an external clock source (like an NTP server).
@ -241,6 +238,7 @@ config RTC_DRV_AS3722
config RTC_DRV_DS1307
tristate "Dallas/Maxim DS1307/37/38/39/40/41, ST M41T00, EPSON RX-8025, ISL12057"
select REGMAP_I2C
select WATCHDOG_CORE if WATCHDOG
help
If you say yes here you get support for various compatible RTC
chips (often with battery backup) connected with I2C. This driver
@ -1335,7 +1333,7 @@ config RTC_DRV_IMXDI
config RTC_DRV_FSL_FTM_ALARM
tristate "Freescale FlexTimer alarm timer"
depends on ARCH_LAYERSCAPE || SOC_LS1021A
depends on ARCH_LAYERSCAPE || SOC_LS1021A || COMPILE_TEST
help
For the FlexTimer in LS1012A, LS1021A, LS1028A, LS1043A, LS1046A,
LS1088A, LS208xA, we can use FTM as the wakeup source.
@ -1762,6 +1760,7 @@ config RTC_DRV_MXC_V2
config RTC_DRV_SNVS
tristate "Freescale SNVS RTC support"
select REGMAP_MMIO
depends on ARCH_MXC || COMPILE_TEST
depends on HAS_IOMEM
depends on OF
help
@ -1807,6 +1806,16 @@ config RTC_DRV_MOXART
This driver can also be built as a module. If so, the module
will be called rtc-moxart
config RTC_DRV_MT2712
tristate "MediaTek MT2712 SoC based RTC"
depends on ARCH_MEDIATEK || COMPILE_TEST
help
This enables support for the real time clock built in the MediaTek
SoCs for MT2712.
This drive can also be built as a module. If so, the module
will be called rtc-mt2712.
config RTC_DRV_MT6397
tristate "MediaTek PMIC based RTC"
depends on MFD_MT6397 || (COMPILE_TEST && IRQ_DOMAIN)

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

@ -6,7 +6,6 @@
ccflags-$(CONFIG_RTC_DEBUG) := -DDEBUG
obj-$(CONFIG_RTC_LIB) += lib.o
obj-$(CONFIG_RTC_HCTOSYS) += hctosys.o
obj-$(CONFIG_RTC_SYSTOHC) += systohc.o
obj-$(CONFIG_RTC_CLASS) += rtc-core.o
obj-$(CONFIG_RTC_MC146818_LIB) += rtc-mc146818-lib.o
@ -106,6 +105,7 @@ obj-$(CONFIG_RTC_DRV_MESON) += rtc-meson.o
obj-$(CONFIG_RTC_DRV_MOXART) += rtc-moxart.o
obj-$(CONFIG_RTC_DRV_MPC5121) += rtc-mpc5121.o
obj-$(CONFIG_RTC_DRV_MSM6242) += rtc-msm6242.o
obj-$(CONFIG_RTC_DRV_MT2712) += rtc-mt2712.o
obj-$(CONFIG_RTC_DRV_MT6397) += rtc-mt6397.o
obj-$(CONFIG_RTC_DRV_MT7622) += rtc-mt7622.o
obj-$(CONFIG_RTC_DRV_MV) += rtc-mv.o

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

@ -34,6 +34,50 @@ static void rtc_device_release(struct device *dev)
#ifdef CONFIG_RTC_HCTOSYS_DEVICE
/* Result of the last RTC to system clock attempt. */
int rtc_hctosys_ret = -ENODEV;
/* IMPORTANT: the RTC only stores whole seconds. It is arbitrary
* whether it stores the most close value or the value with partial
* seconds truncated. However, it is important that we use it to store
* the truncated value. This is because otherwise it is necessary,
* in an rtc sync function, to read both xtime.tv_sec and
* xtime.tv_nsec. On some processors (i.e. ARM), an atomic read
* of >32bits is not possible. So storing the most close value would
* slow down the sync API. So here we have the truncated value and
* the best guess is to add 0.5s.
*/
static void rtc_hctosys(struct rtc_device *rtc)
{
int err;
struct rtc_time tm;
struct timespec64 tv64 = {
.tv_nsec = NSEC_PER_SEC >> 1,
};
err = rtc_read_time(rtc, &tm);
if (err) {
dev_err(rtc->dev.parent,
"hctosys: unable to read the hardware clock\n");
goto err_read;
}
tv64.tv_sec = rtc_tm_to_time64(&tm);
#if BITS_PER_LONG == 32
if (tv64.tv_sec > INT_MAX) {
err = -ERANGE;
goto err_read;
}
#endif
err = do_settimeofday64(&tv64);
dev_info(rtc->dev.parent, "setting system clock to %ptR UTC (%lld)\n",
&tm, (long long)tv64.tv_sec);
err_read:
rtc_hctosys_ret = err;
}
#endif
#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_RTC_HCTOSYS_DEVICE)
@ -375,6 +419,11 @@ int __rtc_register_device(struct module *owner, struct rtc_device *rtc)
dev_info(rtc->dev.parent, "registered as %s\n",
dev_name(&rtc->dev));
#ifdef CONFIG_RTC_HCTOSYS_DEVICE
if (!strcmp(dev_name(&rtc->dev), CONFIG_RTC_HCTOSYS_DEVICE))
rtc_hctosys(rtc);
#endif
return 0;
}
EXPORT_SYMBOL_GPL(__rtc_register_device);

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

@ -1,69 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
/*
* RTC subsystem, initialize system time on startup
*
* Copyright (C) 2005 Tower Technologies
* Author: Alessandro Zummo <a.zummo@towertech.it>
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/rtc.h>
/* IMPORTANT: the RTC only stores whole seconds. It is arbitrary
* whether it stores the most close value or the value with partial
* seconds truncated. However, it is important that we use it to store
* the truncated value. This is because otherwise it is necessary,
* in an rtc sync function, to read both xtime.tv_sec and
* xtime.tv_nsec. On some processors (i.e. ARM), an atomic read
* of >32bits is not possible. So storing the most close value would
* slow down the sync API. So here we have the truncated value and
* the best guess is to add 0.5s.
*/
static int __init rtc_hctosys(void)
{
int err = -ENODEV;
struct rtc_time tm;
struct timespec64 tv64 = {
.tv_nsec = NSEC_PER_SEC >> 1,
};
struct rtc_device *rtc = rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE);
if (!rtc) {
pr_info("unable to open rtc device (%s)\n",
CONFIG_RTC_HCTOSYS_DEVICE);
goto err_open;
}
err = rtc_read_time(rtc, &tm);
if (err) {
dev_err(rtc->dev.parent,
"hctosys: unable to read the hardware clock\n");
goto err_read;
}
tv64.tv_sec = rtc_tm_to_time64(&tm);
#if BITS_PER_LONG == 32
if (tv64.tv_sec > INT_MAX) {
err = -ERANGE;
goto err_read;
}
#endif
err = do_settimeofday64(&tv64);
dev_info(rtc->dev.parent, "setting system clock to %ptR UTC (%lld)\n",
&tm, (long long)tv64.tv_sec);
err_read:
rtc_class_close(rtc);
err_open:
rtc_hctosys_ret = err;
return err;
}
late_initcall(rtc_hctosys);

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

@ -28,7 +28,6 @@ struct pm860x_rtc_info {
int irq;
int vrtc;
int (*sync)(unsigned int ticks);
};
#define REG_VRTC_MEAS1 0x7D
@ -76,33 +75,6 @@ static int pm860x_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
return 0;
}
/*
* Calculate the next alarm time given the requested alarm time mask
* and the current time.
*/
static void rtc_next_alarm_time(struct rtc_time *next, struct rtc_time *now,
struct rtc_time *alrm)
{
unsigned long next_time;
unsigned long now_time;
next->tm_year = now->tm_year;
next->tm_mon = now->tm_mon;
next->tm_mday = now->tm_mday;
next->tm_hour = alrm->tm_hour;
next->tm_min = alrm->tm_min;
next->tm_sec = alrm->tm_sec;
rtc_tm_to_time(now, &now_time);
rtc_tm_to_time(next, &next_time);
if (next_time < now_time) {
/* Advance one day */
next_time += 60 * 60 * 24;
rtc_time_to_tm(next_time, next);
}
}
static int pm860x_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
struct pm860x_rtc_info *info = dev_get_drvdata(dev);
@ -123,7 +95,7 @@ static int pm860x_rtc_read_time(struct device *dev, struct rtc_time *tm)
dev_dbg(info->dev, "get base:0x%lx, RO count:0x%lx, ticks:0x%lx\n",
base, data, ticks);
rtc_time_to_tm(ticks, tm);
rtc_time64_to_tm(ticks, tm);
return 0;
}
@ -140,7 +112,7 @@ static int pm860x_rtc_set_time(struct device *dev, struct rtc_time *tm)
1900 + tm->tm_year);
return -EINVAL;
}
rtc_tm_to_time(tm, &ticks);
ticks = rtc_tm_to_time64(tm);
/* load 32-bit read-only counter */
pm860x_bulk_read(info->i2c, PM8607_RTC_COUNTER1, 4, buf);
@ -155,8 +127,6 @@ static int pm860x_rtc_set_time(struct device *dev, struct rtc_time *tm)
pm860x_page_reg_write(info->i2c, REG2_DATA, (base >> 8) & 0xFF);
pm860x_page_reg_write(info->i2c, REG3_DATA, base & 0xFF);
if (info->sync)
info->sync(ticks);
return 0;
}
@ -180,7 +150,7 @@ static int pm860x_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
dev_dbg(info->dev, "get base:0x%lx, RO count:0x%lx, ticks:0x%lx\n",
base, data, ticks);
rtc_time_to_tm(ticks, &alrm->time);
rtc_time64_to_tm(ticks, &alrm->time);
ret = pm860x_reg_read(info->i2c, PM8607_RTC1);
alrm->enabled = (ret & ALARM_EN) ? 1 : 0;
alrm->pending = (ret & (ALARM | ALARM_WAKEUP)) ? 1 : 0;
@ -190,7 +160,6 @@ static int pm860x_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
static int pm860x_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
struct pm860x_rtc_info *info = dev_get_drvdata(dev);
struct rtc_time now_tm, alarm_tm;
unsigned long ticks, base, data;
unsigned char buf[8];
int mask;
@ -203,18 +172,7 @@ static int pm860x_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
base = ((unsigned long)buf[1] << 24) | (buf[3] << 16) |
(buf[5] << 8) | buf[7];
/* load 32-bit read-only counter */
pm860x_bulk_read(info->i2c, PM8607_RTC_COUNTER1, 4, buf);
data = ((unsigned long)buf[3] << 24) | (buf[2] << 16) |
(buf[1] << 8) | buf[0];
ticks = base + data;
dev_dbg(info->dev, "get base:0x%lx, RO count:0x%lx, ticks:0x%lx\n",
base, data, ticks);
rtc_time_to_tm(ticks, &now_tm);
rtc_next_alarm_time(&alarm_tm, &now_tm, &alrm->time);
/* get new ticks for alarm in 24 hours */
rtc_tm_to_time(&alarm_tm, &ticks);
ticks = rtc_tm_to_time64(&alrm->time);
data = ticks - base;
buf[0] = data & 0xff;
@ -309,20 +267,15 @@ static int pm860x_rtc_dt_init(struct platform_device *pdev,
return 0;
}
#else
#define pm860x_rtc_dt_init(x, y) (-1)
#define pm860x_rtc_dt_init(x, y) do { } while (0)
#endif
static int pm860x_rtc_probe(struct platform_device *pdev)
{
struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
struct pm860x_rtc_pdata *pdata = NULL;
struct pm860x_rtc_info *info;
struct rtc_time tm;
unsigned long ticks = 0;
int ret;
pdata = dev_get_platdata(&pdev->dev);
info = devm_kzalloc(&pdev->dev, sizeof(struct pm860x_rtc_info),
GFP_KERNEL);
if (!info)
@ -336,6 +289,10 @@ static int pm860x_rtc_probe(struct platform_device *pdev)
info->dev = &pdev->dev;
dev_set_drvdata(&pdev->dev, info);
info->rtc_dev = devm_rtc_allocate_device(&pdev->dev);
if (IS_ERR(info->rtc_dev))
return PTR_ERR(info->rtc_dev);
ret = devm_request_threaded_irq(&pdev->dev, info->irq, NULL,
rtc_update_handler, IRQF_ONESHOT, "rtc",
info);
@ -351,39 +308,14 @@ static int pm860x_rtc_probe(struct platform_device *pdev)
pm860x_page_reg_write(info->i2c, REG2_ADDR, REG2_DATA);
pm860x_page_reg_write(info->i2c, REG3_ADDR, REG3_DATA);
ret = pm860x_rtc_read_time(&pdev->dev, &tm);
if (ret < 0) {
dev_err(&pdev->dev, "Failed to read initial time.\n");
return ret;
}
if ((tm.tm_year < 70) || (tm.tm_year > 138)) {
tm.tm_year = 70;
tm.tm_mon = 0;
tm.tm_mday = 1;
tm.tm_hour = 0;
tm.tm_min = 0;
tm.tm_sec = 0;
ret = pm860x_rtc_set_time(&pdev->dev, &tm);
if (ret < 0) {
dev_err(&pdev->dev, "Failed to set initial time.\n");
return ret;
}
}
rtc_tm_to_time(&tm, &ticks);
if (pm860x_rtc_dt_init(pdev, info)) {
if (pdata && pdata->sync) {
pdata->sync(ticks);
info->sync = pdata->sync;
}
}
pm860x_rtc_dt_init(pdev, info);
info->rtc_dev = devm_rtc_device_register(&pdev->dev, "88pm860x-rtc",
&pm860x_rtc_ops, THIS_MODULE);
ret = PTR_ERR(info->rtc_dev);
if (IS_ERR(info->rtc_dev)) {
dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret);
info->rtc_dev->ops = &pm860x_rtc_ops;
info->rtc_dev->range_max = U32_MAX;
ret = rtc_register_device(info->rtc_dev);
if (ret)
return ret;
}
/*
* enable internal XO instead of internal 3.25MHz clock since it can
@ -393,12 +325,6 @@ static int pm860x_rtc_probe(struct platform_device *pdev)
#ifdef VRTC_CALIBRATION
/* <00> -- 2.7V, <01> -- 2.9V, <10> -- 3.1V, <11> -- 3.3V */
if (pm860x_rtc_dt_init(pdev, info)) {
if (pdata && pdata->vrtc)
info->vrtc = pdata->vrtc & 0x3;
else
info->vrtc = 1;
}
pm860x_set_bits(info->i2c, PM8607_MEAS_EN2, MEAS2_VRTC, MEAS2_VRTC);
/* calibrate VRTC */

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

@ -100,7 +100,7 @@ static int ab8500_rtc_read_time(struct device *dev, struct rtc_time *tm)
secs = secs / COUNTS_PER_SEC;
secs = secs + (mins * 60);
rtc_time_to_tm(secs, tm);
rtc_time64_to_tm(secs, tm);
return 0;
}
@ -110,7 +110,7 @@ static int ab8500_rtc_set_time(struct device *dev, struct rtc_time *tm)
unsigned char buf[ARRAY_SIZE(ab8500_rtc_time_regs)];
unsigned long no_secs, no_mins, secs = 0;
rtc_tm_to_time(tm, &secs);
secs = rtc_tm_to_time64(tm);
no_mins = secs / 60;
@ -168,7 +168,7 @@ static int ab8500_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
mins = (buf[0] << 16) | (buf[1] << 8) | (buf[2]);
secs = mins * 60;
rtc_time_to_tm(secs, &alarm->time);
rtc_time64_to_tm(secs, &alarm->time);
return 0;
}
@ -188,7 +188,7 @@ static int ab8500_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
struct rtc_time curtm;
/* Get the number of seconds since 1970 */
rtc_tm_to_time(&alarm->time, &secs);
secs = rtc_tm_to_time64(&alarm->time);
/*
* Check whether alarm is set less than 1min.
@ -196,7 +196,7 @@ static int ab8500_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
* return -EINVAL, so UIE EMUL can take it up, incase of UIE_ON
*/
ab8500_rtc_read_time(dev, &curtm); /* Read current time */
rtc_tm_to_time(&curtm, &cursec);
cursec = rtc_tm_to_time64(&curtm);
if ((secs - cursec) < 59) {
dev_dbg(dev, "Alarm less than 1 minute not supported\r\n");
return -EINVAL;

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

@ -34,7 +34,7 @@ static int au1xtoy_rtc_read_time(struct device *dev, struct rtc_time *tm)
t = alchemy_rdsys(AU1000_SYS_TOYREAD);
rtc_time_to_tm(t, tm);
rtc_time64_to_tm(t, tm);
return 0;
}
@ -43,7 +43,7 @@ static int au1xtoy_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
unsigned long t;
rtc_tm_to_time(tm, &t);
t = rtc_tm_to_time64(tm);
alchemy_wrsys(t, AU1000_SYS_TOYWRITE);
@ -65,17 +65,13 @@ static int au1xtoy_rtc_probe(struct platform_device *pdev)
{
struct rtc_device *rtcdev;
unsigned long t;
int ret;
t = alchemy_rdsys(AU1000_SYS_CNTRCTRL);
if (!(t & CNTR_OK)) {
dev_err(&pdev->dev, "counters not working; aborting.\n");
ret = -ENODEV;
goto out_err;
return -ENODEV;
}
ret = -ETIMEDOUT;
/* set counter0 tickrate to 1Hz if necessary */
if (alchemy_rdsys(AU1000_SYS_TOYTRIM) != 32767) {
/* wait until hardware gives access to TRIM register */
@ -88,7 +84,7 @@ static int au1xtoy_rtc_probe(struct platform_device *pdev)
* counters are unusable.
*/
dev_err(&pdev->dev, "timeout waiting for access\n");
goto out_err;
return -ETIMEDOUT;
}
/* set 1Hz TOY tick rate */
@ -99,19 +95,16 @@ static int au1xtoy_rtc_probe(struct platform_device *pdev)
while (alchemy_rdsys(AU1000_SYS_CNTRCTRL) & SYS_CNTRL_C0S)
msleep(1);
rtcdev = devm_rtc_device_register(&pdev->dev, "rtc-au1xxx",
&au1xtoy_rtc_ops, THIS_MODULE);
if (IS_ERR(rtcdev)) {
ret = PTR_ERR(rtcdev);
goto out_err;
}
rtcdev = devm_rtc_allocate_device(&pdev->dev);
if (IS_ERR(rtcdev))
return PTR_ERR(rtcdev);
rtcdev->ops = &au1xtoy_rtc_ops;
rtcdev->range_max = U32_MAX;
platform_set_drvdata(pdev, rtcdev);
return 0;
out_err:
return ret;
return rtc_register_device(rtcdev);
}
static struct platform_driver au1xrtc_driver = {

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

@ -542,10 +542,8 @@ static int bd70528_probe(struct platform_device *pdev)
irq = platform_get_irq_byname(pdev, irq_name);
if (irq < 0) {
dev_err(&pdev->dev, "Failed to get irq\n");
if (irq < 0)
return irq;
}
platform_set_drvdata(pdev, bd_rtc);

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

@ -649,10 +649,11 @@ static struct cmos_rtc cmos_rtc;
static irqreturn_t cmos_interrupt(int irq, void *p)
{
unsigned long flags;
u8 irqstat;
u8 rtc_control;
spin_lock(&rtc_lock);
spin_lock_irqsave(&rtc_lock, flags);
/* When the HPET interrupt handler calls us, the interrupt
* status is passed as arg1 instead of the irq number. But
@ -686,7 +687,7 @@ static irqreturn_t cmos_interrupt(int irq, void *p)
hpet_mask_rtc_irq_bit(RTC_AIE);
CMOS_READ(RTC_INTR_FLAGS);
}
spin_unlock(&rtc_lock);
spin_unlock_irqrestore(&rtc_lock, flags);
if (is_intr(irqstat)) {
rtc_update_irq(p, 1, irqstat);

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

@ -56,14 +56,14 @@ static void cpcap2rtc_time(struct rtc_time *rtc, struct cpcap_time *cpcap)
tod = (cpcap->tod1 & TOD1_MASK) | ((cpcap->tod2 & TOD2_MASK) << 8);
time = tod + ((cpcap->day & DAY_MASK) * SECS_PER_DAY);
rtc_time_to_tm(time, rtc);
rtc_time64_to_tm(time, rtc);
}
static void rtc2cpcap_time(struct cpcap_time *cpcap, struct rtc_time *rtc)
{
unsigned long time;
rtc_tm_to_time(rtc, &time);
time = rtc_tm_to_time64(rtc);
cpcap->day = time / SECS_PER_DAY;
time %= SECS_PER_DAY;
@ -256,12 +256,13 @@ static int cpcap_rtc_probe(struct platform_device *pdev)
return -ENODEV;
platform_set_drvdata(pdev, rtc);
rtc->rtc_dev = devm_rtc_device_register(dev, "cpcap_rtc",
&cpcap_rtc_ops, THIS_MODULE);
rtc->rtc_dev = devm_rtc_allocate_device(dev);
if (IS_ERR(rtc->rtc_dev))
return PTR_ERR(rtc->rtc_dev);
rtc->rtc_dev->ops = &cpcap_rtc_ops;
rtc->rtc_dev->range_max = (1 << 14) * SECS_PER_DAY - 1;
err = cpcap_get_vendor(dev, rtc->regmap, &rtc->vendor);
if (err)
return err;
@ -298,7 +299,7 @@ static int cpcap_rtc_probe(struct platform_device *pdev)
/* ignore error and continue without wakeup support */
}
return 0;
return rtc_register_device(rtc->rtc_dev);
}
static const struct of_device_id cpcap_rtc_of_match[] = {

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

@ -103,13 +103,11 @@ static int da9052_set_alarm(struct da9052_rtc *rtc, struct rtc_time *rtc_tm)
int ret;
uint8_t v[3];
ret = rtc_tm_to_time(rtc_tm, &alm_time);
if (ret != 0)
return ret;
alm_time = rtc_tm_to_time64(rtc_tm);
if (rtc_tm->tm_sec > 0) {
alm_time += 60 - rtc_tm->tm_sec;
rtc_time_to_tm(alm_time, rtc_tm);
rtc_time64_to_tm(alm_time, rtc_tm);
}
BUG_ON(rtc_tm->tm_sec); /* it will cause repeated irqs if not zero */
@ -298,12 +296,18 @@ static int da9052_rtc_probe(struct platform_device *pdev)
rtc_err(rtc, "Failed to disable TICKS: %d\n", ret);
device_init_wakeup(&pdev->dev, true);
rtc->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
&da9052_rtc_ops, THIS_MODULE);
rtc->rtc = devm_rtc_allocate_device(&pdev->dev);
if (IS_ERR(rtc->rtc))
return PTR_ERR(rtc->rtc);
rtc->rtc->ops = &da9052_rtc_ops;
rtc->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
rtc->rtc->range_max = RTC_TIMESTAMP_END_2063;
ret = rtc_register_device(rtc->rtc);
if (ret)
return ret;
ret = da9052_request_irq(rtc->da9052, DA9052_IRQ_ALARM, "ALM",
da9052_rtc_irq, rtc);
if (ret != 0) {

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

@ -227,7 +227,7 @@ davinci_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
return ret;
}
static int convertfromdays(u16 days, struct rtc_time *tm)
static void convertfromdays(u16 days, struct rtc_time *tm)
{
int tmp_days, year, mon;
@ -250,24 +250,17 @@ static int convertfromdays(u16 days, struct rtc_time *tm)
break;
}
}
return 0;
}
static int convert2days(u16 *days, struct rtc_time *tm)
static void convert2days(u16 *days, struct rtc_time *tm)
{
int i;
*days = 0;
/* epoch == 1900 */
if (tm->tm_year < 100 || tm->tm_year > 199)
return -EINVAL;
for (i = 2000; i < 1900 + tm->tm_year; i++)
*days += rtc_year_days(1, 12, i);
*days += rtc_year_days(tm->tm_mday, tm->tm_mon, 1900 + tm->tm_year);
return 0;
}
static int davinci_rtc_read_time(struct device *dev, struct rtc_time *tm)
@ -300,8 +293,7 @@ static int davinci_rtc_read_time(struct device *dev, struct rtc_time *tm)
days <<= 8;
days |= day0;
if (convertfromdays(days, tm) < 0)
return -EINVAL;
convertfromdays(days, tm);
return 0;
}
@ -313,8 +305,7 @@ static int davinci_rtc_set_time(struct device *dev, struct rtc_time *tm)
u8 rtc_cctrl;
unsigned long flags;
if (convert2days(&days, tm) < 0)
return -EINVAL;
convert2days(&days, tm);
spin_lock_irqsave(&davinci_rtc_lock, flags);
@ -396,8 +387,7 @@ static int davinci_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
days <<= 8;
days |= day0;
if (convertfromdays(days, &alm->time) < 0)
return -EINVAL;
convertfromdays(days, &alm->time);
alm->pending = !!(rtcss_read(davinci_rtc,
PRTCSS_RTC_CCTRL) &
@ -413,29 +403,7 @@ static int davinci_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
unsigned long flags;
u16 days;
if (alm->time.tm_mday <= 0 && alm->time.tm_mon < 0
&& alm->time.tm_year < 0) {
struct rtc_time tm;
unsigned long now, then;
davinci_rtc_read_time(dev, &tm);
rtc_tm_to_time(&tm, &now);
alm->time.tm_mday = tm.tm_mday;
alm->time.tm_mon = tm.tm_mon;
alm->time.tm_year = tm.tm_year;
rtc_tm_to_time(&alm->time, &then);
if (then < now) {
rtc_time_to_tm(now + 24 * 60 * 60, &tm);
alm->time.tm_mday = tm.tm_mday;
alm->time.tm_mon = tm.tm_mon;
alm->time.tm_year = tm.tm_year;
}
}
if (convert2days(&days, &alm->time) < 0)
return -EINVAL;
convert2days(&days, &alm->time);
spin_lock_irqsave(&davinci_rtc_lock, flags);
@ -485,13 +453,13 @@ static int __init davinci_rtc_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, davinci_rtc);
davinci_rtc->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
&davinci_rtc_ops, THIS_MODULE);
if (IS_ERR(davinci_rtc->rtc)) {
dev_err(dev, "unable to register RTC device, err %d\n",
ret);
davinci_rtc->rtc = devm_rtc_allocate_device(&pdev->dev);
if (IS_ERR(davinci_rtc->rtc))
return PTR_ERR(davinci_rtc->rtc);
}
davinci_rtc->rtc->ops = &davinci_rtc_ops;
davinci_rtc->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
davinci_rtc->rtc->range_max = RTC_TIMESTAMP_BEGIN_2000 + (1 << 16) * 86400ULL - 1;
rtcif_write(davinci_rtc, PRTCIF_INTFLG_RTCSS, PRTCIF_INTFLG);
rtcif_write(davinci_rtc, 0, PRTCIF_INTEN);
@ -516,7 +484,7 @@ static int __init davinci_rtc_probe(struct platform_device *pdev)
device_init_wakeup(&pdev->dev, 0);
return 0;
return rtc_register_device(davinci_rtc->rtc);
}
static int __exit davinci_rtc_remove(struct platform_device *pdev)

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

@ -325,17 +325,13 @@ static int ds1305_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
u8 buf[1 + DS1305_ALM_LEN];
/* convert desired alarm to time_t */
status = rtc_tm_to_time(&alm->time, &later);
if (status < 0)
return status;
later = rtc_tm_to_time64(&alm->time);
/* Read current time as time_t */
status = ds1305_get_time(dev, &tm);
if (status < 0)
return status;
status = rtc_tm_to_time(&tm, &now);
if (status < 0)
return status;
now = rtc_tm_to_time64(&tm);
/* make sure alarm fires within the next 24 hours */
if (later <= now)
@ -694,6 +690,8 @@ static int ds1305_probe(struct spi_device *spi)
return PTR_ERR(ds1305->rtc);
ds1305->rtc->ops = &ds1305_ops;
ds1305->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
ds1305->rtc->range_max = RTC_TIMESTAMP_END_2099;
ds1305_nvmem_cfg.priv = ds1305;
ds1305->rtc->nvram_old_abi = true;

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

@ -22,6 +22,7 @@
#include <linux/hwmon-sysfs.h>
#include <linux/clk-provider.h>
#include <linux/regmap.h>
#include <linux/watchdog.h>
/*
* We can't determine type by probing, but if we expect pre-Linux code
@ -144,6 +145,15 @@ enum ds_type {
# define M41TXX_BIT_CALIB_SIGN BIT(5)
# define M41TXX_M_CALIBRATION GENMASK(4, 0)
#define DS1388_REG_WDOG_HUN_SECS 0x08
#define DS1388_REG_WDOG_SECS 0x09
#define DS1388_REG_FLAG 0x0b
# define DS1388_BIT_WF BIT(6)
# define DS1388_BIT_OSF BIT(7)
#define DS1388_REG_CONTROL 0x0c
# define DS1388_BIT_RST BIT(0)
# define DS1388_BIT_WDE BIT(1)
/* negative offset step is -2.034ppm */
#define M41TXX_NEG_OFFSET_STEP_PPB 2034
/* positive offset step is +4.068ppm */
@ -252,6 +262,13 @@ static int ds1307_get_time(struct device *dev, struct rtc_time *t)
if (tmp & DS1340_BIT_OSF)
return -EINVAL;
break;
case ds_1388:
ret = regmap_read(ds1307->regmap, DS1388_REG_FLAG, &tmp);
if (ret)
return ret;
if (tmp & DS1388_BIT_OSF)
return -EINVAL;
break;
case mcp794xx:
if (!(tmp & MCP794XX_BIT_ST))
return -EINVAL;
@ -845,6 +862,72 @@ static int m41txx_rtc_set_offset(struct device *dev, long offset)
ctrl_reg);
}
#ifdef CONFIG_WATCHDOG_CORE
static int ds1388_wdt_start(struct watchdog_device *wdt_dev)
{
struct ds1307 *ds1307 = watchdog_get_drvdata(wdt_dev);
u8 regs[2];
int ret;
ret = regmap_update_bits(ds1307->regmap, DS1388_REG_FLAG,
DS1388_BIT_WF, 0);
if (ret)
return ret;
ret = regmap_update_bits(ds1307->regmap, DS1388_REG_CONTROL,
DS1388_BIT_WDE | DS1388_BIT_RST, 0);
if (ret)
return ret;
/*
* watchdog timeouts are measured in seconds. So ignore hundredths of
* seconds field.
*/
regs[0] = 0;
regs[1] = bin2bcd(wdt_dev->timeout);
ret = regmap_bulk_write(ds1307->regmap, DS1388_REG_WDOG_HUN_SECS, regs,
sizeof(regs));
if (ret)
return ret;
return regmap_update_bits(ds1307->regmap, DS1388_REG_CONTROL,
DS1388_BIT_WDE | DS1388_BIT_RST,
DS1388_BIT_WDE | DS1388_BIT_RST);
}
static int ds1388_wdt_stop(struct watchdog_device *wdt_dev)
{
struct ds1307 *ds1307 = watchdog_get_drvdata(wdt_dev);
return regmap_update_bits(ds1307->regmap, DS1388_REG_CONTROL,
DS1388_BIT_WDE | DS1388_BIT_RST, 0);
}
static int ds1388_wdt_ping(struct watchdog_device *wdt_dev)
{
struct ds1307 *ds1307 = watchdog_get_drvdata(wdt_dev);
u8 regs[2];
return regmap_bulk_read(ds1307->regmap, DS1388_REG_WDOG_HUN_SECS, regs,
sizeof(regs));
}
static int ds1388_wdt_set_timeout(struct watchdog_device *wdt_dev,
unsigned int val)
{
struct ds1307 *ds1307 = watchdog_get_drvdata(wdt_dev);
u8 regs[2];
wdt_dev->timeout = val;
regs[0] = 0;
regs[1] = bin2bcd(wdt_dev->timeout);
return regmap_bulk_write(ds1307->regmap, DS1388_REG_WDOG_HUN_SECS, regs,
sizeof(regs));
}
#endif
static const struct rtc_class_ops rx8130_rtc_ops = {
.read_time = ds1307_get_time,
.set_time = ds1307_set_time,
@ -1567,6 +1650,48 @@ static void ds1307_clks_register(struct ds1307 *ds1307)
#endif /* CONFIG_COMMON_CLK */
#ifdef CONFIG_WATCHDOG_CORE
static const struct watchdog_info ds1388_wdt_info = {
.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
.identity = "DS1388 watchdog",
};
static const struct watchdog_ops ds1388_wdt_ops = {
.owner = THIS_MODULE,
.start = ds1388_wdt_start,
.stop = ds1388_wdt_stop,
.ping = ds1388_wdt_ping,
.set_timeout = ds1388_wdt_set_timeout,
};
static void ds1307_wdt_register(struct ds1307 *ds1307)
{
struct watchdog_device *wdt;
if (ds1307->type != ds_1388)
return;
wdt = devm_kzalloc(ds1307->dev, sizeof(*wdt), GFP_KERNEL);
if (!wdt)
return;
wdt->info = &ds1388_wdt_info;
wdt->ops = &ds1388_wdt_ops;
wdt->timeout = 99;
wdt->max_timeout = 99;
wdt->min_timeout = 1;
watchdog_init_timeout(wdt, 0, ds1307->dev);
watchdog_set_drvdata(wdt, ds1307);
devm_watchdog_register_device(ds1307->dev, wdt);
}
#else
static void ds1307_wdt_register(struct ds1307 *ds1307)
{
}
#endif /* CONFIG_WATCHDOG_CORE */
static const struct regmap_config regmap_config = {
.reg_bits = 8,
.val_bits = 8,
@ -1856,6 +1981,7 @@ static int ds1307_probe(struct i2c_client *client,
ds1307_hwmon_register(ds1307);
ds1307_clks_register(ds1307);
ds1307_wdt_register(ds1307);
return 0;

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

@ -164,7 +164,7 @@ static int ds1374_read_time(struct device *dev, struct rtc_time *time)
ret = ds1374_read_rtc(client, &itime, DS1374_REG_TOD0, 4);
if (!ret)
rtc_time_to_tm(itime, time);
rtc_time64_to_tm(itime, time);
return ret;
}
@ -172,9 +172,8 @@ static int ds1374_read_time(struct device *dev, struct rtc_time *time)
static int ds1374_set_time(struct device *dev, struct rtc_time *time)
{
struct i2c_client *client = to_i2c_client(dev);
unsigned long itime;
unsigned long itime = rtc_tm_to_time64(time);
rtc_tm_to_time(time, &itime);
return ds1374_write_rtc(client, itime, DS1374_REG_TOD0, 4);
}
@ -212,7 +211,7 @@ static int ds1374_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
if (ret)
goto out;
rtc_time_to_tm(now + cur_alarm, &alarm->time);
rtc_time64_to_tm(now + cur_alarm, &alarm->time);
alarm->enabled = !!(cr & DS1374_REG_CR_WACE);
alarm->pending = !!(sr & DS1374_REG_SR_AF);
@ -237,8 +236,8 @@ static int ds1374_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
if (ret < 0)
return ret;
rtc_tm_to_time(&alarm->time, &new_alarm);
rtc_tm_to_time(&now, &itime);
new_alarm = rtc_tm_to_time64(&alarm->time);
itime = rtc_tm_to_time64(&now);
/* This can happen due to races, in addition to dates that are
* truly in the past. To avoid requiring the caller to check for
@ -620,6 +619,10 @@ static int ds1374_probe(struct i2c_client *client,
if (!ds1374)
return -ENOMEM;
ds1374->rtc = devm_rtc_allocate_device(&client->dev);
if (IS_ERR(ds1374->rtc))
return PTR_ERR(ds1374->rtc);
ds1374->client = client;
i2c_set_clientdata(client, ds1374);
@ -641,12 +644,12 @@ static int ds1374_probe(struct i2c_client *client,
device_set_wakeup_capable(&client->dev, 1);
}
ds1374->rtc = devm_rtc_device_register(&client->dev, client->name,
&ds1374_rtc_ops, THIS_MODULE);
if (IS_ERR(ds1374->rtc)) {
dev_err(&client->dev, "unable to register the class device\n");
return PTR_ERR(ds1374->rtc);
}
ds1374->rtc->ops = &ds1374_rtc_ops;
ds1374->rtc->range_max = U32_MAX;
ret = rtc_register_device(ds1374->rtc);
if (ret)
return ret;
#ifdef CONFIG_RTC_DRV_DS1374_WDT
save_client = client;

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

@ -20,6 +20,7 @@
#include <linux/fsl/ftm.h>
#include <linux/rtc.h>
#include <linux/time.h>
#include <linux/acpi.h>
#define FTM_SC_CLK(c) ((c) << FTM_SC_CLK_MASK_SHIFT)
@ -151,6 +152,8 @@ static irqreturn_t ftm_rtc_alarm_interrupt(int irq, void *dev)
{
struct ftm_rtc *rtc = dev;
rtc_update_irq(rtc->rtc_dev, 1, RTC_IRQF | RTC_AF);
ftm_irq_acknowledge(rtc);
ftm_irq_disable(rtc);
ftm_clean_alarm(rtc);
@ -242,7 +245,6 @@ static const struct rtc_class_ops ftm_rtc_ops = {
static int ftm_rtc_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
int irq;
int ret;
struct ftm_rtc *rtc;
@ -265,10 +267,10 @@ static int ftm_rtc_probe(struct platform_device *pdev)
return PTR_ERR(rtc->base);
}
irq = irq_of_parse_and_map(np, 0);
if (irq <= 0) {
dev_err(&pdev->dev, "unable to get IRQ from DT, %d\n", irq);
return -EINVAL;
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(&pdev->dev, "can't get irq number\n");
return irq;
}
ret = devm_request_irq(&pdev->dev, irq, ftm_rtc_alarm_interrupt,
@ -278,7 +280,9 @@ static int ftm_rtc_probe(struct platform_device *pdev)
return ret;
}
rtc->big_endian = of_property_read_bool(np, "big-endian");
rtc->big_endian =
device_property_read_bool(&pdev->dev, "big-endian");
rtc->alarm_freq = (u32)FIXED_FREQ_CLK / (u32)MAX_FREQ_DIV;
rtc->rtc_dev->ops = &ftm_rtc_ops;
@ -305,11 +309,18 @@ static const struct of_device_id ftm_rtc_match[] = {
{ },
};
static const struct acpi_device_id ftm_imx_acpi_ids[] = {
{"NXP0011",},
{ }
};
MODULE_DEVICE_TABLE(acpi, ftm_imx_acpi_ids);
static struct platform_driver ftm_rtc_driver = {
.probe = ftm_rtc_probe,
.driver = {
.name = "ftm-alarm",
.of_match_table = ftm_rtc_match,
.acpi_match_table = ACPI_PTR(ftm_imx_acpi_ids),
},
};

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

@ -37,7 +37,7 @@ struct imx_sc_msg_timer_rtc_set_alarm {
u8 hour;
u8 min;
u8 sec;
} __packed;
} __packed __aligned(4);
static int imx_sc_rtc_read_time(struct device *dev, struct rtc_time *tm)
{

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

@ -46,6 +46,7 @@
enum jz4740_rtc_type {
ID_JZ4740,
ID_JZ4760,
ID_JZ4780,
};
@ -106,7 +107,7 @@ static inline int jz4740_rtc_reg_write(struct jz4740_rtc *rtc, size_t reg,
{
int ret = 0;
if (rtc->type >= ID_JZ4780)
if (rtc->type >= ID_JZ4760)
ret = jz4780_rtc_enable_write(rtc);
if (ret == 0)
ret = jz4740_rtc_wait_write_ready(rtc);
@ -298,6 +299,7 @@ static void jz4740_rtc_power_off(void)
static const struct of_device_id jz4740_rtc_of_match[] = {
{ .compatible = "ingenic,jz4740-rtc", .data = (void *)ID_JZ4740 },
{ .compatible = "ingenic,jz4760-rtc", .data = (void *)ID_JZ4760 },
{ .compatible = "ingenic,jz4780-rtc", .data = (void *)ID_JZ4780 },
{},
};
@ -372,13 +374,14 @@ static int jz4740_rtc_probe(struct platform_device *pdev)
if (!pm_power_off) {
/* Default: 60ms */
rtc->reset_pin_assert_time = 60;
of_property_read_u32(np, "reset-pin-assert-time-ms",
of_property_read_u32(np,
"ingenic,reset-pin-assert-time-ms",
&rtc->reset_pin_assert_time);
/* Default: 100ms */
rtc->min_wakeup_pin_assert_time = 100;
of_property_read_u32(np,
"min-wakeup-pin-assert-time-ms",
"ingenic,min-wakeup-pin-assert-time-ms",
&rtc->min_wakeup_pin_assert_time);
dev_for_power_off = &pdev->dev;

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

@ -160,15 +160,10 @@ static int m48t35_probe(struct platform_device *pdev)
return -ENOMEM;
priv->size = resource_size(res);
/*
* kludge: remove the #ifndef after ioc3 resource
* conflicts are resolved
*/
#ifndef CONFIG_SGI_IP27
if (!devm_request_mem_region(&pdev->dev, res->start, priv->size,
pdev->name))
return -EBUSY;
#endif
priv->baseaddr = res->start;
priv->reg = devm_ioremap(&pdev->dev, priv->baseaddr, priv->size);
if (!priv->reg)

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

@ -111,7 +111,7 @@ static int mpc5121_rtc_read_time(struct device *dev, struct rtc_time *tm)
*/
now = in_be32(&regs->actual_time) + in_be32(&regs->target_time);
rtc_time_to_tm(now, tm);
rtc_time64_to_tm(now, tm);
/*
* update second minute hour registers
@ -126,16 +126,14 @@ static int mpc5121_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
struct mpc5121_rtc_data *rtc = dev_get_drvdata(dev);
struct mpc5121_rtc_regs __iomem *regs = rtc->regs;
int ret;
unsigned long now;
/*
* The actual_time register is read only so we write the offset
* between it and linux time to the target_time register.
*/
ret = rtc_tm_to_time(tm, &now);
if (ret == 0)
out_be32(&regs->target_time, now - in_be32(&regs->actual_time));
now = rtc_tm_to_time64(tm);
out_be32(&regs->target_time, now - in_be32(&regs->actual_time));
/*
* update second minute hour registers
@ -315,8 +313,8 @@ static int mpc5121_rtc_probe(struct platform_device *op)
if (!rtc)
return -ENOMEM;
rtc->regs = of_iomap(op->dev.of_node, 0);
if (!rtc->regs) {
rtc->regs = devm_platform_ioremap_resource(op, 0);
if (IS_ERR(rtc->regs)) {
dev_err(&op->dev, "%s: couldn't map io space\n", __func__);
return -ENOSYS;
}
@ -326,8 +324,8 @@ static int mpc5121_rtc_probe(struct platform_device *op)
platform_set_drvdata(op, rtc);
rtc->irq = irq_of_parse_and_map(op->dev.of_node, 1);
err = request_irq(rtc->irq, mpc5121_rtc_handler, 0,
"mpc5121-rtc", &op->dev);
err = devm_request_irq(&op->dev, rtc->irq, mpc5121_rtc_handler, 0,
"mpc5121-rtc", &op->dev);
if (err) {
dev_err(&op->dev, "%s: could not request irq: %i\n",
__func__, rtc->irq);
@ -335,14 +333,26 @@ static int mpc5121_rtc_probe(struct platform_device *op)
}
rtc->irq_periodic = irq_of_parse_and_map(op->dev.of_node, 0);
err = request_irq(rtc->irq_periodic, mpc5121_rtc_handler_upd,
0, "mpc5121-rtc_upd", &op->dev);
err = devm_request_irq(&op->dev, rtc->irq_periodic,
mpc5121_rtc_handler_upd, 0, "mpc5121-rtc_upd",
&op->dev);
if (err) {
dev_err(&op->dev, "%s: could not request irq: %i\n",
__func__, rtc->irq_periodic);
goto out_dispose2;
}
rtc->rtc = devm_rtc_allocate_device(&op->dev);
if (IS_ERR(rtc->rtc)) {
err = PTR_ERR(rtc->rtc);
goto out_dispose2;
}
rtc->rtc->ops = &mpc5200_rtc_ops;
rtc->rtc->uie_unsupported = 1;
rtc->rtc->range_min = RTC_TIMESTAMP_BEGIN_0000;
rtc->rtc->range_max = 65733206399ULL; /* 4052-12-31 23:59:59 */
if (of_device_is_compatible(op->dev.of_node, "fsl,mpc5121-rtc")) {
u32 ka;
ka = in_be32(&rtc->regs->keep_alive);
@ -351,30 +361,26 @@ static int mpc5121_rtc_probe(struct platform_device *op)
"mpc5121-rtc: Battery or oscillator failure!\n");
out_be32(&rtc->regs->keep_alive, ka);
}
rtc->rtc = devm_rtc_device_register(&op->dev, "mpc5121-rtc",
&mpc5121_rtc_ops, THIS_MODULE);
} else {
rtc->rtc = devm_rtc_device_register(&op->dev, "mpc5200-rtc",
&mpc5200_rtc_ops, THIS_MODULE);
rtc->rtc->ops = &mpc5121_rtc_ops;
/*
* This is a limitation of the driver that abuses the target
* time register, the actual maximum year for the mpc5121 is
* also 4052.
*/
rtc->rtc->range_min = 0;
rtc->rtc->range_max = U32_MAX;
}
if (IS_ERR(rtc->rtc)) {
err = PTR_ERR(rtc->rtc);
goto out_free_irq;
}
rtc->rtc->uie_unsupported = 1;
err = rtc_register_device(rtc->rtc);
if (err)
goto out_dispose2;
return 0;
out_free_irq:
free_irq(rtc->irq_periodic, &op->dev);
out_dispose2:
irq_dispose_mapping(rtc->irq_periodic);
free_irq(rtc->irq, &op->dev);
out_dispose:
irq_dispose_mapping(rtc->irq);
iounmap(rtc->regs);
return err;
}
@ -388,9 +394,6 @@ static int mpc5121_rtc_remove(struct platform_device *op)
out_8(&regs->alm_enable, 0);
out_8(&regs->int_enable, in_8(&regs->int_enable) & ~0x1);
iounmap(rtc->regs);
free_irq(rtc->irq, &op->dev);
free_irq(rtc->irq_periodic, &op->dev);
irq_dispose_mapping(rtc->irq);
irq_dispose_mapping(rtc->irq_periodic);

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

@ -0,0 +1,423 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2019 MediaTek Inc.
* Author: Ran Bi <ran.bi@mediatek.com>
*/
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/irqdomain.h>
#include <linux/module.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/platform_device.h>
#include <linux/rtc.h>
#define MT2712_BBPU 0x0000
#define MT2712_BBPU_CLRPKY BIT(4)
#define MT2712_BBPU_RELOAD BIT(5)
#define MT2712_BBPU_CBUSY BIT(6)
#define MT2712_BBPU_KEY (0x43 << 8)
#define MT2712_IRQ_STA 0x0004
#define MT2712_IRQ_STA_AL BIT(0)
#define MT2712_IRQ_STA_TC BIT(1)
#define MT2712_IRQ_EN 0x0008
#define MT2712_IRQ_EN_AL BIT(0)
#define MT2712_IRQ_EN_TC BIT(1)
#define MT2712_IRQ_EN_ONESHOT BIT(2)
#define MT2712_CII_EN 0x000c
#define MT2712_AL_MASK 0x0010
#define MT2712_AL_MASK_DOW BIT(4)
#define MT2712_TC_SEC 0x0014
#define MT2712_TC_MIN 0x0018
#define MT2712_TC_HOU 0x001c
#define MT2712_TC_DOM 0x0020
#define MT2712_TC_DOW 0x0024
#define MT2712_TC_MTH 0x0028
#define MT2712_TC_YEA 0x002c
#define MT2712_AL_SEC 0x0030
#define MT2712_AL_MIN 0x0034
#define MT2712_AL_HOU 0x0038
#define MT2712_AL_DOM 0x003c
#define MT2712_AL_DOW 0x0040
#define MT2712_AL_MTH 0x0044
#define MT2712_AL_YEA 0x0048
#define MT2712_SEC_MASK 0x003f
#define MT2712_MIN_MASK 0x003f
#define MT2712_HOU_MASK 0x001f
#define MT2712_DOM_MASK 0x001f
#define MT2712_DOW_MASK 0x0007
#define MT2712_MTH_MASK 0x000f
#define MT2712_YEA_MASK 0x007f
#define MT2712_POWERKEY1 0x004c
#define MT2712_POWERKEY2 0x0050
#define MT2712_POWERKEY1_KEY 0xa357
#define MT2712_POWERKEY2_KEY 0x67d2
#define MT2712_CON0 0x005c
#define MT2712_CON1 0x0060
#define MT2712_PROT 0x0070
#define MT2712_PROT_UNLOCK1 0x9136
#define MT2712_PROT_UNLOCK2 0x586a
#define MT2712_WRTGR 0x0078
#define MT2712_RTC_TIMESTAMP_END_2127 4985971199LL
struct mt2712_rtc {
struct rtc_device *rtc;
void __iomem *base;
int irq;
u8 irq_wake_enabled;
u8 powerlost;
};
static inline u32 mt2712_readl(struct mt2712_rtc *mt2712_rtc, u32 reg)
{
return readl(mt2712_rtc->base + reg);
}
static inline void mt2712_writel(struct mt2712_rtc *mt2712_rtc,
u32 reg, u32 val)
{
writel(val, mt2712_rtc->base + reg);
}
static void mt2712_rtc_write_trigger(struct mt2712_rtc *mt2712_rtc)
{
unsigned long timeout = jiffies + HZ / 10;
mt2712_writel(mt2712_rtc, MT2712_WRTGR, 1);
while (1) {
if (!(mt2712_readl(mt2712_rtc, MT2712_BBPU)
& MT2712_BBPU_CBUSY))
break;
if (time_after(jiffies, timeout)) {
dev_err(&mt2712_rtc->rtc->dev,
"%s time out!\n", __func__);
break;
}
cpu_relax();
}
}
static void mt2712_rtc_writeif_unlock(struct mt2712_rtc *mt2712_rtc)
{
mt2712_writel(mt2712_rtc, MT2712_PROT, MT2712_PROT_UNLOCK1);
mt2712_rtc_write_trigger(mt2712_rtc);
mt2712_writel(mt2712_rtc, MT2712_PROT, MT2712_PROT_UNLOCK2);
mt2712_rtc_write_trigger(mt2712_rtc);
}
static irqreturn_t rtc_irq_handler_thread(int irq, void *data)
{
struct mt2712_rtc *mt2712_rtc = data;
u16 irqsta;
/* Clear interrupt */
irqsta = mt2712_readl(mt2712_rtc, MT2712_IRQ_STA);
if (irqsta & MT2712_IRQ_STA_AL) {
rtc_update_irq(mt2712_rtc->rtc, 1, RTC_IRQF | RTC_AF);
return IRQ_HANDLED;
}
return IRQ_NONE;
}
static void __mt2712_rtc_read_time(struct mt2712_rtc *mt2712_rtc,
struct rtc_time *tm, int *sec)
{
tm->tm_sec = mt2712_readl(mt2712_rtc, MT2712_TC_SEC)
& MT2712_SEC_MASK;
tm->tm_min = mt2712_readl(mt2712_rtc, MT2712_TC_MIN)
& MT2712_MIN_MASK;
tm->tm_hour = mt2712_readl(mt2712_rtc, MT2712_TC_HOU)
& MT2712_HOU_MASK;
tm->tm_mday = mt2712_readl(mt2712_rtc, MT2712_TC_DOM)
& MT2712_DOM_MASK;
tm->tm_mon = (mt2712_readl(mt2712_rtc, MT2712_TC_MTH) - 1)
& MT2712_MTH_MASK;
tm->tm_year = (mt2712_readl(mt2712_rtc, MT2712_TC_YEA) + 100)
& MT2712_YEA_MASK;
*sec = mt2712_readl(mt2712_rtc, MT2712_TC_SEC) & MT2712_SEC_MASK;
}
static int mt2712_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
struct mt2712_rtc *mt2712_rtc = dev_get_drvdata(dev);
int sec;
if (mt2712_rtc->powerlost)
return -EINVAL;
do {
__mt2712_rtc_read_time(mt2712_rtc, tm, &sec);
} while (sec < tm->tm_sec); /* SEC has carried */
return 0;
}
static int mt2712_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
struct mt2712_rtc *mt2712_rtc = dev_get_drvdata(dev);
mt2712_writel(mt2712_rtc, MT2712_TC_SEC, tm->tm_sec & MT2712_SEC_MASK);
mt2712_writel(mt2712_rtc, MT2712_TC_MIN, tm->tm_min & MT2712_MIN_MASK);
mt2712_writel(mt2712_rtc, MT2712_TC_HOU, tm->tm_hour & MT2712_HOU_MASK);
mt2712_writel(mt2712_rtc, MT2712_TC_DOM, tm->tm_mday & MT2712_DOM_MASK);
mt2712_writel(mt2712_rtc, MT2712_TC_MTH,
(tm->tm_mon + 1) & MT2712_MTH_MASK);
mt2712_writel(mt2712_rtc, MT2712_TC_YEA,
(tm->tm_year - 100) & MT2712_YEA_MASK);
mt2712_rtc_write_trigger(mt2712_rtc);
if (mt2712_rtc->powerlost)
mt2712_rtc->powerlost = false;
return 0;
}
static int mt2712_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
{
struct mt2712_rtc *mt2712_rtc = dev_get_drvdata(dev);
struct rtc_time *tm = &alm->time;
u16 irqen;
irqen = mt2712_readl(mt2712_rtc, MT2712_IRQ_EN);
alm->enabled = !!(irqen & MT2712_IRQ_EN_AL);
tm->tm_sec = mt2712_readl(mt2712_rtc, MT2712_AL_SEC) & MT2712_SEC_MASK;
tm->tm_min = mt2712_readl(mt2712_rtc, MT2712_AL_MIN) & MT2712_MIN_MASK;
tm->tm_hour = mt2712_readl(mt2712_rtc, MT2712_AL_HOU) & MT2712_HOU_MASK;
tm->tm_mday = mt2712_readl(mt2712_rtc, MT2712_AL_DOM) & MT2712_DOM_MASK;
tm->tm_mon = (mt2712_readl(mt2712_rtc, MT2712_AL_MTH) - 1)
& MT2712_MTH_MASK;
tm->tm_year = (mt2712_readl(mt2712_rtc, MT2712_AL_YEA) + 100)
& MT2712_YEA_MASK;
return 0;
}
static int mt2712_rtc_alarm_irq_enable(struct device *dev,
unsigned int enabled)
{
struct mt2712_rtc *mt2712_rtc = dev_get_drvdata(dev);
u16 irqen;
irqen = mt2712_readl(mt2712_rtc, MT2712_IRQ_EN);
if (enabled)
irqen |= MT2712_IRQ_EN_AL;
else
irqen &= ~MT2712_IRQ_EN_AL;
mt2712_writel(mt2712_rtc, MT2712_IRQ_EN, irqen);
mt2712_rtc_write_trigger(mt2712_rtc);
return 0;
}
static int mt2712_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
{
struct mt2712_rtc *mt2712_rtc = dev_get_drvdata(dev);
struct rtc_time *tm = &alm->time;
dev_dbg(&mt2712_rtc->rtc->dev, "set al time: %ptR, alm en: %d\n",
tm, alm->enabled);
mt2712_writel(mt2712_rtc, MT2712_AL_SEC,
(mt2712_readl(mt2712_rtc, MT2712_AL_SEC)
& ~(MT2712_SEC_MASK)) | (tm->tm_sec & MT2712_SEC_MASK));
mt2712_writel(mt2712_rtc, MT2712_AL_MIN,
(mt2712_readl(mt2712_rtc, MT2712_AL_MIN)
& ~(MT2712_MIN_MASK)) | (tm->tm_min & MT2712_MIN_MASK));
mt2712_writel(mt2712_rtc, MT2712_AL_HOU,
(mt2712_readl(mt2712_rtc, MT2712_AL_HOU)
& ~(MT2712_HOU_MASK)) | (tm->tm_hour & MT2712_HOU_MASK));
mt2712_writel(mt2712_rtc, MT2712_AL_DOM,
(mt2712_readl(mt2712_rtc, MT2712_AL_DOM)
& ~(MT2712_DOM_MASK)) | (tm->tm_mday & MT2712_DOM_MASK));
mt2712_writel(mt2712_rtc, MT2712_AL_MTH,
(mt2712_readl(mt2712_rtc, MT2712_AL_MTH)
& ~(MT2712_MTH_MASK))
| ((tm->tm_mon + 1) & MT2712_MTH_MASK));
mt2712_writel(mt2712_rtc, MT2712_AL_YEA,
(mt2712_readl(mt2712_rtc, MT2712_AL_YEA)
& ~(MT2712_YEA_MASK))
| ((tm->tm_year - 100) & MT2712_YEA_MASK));
/* mask day of week */
mt2712_writel(mt2712_rtc, MT2712_AL_MASK, MT2712_AL_MASK_DOW);
mt2712_rtc_write_trigger(mt2712_rtc);
mt2712_rtc_alarm_irq_enable(dev, alm->enabled);
return 0;
}
/* Init RTC register */
static void mt2712_rtc_hw_init(struct mt2712_rtc *mt2712_rtc)
{
u32 p1, p2;
mt2712_writel(mt2712_rtc, MT2712_BBPU,
MT2712_BBPU_KEY | MT2712_BBPU_RELOAD);
mt2712_writel(mt2712_rtc, MT2712_CII_EN, 0);
mt2712_writel(mt2712_rtc, MT2712_AL_MASK, 0);
/* necessary before set MT2712_POWERKEY */
mt2712_writel(mt2712_rtc, MT2712_CON0, 0x4848);
mt2712_writel(mt2712_rtc, MT2712_CON1, 0x0048);
mt2712_rtc_write_trigger(mt2712_rtc);
p1 = mt2712_readl(mt2712_rtc, MT2712_POWERKEY1);
p2 = mt2712_readl(mt2712_rtc, MT2712_POWERKEY2);
if (p1 != MT2712_POWERKEY1_KEY || p2 != MT2712_POWERKEY2_KEY) {
mt2712_rtc->powerlost = true;
dev_dbg(&mt2712_rtc->rtc->dev,
"powerkey not set (lost power)\n");
} else {
mt2712_rtc->powerlost = false;
}
/* RTC need POWERKEY1/2 match, then goto normal work mode */
mt2712_writel(mt2712_rtc, MT2712_POWERKEY1, MT2712_POWERKEY1_KEY);
mt2712_writel(mt2712_rtc, MT2712_POWERKEY2, MT2712_POWERKEY2_KEY);
mt2712_rtc_write_trigger(mt2712_rtc);
mt2712_rtc_writeif_unlock(mt2712_rtc);
}
static const struct rtc_class_ops mt2712_rtc_ops = {
.read_time = mt2712_rtc_read_time,
.set_time = mt2712_rtc_set_time,
.read_alarm = mt2712_rtc_read_alarm,
.set_alarm = mt2712_rtc_set_alarm,
.alarm_irq_enable = mt2712_rtc_alarm_irq_enable,
};
static int mt2712_rtc_probe(struct platform_device *pdev)
{
struct resource *res;
struct mt2712_rtc *mt2712_rtc;
int ret;
mt2712_rtc = devm_kzalloc(&pdev->dev,
sizeof(struct mt2712_rtc), GFP_KERNEL);
if (!mt2712_rtc)
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
mt2712_rtc->base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(mt2712_rtc->base))
return PTR_ERR(mt2712_rtc->base);
/* rtc hw init */
mt2712_rtc_hw_init(mt2712_rtc);
mt2712_rtc->irq = platform_get_irq(pdev, 0);
if (mt2712_rtc->irq < 0) {
dev_err(&pdev->dev, "No IRQ resource\n");
return mt2712_rtc->irq;
}
platform_set_drvdata(pdev, mt2712_rtc);
mt2712_rtc->rtc = devm_rtc_allocate_device(&pdev->dev);
if (IS_ERR(mt2712_rtc->rtc))
return PTR_ERR(mt2712_rtc->rtc);
ret = devm_request_threaded_irq(&pdev->dev, mt2712_rtc->irq, NULL,
rtc_irq_handler_thread,
IRQF_ONESHOT | IRQF_TRIGGER_LOW,
dev_name(&mt2712_rtc->rtc->dev),
mt2712_rtc);
if (ret) {
dev_err(&pdev->dev, "Failed to request alarm IRQ: %d: %d\n",
mt2712_rtc->irq, ret);
return ret;
}
device_init_wakeup(&pdev->dev, true);
mt2712_rtc->rtc->ops = &mt2712_rtc_ops;
mt2712_rtc->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
mt2712_rtc->rtc->range_max = MT2712_RTC_TIMESTAMP_END_2127;
ret = rtc_register_device(mt2712_rtc->rtc);
if (ret) {
dev_err(&pdev->dev, "register rtc device failed\n");
return ret;
}
return 0;
}
#ifdef CONFIG_PM_SLEEP
static int mt2712_rtc_suspend(struct device *dev)
{
int wake_status = 0;
struct mt2712_rtc *mt2712_rtc = dev_get_drvdata(dev);
if (device_may_wakeup(dev)) {
wake_status = enable_irq_wake(mt2712_rtc->irq);
if (!wake_status)
mt2712_rtc->irq_wake_enabled = true;
}
return 0;
}
static int mt2712_rtc_resume(struct device *dev)
{
int wake_status = 0;
struct mt2712_rtc *mt2712_rtc = dev_get_drvdata(dev);
if (device_may_wakeup(dev) && mt2712_rtc->irq_wake_enabled) {
wake_status = disable_irq_wake(mt2712_rtc->irq);
if (!wake_status)
mt2712_rtc->irq_wake_enabled = false;
}
return 0;
}
static SIMPLE_DEV_PM_OPS(mt2712_pm_ops, mt2712_rtc_suspend,
mt2712_rtc_resume);
#endif
static const struct of_device_id mt2712_rtc_of_match[] = {
{ .compatible = "mediatek,mt2712-rtc", },
{ },
};
MODULE_DEVICE_TABLE(of, mt2712_rtc_of_match);
static struct platform_driver mt2712_rtc_driver = {
.driver = {
.name = "mt2712-rtc",
.of_match_table = mt2712_rtc_of_match,
#ifdef CONFIG_PM_SLEEP
.pm = &mt2712_pm_ops,
#endif
},
.probe = mt2712_rtc_probe,
};
module_platform_driver(mt2712_rtc_driver);
MODULE_DESCRIPTION("MediaTek MT2712 SoC based RTC Driver");
MODULE_AUTHOR("Ran Bi <ran.bi@mediatek.com>");
MODULE_LICENSE("GPL");

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

@ -307,6 +307,14 @@ static const struct rtc_class_ops mxc_rtc_ops = {
.alarm_irq_enable = mxc_rtc_alarm_irq_enable,
};
static void mxc_rtc_action(void *p)
{
struct rtc_plat_data *pdata = p;
clk_disable_unprepare(pdata->clk_ref);
clk_disable_unprepare(pdata->clk_ipg);
}
static int mxc_rtc_probe(struct platform_device *pdev)
{
struct rtc_device *rtc;
@ -366,14 +374,20 @@ static int mxc_rtc_probe(struct platform_device *pdev)
pdata->clk_ref = devm_clk_get(&pdev->dev, "ref");
if (IS_ERR(pdata->clk_ref)) {
clk_disable_unprepare(pdata->clk_ipg);
dev_err(&pdev->dev, "unable to get ref clock!\n");
ret = PTR_ERR(pdata->clk_ref);
goto exit_put_clk_ipg;
return PTR_ERR(pdata->clk_ref);
}
ret = clk_prepare_enable(pdata->clk_ref);
if (ret) {
clk_disable_unprepare(pdata->clk_ipg);
return ret;
}
ret = devm_add_action_or_reset(&pdev->dev, mxc_rtc_action, pdata);
if (ret)
goto exit_put_clk_ipg;
return ret;
rate = clk_get_rate(pdata->clk_ref);
@ -385,16 +399,14 @@ static int mxc_rtc_probe(struct platform_device *pdev)
reg = RTC_INPUT_CLK_38400HZ;
else {
dev_err(&pdev->dev, "rtc clock is not valid (%lu)\n", rate);
ret = -EINVAL;
goto exit_put_clk_ref;
return -EINVAL;
}
reg |= RTC_ENABLE_BIT;
writew(reg, (pdata->ioaddr + RTC_RTCCTL));
if (((readw(pdata->ioaddr + RTC_RTCCTL)) & RTC_ENABLE_BIT) == 0) {
dev_err(&pdev->dev, "hardware module can't be enabled!\n");
ret = -EIO;
goto exit_put_clk_ref;
return -EIO;
}
platform_set_drvdata(pdev, pdata);
@ -417,29 +429,10 @@ static int mxc_rtc_probe(struct platform_device *pdev)
}
ret = rtc_register_device(rtc);
if (ret)
goto exit_put_clk_ref;
return 0;
exit_put_clk_ref:
clk_disable_unprepare(pdata->clk_ref);
exit_put_clk_ipg:
clk_disable_unprepare(pdata->clk_ipg);
return ret;
}
static int mxc_rtc_remove(struct platform_device *pdev)
{
struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
clk_disable_unprepare(pdata->clk_ref);
clk_disable_unprepare(pdata->clk_ipg);
return 0;
}
static struct platform_driver mxc_rtc_driver = {
.driver = {
.name = "mxc_rtc",
@ -447,7 +440,6 @@ static struct platform_driver mxc_rtc_driver = {
},
.id_table = imx_rtc_devtype,
.probe = mxc_rtc_probe,
.remove = mxc_rtc_remove,
};
module_platform_driver(mxc_rtc_driver)

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

@ -9,7 +9,6 @@
* Copyright (C) 2014 Johan Hovold <johan@kernel.org>
*/
#include <dt-bindings/gpio/gpio.h>
#include <linux/bcd.h>
#include <linux/clk.h>
#include <linux/delay.h>

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

@ -9,6 +9,7 @@
* Copyright (C) 2019 Micro Crystal AG
* Author: Alexandre Belloni <alexandre.belloni@bootlin.com>
*/
#include <linux/clk-provider.h>
#include <linux/i2c.h>
#include <linux/bcd.h>
#include <linux/rtc.h>
@ -44,6 +45,10 @@
#define PCF85063_OFFSET_STEP0 4340
#define PCF85063_OFFSET_STEP1 4069
#define PCF85063_REG_CLKO_F_MASK 0x07 /* frequency mask */
#define PCF85063_REG_CLKO_F_32768HZ 0x00
#define PCF85063_REG_CLKO_F_OFF 0x07
#define PCF85063_REG_RAM 0x03
#define PCF85063_REG_SC 0x04 /* datetime */
@ -61,6 +66,9 @@ struct pcf85063_config {
struct pcf85063 {
struct rtc_device *rtc;
struct regmap *regmap;
#ifdef CONFIG_COMMON_CLK
struct clk_hw clkout_hw;
#endif
};
static int pcf85063_rtc_read_time(struct device *dev, struct rtc_time *tm)
@ -357,6 +365,150 @@ static int pcf85063_load_capacitance(struct pcf85063 *pcf85063,
PCF85063_REG_CTRL1_CAP_SEL, reg);
}
#ifdef CONFIG_COMMON_CLK
/*
* Handling of the clkout
*/
#define clkout_hw_to_pcf85063(_hw) container_of(_hw, struct pcf85063, clkout_hw)
static int clkout_rates[] = {
32768,
16384,
8192,
4096,
2048,
1024,
1,
0
};
static unsigned long pcf85063_clkout_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct pcf85063 *pcf85063 = clkout_hw_to_pcf85063(hw);
unsigned int buf;
int ret = regmap_read(pcf85063->regmap, PCF85063_REG_CTRL2, &buf);
if (ret < 0)
return 0;
buf &= PCF85063_REG_CLKO_F_MASK;
return clkout_rates[buf];
}
static long pcf85063_clkout_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
int i;
for (i = 0; i < ARRAY_SIZE(clkout_rates); i++)
if (clkout_rates[i] <= rate)
return clkout_rates[i];
return 0;
}
static int pcf85063_clkout_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct pcf85063 *pcf85063 = clkout_hw_to_pcf85063(hw);
int i;
for (i = 0; i < ARRAY_SIZE(clkout_rates); i++)
if (clkout_rates[i] == rate)
return regmap_update_bits(pcf85063->regmap,
PCF85063_REG_CTRL2,
PCF85063_REG_CLKO_F_MASK, i);
return -EINVAL;
}
static int pcf85063_clkout_control(struct clk_hw *hw, bool enable)
{
struct pcf85063 *pcf85063 = clkout_hw_to_pcf85063(hw);
unsigned int buf;
int ret;
ret = regmap_read(pcf85063->regmap, PCF85063_REG_OFFSET, &buf);
if (ret < 0)
return ret;
buf &= PCF85063_REG_CLKO_F_MASK;
if (enable) {
if (buf == PCF85063_REG_CLKO_F_OFF)
buf = PCF85063_REG_CLKO_F_32768HZ;
else
return 0;
} else {
if (buf != PCF85063_REG_CLKO_F_OFF)
buf = PCF85063_REG_CLKO_F_OFF;
else
return 0;
}
return regmap_update_bits(pcf85063->regmap, PCF85063_REG_CTRL2,
PCF85063_REG_CLKO_F_MASK, buf);
}
static int pcf85063_clkout_prepare(struct clk_hw *hw)
{
return pcf85063_clkout_control(hw, 1);
}
static void pcf85063_clkout_unprepare(struct clk_hw *hw)
{
pcf85063_clkout_control(hw, 0);
}
static int pcf85063_clkout_is_prepared(struct clk_hw *hw)
{
struct pcf85063 *pcf85063 = clkout_hw_to_pcf85063(hw);
unsigned int buf;
int ret = regmap_read(pcf85063->regmap, PCF85063_REG_CTRL2, &buf);
if (ret < 0)
return 0;
return (buf & PCF85063_REG_CLKO_F_MASK) != PCF85063_REG_CLKO_F_OFF;
}
static const struct clk_ops pcf85063_clkout_ops = {
.prepare = pcf85063_clkout_prepare,
.unprepare = pcf85063_clkout_unprepare,
.is_prepared = pcf85063_clkout_is_prepared,
.recalc_rate = pcf85063_clkout_recalc_rate,
.round_rate = pcf85063_clkout_round_rate,
.set_rate = pcf85063_clkout_set_rate,
};
static struct clk *pcf85063_clkout_register_clk(struct pcf85063 *pcf85063)
{
struct clk *clk;
struct clk_init_data init;
init.name = "pcf85063-clkout";
init.ops = &pcf85063_clkout_ops;
init.flags = 0;
init.parent_names = NULL;
init.num_parents = 0;
pcf85063->clkout_hw.init = &init;
/* optional override of the clockname */
of_property_read_string(pcf85063->rtc->dev.of_node,
"clock-output-names", &init.name);
/* register the clock */
clk = devm_clk_register(&pcf85063->rtc->dev, &pcf85063->clkout_hw);
if (!IS_ERR(clk))
of_clk_add_provider(pcf85063->rtc->dev.of_node,
of_clk_src_simple_get, clk);
return clk;
}
#endif
static const struct pcf85063_config pcf85063a_config = {
.regmap = {
.reg_bits = 8,
@ -457,6 +609,11 @@ static int pcf85063_probe(struct i2c_client *client)
nvmem_cfg.priv = pcf85063->regmap;
rtc_nvmem_register(pcf85063->rtc, &nvmem_cfg);
#ifdef CONFIG_COMMON_CLK
/* register clk in common clk framework */
pcf85063_clkout_register_clk(pcf85063);
#endif
return rtc_register_device(pcf85063->rtc);
}

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

@ -36,32 +36,24 @@ static int pl030_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
struct pl030_rtc *rtc = dev_get_drvdata(dev);
rtc_time_to_tm(readl(rtc->base + RTC_MR), &alrm->time);
rtc_time64_to_tm(readl(rtc->base + RTC_MR), &alrm->time);
return 0;
}
static int pl030_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
struct pl030_rtc *rtc = dev_get_drvdata(dev);
unsigned long time;
int ret;
/*
* At the moment, we can only deal with non-wildcarded alarm times.
*/
ret = rtc_valid_tm(&alrm->time);
if (ret == 0)
ret = rtc_tm_to_time(&alrm->time, &time);
if (ret == 0)
writel(time, rtc->base + RTC_MR);
return ret;
writel(rtc_tm_to_time64(&alrm->time), rtc->base + RTC_MR);
return 0;
}
static int pl030_read_time(struct device *dev, struct rtc_time *tm)
{
struct pl030_rtc *rtc = dev_get_drvdata(dev);
rtc_time_to_tm(readl(rtc->base + RTC_DR), tm);
rtc_time64_to_tm(readl(rtc->base + RTC_DR), tm);
return 0;
}
@ -77,14 +69,10 @@ static int pl030_read_time(struct device *dev, struct rtc_time *tm)
static int pl030_set_time(struct device *dev, struct rtc_time *tm)
{
struct pl030_rtc *rtc = dev_get_drvdata(dev);
unsigned long time;
int ret;
ret = rtc_tm_to_time(tm, &time);
if (ret == 0)
writel(time + 1, rtc->base + RTC_LR);
writel(rtc_tm_to_time64(tm) + 1, rtc->base + RTC_LR);
return ret;
return 0;
}
static const struct rtc_class_ops pl030_ops = {
@ -116,6 +104,7 @@ static int pl030_probe(struct amba_device *dev, const struct amba_id *id)
}
rtc->rtc->ops = &pl030_ops;
rtc->rtc->range_max = U32_MAX;
rtc->base = ioremap(dev->res.start, resource_size(&dev->res));
if (!rtc->base) {
ret = -ENOMEM;

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

@ -80,6 +80,8 @@ struct pl031_vendor_data {
bool clockwatch;
bool st_weekday;
unsigned long irqflags;
time64_t range_min;
timeu64_t range_max;
};
struct pl031_local {
@ -123,11 +125,9 @@ static int pl031_stv2_tm_to_time(struct device *dev,
return -EINVAL;
} else if (wday == -1) {
/* wday is not provided, calculate it here */
unsigned long time;
struct rtc_time calc_tm;
rtc_tm_to_time(tm, &time);
rtc_time_to_tm(time, &calc_tm);
rtc_time64_to_tm(rtc_tm_to_time64(tm), &calc_tm);
wday = calc_tm.tm_wday;
}
@ -210,17 +210,13 @@ static int pl031_stv2_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
unsigned long bcd_year;
int ret;
/* At the moment, we can only deal with non-wildcarded alarm times. */
ret = rtc_valid_tm(&alarm->time);
ret = pl031_stv2_tm_to_time(dev, &alarm->time,
&time, &bcd_year);
if (ret == 0) {
ret = pl031_stv2_tm_to_time(dev, &alarm->time,
&time, &bcd_year);
if (ret == 0) {
writel(bcd_year, ldata->base + RTC_YMR);
writel(time, ldata->base + RTC_MR);
writel(bcd_year, ldata->base + RTC_YMR);
writel(time, ldata->base + RTC_MR);
pl031_alarm_irq_enable(dev, alarm->enabled);
}
pl031_alarm_irq_enable(dev, alarm->enabled);
}
return ret;
@ -248,30 +244,25 @@ static int pl031_read_time(struct device *dev, struct rtc_time *tm)
{
struct pl031_local *ldata = dev_get_drvdata(dev);
rtc_time_to_tm(readl(ldata->base + RTC_DR), tm);
rtc_time64_to_tm(readl(ldata->base + RTC_DR), tm);
return 0;
}
static int pl031_set_time(struct device *dev, struct rtc_time *tm)
{
unsigned long time;
struct pl031_local *ldata = dev_get_drvdata(dev);
int ret;
ret = rtc_tm_to_time(tm, &time);
writel(rtc_tm_to_time64(tm), ldata->base + RTC_LR);
if (ret == 0)
writel(time, ldata->base + RTC_LR);
return ret;
return 0;
}
static int pl031_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
{
struct pl031_local *ldata = dev_get_drvdata(dev);
rtc_time_to_tm(readl(ldata->base + RTC_MR), &alarm->time);
rtc_time64_to_tm(readl(ldata->base + RTC_MR), &alarm->time);
alarm->pending = readl(ldata->base + RTC_RIS) & RTC_BIT_AI;
alarm->enabled = readl(ldata->base + RTC_IMSC) & RTC_BIT_AI;
@ -282,20 +273,10 @@ static int pl031_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
static int pl031_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
{
struct pl031_local *ldata = dev_get_drvdata(dev);
unsigned long time;
int ret;
/* At the moment, we can only deal with non-wildcarded alarm times. */
ret = rtc_valid_tm(&alarm->time);
if (ret == 0) {
ret = rtc_tm_to_time(&alarm->time, &time);
if (ret == 0) {
writel(time, ldata->base + RTC_MR);
pl031_alarm_irq_enable(dev, alarm->enabled);
}
}
writel(rtc_tm_to_time64(&alarm->time), ldata->base + RTC_MR);
return ret;
return 0;
}
static int pl031_remove(struct amba_device *adev)
@ -383,6 +364,8 @@ static int pl031_probe(struct amba_device *adev, const struct amba_id *id)
return PTR_ERR(ldata->rtc);
ldata->rtc->ops = ops;
ldata->rtc->range_min = vendor->range_min;
ldata->rtc->range_max = vendor->range_max;
ret = rtc_register_device(ldata->rtc);
if (ret)
@ -413,6 +396,7 @@ static struct pl031_vendor_data arm_pl031 = {
.set_alarm = pl031_set_alarm,
.alarm_irq_enable = pl031_alarm_irq_enable,
},
.range_max = U32_MAX,
};
/* The First ST derivative */
@ -426,6 +410,7 @@ static struct pl031_vendor_data stv1_pl031 = {
},
.clockwatch = true,
.st_weekday = true,
.range_max = U32_MAX,
};
/* And the second ST derivative */
@ -446,6 +431,8 @@ static struct pl031_vendor_data stv2_pl031 = {
* remove IRQF_COND_SUSPEND
*/
.irqflags = IRQF_SHARED | IRQF_COND_SUSPEND,
.range_min = RTC_TIMESTAMP_BEGIN_0000,
.range_max = RTC_TIMESTAMP_END_9999,
};
static const struct amba_id pl031_ids[] = {

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

@ -84,7 +84,7 @@ static int pm8xxx_rtc_set_time(struct device *dev, struct rtc_time *tm)
if (!rtc_dd->allow_set_time)
return -EACCES;
rtc_tm_to_time(tm, &secs);
secs = rtc_tm_to_time64(tm);
dev_dbg(dev, "Seconds value to be written to RTC = %lu\n", secs);
@ -208,7 +208,7 @@ static int pm8xxx_rtc_read_time(struct device *dev, struct rtc_time *tm)
secs = value[0] | (value[1] << 8) | (value[2] << 16) |
((unsigned long)value[3] << 24);
rtc_time_to_tm(secs, tm);
rtc_time64_to_tm(secs, tm);
dev_dbg(dev, "secs = %lu, h:m:s == %ptRt, y-m-d = %ptRdr\n", secs, tm, tm);
@ -224,7 +224,7 @@ static int pm8xxx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev);
const struct pm8xxx_rtc_regs *regs = rtc_dd->regs;
rtc_tm_to_time(&alarm->time, &secs);
secs = rtc_tm_to_time64(&alarm->time);
for (i = 0; i < NUM_8_BIT_RTC_REGS; i++) {
value[i] = secs & 0xFF;
@ -280,13 +280,7 @@ static int pm8xxx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
secs = value[0] | (value[1] << 8) | (value[2] << 16) |
((unsigned long)value[3] << 24);
rtc_time_to_tm(secs, &alarm->time);
rc = rtc_valid_tm(&alarm->time);
if (rc < 0) {
dev_err(dev, "Invalid alarm time read from RTC\n");
return rc;
}
rtc_time64_to_tm(secs, &alarm->time);
dev_dbg(dev, "Alarm set for - h:m:s=%ptRt, y-m-d=%ptRdr\n",
&alarm->time, &alarm->time);
@ -301,6 +295,7 @@ static int pm8xxx_rtc_alarm_irq_enable(struct device *dev, unsigned int enable)
struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev);
const struct pm8xxx_rtc_regs *regs = rtc_dd->regs;
unsigned int ctrl_reg;
u8 value[NUM_8_BIT_RTC_REGS] = {0};
spin_lock_irqsave(&rtc_dd->ctrl_reg_lock, irq_flags);
@ -319,6 +314,16 @@ static int pm8xxx_rtc_alarm_irq_enable(struct device *dev, unsigned int enable)
goto rtc_rw_fail;
}
/* Clear Alarm register */
if (!enable) {
rc = regmap_bulk_write(rtc_dd->regmap, regs->alarm_rw, value,
sizeof(value));
if (rc) {
dev_err(dev, "Clear RTC ALARM register failed\n");
goto rtc_rw_fail;
}
}
rtc_rw_fail:
spin_unlock_irqrestore(&rtc_dd->ctrl_reg_lock, irq_flags);
return rc;
@ -486,13 +491,12 @@ static int pm8xxx_rtc_probe(struct platform_device *pdev)
device_init_wakeup(&pdev->dev, 1);
/* Register the RTC device */
rtc_dd->rtc = devm_rtc_device_register(&pdev->dev, "pm8xxx_rtc",
&pm8xxx_rtc_ops, THIS_MODULE);
if (IS_ERR(rtc_dd->rtc)) {
dev_err(&pdev->dev, "%s: RTC registration failed (%ld)\n",
__func__, PTR_ERR(rtc_dd->rtc));
rtc_dd->rtc = devm_rtc_allocate_device(&pdev->dev);
if (IS_ERR(rtc_dd->rtc))
return PTR_ERR(rtc_dd->rtc);
}
rtc_dd->rtc->ops = &pm8xxx_rtc_ops;
rtc_dd->rtc->range_max = U32_MAX;
/* Request the alarm IRQ */
rc = devm_request_any_context_irq(&pdev->dev, rtc_dd->rtc_alarm_irq,
@ -504,9 +508,7 @@ static int pm8xxx_rtc_probe(struct platform_device *pdev)
return rc;
}
dev_dbg(&pdev->dev, "Probe success !!\n");
return 0;
return rtc_register_device(rtc_dd->rtc);
}
#ifdef CONFIG_PM_SLEEP

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

@ -85,7 +85,7 @@ static int puv3_rtc_setpie(struct device *dev, int enabled)
/* Time read/write */
static int puv3_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
{
rtc_time_to_tm(readl(RTC_RCNR), rtc_tm);
rtc_time64_to_tm(readl(RTC_RCNR), rtc_tm);
dev_dbg(dev, "read time %ptRr\n", rtc_tm);
@ -94,12 +94,9 @@ static int puv3_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
static int puv3_rtc_settime(struct device *dev, struct rtc_time *tm)
{
unsigned long rtc_count = 0;
dev_dbg(dev, "set time %ptRr\n", tm);
rtc_tm_to_time(tm, &rtc_count);
writel(rtc_count, RTC_RCNR);
writel(rtc_tm_to_time64(tm), RTC_RCNR);
return 0;
}
@ -108,7 +105,7 @@ static int puv3_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm)
{
struct rtc_time *alm_tm = &alrm->time;
rtc_time_to_tm(readl(RTC_RTAR), alm_tm);
rtc_time64_to_tm(readl(RTC_RTAR), alm_tm);
alrm->enabled = readl(RTC_RTSR) & RTC_RTSR_ALE;
@ -120,12 +117,10 @@ static int puv3_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm)
static int puv3_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
{
struct rtc_time *tm = &alrm->time;
unsigned long rtcalarm_count = 0;
dev_dbg(dev, "set alarm: %d, %ptRr\n", alrm->enabled, tm);
rtc_tm_to_time(tm, &rtcalarm_count);
writel(rtcalarm_count, RTC_RTAR);
writel(rtc_tm_to_time64(tm), RTC_RTAR);
puv3_rtc_setaie(dev, alrm->enabled);
@ -234,6 +229,7 @@ static int puv3_rtc_probe(struct platform_device *pdev)
/* register RTC and exit */
rtc->ops = &puv3_rtcops;
rtc->range_max = U32_MAX;
ret = rtc_register_device(rtc);
if (ret)
goto err_nortc;

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

@ -111,20 +111,17 @@ static int sa1100_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
struct sa1100_rtc *info = dev_get_drvdata(dev);
rtc_time_to_tm(readl_relaxed(info->rcnr), tm);
rtc_time64_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)
writel_relaxed(time, info->rcnr);
return ret;
writel_relaxed(rtc_tm_to_time64(tm), info->rcnr);
return 0;
}
static int sa1100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
@ -141,24 +138,18 @@ static int sa1100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
static int sa1100_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
struct sa1100_rtc *info = dev_get_drvdata(dev);
unsigned long time;
int ret;
spin_lock_irq(&info->lock);
ret = rtc_tm_to_time(&alrm->time, &time);
if (ret != 0)
goto out;
writel_relaxed(readl_relaxed(info->rtsr) &
(RTSR_HZE | RTSR_ALE | RTSR_AL), info->rtsr);
writel_relaxed(time, info->rtar);
writel_relaxed(rtc_tm_to_time64(&alrm->time), info->rtar);
if (alrm->enabled)
writel_relaxed(readl_relaxed(info->rtsr) | RTSR_ALE, info->rtsr);
else
writel_relaxed(readl_relaxed(info->rtsr) & ~RTSR_ALE, info->rtsr);
out:
spin_unlock_irq(&info->lock);
return ret;
return 0;
}
static int sa1100_rtc_proc(struct device *dev, struct seq_file *seq)
@ -182,7 +173,6 @@ static const struct rtc_class_ops sa1100_rtc_ops = {
int sa1100_rtc_init(struct platform_device *pdev, struct sa1100_rtc *info)
{
struct rtc_device *rtc;
int ret;
spin_lock_init(&info->lock);
@ -211,15 +201,15 @@ int sa1100_rtc_init(struct platform_device *pdev, struct sa1100_rtc *info)
writel_relaxed(0, info->rcnr);
}
rtc = devm_rtc_device_register(&pdev->dev, pdev->name, &sa1100_rtc_ops,
THIS_MODULE);
if (IS_ERR(rtc)) {
clk_disable_unprepare(info->clk);
return PTR_ERR(rtc);
}
info->rtc = rtc;
info->rtc->ops = &sa1100_rtc_ops;
info->rtc->max_user_freq = RTC_FREQ;
info->rtc->range_max = U32_MAX;
rtc->max_user_freq = RTC_FREQ;
ret = rtc_register_device(info->rtc);
if (ret) {
clk_disable_unprepare(info->clk);
return ret;
}
/* Fix for a nasty initialization problem the in SA11xx RTSR register.
* See also the comments in sa1100_rtc_interrupt().
@ -267,6 +257,10 @@ static int sa1100_rtc_probe(struct platform_device *pdev)
info->irq_1hz = irq_1hz;
info->irq_alarm = irq_alarm;
info->rtc = devm_rtc_allocate_device(&pdev->dev);
if (IS_ERR(info->rtc))
return PTR_ERR(info->rtc);
ret = devm_request_irq(&pdev->dev, irq_1hz, sa1100_rtc_interrupt, 0,
"rtc 1Hz", &pdev->dev);
if (ret) {

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

@ -504,8 +504,7 @@ static int __init sh_rtc_probe(struct platform_device *pdev)
if (unlikely(!rtc->res))
return -EBUSY;
rtc->regbase = devm_ioremap(&pdev->dev, rtc->res->start,
rtc->regsize);
rtc->regbase = devm_ioremap(&pdev->dev, rtc->res->start, rtc->regsize);
if (unlikely(!rtc->regbase))
return -EINVAL;

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

@ -90,13 +90,13 @@ static int sirfsoc_rtc_read_alarm(struct device *dev,
*/
/* if alarm is in next overflow cycle */
if (rtc_count > rtc_alarm)
rtc_time_to_tm((rtcdrv->overflow_rtc + 1)
<< (BITS_PER_LONG - RTC_SHIFT)
| rtc_alarm >> RTC_SHIFT, &(alrm->time));
rtc_time64_to_tm((rtcdrv->overflow_rtc + 1)
<< (BITS_PER_LONG - RTC_SHIFT)
| rtc_alarm >> RTC_SHIFT, &alrm->time);
else
rtc_time_to_tm(rtcdrv->overflow_rtc
<< (BITS_PER_LONG - RTC_SHIFT)
| rtc_alarm >> RTC_SHIFT, &(alrm->time));
rtc_time64_to_tm(rtcdrv->overflow_rtc
<< (BITS_PER_LONG - RTC_SHIFT)
| rtc_alarm >> RTC_SHIFT, &alrm->time);
if (sirfsoc_rtc_readl(rtcdrv, RTC_STATUS) & SIRFSOC_RTC_AL0E)
alrm->enabled = 1;
@ -113,7 +113,7 @@ static int sirfsoc_rtc_set_alarm(struct device *dev,
rtcdrv = dev_get_drvdata(dev);
if (alrm->enabled) {
rtc_tm_to_time(&(alrm->time), &rtc_alarm);
rtc_alarm = rtc_tm_to_time64(&alrm->time);
spin_lock_irq(&rtcdrv->lock);
@ -181,8 +181,8 @@ static int sirfsoc_rtc_read_time(struct device *dev,
cpu_relax();
} 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);
rtc_time64_to_tm(rtcdrv->overflow_rtc << (BITS_PER_LONG - RTC_SHIFT)
| tmp_rtc >> RTC_SHIFT, tm);
return 0;
}
@ -193,7 +193,7 @@ static int sirfsoc_rtc_set_time(struct device *dev,
struct sirfsoc_rtc_drv *rtcdrv;
rtcdrv = dev_get_drvdata(dev);
rtc_tm_to_time(tm, &rtc_time);
rtc_time = rtc_tm_to_time64(tm);
rtcdrv->overflow_rtc = rtc_time >> (BITS_PER_LONG - RTC_SHIFT);
@ -341,28 +341,22 @@ static int sirfsoc_rtc_probe(struct platform_device *pdev)
rtcdrv->overflow_rtc =
sirfsoc_rtc_readl(rtcdrv, RTC_SW_VALUE);
rtcdrv->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
&sirfsoc_rtc_ops, THIS_MODULE);
if (IS_ERR(rtcdrv->rtc)) {
err = PTR_ERR(rtcdrv->rtc);
dev_err(&pdev->dev, "can't register RTC device\n");
return err;
}
rtcdrv->rtc = devm_rtc_allocate_device(&pdev->dev);
if (IS_ERR(rtcdrv->rtc))
return PTR_ERR(rtcdrv->rtc);
rtcdrv->rtc->ops = &sirfsoc_rtc_ops;
rtcdrv->rtc->range_max = (1ULL << 60) - 1;
rtcdrv->irq = platform_get_irq(pdev, 0);
err = devm_request_irq(
&pdev->dev,
rtcdrv->irq,
sirfsoc_rtc_irq_handler,
IRQF_SHARED,
pdev->name,
rtcdrv);
err = devm_request_irq(&pdev->dev, rtcdrv->irq, sirfsoc_rtc_irq_handler,
IRQF_SHARED, pdev->name, rtcdrv);
if (err) {
dev_err(&pdev->dev, "Unable to register for the SiRF SOC RTC IRQ\n");
return err;
}
return 0;
return rtc_register_device(rtcdrv->rtc);
}
#ifdef CONFIG_PM_SLEEP

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

@ -7,7 +7,6 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/pm_wakeirq.h>
#include <linux/rtc.h>
@ -264,6 +263,12 @@ static const struct regmap_config snvs_rtc_config = {
.reg_stride = 4,
};
static void snvs_rtc_action(void *data)
{
if (data)
clk_disable_unprepare(data);
}
static int snvs_rtc_probe(struct platform_device *pdev)
{
struct snvs_rtc_data *data;
@ -314,6 +319,10 @@ static int snvs_rtc_probe(struct platform_device *pdev)
}
}
ret = devm_add_action_or_reset(&pdev->dev, snvs_rtc_action, data->clk);
if (ret)
return ret;
platform_set_drvdata(pdev, data);
/* Initialize glitch detect */
@ -326,7 +335,7 @@ static int snvs_rtc_probe(struct platform_device *pdev)
ret = snvs_rtc_enable(data, true);
if (ret) {
dev_err(&pdev->dev, "failed to enable rtc %d\n", ret);
goto error_rtc_device_register;
return ret;
}
device_init_wakeup(&pdev->dev, true);
@ -339,24 +348,13 @@ static int snvs_rtc_probe(struct platform_device *pdev)
if (ret) {
dev_err(&pdev->dev, "failed to request irq %d: %d\n",
data->irq, ret);
goto error_rtc_device_register;
return ret;
}
data->rtc->ops = &snvs_rtc_ops;
data->rtc->range_max = U32_MAX;
ret = rtc_register_device(data->rtc);
if (ret) {
dev_err(&pdev->dev, "failed to register rtc: %d\n", ret);
goto error_rtc_device_register;
}
return 0;
error_rtc_device_register:
if (data->clk)
clk_disable_unprepare(data->clk);
return ret;
return rtc_register_device(data->rtc);
}
static int __maybe_unused snvs_rtc_suspend_noirq(struct device *dev)

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

@ -27,7 +27,7 @@ static u32 starfire_get_time(void)
static int starfire_read_time(struct device *dev, struct rtc_time *tm)
{
rtc_time_to_tm(starfire_get_time(), tm);
rtc_time64_to_tm(starfire_get_time(), tm);
return 0;
}
@ -39,14 +39,16 @@ static int __init starfire_rtc_probe(struct platform_device *pdev)
{
struct rtc_device *rtc;
rtc = devm_rtc_device_register(&pdev->dev, "starfire",
&starfire_rtc_ops, THIS_MODULE);
rtc = devm_rtc_allocate_device(&pdev->dev);
if (IS_ERR(rtc))
return PTR_ERR(rtc);
rtc->ops = &starfire_rtc_ops;
rtc->range_max = U32_MAX;
platform_set_drvdata(pdev, rtc);
return 0;
return rtc_register_device(rtc);
}
static struct platform_driver starfire_rtc_driver = {

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

@ -108,7 +108,6 @@
* driver, even though it is somewhat limited.
*/
#define SUN6I_YEAR_MIN 1970
#define SUN6I_YEAR_MAX 2033
#define SUN6I_YEAR_OFF (SUN6I_YEAR_MIN - 1900)
/*
@ -250,19 +249,17 @@ static void __init sun6i_rtc_clk_init(struct device_node *node,
writel(reg, rtc->base + SUN6I_LOSC_CTRL);
}
/* Switch to the external, more precise, oscillator */
reg |= SUN6I_LOSC_CTRL_EXT_OSC;
if (rtc->data->has_losc_en)
reg |= SUN6I_LOSC_CTRL_EXT_LOSC_EN;
/* Switch to the external, more precise, oscillator, if present */
if (of_get_property(node, "clocks", NULL)) {
reg |= SUN6I_LOSC_CTRL_EXT_OSC;
if (rtc->data->has_losc_en)
reg |= SUN6I_LOSC_CTRL_EXT_LOSC_EN;
}
writel(reg, rtc->base + SUN6I_LOSC_CTRL);
/* Yes, I know, this is ugly. */
sun6i_rtc = rtc;
/* Deal with old DTs */
if (!of_get_property(node, "clocks", NULL))
goto err;
/* Only read IOSC name from device tree if it is exported */
if (rtc->data->export_iosc)
of_property_read_string_index(node, "clock-output-names", 2,
@ -279,11 +276,13 @@ static void __init sun6i_rtc_clk_init(struct device_node *node,
}
parents[0] = clk_hw_get_name(rtc->int_osc);
/* If there is no external oscillator, this will be NULL and ... */
parents[1] = of_clk_get_parent_name(node, 0);
rtc->hw.init = &init;
init.parent_names = parents;
/* ... number of clock parents will be 1. */
init.num_parents = of_clk_get_parent_count(node) + 1;
of_property_read_string_index(node, "clock-output-names", 0,
&init.name);
@ -499,7 +498,7 @@ static int sun6i_rtc_getalarm(struct device *dev, struct rtc_wkalrm *wkalrm)
wkalrm->enabled = !!(alrm_en & SUN6I_ALRM_EN_CNT_EN);
wkalrm->pending = !!(alrm_st & SUN6I_ALRM_EN_CNT_EN);
rtc_time_to_tm(chip->alarm, &wkalrm->time);
rtc_time64_to_tm(chip->alarm, &wkalrm->time);
return 0;
}
@ -520,8 +519,8 @@ static int sun6i_rtc_setalarm(struct device *dev, struct rtc_wkalrm *wkalrm)
return -EINVAL;
}
rtc_tm_to_time(alrm_tm, &time_set);
rtc_tm_to_time(&tm_now, &time_now);
time_set = rtc_tm_to_time64(alrm_tm);
time_now = rtc_tm_to_time64(&tm_now);
if (time_set <= time_now) {
dev_err(dev, "Date to set in the past\n");
return -EINVAL;
@ -569,14 +568,6 @@ static int sun6i_rtc_settime(struct device *dev, struct rtc_time *rtc_tm)
struct sun6i_rtc_dev *chip = dev_get_drvdata(dev);
u32 date = 0;
u32 time = 0;
int year;
year = rtc_tm->tm_year + 1900;
if (year < SUN6I_YEAR_MIN || year > SUN6I_YEAR_MAX) {
dev_err(dev, "rtc only supports year in range %d - %d\n",
SUN6I_YEAR_MIN, SUN6I_YEAR_MAX);
return -EINVAL;
}
rtc_tm->tm_year -= SUN6I_YEAR_OFF;
rtc_tm->tm_mon += 1;
@ -585,7 +576,7 @@ static int sun6i_rtc_settime(struct device *dev, struct rtc_time *rtc_tm)
SUN6I_DATE_SET_MON_VALUE(rtc_tm->tm_mon) |
SUN6I_DATE_SET_YEAR_VALUE(rtc_tm->tm_year);
if (is_leap_year(year))
if (is_leap_year(rtc_tm->tm_year + SUN6I_YEAR_MIN))
date |= SUN6I_LEAP_SET_VALUE(1);
time = SUN6I_TIME_SET_SEC_VALUE(rtc_tm->tm_sec) |
@ -726,12 +717,16 @@ static int sun6i_rtc_probe(struct platform_device *pdev)
device_init_wakeup(&pdev->dev, 1);
chip->rtc = devm_rtc_device_register(&pdev->dev, "rtc-sun6i",
&sun6i_rtc_ops, THIS_MODULE);
if (IS_ERR(chip->rtc)) {
dev_err(&pdev->dev, "unable to register device\n");
chip->rtc = devm_rtc_allocate_device(&pdev->dev);
if (IS_ERR(chip->rtc))
return PTR_ERR(chip->rtc);
}
chip->rtc->ops = &sun6i_rtc_ops;
chip->rtc->range_max = 2019686399LL; /* 2033-12-31 23:59:59 */
ret = rtc_register_device(chip->rtc);
if (ret)
return ret;
dev_info(&pdev->dev, "RTC enabled\n");

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

@ -38,6 +38,8 @@
#define RTC_CALIB_DEF 0x198233
#define RTC_CALIB_MASK 0x1FFFFF
#define RTC_ALRM_MASK BIT(1)
#define RTC_MSEC 1000
struct xlnx_rtc_dev {
struct rtc_device *rtc;
@ -123,11 +125,28 @@ static int xlnx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
static int xlnx_rtc_alarm_irq_enable(struct device *dev, u32 enabled)
{
struct xlnx_rtc_dev *xrtcdev = dev_get_drvdata(dev);
unsigned int status;
ulong timeout;
timeout = jiffies + msecs_to_jiffies(RTC_MSEC);
if (enabled) {
while (1) {
status = readl(xrtcdev->reg_base + RTC_INT_STS);
if (!((status & RTC_ALRM_MASK) == RTC_ALRM_MASK))
break;
if (time_after_eq(jiffies, timeout)) {
dev_err(dev, "Time out occur, while clearing alarm status bit\n");
return -ETIMEDOUT;
}
writel(RTC_INT_ALRM, xrtcdev->reg_base + RTC_INT_STS);
}
if (enabled)
writel(RTC_INT_ALRM, xrtcdev->reg_base + RTC_INT_EN);
else
} else {
writel(RTC_INT_ALRM, xrtcdev->reg_base + RTC_INT_DIS);
}
return 0;
}
@ -183,8 +202,8 @@ static irqreturn_t xlnx_rtc_interrupt(int irq, void *id)
if (!(status & (RTC_INT_SEC | RTC_INT_ALRM)))
return IRQ_NONE;
/* Clear RTC_INT_ALRM interrupt only */
writel(RTC_INT_ALRM, xrtcdev->reg_base + RTC_INT_STS);
/* Disable RTC_INT_ALRM interrupt only */
writel(RTC_INT_ALRM, xrtcdev->reg_base + RTC_INT_DIS);
if (status & RTC_INT_ALRM)
rtc_update_irq(xrtcdev->rtc, 1, RTC_IRQF | RTC_AF);

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

@ -279,7 +279,7 @@ static bool rtc_does_wakealarm(struct rtc_device *rtc)
static umode_t rtc_attr_is_visible(struct kobject *kobj,
struct attribute *attr, int n)
{
struct device *dev = container_of(kobj, struct device, kobj);
struct device *dev = kobj_to_dev(kobj);
struct rtc_device *rtc = to_rtc_device(dev);
umode_t mode = attr->mode;

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

@ -34,18 +34,6 @@ static inline time64_t rtc_tm_sub(struct rtc_time *lhs, struct rtc_time *rhs)
return rtc_tm_to_time64(lhs) - rtc_tm_to_time64(rhs);
}
static inline void rtc_time_to_tm(unsigned long time, struct rtc_time *tm)
{
rtc_time64_to_tm(time, tm);
}
static inline int rtc_tm_to_time(struct rtc_time *tm, unsigned long *time)
{
*time = rtc_tm_to_time64(tm);
return 0;
}
#include <linux/device.h>
#include <linux/seq_file.h>
#include <linux/cdev.h>

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

@ -12,6 +12,9 @@
#ifndef _UAPI_LINUX_RTC_H_
#define _UAPI_LINUX_RTC_H_
#include <linux/const.h>
#include <linux/ioctl.h>
/*
* The struct used to pass data via the following ioctl. Similar to the
* struct tm in <time.h>, but it needs to be here so that the kernel
@ -92,10 +95,10 @@ struct rtc_pll_info {
#define RTC_PLL_GET _IOR('p', 0x11, struct rtc_pll_info) /* Get PLL correction */
#define RTC_PLL_SET _IOW('p', 0x12, struct rtc_pll_info) /* Set PLL correction */
#define RTC_VL_DATA_INVALID BIT(0) /* Voltage too low, RTC data is invalid */
#define RTC_VL_BACKUP_LOW BIT(1) /* Backup voltage is low */
#define RTC_VL_BACKUP_EMPTY BIT(2) /* Backup empty or not present */
#define RTC_VL_ACCURACY_LOW BIT(3) /* Voltage is low, RTC accuracy is reduced */
#define RTC_VL_DATA_INVALID _BITUL(0) /* Voltage too low, RTC data is invalid */
#define RTC_VL_BACKUP_LOW _BITUL(1) /* Backup voltage is low */
#define RTC_VL_BACKUP_EMPTY _BITUL(2) /* Backup empty or not present */
#define RTC_VL_ACCURACY_LOW _BITUL(3) /* Voltage is low, RTC accuracy is reduced */
#define RTC_VL_READ _IOR('p', 0x13, unsigned int) /* Voltage low detection */
#define RTC_VL_CLR _IO('p', 0x14) /* Clear voltage low information */