RTC for 5.14
Drivers: - add or fix SPDX identifiers - NXP pcf*: fix datasheet URLs - imxdi: add wakeup support - pcf2127: handle timestamp interrupts, this fixes a possible interrupt storm - bd70528: Drop BD70528 support -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEBqsFVZXh8s/0O5JiY6TcMGxwOjIFAmDqFFsACgkQY6TcMGxw OjKTCQ//W43oZ2yhWgj4xn1HCzGc4deQtBx6XtQKQvOaUYVnDUr1xI5JwMOZvlpp mKhKUayBzoecxjI0CinNRnkZ0W8izcwktmk4ZVk39GYOR98X6WHQ8LPRX248HACe OOmMWhSTKEJySW2mfX9I4bcg4dUJJD8fStuEqi0ZGaSfjpFXh8kI2i8xscvH2aFD eRScU/TUmn0wGsP+CIXwZCYUd/0OFovc0e0Io1i6qmDAz9GABtzgc0h2CdvH5sqj 6QK6DR9AF5AcZFg5GGu2Pbz7i8HM4rxkZkF/YqHTK9nZfiN4bjlHOPwEysEMfOZ5 nrjR7sGt3UDF1BCZPUHuyY20a5kslXoK4l8GLAG7fBQpOR24a4Nt3E8RL0G4EELF /Mtn1RuuSUpJIYb9gLD8UTNgfP7PBgpkxXrbzqxEoVe0d2dpH8+zfKDzkos5HAEK /ksr6Oojpb0/wnIjiJG/PZBVCPNg6cJHGBwo7A0j0Q+XERgNDFUnBsOyd/jXnF+P /9/nnZBxRsxnWODhfdnL6mTiPsGYOEjj6/f45i44BojeuFKrCVym+33CTnf++Yfm G5XZnXElxAJaum/DObKhyqqQ6EEKuZCUtuakiM2FAJBX6G4euAD8Xl8qNpEWBAUt OqkHZ8KgoRMBRDHzqCrXnC+vErSPVgRaR7Pwgh04/b7m75sBdPI= =5VbG -----END PGP SIGNATURE----- Merge tag 'rtc-5.14' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux Pull RTC updates from Alexandre Belloni: "Mostly documentation/comment changes and non urgent fixes. - add or fix SPDX identifiers - NXP pcf*: fix datasheet URLs - imxdi: add wakeup support - pcf2127: handle timestamp interrupts, this fixes a possible interrupt storm - bd70528: Drop BD70528 support" * tag 'rtc-5.14' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux: (33 commits) rtc: pcf8523: rename register and bit defines rtc: pcf2127: handle timestamp interrupts rtc: at91sam9: Remove unnecessary offset variable checks rtc: s5m: Check return value of s5m_check_peding_alarm_interrupt() rtc: spear: convert to SPDX identifier rtc: tps6586x: convert to SPDX identifier rtc: tps80031: convert to SPDX identifier rtc: rtd119x: Fix format of SPDX identifier rtc: sc27xx: Fix format of SPDX identifier rtc: palmas: convert to SPDX identifier rtc: max6900: convert to SPDX identifier rtc: ds1374: convert to SPDX identifier rtc: au1xxx: convert to SPDX identifier rtc: pcf85063: Update the PCF85063A datasheet revision dt-bindings: rtc: ti,bq32k: take maintainership rtc: pcf8563: Fix the datasheet URL rtc: pcf85063: Fix the datasheet URL rtc: pcf2127: Fix the datasheet URL dt-bindings: rtc: ti,bq32k: Convert to json-schema dt-bindings: rtc: rx8900: Convert to YAML schema ...
This commit is contained in:
commit
de55409658
|
@ -1,22 +0,0 @@
|
||||||
Real Time Clock driver for:
|
|
||||||
- Epson RX8900
|
|
||||||
- Micro Crystal rv8803
|
|
||||||
|
|
||||||
Required properties:
|
|
||||||
- compatible: should be: "microcrystal,rv8803" or "epson,rx8900"
|
|
||||||
- reg : the I2C address of the device for I2C
|
|
||||||
|
|
||||||
Optional properties:
|
|
||||||
- epson,vdet-disable : boolean, if present will disable voltage detector.
|
|
||||||
Should be set if no backup battery is used.
|
|
||||||
- trickle-diode-disable : boolean, if present will disable internal trickle
|
|
||||||
charger diode
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
rtc: rtc@32 {
|
|
||||||
compatible = "epson,rx8900"
|
|
||||||
reg = <0x32>;
|
|
||||||
epson,vdet-disable;
|
|
||||||
trickle-diode-disable;
|
|
||||||
};
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
$id: http://devicetree.org/schemas/rtc/epson,rx8900.yaml#
|
||||||
|
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||||
|
|
||||||
|
title: EPSON RX8900 / Microcrystal RV8803 Real-Time Clock DT bindings
|
||||||
|
|
||||||
|
maintainers:
|
||||||
|
- Marek Vasut <marex@denx.de>
|
||||||
|
|
||||||
|
allOf:
|
||||||
|
- $ref: rtc.yaml#
|
||||||
|
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
enum:
|
||||||
|
- epson,rx8900
|
||||||
|
- microcrystal,rv8803
|
||||||
|
|
||||||
|
reg:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
epson,vdet-disable:
|
||||||
|
type: boolean
|
||||||
|
description: |
|
||||||
|
Disable voltage detector. Should be set if no backup battery is used.
|
||||||
|
|
||||||
|
trickle-diode-disable: true
|
||||||
|
|
||||||
|
required:
|
||||||
|
- compatible
|
||||||
|
- reg
|
||||||
|
|
||||||
|
additionalProperties: false
|
||||||
|
|
||||||
|
examples:
|
||||||
|
- |
|
||||||
|
i2c {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
rtc@32 {
|
||||||
|
compatible = "epson,rx8900";
|
||||||
|
reg = <0x32>;
|
||||||
|
epson,vdet-disable;
|
||||||
|
trickle-diode-disable;
|
||||||
|
};
|
||||||
|
};
|
|
@ -1,28 +0,0 @@
|
||||||
* Faraday Technology FTRTC010 Real Time Clock
|
|
||||||
|
|
||||||
This RTC appears in for example the Storlink Gemini family of
|
|
||||||
SoCs.
|
|
||||||
|
|
||||||
Required properties:
|
|
||||||
- compatible : Should be one of:
|
|
||||||
"faraday,ftrtc010"
|
|
||||||
"cortina,gemini-rtc", "faraday,ftrtc010"
|
|
||||||
|
|
||||||
Optional properties:
|
|
||||||
- clocks: when present should contain clock references to the
|
|
||||||
PCLK and EXTCLK clocks. Faraday calls the later CLK1HZ and
|
|
||||||
says the clock should be 1 Hz, but implementers actually seem
|
|
||||||
to choose different clocks here, like Cortina who chose
|
|
||||||
32768 Hz (a typical low-power clock).
|
|
||||||
- clock-names: should name the clocks "PCLK" and "EXTCLK"
|
|
||||||
respectively.
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
|
|
||||||
rtc@45000000 {
|
|
||||||
compatible = "cortina,gemini-rtc";
|
|
||||||
reg = <0x45000000 0x100>;
|
|
||||||
interrupts = <17 IRQ_TYPE_LEVEL_HIGH>;
|
|
||||||
clocks = <&foo 0>, <&foo 1>;
|
|
||||||
clock-names = "PCLK", "EXTCLK";
|
|
||||||
};
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
$id: http://devicetree.org/schemas/rtc/faraday,ftrtc010.yaml#
|
||||||
|
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||||
|
|
||||||
|
title: Faraday Technology FTRTC010 Real Time Clock
|
||||||
|
|
||||||
|
maintainers:
|
||||||
|
- Linus Walleij <linus.walleij@linaro.org>
|
||||||
|
|
||||||
|
description: |
|
||||||
|
This RTC appears in for example the Storlink Gemini family of SoCs.
|
||||||
|
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
oneOf:
|
||||||
|
- const: faraday,ftrtc010
|
||||||
|
- items:
|
||||||
|
- const: cortina,gemini-rtc
|
||||||
|
- const: faraday,ftrtc010
|
||||||
|
|
||||||
|
resets:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
reg:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
interrupts:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
clocks:
|
||||||
|
minItems: 2
|
||||||
|
items:
|
||||||
|
- description: PCLK clocks
|
||||||
|
- description: EXTCLK clocks. Faraday calls it CLK1HZ and says the clock
|
||||||
|
should be 1 Hz, but implementers actually seem to choose different
|
||||||
|
clocks here, like Cortina who chose 32768 Hz (a typical low-power clock).
|
||||||
|
|
||||||
|
clock-names:
|
||||||
|
items:
|
||||||
|
- const: "PCLK"
|
||||||
|
- const: "EXTCLK"
|
||||||
|
|
||||||
|
required:
|
||||||
|
- compatible
|
||||||
|
|
||||||
|
additionalProperties: false
|
||||||
|
|
||||||
|
examples:
|
||||||
|
- |
|
||||||
|
#include <dt-bindings/interrupt-controller/irq.h>
|
||||||
|
rtc@45000000 {
|
||||||
|
compatible = "cortina,gemini-rtc", "faraday,ftrtc010";
|
||||||
|
reg = <0x45000000 0x100>;
|
||||||
|
interrupts = <17 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
|
clocks = <&foo 0>, <&foo 1>;
|
||||||
|
clock-names = "PCLK", "EXTCLK";
|
||||||
|
};
|
|
@ -21,10 +21,19 @@ Optional properties:
|
||||||
clock name
|
clock name
|
||||||
- wakeup-source: Enables wake up of host system on alarm
|
- wakeup-source: Enables wake up of host system on alarm
|
||||||
|
|
||||||
|
Optional child node:
|
||||||
|
- clock: Provide this if the square wave pin is used as boot-enabled fixed clock.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
rtc@68 {
|
rtc@68 {
|
||||||
compatible = "st,m41t80";
|
compatible = "st,m41t80";
|
||||||
reg = <0x68>;
|
reg = <0x68>;
|
||||||
interrupt-parent = <&UIC0>;
|
interrupt-parent = <&UIC0>;
|
||||||
interrupts = <0x9 0x8>;
|
interrupts = <0x9 0x8>;
|
||||||
|
|
||||||
|
clock {
|
||||||
|
compatible = "fixed-clock";
|
||||||
|
#clock-cells = <0>;
|
||||||
|
clock-frequency = <32768>;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
$id: http://devicetree.org/schemas/rtc/ti,bq32000.yaml#
|
||||||
|
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||||
|
|
||||||
|
title: TI BQ32000 I2C Serial Real-Time Clock
|
||||||
|
|
||||||
|
maintainers:
|
||||||
|
- Alexandre Belloni <alexandre.belloni@bootlin.com>
|
||||||
|
|
||||||
|
allOf:
|
||||||
|
- $ref: rtc.yaml#
|
||||||
|
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
const: ti,bq32000
|
||||||
|
|
||||||
|
reg:
|
||||||
|
const: 0x68
|
||||||
|
|
||||||
|
interrupts:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
start-year: true
|
||||||
|
|
||||||
|
trickle-resistor-ohms:
|
||||||
|
enum: [ 1120, 20180 ]
|
||||||
|
|
||||||
|
trickle-diode-disable: true
|
||||||
|
|
||||||
|
required:
|
||||||
|
- compatible
|
||||||
|
- reg
|
||||||
|
|
||||||
|
additionalProperties: false
|
||||||
|
|
||||||
|
examples:
|
||||||
|
- |
|
||||||
|
i2c {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
bq32000: rtc@68 {
|
||||||
|
compatible = "ti,bq32000";
|
||||||
|
reg = <0x68>;
|
||||||
|
trickle-resistor-ohms = <1120>;
|
||||||
|
};
|
||||||
|
};
|
|
@ -1,18 +0,0 @@
|
||||||
* TI BQ32000 I2C Serial Real-Time Clock
|
|
||||||
|
|
||||||
Required properties:
|
|
||||||
- compatible: Should contain "ti,bq32000".
|
|
||||||
- reg: I2C address for chip
|
|
||||||
|
|
||||||
Optional properties:
|
|
||||||
- trickle-resistor-ohms : Selected resistor for trickle charger
|
|
||||||
Values usable are 1120 and 20180
|
|
||||||
Should be given if trickle charger should be enabled
|
|
||||||
- trickle-diode-disable : Do not use internal trickle charger diode
|
|
||||||
Should be given if internal trickle charger diode should be disabled
|
|
||||||
Example:
|
|
||||||
bq32000: rtc@68 {
|
|
||||||
compatible = "ti,bq32000";
|
|
||||||
trickle-resistor-ohms = <1120>;
|
|
||||||
reg = <0x68>;
|
|
||||||
};
|
|
|
@ -501,11 +501,11 @@ config RTC_DRV_M41T80_WDT
|
||||||
watchdog timer in the ST M41T60 and M41T80 RTC chips series.
|
watchdog timer in the ST M41T60 and M41T80 RTC chips series.
|
||||||
|
|
||||||
config RTC_DRV_BD70528
|
config RTC_DRV_BD70528
|
||||||
tristate "ROHM BD70528, BD71815 and BD71828 PMIC RTC"
|
tristate "ROHM BD71815 and BD71828 PMIC RTC"
|
||||||
depends on MFD_ROHM_BD71828 || MFD_ROHM_BD70528 && (BD70528_WATCHDOG || !BD70528_WATCHDOG)
|
depends on MFD_ROHM_BD71828
|
||||||
help
|
help
|
||||||
If you say Y here you will get support for the RTC
|
If you say Y here you will get support for the RTC
|
||||||
block on ROHM BD70528, BD71815 and BD71828 Power Management IC.
|
block on ROHM BD71815 and BD71828 Power Management IC.
|
||||||
|
|
||||||
This driver can also be built as a module. If so, the module
|
This driver can also be built as a module. If so, the module
|
||||||
will be called rtc-bd70528.
|
will be called rtc-bd70528.
|
||||||
|
|
|
@ -23,8 +23,8 @@ static bool is_rtc_hctosys(struct rtc_device *rtc)
|
||||||
int size;
|
int size;
|
||||||
char name[NAME_SIZE];
|
char name[NAME_SIZE];
|
||||||
|
|
||||||
size = scnprintf(name, NAME_SIZE, "rtc%d", rtc->id);
|
size = snprintf(name, NAME_SIZE, "rtc%d", rtc->id);
|
||||||
if (size > NAME_SIZE)
|
if (size >= NAME_SIZE)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return !strncmp(name, CONFIG_RTC_HCTOSYS_DEVICE, NAME_SIZE);
|
return !strncmp(name, CONFIG_RTC_HCTOSYS_DEVICE, NAME_SIZE);
|
||||||
|
|
|
@ -184,7 +184,7 @@ static int at91_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm)
|
||||||
return -EILSEQ;
|
return -EILSEQ;
|
||||||
|
|
||||||
memset(alrm, 0, sizeof(*alrm));
|
memset(alrm, 0, sizeof(*alrm));
|
||||||
if (alarm != ALARM_DISABLED && offset != 0) {
|
if (alarm != ALARM_DISABLED) {
|
||||||
rtc_time64_to_tm(offset + alarm, tm);
|
rtc_time64_to_tm(offset + alarm, tm);
|
||||||
|
|
||||||
dev_dbg(dev, "%s: %ptR\n", __func__, tm);
|
dev_dbg(dev, "%s: %ptR\n", __func__, tm);
|
||||||
|
|
|
@ -1,11 +1,8 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
/*
|
/*
|
||||||
* Au1xxx counter0 (aka Time-Of-Year counter) RTC interface driver.
|
* Au1xxx counter0 (aka Time-Of-Year counter) RTC interface driver.
|
||||||
*
|
*
|
||||||
* Copyright (C) 2008 Manuel Lauss <mano@roarinelk.homelinux.net>
|
* Copyright (C) 2008 Manuel Lauss <mano@roarinelk.homelinux.net>
|
||||||
*
|
|
||||||
* This file is subject to the terms and conditions of the GNU General Public
|
|
||||||
* License. See the file "COPYING" in the main directory of this archive
|
|
||||||
* for more details.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* All current Au1xxx SoCs have 2 counters fed by an external 32.768 kHz
|
/* All current Au1xxx SoCs have 2 counters fed by an external 32.768 kHz
|
||||||
|
|
|
@ -2,10 +2,9 @@
|
||||||
//
|
//
|
||||||
// Copyright (C) 2018 ROHM Semiconductors
|
// Copyright (C) 2018 ROHM Semiconductors
|
||||||
//
|
//
|
||||||
// RTC driver for ROHM BD70528 PMIC
|
// RTC driver for ROHM BD71828 and BD71815 PMIC
|
||||||
|
|
||||||
#include <linux/bcd.h>
|
#include <linux/bcd.h>
|
||||||
#include <linux/mfd/rohm-bd70528.h>
|
|
||||||
#include <linux/mfd/rohm-bd71815.h>
|
#include <linux/mfd/rohm-bd71815.h>
|
||||||
#include <linux/mfd/rohm-bd71828.h>
|
#include <linux/mfd/rohm-bd71828.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
|
@ -39,11 +38,6 @@ struct bd70528_rtc_data {
|
||||||
u8 year;
|
u8 year;
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
struct bd70528_rtc_wake {
|
|
||||||
struct bd70528_rtc_day time;
|
|
||||||
u8 ctrl;
|
|
||||||
} __packed;
|
|
||||||
|
|
||||||
struct bd71828_rtc_alm {
|
struct bd71828_rtc_alm {
|
||||||
struct bd70528_rtc_data alm0;
|
struct bd70528_rtc_data alm0;
|
||||||
struct bd70528_rtc_data alm1;
|
struct bd70528_rtc_data alm1;
|
||||||
|
@ -51,141 +45,14 @@ struct bd71828_rtc_alm {
|
||||||
u8 alm1_mask;
|
u8 alm1_mask;
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
struct bd70528_rtc_alm {
|
|
||||||
struct bd70528_rtc_data data;
|
|
||||||
u8 alm_mask;
|
|
||||||
u8 alm_repeat;
|
|
||||||
} __packed;
|
|
||||||
|
|
||||||
struct bd70528_rtc {
|
struct bd70528_rtc {
|
||||||
struct rohm_regmap_dev *parent;
|
struct rohm_regmap_dev *parent;
|
||||||
struct regmap *regmap;
|
struct regmap *regmap;
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
u8 reg_time_start;
|
u8 reg_time_start;
|
||||||
u8 bd718xx_alm_block_start;
|
u8 bd718xx_alm_block_start;
|
||||||
bool has_rtc_timers;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static int bd70528_set_wake(struct rohm_regmap_dev *bd70528,
|
|
||||||
int enable, int *old_state)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
unsigned int ctrl_reg;
|
|
||||||
|
|
||||||
ret = regmap_read(bd70528->regmap, BD70528_REG_WAKE_EN, &ctrl_reg);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
if (old_state) {
|
|
||||||
if (ctrl_reg & BD70528_MASK_WAKE_EN)
|
|
||||||
*old_state |= BD70528_WAKE_STATE_BIT;
|
|
||||||
else
|
|
||||||
*old_state &= ~BD70528_WAKE_STATE_BIT;
|
|
||||||
|
|
||||||
if (!enable == !(*old_state & BD70528_WAKE_STATE_BIT))
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (enable)
|
|
||||||
ctrl_reg |= BD70528_MASK_WAKE_EN;
|
|
||||||
else
|
|
||||||
ctrl_reg &= ~BD70528_MASK_WAKE_EN;
|
|
||||||
|
|
||||||
return regmap_write(bd70528->regmap, BD70528_REG_WAKE_EN,
|
|
||||||
ctrl_reg);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int bd70528_set_elapsed_tmr(struct rohm_regmap_dev *bd70528,
|
|
||||||
int enable, int *old_state)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
unsigned int ctrl_reg;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* TBD
|
|
||||||
* What is the purpose of elapsed timer ?
|
|
||||||
* Is the timeout registers counting down, or is the disable - re-enable
|
|
||||||
* going to restart the elapsed-time counting? If counting is restarted
|
|
||||||
* the timeout should be decreased by the amount of time that has
|
|
||||||
* elapsed since starting the timer. Maybe we should store the monotonic
|
|
||||||
* clock value when timer is started so that if RTC is set while timer
|
|
||||||
* is armed we could do the compensation. This is a hack if RTC/system
|
|
||||||
* clk are drifting. OTOH, RTC controlled via I2C is in any case
|
|
||||||
* inaccurate...
|
|
||||||
*/
|
|
||||||
ret = regmap_read(bd70528->regmap, BD70528_REG_ELAPSED_TIMER_EN,
|
|
||||||
&ctrl_reg);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
if (old_state) {
|
|
||||||
if (ctrl_reg & BD70528_MASK_ELAPSED_TIMER_EN)
|
|
||||||
*old_state |= BD70528_ELAPSED_STATE_BIT;
|
|
||||||
else
|
|
||||||
*old_state &= ~BD70528_ELAPSED_STATE_BIT;
|
|
||||||
|
|
||||||
if ((!enable) == (!(*old_state & BD70528_ELAPSED_STATE_BIT)))
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (enable)
|
|
||||||
ctrl_reg |= BD70528_MASK_ELAPSED_TIMER_EN;
|
|
||||||
else
|
|
||||||
ctrl_reg &= ~BD70528_MASK_ELAPSED_TIMER_EN;
|
|
||||||
|
|
||||||
return regmap_write(bd70528->regmap, BD70528_REG_ELAPSED_TIMER_EN,
|
|
||||||
ctrl_reg);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int bd70528_set_rtc_based_timers(struct bd70528_rtc *r, int new_state,
|
|
||||||
int *old_state)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
ret = bd70528_wdt_set(r->parent, new_state & BD70528_WDT_STATE_BIT,
|
|
||||||
old_state);
|
|
||||||
if (ret) {
|
|
||||||
dev_err(r->dev,
|
|
||||||
"Failed to disable WDG for RTC setting (%d)\n", ret);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
ret = bd70528_set_elapsed_tmr(r->parent,
|
|
||||||
new_state & BD70528_ELAPSED_STATE_BIT,
|
|
||||||
old_state);
|
|
||||||
if (ret) {
|
|
||||||
dev_err(r->dev,
|
|
||||||
"Failed to disable 'elapsed timer' for RTC setting\n");
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
ret = bd70528_set_wake(r->parent, new_state & BD70528_WAKE_STATE_BIT,
|
|
||||||
old_state);
|
|
||||||
if (ret) {
|
|
||||||
dev_err(r->dev,
|
|
||||||
"Failed to disable 'wake timer' for RTC setting\n");
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int bd70528_re_enable_rtc_based_timers(struct bd70528_rtc *r,
|
|
||||||
int old_state)
|
|
||||||
{
|
|
||||||
if (!r->has_rtc_timers)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return bd70528_set_rtc_based_timers(r, old_state, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int bd70528_disable_rtc_based_timers(struct bd70528_rtc *r,
|
|
||||||
int *old_state)
|
|
||||||
{
|
|
||||||
if (!r->has_rtc_timers)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return bd70528_set_rtc_based_timers(r, 0, old_state);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void tmday2rtc(struct rtc_time *t, struct bd70528_rtc_day *d)
|
static inline void tmday2rtc(struct rtc_time *t, struct bd70528_rtc_day *d)
|
||||||
{
|
{
|
||||||
d->sec &= ~BD70528_MASK_RTC_SEC;
|
d->sec &= ~BD70528_MASK_RTC_SEC;
|
||||||
|
@ -267,52 +134,6 @@ static int bd71828_set_alarm(struct device *dev, struct rtc_wkalrm *a)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int bd70528_set_alarm(struct device *dev, struct rtc_wkalrm *a)
|
|
||||||
{
|
|
||||||
struct bd70528_rtc_wake wake;
|
|
||||||
struct bd70528_rtc_alm alm;
|
|
||||||
int ret;
|
|
||||||
struct bd70528_rtc *r = dev_get_drvdata(dev);
|
|
||||||
|
|
||||||
ret = regmap_bulk_read(r->regmap, BD70528_REG_RTC_WAKE_START, &wake,
|
|
||||||
sizeof(wake));
|
|
||||||
if (ret) {
|
|
||||||
dev_err(dev, "Failed to read wake regs\n");
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = regmap_bulk_read(r->regmap, BD70528_REG_RTC_ALM_START, &alm,
|
|
||||||
sizeof(alm));
|
|
||||||
if (ret) {
|
|
||||||
dev_err(dev, "Failed to read alarm regs\n");
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
tm2rtc(&a->time, &alm.data);
|
|
||||||
tmday2rtc(&a->time, &wake.time);
|
|
||||||
|
|
||||||
if (a->enabled) {
|
|
||||||
alm.alm_mask &= ~BD70528_MASK_ALM_EN;
|
|
||||||
wake.ctrl |= BD70528_MASK_WAKE_EN;
|
|
||||||
} else {
|
|
||||||
alm.alm_mask |= BD70528_MASK_ALM_EN;
|
|
||||||
wake.ctrl &= ~BD70528_MASK_WAKE_EN;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = regmap_bulk_write(r->regmap, BD70528_REG_RTC_WAKE_START, &wake,
|
|
||||||
sizeof(wake));
|
|
||||||
if (ret) {
|
|
||||||
dev_err(dev, "Failed to set wake time\n");
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
ret = regmap_bulk_write(r->regmap, BD70528_REG_RTC_ALM_START, &alm,
|
|
||||||
sizeof(alm));
|
|
||||||
if (ret)
|
|
||||||
dev_err(dev, "Failed to set alarm time\n");
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int bd71828_read_alarm(struct device *dev, struct rtc_wkalrm *a)
|
static int bd71828_read_alarm(struct device *dev, struct rtc_wkalrm *a)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -336,75 +157,25 @@ static int bd71828_read_alarm(struct device *dev, struct rtc_wkalrm *a)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int bd70528_read_alarm(struct device *dev, struct rtc_wkalrm *a)
|
static int bd71828_set_time(struct device *dev, struct rtc_time *t)
|
||||||
{
|
{
|
||||||
struct bd70528_rtc_alm alm;
|
|
||||||
int ret;
|
int ret;
|
||||||
struct bd70528_rtc *r = dev_get_drvdata(dev);
|
|
||||||
|
|
||||||
ret = regmap_bulk_read(r->regmap, BD70528_REG_RTC_ALM_START, &alm,
|
|
||||||
sizeof(alm));
|
|
||||||
if (ret) {
|
|
||||||
dev_err(dev, "Failed to read alarm regs\n");
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
rtc2tm(&alm.data, &a->time);
|
|
||||||
a->time.tm_mday = -1;
|
|
||||||
a->time.tm_mon = -1;
|
|
||||||
a->time.tm_year = -1;
|
|
||||||
a->enabled = !(alm.alm_mask & BD70528_MASK_ALM_EN);
|
|
||||||
a->pending = 0;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int bd70528_set_time_locked(struct device *dev, struct rtc_time *t)
|
|
||||||
{
|
|
||||||
int ret, tmpret, old_states;
|
|
||||||
struct bd70528_rtc_data rtc_data;
|
struct bd70528_rtc_data rtc_data;
|
||||||
struct bd70528_rtc *r = dev_get_drvdata(dev);
|
struct bd70528_rtc *r = dev_get_drvdata(dev);
|
||||||
|
|
||||||
ret = bd70528_disable_rtc_based_timers(r, &old_states);
|
ret = regmap_bulk_read(r->regmap, r->reg_time_start, &rtc_data,
|
||||||
if (ret)
|
sizeof(rtc_data));
|
||||||
return ret;
|
if (ret) {
|
||||||
|
|
||||||
tmpret = regmap_bulk_read(r->regmap, r->reg_time_start, &rtc_data,
|
|
||||||
sizeof(rtc_data));
|
|
||||||
if (tmpret) {
|
|
||||||
dev_err(dev, "Failed to read RTC time registers\n");
|
dev_err(dev, "Failed to read RTC time registers\n");
|
||||||
goto renable_out;
|
return ret;
|
||||||
}
|
}
|
||||||
tm2rtc(t, &rtc_data);
|
tm2rtc(t, &rtc_data);
|
||||||
|
|
||||||
tmpret = regmap_bulk_write(r->regmap, r->reg_time_start, &rtc_data,
|
ret = regmap_bulk_write(r->regmap, r->reg_time_start, &rtc_data,
|
||||||
sizeof(rtc_data));
|
sizeof(rtc_data));
|
||||||
if (tmpret) {
|
if (ret)
|
||||||
dev_err(dev, "Failed to set RTC time\n");
|
dev_err(dev, "Failed to set RTC time\n");
|
||||||
goto renable_out;
|
|
||||||
}
|
|
||||||
|
|
||||||
renable_out:
|
|
||||||
ret = bd70528_re_enable_rtc_based_timers(r, old_states);
|
|
||||||
if (tmpret)
|
|
||||||
ret = tmpret;
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int bd71828_set_time(struct device *dev, struct rtc_time *t)
|
|
||||||
{
|
|
||||||
return bd70528_set_time_locked(dev, t);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int bd70528_set_time(struct device *dev, struct rtc_time *t)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
struct bd70528_rtc *r = dev_get_drvdata(dev);
|
|
||||||
|
|
||||||
bd70528_wdt_lock(r->parent);
|
|
||||||
ret = bd70528_set_time_locked(dev, t);
|
|
||||||
bd70528_wdt_unlock(r->parent);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -427,31 +198,6 @@ static int bd70528_get_time(struct device *dev, struct rtc_time *t)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int bd70528_alm_enable(struct device *dev, unsigned int enabled)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
unsigned int enableval = BD70528_MASK_ALM_EN;
|
|
||||||
struct bd70528_rtc *r = dev_get_drvdata(dev);
|
|
||||||
|
|
||||||
if (enabled)
|
|
||||||
enableval = 0;
|
|
||||||
|
|
||||||
bd70528_wdt_lock(r->parent);
|
|
||||||
ret = bd70528_set_wake(r->parent, enabled, NULL);
|
|
||||||
if (ret) {
|
|
||||||
dev_err(dev, "Failed to change wake state\n");
|
|
||||||
goto out_unlock;
|
|
||||||
}
|
|
||||||
ret = regmap_update_bits(r->regmap, BD70528_REG_RTC_ALM_MASK,
|
|
||||||
BD70528_MASK_ALM_EN, enableval);
|
|
||||||
if (ret)
|
|
||||||
dev_err(dev, "Failed to change alarm state\n");
|
|
||||||
|
|
||||||
out_unlock:
|
|
||||||
bd70528_wdt_unlock(r->parent);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int bd71828_alm_enable(struct device *dev, unsigned int enabled)
|
static int bd71828_alm_enable(struct device *dev, unsigned int enabled)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -470,14 +216,6 @@ static int bd71828_alm_enable(struct device *dev, unsigned int enabled)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct rtc_class_ops bd70528_rtc_ops = {
|
|
||||||
.read_time = bd70528_get_time,
|
|
||||||
.set_time = bd70528_set_time,
|
|
||||||
.read_alarm = bd70528_read_alarm,
|
|
||||||
.set_alarm = bd70528_set_alarm,
|
|
||||||
.alarm_irq_enable = bd70528_alm_enable,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct rtc_class_ops bd71828_rtc_ops = {
|
static const struct rtc_class_ops bd71828_rtc_ops = {
|
||||||
.read_time = bd70528_get_time,
|
.read_time = bd70528_get_time,
|
||||||
.set_time = bd71828_set_time,
|
.set_time = bd71828_set_time,
|
||||||
|
@ -503,7 +241,6 @@ static int bd70528_probe(struct platform_device *pdev)
|
||||||
struct rtc_device *rtc;
|
struct rtc_device *rtc;
|
||||||
int irq;
|
int irq;
|
||||||
unsigned int hr;
|
unsigned int hr;
|
||||||
bool enable_main_irq = false;
|
|
||||||
u8 hour_reg;
|
u8 hour_reg;
|
||||||
enum rohm_chip_type chip = platform_get_device_id(pdev)->driver_data;
|
enum rohm_chip_type chip = platform_get_device_id(pdev)->driver_data;
|
||||||
|
|
||||||
|
@ -518,21 +255,9 @@ static int bd70528_probe(struct platform_device *pdev)
|
||||||
}
|
}
|
||||||
|
|
||||||
bd_rtc->dev = &pdev->dev;
|
bd_rtc->dev = &pdev->dev;
|
||||||
|
rtc_ops = &bd71828_rtc_ops;
|
||||||
|
|
||||||
switch (chip) {
|
switch (chip) {
|
||||||
case ROHM_CHIP_TYPE_BD70528:
|
|
||||||
bd_rtc->parent = dev_get_drvdata(pdev->dev.parent);
|
|
||||||
if (!bd_rtc->parent) {
|
|
||||||
dev_err(&pdev->dev, "No MFD data\n");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
irq_name = "bd70528-rtc-alm";
|
|
||||||
bd_rtc->has_rtc_timers = true;
|
|
||||||
bd_rtc->reg_time_start = BD70528_REG_RTC_START;
|
|
||||||
hour_reg = BD70528_REG_RTC_HOUR;
|
|
||||||
enable_main_irq = true;
|
|
||||||
rtc_ops = &bd70528_rtc_ops;
|
|
||||||
break;
|
|
||||||
case ROHM_CHIP_TYPE_BD71815:
|
case ROHM_CHIP_TYPE_BD71815:
|
||||||
irq_name = "bd71815-rtc-alm-0";
|
irq_name = "bd71815-rtc-alm-0";
|
||||||
bd_rtc->reg_time_start = BD71815_REG_RTC_START;
|
bd_rtc->reg_time_start = BD71815_REG_RTC_START;
|
||||||
|
@ -549,14 +274,12 @@ static int bd70528_probe(struct platform_device *pdev)
|
||||||
*/
|
*/
|
||||||
bd_rtc->bd718xx_alm_block_start = BD71815_REG_RTC_ALM_START;
|
bd_rtc->bd718xx_alm_block_start = BD71815_REG_RTC_ALM_START;
|
||||||
hour_reg = BD71815_REG_HOUR;
|
hour_reg = BD71815_REG_HOUR;
|
||||||
rtc_ops = &bd71828_rtc_ops;
|
|
||||||
break;
|
break;
|
||||||
case ROHM_CHIP_TYPE_BD71828:
|
case ROHM_CHIP_TYPE_BD71828:
|
||||||
irq_name = "bd71828-rtc-alm-0";
|
irq_name = "bd71828-rtc-alm-0";
|
||||||
bd_rtc->reg_time_start = BD71828_REG_RTC_START;
|
bd_rtc->reg_time_start = BD71828_REG_RTC_START;
|
||||||
bd_rtc->bd718xx_alm_block_start = BD71828_REG_RTC_ALM_START;
|
bd_rtc->bd718xx_alm_block_start = BD71828_REG_RTC_ALM_START;
|
||||||
hour_reg = BD71828_REG_RTC_HOUR;
|
hour_reg = BD71828_REG_RTC_HOUR;
|
||||||
rtc_ops = &bd71828_rtc_ops;
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
dev_err(&pdev->dev, "Unknown chip\n");
|
dev_err(&pdev->dev, "Unknown chip\n");
|
||||||
|
@ -611,27 +334,10 @@ static int bd70528_probe(struct platform_device *pdev)
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
/*
|
|
||||||
* BD70528 irq controller is not touching the main mask register.
|
|
||||||
* So enable the RTC block interrupts at main level. We can just
|
|
||||||
* leave them enabled as irq-controller should disable irqs
|
|
||||||
* from sub-registers when IRQ is disabled or freed.
|
|
||||||
*/
|
|
||||||
if (enable_main_irq) {
|
|
||||||
ret = regmap_update_bits(bd_rtc->regmap,
|
|
||||||
BD70528_REG_INT_MAIN_MASK,
|
|
||||||
BD70528_INT_RTC_MASK, 0);
|
|
||||||
if (ret) {
|
|
||||||
dev_err(&pdev->dev, "Failed to enable RTC interrupts\n");
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return devm_rtc_register_device(rtc);
|
return devm_rtc_register_device(rtc);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct platform_device_id bd718x7_rtc_id[] = {
|
static const struct platform_device_id bd718x7_rtc_id[] = {
|
||||||
{ "bd70528-rtc", ROHM_CHIP_TYPE_BD70528 },
|
|
||||||
{ "bd71828-rtc", ROHM_CHIP_TYPE_BD71828 },
|
{ "bd71828-rtc", ROHM_CHIP_TYPE_BD71828 },
|
||||||
{ "bd71815-rtc", ROHM_CHIP_TYPE_BD71815 },
|
{ "bd71815-rtc", ROHM_CHIP_TYPE_BD71815 },
|
||||||
{ },
|
{ },
|
||||||
|
@ -649,6 +355,6 @@ static struct platform_driver bd70528_rtc = {
|
||||||
module_platform_driver(bd70528_rtc);
|
module_platform_driver(bd70528_rtc);
|
||||||
|
|
||||||
MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>");
|
MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>");
|
||||||
MODULE_DESCRIPTION("ROHM BD70528 and BD71828 PMIC RTC driver");
|
MODULE_DESCRIPTION("ROHM BD71828 and BD71815 PMIC RTC driver");
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
MODULE_ALIAS("platform:bd70528-rtc");
|
MODULE_ALIAS("platform:bd70528-rtc");
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
/*
|
/*
|
||||||
* RTC client/driver for the Maxim/Dallas DS1374 Real-Time Clock over I2C
|
* RTC client/driver for the Maxim/Dallas DS1374 Real-Time Clock over I2C
|
||||||
*
|
*
|
||||||
|
@ -6,11 +7,7 @@
|
||||||
*
|
*
|
||||||
* Copyright (C) 2014 Rose Technology
|
* Copyright (C) 2014 Rose Technology
|
||||||
* Copyright (C) 2006-2007 Freescale Semiconductor
|
* Copyright (C) 2006-2007 Freescale Semiconductor
|
||||||
*
|
* Copyright (c) 2005 MontaVista Software, Inc.
|
||||||
* 2005 (c) MontaVista Software, Inc. This file is licensed under
|
|
||||||
* the terms of the GNU General Public License version 2. This program
|
|
||||||
* is licensed "as is" without any warranty of any kind, whether express
|
|
||||||
* or implied.
|
|
||||||
*/
|
*/
|
||||||
/*
|
/*
|
||||||
* It would be more efficient to use i2c msgs/i2c_transfer directly but, as
|
* It would be more efficient to use i2c msgs/i2c_transfer directly but, as
|
||||||
|
|
|
@ -280,7 +280,6 @@ static struct platform_driver efi_rtc_driver = {
|
||||||
|
|
||||||
module_platform_driver_probe(efi_rtc_driver, efi_rtc_probe);
|
module_platform_driver_probe(efi_rtc_driver, efi_rtc_probe);
|
||||||
|
|
||||||
MODULE_ALIAS("platform:rtc-efi");
|
|
||||||
MODULE_AUTHOR("dann frazier <dannf@dannf.org>");
|
MODULE_AUTHOR("dann frazier <dannf@dannf.org>");
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
MODULE_DESCRIPTION("EFI RTC driver");
|
MODULE_DESCRIPTION("EFI RTC driver");
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/pm_wakeirq.h>
|
||||||
#include <linux/rtc.h>
|
#include <linux/rtc.h>
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
#include <linux/spinlock.h>
|
#include <linux/spinlock.h>
|
||||||
|
@ -811,6 +812,9 @@ static int __init dryice_rtc_probe(struct platform_device *pdev)
|
||||||
|
|
||||||
platform_set_drvdata(pdev, imxdi);
|
platform_set_drvdata(pdev, imxdi);
|
||||||
|
|
||||||
|
device_init_wakeup(&pdev->dev, true);
|
||||||
|
dev_pm_set_wake_irq(&pdev->dev, norm_irq);
|
||||||
|
|
||||||
imxdi->rtc->ops = &dryice_rtc_ops;
|
imxdi->rtc->ops = &dryice_rtc_ops;
|
||||||
imxdi->rtc->range_max = U32_MAX;
|
imxdi->rtc->range_max = U32_MAX;
|
||||||
|
|
||||||
|
|
|
@ -544,10 +544,22 @@ static struct clk *m41t80_sqw_register_clk(struct m41t80_data *m41t80)
|
||||||
{
|
{
|
||||||
struct i2c_client *client = m41t80->client;
|
struct i2c_client *client = m41t80->client;
|
||||||
struct device_node *node = client->dev.of_node;
|
struct device_node *node = client->dev.of_node;
|
||||||
|
struct device_node *fixed_clock;
|
||||||
struct clk *clk;
|
struct clk *clk;
|
||||||
struct clk_init_data init;
|
struct clk_init_data init;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
fixed_clock = of_get_child_by_name(node, "clock");
|
||||||
|
if (fixed_clock) {
|
||||||
|
/*
|
||||||
|
* skip registering square wave clock when a fixed
|
||||||
|
* clock has been registered. The fixed clock is
|
||||||
|
* registered automatically when being referenced.
|
||||||
|
*/
|
||||||
|
of_node_put(fixed_clock);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* First disable the clock */
|
/* First disable the clock */
|
||||||
ret = i2c_smbus_read_byte_data(client, M41T80_REG_ALARM_MON);
|
ret = i2c_smbus_read_byte_data(client, M41T80_REG_ALARM_MON);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
|
@ -599,10 +611,8 @@ static unsigned long wdt_is_open;
|
||||||
static int boot_flag;
|
static int boot_flag;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* wdt_ping:
|
* wdt_ping - Reload counter one with the watchdog timeout.
|
||||||
*
|
* We don't bother reloading the cascade counter.
|
||||||
* Reload counter one with the watchdog timeout. We don't bother reloading
|
|
||||||
* the cascade counter.
|
|
||||||
*/
|
*/
|
||||||
static void wdt_ping(void)
|
static void wdt_ping(void)
|
||||||
{
|
{
|
||||||
|
@ -638,9 +648,7 @@ static void wdt_ping(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* wdt_disable:
|
* wdt_disable - disables watchdog.
|
||||||
*
|
|
||||||
* disables watchdog.
|
|
||||||
*/
|
*/
|
||||||
static void wdt_disable(void)
|
static void wdt_disable(void)
|
||||||
{
|
{
|
||||||
|
@ -677,7 +685,7 @@ static void wdt_disable(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* wdt_write:
|
* wdt_write - write to watchdog.
|
||||||
* @file: file handle to the watchdog
|
* @file: file handle to the watchdog
|
||||||
* @buf: buffer to write (unused as data does not matter here
|
* @buf: buffer to write (unused as data does not matter here
|
||||||
* @count: count of bytes
|
* @count: count of bytes
|
||||||
|
@ -703,7 +711,7 @@ static ssize_t wdt_read(struct file *file, char __user *buf,
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* wdt_ioctl:
|
* wdt_ioctl - ioctl handler to set watchdog.
|
||||||
* @file: file handle to the device
|
* @file: file handle to the device
|
||||||
* @cmd: watchdog command
|
* @cmd: watchdog command
|
||||||
* @arg: argument pointer
|
* @arg: argument pointer
|
||||||
|
@ -778,7 +786,7 @@ static long wdt_unlocked_ioctl(struct file *file, unsigned int cmd,
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* wdt_open:
|
* wdt_open - open a watchdog.
|
||||||
* @inode: inode of device
|
* @inode: inode of device
|
||||||
* @file: file handle to device
|
* @file: file handle to device
|
||||||
*
|
*
|
||||||
|
@ -802,7 +810,7 @@ static int wdt_open(struct inode *inode, struct file *file)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* wdt_close:
|
* wdt_release - release a watchdog.
|
||||||
* @inode: inode to board
|
* @inode: inode to board
|
||||||
* @file: file handle to board
|
* @file: file handle to board
|
||||||
*
|
*
|
||||||
|
@ -815,7 +823,7 @@ static int wdt_release(struct inode *inode, struct file *file)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* notify_sys:
|
* wdt_notify_sys - notify to watchdog.
|
||||||
* @this: our notifier block
|
* @this: our notifier block
|
||||||
* @code: the event being reported
|
* @code: the event being reported
|
||||||
* @unused: unused
|
* @unused: unused
|
||||||
|
|
|
@ -1,14 +1,12 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
/*
|
/*
|
||||||
* rtc class driver for the Maxim MAX6900 chip
|
* rtc class driver for the Maxim MAX6900 chip
|
||||||
*
|
*
|
||||||
|
* Copyright (c) 2007 MontaVista, Software, Inc.
|
||||||
|
*
|
||||||
* Author: Dale Farnsworth <dale@farnsworth.org>
|
* Author: Dale Farnsworth <dale@farnsworth.org>
|
||||||
*
|
*
|
||||||
* based on previously existing rtc class drivers
|
* based on previously existing rtc class drivers
|
||||||
*
|
|
||||||
* 2007 (c) MontaVista, Software, Inc. This file is licensed under
|
|
||||||
* the terms of the GNU General Public License version 2. This program
|
|
||||||
* is licensed "as is" without any warranty of any kind, whether express
|
|
||||||
* or implied.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
|
|
|
@ -717,8 +717,8 @@ static int max77686_init_rtc_regmap(struct max77686_rtc_info *info)
|
||||||
|
|
||||||
add_rtc_irq:
|
add_rtc_irq:
|
||||||
ret = regmap_add_irq_chip(info->rtc_regmap, info->rtc_irq,
|
ret = regmap_add_irq_chip(info->rtc_regmap, info->rtc_irq,
|
||||||
IRQF_TRIGGER_FALLING | IRQF_ONESHOT |
|
IRQF_ONESHOT | IRQF_SHARED,
|
||||||
IRQF_SHARED, 0, info->drv_data->rtc_irq_chip,
|
0, info->drv_data->rtc_irq_chip,
|
||||||
&info->rtc_irq_data);
|
&info->rtc_irq_data);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dev_err(info->dev, "Failed to add RTC irq chip: %d\n", ret);
|
dev_err(info->dev, "Failed to add RTC irq chip: %d\n", ret);
|
||||||
|
|
|
@ -372,6 +372,7 @@ static const struct of_device_id mxc_ids[] = {
|
||||||
{ .compatible = "fsl,imx53-rtc", },
|
{ .compatible = "fsl,imx53-rtc", },
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
MODULE_DEVICE_TABLE(of, mxc_ids);
|
||||||
|
|
||||||
static struct platform_driver mxc_rtc_driver = {
|
static struct platform_driver mxc_rtc_driver = {
|
||||||
.driver = {
|
.driver = {
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
/*
|
/*
|
||||||
* rtc-palmas.c -- Palmas Real Time Clock driver.
|
* rtc-palmas.c -- Palmas Real Time Clock driver.
|
||||||
|
|
||||||
|
@ -7,20 +8,6 @@
|
||||||
* Copyright (c) 2012, NVIDIA Corporation.
|
* Copyright (c) 2012, NVIDIA Corporation.
|
||||||
*
|
*
|
||||||
* Author: Laxman Dewangan <ldewangan@nvidia.com>
|
* Author: Laxman Dewangan <ldewangan@nvidia.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 version 2.
|
|
||||||
*
|
|
||||||
* This program is distributed "as is" WITHOUT ANY WARRANTY of any kind,
|
|
||||||
* whether express or implied; 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, write to the Free Software
|
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
|
||||||
* 02111-1307, USA
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/bcd.h>
|
#include <linux/bcd.h>
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
*
|
*
|
||||||
* based on the other drivers in this same directory.
|
* based on the other drivers in this same directory.
|
||||||
*
|
*
|
||||||
* Datasheet: http://cache.nxp.com/documents/data_sheet/PCF2127.pdf
|
* Datasheet: https://www.nxp.com/docs/en/data-sheet/PCF2127.pdf
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/i2c.h>
|
#include <linux/i2c.h>
|
||||||
|
@ -94,10 +94,20 @@
|
||||||
#define PCF2127_WD_VAL_MAX 255
|
#define PCF2127_WD_VAL_MAX 255
|
||||||
#define PCF2127_WD_VAL_DEFAULT 60
|
#define PCF2127_WD_VAL_DEFAULT 60
|
||||||
|
|
||||||
|
/* Mask for currently enabled interrupts */
|
||||||
|
#define PCF2127_CTRL1_IRQ_MASK (PCF2127_BIT_CTRL1_TSF1)
|
||||||
|
#define PCF2127_CTRL2_IRQ_MASK ( \
|
||||||
|
PCF2127_BIT_CTRL2_AF | \
|
||||||
|
PCF2127_BIT_CTRL2_WDTF | \
|
||||||
|
PCF2127_BIT_CTRL2_TSF2)
|
||||||
|
|
||||||
struct pcf2127 {
|
struct pcf2127 {
|
||||||
struct rtc_device *rtc;
|
struct rtc_device *rtc;
|
||||||
struct watchdog_device wdd;
|
struct watchdog_device wdd;
|
||||||
struct regmap *regmap;
|
struct regmap *regmap;
|
||||||
|
time64_t ts;
|
||||||
|
bool ts_valid;
|
||||||
|
bool irq_enabled;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -434,23 +444,96 @@ static int pcf2127_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
|
||||||
return pcf2127_rtc_alarm_irq_enable(dev, alrm->enabled);
|
return pcf2127_rtc_alarm_irq_enable(dev, alrm->enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This function reads ctrl2 register, caller is responsible for calling
|
||||||
|
* pcf2127_wdt_active_ping()
|
||||||
|
*/
|
||||||
|
static int pcf2127_rtc_ts_read(struct device *dev, time64_t *ts)
|
||||||
|
{
|
||||||
|
struct pcf2127 *pcf2127 = dev_get_drvdata(dev);
|
||||||
|
struct rtc_time tm;
|
||||||
|
int ret;
|
||||||
|
unsigned char data[25];
|
||||||
|
|
||||||
|
ret = regmap_bulk_read(pcf2127->regmap, PCF2127_REG_CTRL1, data,
|
||||||
|
sizeof(data));
|
||||||
|
if (ret) {
|
||||||
|
dev_err(dev, "%s: read error ret=%d\n", __func__, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
dev_dbg(dev,
|
||||||
|
"%s: raw data is cr1=%02x, cr2=%02x, cr3=%02x, ts_sc=%02x, ts_mn=%02x, ts_hr=%02x, ts_dm=%02x, ts_mo=%02x, ts_yr=%02x\n",
|
||||||
|
__func__, data[PCF2127_REG_CTRL1], data[PCF2127_REG_CTRL2],
|
||||||
|
data[PCF2127_REG_CTRL3], data[PCF2127_REG_TS_SC],
|
||||||
|
data[PCF2127_REG_TS_MN], data[PCF2127_REG_TS_HR],
|
||||||
|
data[PCF2127_REG_TS_DM], data[PCF2127_REG_TS_MO],
|
||||||
|
data[PCF2127_REG_TS_YR]);
|
||||||
|
|
||||||
|
tm.tm_sec = bcd2bin(data[PCF2127_REG_TS_SC] & 0x7F);
|
||||||
|
tm.tm_min = bcd2bin(data[PCF2127_REG_TS_MN] & 0x7F);
|
||||||
|
tm.tm_hour = bcd2bin(data[PCF2127_REG_TS_HR] & 0x3F);
|
||||||
|
tm.tm_mday = bcd2bin(data[PCF2127_REG_TS_DM] & 0x3F);
|
||||||
|
/* TS_MO register (month) value range: 1-12 */
|
||||||
|
tm.tm_mon = bcd2bin(data[PCF2127_REG_TS_MO] & 0x1F) - 1;
|
||||||
|
tm.tm_year = bcd2bin(data[PCF2127_REG_TS_YR]);
|
||||||
|
if (tm.tm_year < 70)
|
||||||
|
tm.tm_year += 100; /* assume we are in 1970...2069 */
|
||||||
|
|
||||||
|
ret = rtc_valid_tm(&tm);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(dev, "Invalid timestamp. ret=%d\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
*ts = rtc_tm_to_time64(&tm);
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void pcf2127_rtc_ts_snapshot(struct device *dev)
|
||||||
|
{
|
||||||
|
struct pcf2127 *pcf2127 = dev_get_drvdata(dev);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* Let userspace read the first timestamp */
|
||||||
|
if (pcf2127->ts_valid)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ret = pcf2127_rtc_ts_read(dev, &pcf2127->ts);
|
||||||
|
if (!ret)
|
||||||
|
pcf2127->ts_valid = true;
|
||||||
|
}
|
||||||
|
|
||||||
static irqreturn_t pcf2127_rtc_irq(int irq, void *dev)
|
static irqreturn_t pcf2127_rtc_irq(int irq, void *dev)
|
||||||
{
|
{
|
||||||
struct pcf2127 *pcf2127 = dev_get_drvdata(dev);
|
struct pcf2127 *pcf2127 = dev_get_drvdata(dev);
|
||||||
unsigned int ctrl2 = 0;
|
unsigned int ctrl1, ctrl2;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
|
ret = regmap_read(pcf2127->regmap, PCF2127_REG_CTRL1, &ctrl1);
|
||||||
|
if (ret)
|
||||||
|
return IRQ_NONE;
|
||||||
|
|
||||||
ret = regmap_read(pcf2127->regmap, PCF2127_REG_CTRL2, &ctrl2);
|
ret = regmap_read(pcf2127->regmap, PCF2127_REG_CTRL2, &ctrl2);
|
||||||
if (ret)
|
if (ret)
|
||||||
return IRQ_NONE;
|
return IRQ_NONE;
|
||||||
|
|
||||||
if (!(ctrl2 & PCF2127_BIT_CTRL2_AF))
|
if (!(ctrl1 & PCF2127_CTRL1_IRQ_MASK || ctrl2 & PCF2127_CTRL2_IRQ_MASK))
|
||||||
return IRQ_NONE;
|
return IRQ_NONE;
|
||||||
|
|
||||||
regmap_write(pcf2127->regmap, PCF2127_REG_CTRL2,
|
if (ctrl1 & PCF2127_BIT_CTRL1_TSF1 || ctrl2 & PCF2127_BIT_CTRL2_TSF2)
|
||||||
ctrl2 & ~(PCF2127_BIT_CTRL2_AF | PCF2127_BIT_CTRL2_WDTF));
|
pcf2127_rtc_ts_snapshot(dev);
|
||||||
|
|
||||||
rtc_update_irq(pcf2127->rtc, 1, RTC_IRQF | RTC_AF);
|
if (ctrl1 & PCF2127_CTRL1_IRQ_MASK)
|
||||||
|
regmap_write(pcf2127->regmap, PCF2127_REG_CTRL1,
|
||||||
|
ctrl1 & ~PCF2127_CTRL1_IRQ_MASK);
|
||||||
|
|
||||||
|
if (ctrl2 & PCF2127_CTRL2_IRQ_MASK)
|
||||||
|
regmap_write(pcf2127->regmap, PCF2127_REG_CTRL2,
|
||||||
|
ctrl2 & ~PCF2127_CTRL2_IRQ_MASK);
|
||||||
|
|
||||||
|
if (ctrl2 & PCF2127_BIT_CTRL2_AF)
|
||||||
|
rtc_update_irq(pcf2127->rtc, 1, RTC_IRQF | RTC_AF);
|
||||||
|
|
||||||
pcf2127_wdt_active_ping(&pcf2127->wdd);
|
pcf2127_wdt_active_ping(&pcf2127->wdd);
|
||||||
|
|
||||||
|
@ -475,23 +558,27 @@ static ssize_t timestamp0_store(struct device *dev,
|
||||||
struct pcf2127 *pcf2127 = dev_get_drvdata(dev->parent);
|
struct pcf2127 *pcf2127 = dev_get_drvdata(dev->parent);
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = regmap_update_bits(pcf2127->regmap, PCF2127_REG_CTRL1,
|
if (pcf2127->irq_enabled) {
|
||||||
PCF2127_BIT_CTRL1_TSF1, 0);
|
pcf2127->ts_valid = false;
|
||||||
if (ret) {
|
} else {
|
||||||
dev_err(dev, "%s: update ctrl1 ret=%d\n", __func__, ret);
|
ret = regmap_update_bits(pcf2127->regmap, PCF2127_REG_CTRL1,
|
||||||
return ret;
|
PCF2127_BIT_CTRL1_TSF1, 0);
|
||||||
}
|
if (ret) {
|
||||||
|
dev_err(dev, "%s: update ctrl1 ret=%d\n", __func__, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
ret = regmap_update_bits(pcf2127->regmap, PCF2127_REG_CTRL2,
|
ret = regmap_update_bits(pcf2127->regmap, PCF2127_REG_CTRL2,
|
||||||
PCF2127_BIT_CTRL2_TSF2, 0);
|
PCF2127_BIT_CTRL2_TSF2, 0);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(dev, "%s: update ctrl2 ret=%d\n", __func__, ret);
|
dev_err(dev, "%s: update ctrl2 ret=%d\n", __func__, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = pcf2127_wdt_active_ping(&pcf2127->wdd);
|
ret = pcf2127_wdt_active_ping(&pcf2127->wdd);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
};
|
};
|
||||||
|
@ -500,50 +587,36 @@ static ssize_t timestamp0_show(struct device *dev,
|
||||||
struct device_attribute *attr, char *buf)
|
struct device_attribute *attr, char *buf)
|
||||||
{
|
{
|
||||||
struct pcf2127 *pcf2127 = dev_get_drvdata(dev->parent);
|
struct pcf2127 *pcf2127 = dev_get_drvdata(dev->parent);
|
||||||
struct rtc_time tm;
|
unsigned int ctrl1, ctrl2;
|
||||||
int ret;
|
int ret;
|
||||||
unsigned char data[25];
|
time64_t ts;
|
||||||
|
|
||||||
ret = regmap_bulk_read(pcf2127->regmap, PCF2127_REG_CTRL1, data,
|
if (pcf2127->irq_enabled) {
|
||||||
sizeof(data));
|
if (!pcf2127->ts_valid)
|
||||||
if (ret) {
|
return 0;
|
||||||
dev_err(dev, "%s: read error ret=%d\n", __func__, ret);
|
ts = pcf2127->ts;
|
||||||
return ret;
|
} else {
|
||||||
|
ret = regmap_read(pcf2127->regmap, PCF2127_REG_CTRL1, &ctrl1);
|
||||||
|
if (ret)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
ret = regmap_read(pcf2127->regmap, PCF2127_REG_CTRL2, &ctrl2);
|
||||||
|
if (ret)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!(ctrl1 & PCF2127_BIT_CTRL1_TSF1) &&
|
||||||
|
!(ctrl2 & PCF2127_BIT_CTRL2_TSF2))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
ret = pcf2127_rtc_ts_read(dev->parent, &ts);
|
||||||
|
if (ret)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
ret = pcf2127_wdt_active_ping(&pcf2127->wdd);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
return sprintf(buf, "%llu\n", (unsigned long long)ts);
|
||||||
dev_dbg(dev,
|
|
||||||
"%s: raw data is cr1=%02x, cr2=%02x, cr3=%02x, ts_sc=%02x, "
|
|
||||||
"ts_mn=%02x, ts_hr=%02x, ts_dm=%02x, ts_mo=%02x, ts_yr=%02x\n",
|
|
||||||
__func__, data[PCF2127_REG_CTRL1], data[PCF2127_REG_CTRL2],
|
|
||||||
data[PCF2127_REG_CTRL3], data[PCF2127_REG_TS_SC],
|
|
||||||
data[PCF2127_REG_TS_MN], data[PCF2127_REG_TS_HR],
|
|
||||||
data[PCF2127_REG_TS_DM], data[PCF2127_REG_TS_MO],
|
|
||||||
data[PCF2127_REG_TS_YR]);
|
|
||||||
|
|
||||||
ret = pcf2127_wdt_active_ping(&pcf2127->wdd);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
if (!(data[PCF2127_REG_CTRL1] & PCF2127_BIT_CTRL1_TSF1) &&
|
|
||||||
!(data[PCF2127_REG_CTRL2] & PCF2127_BIT_CTRL2_TSF2))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
tm.tm_sec = bcd2bin(data[PCF2127_REG_TS_SC] & 0x7F);
|
|
||||||
tm.tm_min = bcd2bin(data[PCF2127_REG_TS_MN] & 0x7F);
|
|
||||||
tm.tm_hour = bcd2bin(data[PCF2127_REG_TS_HR] & 0x3F);
|
|
||||||
tm.tm_mday = bcd2bin(data[PCF2127_REG_TS_DM] & 0x3F);
|
|
||||||
/* TS_MO register (month) value range: 1-12 */
|
|
||||||
tm.tm_mon = bcd2bin(data[PCF2127_REG_TS_MO] & 0x1F) - 1;
|
|
||||||
tm.tm_year = bcd2bin(data[PCF2127_REG_TS_YR]);
|
|
||||||
if (tm.tm_year < 70)
|
|
||||||
tm.tm_year += 100; /* assume we are in 1970...2069 */
|
|
||||||
|
|
||||||
ret = rtc_valid_tm(&tm);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
return sprintf(buf, "%llu\n",
|
|
||||||
(unsigned long long)rtc_tm_to_time64(&tm));
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static DEVICE_ATTR_RW(timestamp0);
|
static DEVICE_ATTR_RW(timestamp0);
|
||||||
|
@ -594,6 +667,7 @@ static int pcf2127_probe(struct device *dev, struct regmap *regmap,
|
||||||
dev_err(dev, "failed to request alarm irq\n");
|
dev_err(dev, "failed to request alarm irq\n");
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
pcf2127->irq_enabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (alarm_irq > 0 || device_property_read_bool(dev, "wakeup-source")) {
|
if (alarm_irq > 0 || device_property_read_bool(dev, "wakeup-source")) {
|
||||||
|
|
|
@ -21,10 +21,10 @@
|
||||||
/*
|
/*
|
||||||
* Information for this driver was pulled from the following datasheets.
|
* Information for this driver was pulled from the following datasheets.
|
||||||
*
|
*
|
||||||
* https://www.nxp.com/documents/data_sheet/PCF85063A.pdf
|
* https://www.nxp.com/docs/en/data-sheet/PCF85063A.pdf
|
||||||
* https://www.nxp.com/documents/data_sheet/PCF85063TP.pdf
|
* https://www.nxp.com/docs/en/data-sheet/PCF85063TP.pdf
|
||||||
*
|
*
|
||||||
* PCF85063A -- Rev. 6 — 18 November 2015
|
* PCF85063A -- Rev. 7 — 30 March 2018
|
||||||
* PCF85063TP -- Rev. 4 — 6 May 2015
|
* PCF85063TP -- Rev. 4 — 6 May 2015
|
||||||
*
|
*
|
||||||
* https://www.microcrystal.com/fileadmin/Media/Products/RTC/App.Manual/RV-8263-C7_App-Manual.pdf
|
* https://www.microcrystal.com/fileadmin/Media/Products/RTC/App.Manual/RV-8263-C7_App-Manual.pdf
|
||||||
|
|
|
@ -10,41 +10,41 @@
|
||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
#include <linux/pm_wakeirq.h>
|
#include <linux/pm_wakeirq.h>
|
||||||
|
|
||||||
#define REG_CONTROL1 0x00
|
#define PCF8523_REG_CONTROL1 0x00
|
||||||
#define REG_CONTROL1_CAP_SEL BIT(7)
|
#define PCF8523_CONTROL1_CAP_SEL BIT(7)
|
||||||
#define REG_CONTROL1_STOP BIT(5)
|
#define PCF8523_CONTROL1_STOP BIT(5)
|
||||||
#define REG_CONTROL1_AIE BIT(1)
|
#define PCF8523_CONTROL1_AIE BIT(1)
|
||||||
|
|
||||||
#define REG_CONTROL2 0x01
|
#define PCF8523_REG_CONTROL2 0x01
|
||||||
#define REG_CONTROL2_AF BIT(3)
|
#define PCF8523_CONTROL2_AF BIT(3)
|
||||||
|
|
||||||
#define REG_CONTROL3 0x02
|
#define PCF8523_REG_CONTROL3 0x02
|
||||||
#define REG_CONTROL3_PM_BLD BIT(7) /* battery low detection disabled */
|
#define PCF8523_CONTROL3_PM_BLD BIT(7) /* battery low detection disabled */
|
||||||
#define REG_CONTROL3_PM_VDD BIT(6) /* switch-over disabled */
|
#define PCF8523_CONTROL3_PM_VDD BIT(6) /* switch-over disabled */
|
||||||
#define REG_CONTROL3_PM_DSM BIT(5) /* direct switching mode */
|
#define PCF8523_CONTROL3_PM_DSM BIT(5) /* direct switching mode */
|
||||||
#define REG_CONTROL3_PM_MASK 0xe0
|
#define PCF8523_CONTROL3_PM_MASK 0xe0
|
||||||
#define REG_CONTROL3_BLF BIT(2) /* battery low bit, read-only */
|
#define PCF8523_CONTROL3_BLF BIT(2) /* battery low bit, read-only */
|
||||||
|
|
||||||
#define REG_SECONDS 0x03
|
#define PCF8523_REG_SECONDS 0x03
|
||||||
#define REG_SECONDS_OS BIT(7)
|
#define PCF8523_SECONDS_OS BIT(7)
|
||||||
|
|
||||||
#define REG_MINUTES 0x04
|
#define PCF8523_REG_MINUTES 0x04
|
||||||
#define REG_HOURS 0x05
|
#define PCF8523_REG_HOURS 0x05
|
||||||
#define REG_DAYS 0x06
|
#define PCF8523_REG_DAYS 0x06
|
||||||
#define REG_WEEKDAYS 0x07
|
#define PCF8523_REG_WEEKDAYS 0x07
|
||||||
#define REG_MONTHS 0x08
|
#define PCF8523_REG_MONTHS 0x08
|
||||||
#define REG_YEARS 0x09
|
#define PCF8523_REG_YEARS 0x09
|
||||||
|
|
||||||
#define REG_MINUTE_ALARM 0x0a
|
#define PCF8523_REG_MINUTE_ALARM 0x0a
|
||||||
#define REG_HOUR_ALARM 0x0b
|
#define PCF8523_REG_HOUR_ALARM 0x0b
|
||||||
#define REG_DAY_ALARM 0x0c
|
#define PCF8523_REG_DAY_ALARM 0x0c
|
||||||
#define REG_WEEKDAY_ALARM 0x0d
|
#define PCF8523_REG_WEEKDAY_ALARM 0x0d
|
||||||
#define ALARM_DIS BIT(7)
|
#define ALARM_DIS BIT(7)
|
||||||
|
|
||||||
#define REG_OFFSET 0x0e
|
#define PCF8523_REG_OFFSET 0x0e
|
||||||
#define REG_OFFSET_MODE BIT(7)
|
#define PCF8523_OFFSET_MODE BIT(7)
|
||||||
|
|
||||||
#define REG_TMR_CLKOUT_CTRL 0x0f
|
#define PCF8523_TMR_CLKOUT_CTRL 0x0f
|
||||||
|
|
||||||
struct pcf8523 {
|
struct pcf8523 {
|
||||||
struct rtc_device *rtc;
|
struct rtc_device *rtc;
|
||||||
|
@ -99,11 +99,11 @@ static int pcf8523_voltage_low(struct i2c_client *client)
|
||||||
u8 value;
|
u8 value;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
err = pcf8523_read(client, REG_CONTROL3, &value);
|
err = pcf8523_read(client, PCF8523_REG_CONTROL3, &value);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
return !!(value & REG_CONTROL3_BLF);
|
return !!(value & PCF8523_CONTROL3_BLF);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pcf8523_load_capacitance(struct i2c_client *client)
|
static int pcf8523_load_capacitance(struct i2c_client *client)
|
||||||
|
@ -112,7 +112,7 @@ static int pcf8523_load_capacitance(struct i2c_client *client)
|
||||||
u8 value;
|
u8 value;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
err = pcf8523_read(client, REG_CONTROL1, &value);
|
err = pcf8523_read(client, PCF8523_REG_CONTROL1, &value);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
@ -126,14 +126,14 @@ static int pcf8523_load_capacitance(struct i2c_client *client)
|
||||||
load);
|
load);
|
||||||
fallthrough;
|
fallthrough;
|
||||||
case 12500:
|
case 12500:
|
||||||
value |= REG_CONTROL1_CAP_SEL;
|
value |= PCF8523_CONTROL1_CAP_SEL;
|
||||||
break;
|
break;
|
||||||
case 7000:
|
case 7000:
|
||||||
value &= ~REG_CONTROL1_CAP_SEL;
|
value &= ~PCF8523_CONTROL1_CAP_SEL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = pcf8523_write(client, REG_CONTROL1, value);
|
err = pcf8523_write(client, PCF8523_REG_CONTROL1, value);
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -143,13 +143,13 @@ static int pcf8523_set_pm(struct i2c_client *client, u8 pm)
|
||||||
u8 value;
|
u8 value;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
err = pcf8523_read(client, REG_CONTROL3, &value);
|
err = pcf8523_read(client, PCF8523_REG_CONTROL3, &value);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
value = (value & ~REG_CONTROL3_PM_MASK) | pm;
|
value = (value & ~PCF8523_CONTROL3_PM_MASK) | pm;
|
||||||
|
|
||||||
err = pcf8523_write(client, REG_CONTROL3, value);
|
err = pcf8523_write(client, PCF8523_REG_CONTROL3, value);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
@ -162,13 +162,13 @@ static irqreturn_t pcf8523_irq(int irq, void *dev_id)
|
||||||
u8 value;
|
u8 value;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
err = pcf8523_read(pcf8523->client, REG_CONTROL2, &value);
|
err = pcf8523_read(pcf8523->client, PCF8523_REG_CONTROL2, &value);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return IRQ_HANDLED;
|
return IRQ_HANDLED;
|
||||||
|
|
||||||
if (value & REG_CONTROL2_AF) {
|
if (value & PCF8523_CONTROL2_AF) {
|
||||||
value &= ~REG_CONTROL2_AF;
|
value &= ~PCF8523_CONTROL2_AF;
|
||||||
pcf8523_write(pcf8523->client, REG_CONTROL2, value);
|
pcf8523_write(pcf8523->client, PCF8523_REG_CONTROL2, value);
|
||||||
rtc_update_irq(pcf8523->rtc, 1, RTC_IRQF | RTC_AF);
|
rtc_update_irq(pcf8523->rtc, 1, RTC_IRQF | RTC_AF);
|
||||||
|
|
||||||
return IRQ_HANDLED;
|
return IRQ_HANDLED;
|
||||||
|
@ -182,13 +182,13 @@ static int pcf8523_stop_rtc(struct i2c_client *client)
|
||||||
u8 value;
|
u8 value;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
err = pcf8523_read(client, REG_CONTROL1, &value);
|
err = pcf8523_read(client, PCF8523_REG_CONTROL1, &value);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
value |= REG_CONTROL1_STOP;
|
value |= PCF8523_CONTROL1_STOP;
|
||||||
|
|
||||||
err = pcf8523_write(client, REG_CONTROL1, value);
|
err = pcf8523_write(client, PCF8523_REG_CONTROL1, value);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
@ -200,13 +200,13 @@ static int pcf8523_start_rtc(struct i2c_client *client)
|
||||||
u8 value;
|
u8 value;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
err = pcf8523_read(client, REG_CONTROL1, &value);
|
err = pcf8523_read(client, PCF8523_REG_CONTROL1, &value);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
value &= ~REG_CONTROL1_STOP;
|
value &= ~PCF8523_CONTROL1_STOP;
|
||||||
|
|
||||||
err = pcf8523_write(client, REG_CONTROL1, value);
|
err = pcf8523_write(client, PCF8523_REG_CONTROL1, value);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
@ -216,7 +216,7 @@ static int pcf8523_start_rtc(struct i2c_client *client)
|
||||||
static int pcf8523_rtc_read_time(struct device *dev, struct rtc_time *tm)
|
static int pcf8523_rtc_read_time(struct device *dev, struct rtc_time *tm)
|
||||||
{
|
{
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
struct i2c_client *client = to_i2c_client(dev);
|
||||||
u8 start = REG_SECONDS, regs[7];
|
u8 start = PCF8523_REG_SECONDS, regs[7];
|
||||||
struct i2c_msg msgs[2];
|
struct i2c_msg msgs[2];
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
@ -242,7 +242,7 @@ static int pcf8523_rtc_read_time(struct device *dev, struct rtc_time *tm)
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
if (regs[0] & REG_SECONDS_OS)
|
if (regs[0] & PCF8523_SECONDS_OS)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
tm->tm_sec = bcd2bin(regs[0] & 0x7f);
|
tm->tm_sec = bcd2bin(regs[0] & 0x7f);
|
||||||
|
@ -267,8 +267,8 @@ static int pcf8523_rtc_set_time(struct device *dev, struct rtc_time *tm)
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
regs[0] = REG_SECONDS;
|
regs[0] = PCF8523_REG_SECONDS;
|
||||||
/* This will purposely overwrite REG_SECONDS_OS */
|
/* This will purposely overwrite PCF8523_SECONDS_OS */
|
||||||
regs[1] = bin2bcd(tm->tm_sec);
|
regs[1] = bin2bcd(tm->tm_sec);
|
||||||
regs[2] = bin2bcd(tm->tm_min);
|
regs[2] = bin2bcd(tm->tm_min);
|
||||||
regs[3] = bin2bcd(tm->tm_hour);
|
regs[3] = bin2bcd(tm->tm_hour);
|
||||||
|
@ -299,7 +299,7 @@ static int pcf8523_rtc_set_time(struct device *dev, struct rtc_time *tm)
|
||||||
static int pcf8523_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *tm)
|
static int pcf8523_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *tm)
|
||||||
{
|
{
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
struct i2c_client *client = to_i2c_client(dev);
|
||||||
u8 start = REG_MINUTE_ALARM, regs[4];
|
u8 start = PCF8523_REG_MINUTE_ALARM, regs[4];
|
||||||
struct i2c_msg msgs[2];
|
struct i2c_msg msgs[2];
|
||||||
u8 value;
|
u8 value;
|
||||||
int err;
|
int err;
|
||||||
|
@ -324,15 +324,15 @@ static int pcf8523_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *tm)
|
||||||
tm->time.tm_mday = bcd2bin(regs[2] & 0x3F);
|
tm->time.tm_mday = bcd2bin(regs[2] & 0x3F);
|
||||||
tm->time.tm_wday = bcd2bin(regs[3] & 0x7);
|
tm->time.tm_wday = bcd2bin(regs[3] & 0x7);
|
||||||
|
|
||||||
err = pcf8523_read(client, REG_CONTROL1, &value);
|
err = pcf8523_read(client, PCF8523_REG_CONTROL1, &value);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
tm->enabled = !!(value & REG_CONTROL1_AIE);
|
tm->enabled = !!(value & PCF8523_CONTROL1_AIE);
|
||||||
|
|
||||||
err = pcf8523_read(client, REG_CONTROL2, &value);
|
err = pcf8523_read(client, PCF8523_REG_CONTROL2, &value);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
tm->pending = !!(value & REG_CONTROL2_AF);
|
tm->pending = !!(value & PCF8523_CONTROL2_AF);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -343,16 +343,16 @@ static int pcf8523_irq_enable(struct device *dev, unsigned int enabled)
|
||||||
u8 value;
|
u8 value;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
err = pcf8523_read(client, REG_CONTROL1, &value);
|
err = pcf8523_read(client, PCF8523_REG_CONTROL1, &value);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
value &= REG_CONTROL1_AIE;
|
value &= PCF8523_CONTROL1_AIE;
|
||||||
|
|
||||||
if (enabled)
|
if (enabled)
|
||||||
value |= REG_CONTROL1_AIE;
|
value |= PCF8523_CONTROL1_AIE;
|
||||||
|
|
||||||
err = pcf8523_write(client, REG_CONTROL1, value);
|
err = pcf8523_write(client, PCF8523_REG_CONTROL1, value);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
@ -370,7 +370,7 @@ static int pcf8523_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *tm)
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
err = pcf8523_write(client, REG_CONTROL2, 0);
|
err = pcf8523_write(client, PCF8523_REG_CONTROL2, 0);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
@ -382,7 +382,7 @@ static int pcf8523_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *tm)
|
||||||
rtc_time64_to_tm(alarm_time, &tm->time);
|
rtc_time64_to_tm(alarm_time, &tm->time);
|
||||||
}
|
}
|
||||||
|
|
||||||
regs[0] = REG_MINUTE_ALARM;
|
regs[0] = PCF8523_REG_MINUTE_ALARM;
|
||||||
regs[1] = bin2bcd(tm->time.tm_min);
|
regs[1] = bin2bcd(tm->time.tm_min);
|
||||||
regs[2] = bin2bcd(tm->time.tm_hour);
|
regs[2] = bin2bcd(tm->time.tm_hour);
|
||||||
regs[3] = bin2bcd(tm->time.tm_mday);
|
regs[3] = bin2bcd(tm->time.tm_mday);
|
||||||
|
@ -418,11 +418,11 @@ static int pcf8523_rtc_ioctl(struct device *dev, unsigned int cmd,
|
||||||
if (ret)
|
if (ret)
|
||||||
flags |= RTC_VL_BACKUP_LOW;
|
flags |= RTC_VL_BACKUP_LOW;
|
||||||
|
|
||||||
ret = pcf8523_read(client, REG_SECONDS, &value);
|
ret = pcf8523_read(client, PCF8523_REG_SECONDS, &value);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (value & REG_SECONDS_OS)
|
if (value & PCF8523_SECONDS_OS)
|
||||||
flags |= RTC_VL_DATA_INVALID;
|
flags |= RTC_VL_DATA_INVALID;
|
||||||
|
|
||||||
return put_user(flags, (unsigned int __user *)arg);
|
return put_user(flags, (unsigned int __user *)arg);
|
||||||
|
@ -442,13 +442,13 @@ static int pcf8523_rtc_read_offset(struct device *dev, long *offset)
|
||||||
u8 value;
|
u8 value;
|
||||||
s8 val;
|
s8 val;
|
||||||
|
|
||||||
err = pcf8523_read(client, REG_OFFSET, &value);
|
err = pcf8523_read(client, PCF8523_REG_OFFSET, &value);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
/* sign extend the 7-bit offset value */
|
/* sign extend the 7-bit offset value */
|
||||||
val = value << 1;
|
val = value << 1;
|
||||||
*offset = (value & REG_OFFSET_MODE ? 4069 : 4340) * (val >> 1);
|
*offset = (value & PCF8523_OFFSET_MODE ? 4069 : 4340) * (val >> 1);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -465,9 +465,9 @@ static int pcf8523_rtc_set_offset(struct device *dev, long offset)
|
||||||
if (abs(reg_m0 * 4340 - offset) < abs(reg_m1 * 4069 - offset))
|
if (abs(reg_m0 * 4340 - offset) < abs(reg_m1 * 4069 - offset))
|
||||||
value = reg_m0 & 0x7f;
|
value = reg_m0 & 0x7f;
|
||||||
else
|
else
|
||||||
value = (reg_m1 & 0x7f) | REG_OFFSET_MODE;
|
value = (reg_m1 & 0x7f) | PCF8523_OFFSET_MODE;
|
||||||
|
|
||||||
return pcf8523_write(client, REG_OFFSET, value);
|
return pcf8523_write(client, PCF8523_REG_OFFSET, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct rtc_class_ops pcf8523_rtc_ops = {
|
static const struct rtc_class_ops pcf8523_rtc_ops = {
|
||||||
|
@ -519,7 +519,7 @@ static int pcf8523_probe(struct i2c_client *client,
|
||||||
rtc->uie_unsupported = 1;
|
rtc->uie_unsupported = 1;
|
||||||
|
|
||||||
if (client->irq > 0) {
|
if (client->irq > 0) {
|
||||||
err = pcf8523_write(client, REG_TMR_CLKOUT_CTRL, 0x38);
|
err = pcf8523_write(client, PCF8523_TMR_CLKOUT_CTRL, 0x38);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
*
|
*
|
||||||
* based on the other drivers in this same directory.
|
* based on the other drivers in this same directory.
|
||||||
*
|
*
|
||||||
* http://www.semiconductors.philips.com/acrobat/datasheets/PCF8563-04.pdf
|
* https://www.nxp.com/docs/en/data-sheet/PCF8563.pdf
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/clk-provider.h>
|
#include <linux/clk-provider.h>
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0+
|
||||||
/*
|
/*
|
||||||
* Realtek RTD129x RTC
|
* Realtek RTD129x RTC
|
||||||
*
|
*
|
||||||
* Copyright (c) 2017 Andreas Färber
|
* Copyright (c) 2017 Andreas Färber
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: GPL-2.0+
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/clk.h>
|
#include <linux/clk.h>
|
||||||
|
|
|
@ -488,9 +488,7 @@ static int s5m_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
|
||||||
|
|
||||||
dev_dbg(dev, "%s: %ptR(%d)\n", __func__, &alrm->time, alrm->time.tm_wday);
|
dev_dbg(dev, "%s: %ptR(%d)\n", __func__, &alrm->time, alrm->time.tm_wday);
|
||||||
|
|
||||||
ret = s5m_check_peding_alarm_interrupt(info, alrm);
|
return s5m_check_peding_alarm_interrupt(info, alrm);
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int s5m_rtc_stop_alarm(struct s5m_rtc_info *info)
|
static int s5m_rtc_stop_alarm(struct s5m_rtc_info *info)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2017 Spreadtrum Communications Inc.
|
* Copyright (C) 2017 Spreadtrum Communications Inc.
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: GPL-2.0
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/bitops.h>
|
#include <linux/bitops.h>
|
||||||
|
|
|
@ -1,12 +1,9 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
/*
|
/*
|
||||||
* drivers/rtc/rtc-spear.c
|
* drivers/rtc/rtc-spear.c
|
||||||
*
|
*
|
||||||
* Copyright (C) 2010 ST Microelectronics
|
* Copyright (C) 2010 ST Microelectronics
|
||||||
* Rajeev Kumar<rajeev-dlh.kumar@st.com>
|
* Rajeev Kumar<rajeev-dlh.kumar@st.com>
|
||||||
*
|
|
||||||
* This file is licensed under the terms of the GNU General Public
|
|
||||||
* License version 2. This program is licensed "as is" without any
|
|
||||||
* warranty of any kind, whether express or implied.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/bcd.h>
|
#include <linux/bcd.h>
|
||||||
|
|
|
@ -754,7 +754,7 @@ static int stm32_rtc_probe(struct platform_device *pdev)
|
||||||
|
|
||||||
ret = clk_prepare_enable(rtc->rtc_ck);
|
ret = clk_prepare_enable(rtc->rtc_ck);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err_no_rtc_ck;
|
||||||
|
|
||||||
if (rtc->data->need_dbp)
|
if (rtc->data->need_dbp)
|
||||||
regmap_update_bits(rtc->dbp, rtc->dbp_reg,
|
regmap_update_bits(rtc->dbp, rtc->dbp_reg,
|
||||||
|
@ -830,10 +830,12 @@ static int stm32_rtc_probe(struct platform_device *pdev)
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
|
clk_disable_unprepare(rtc->rtc_ck);
|
||||||
|
err_no_rtc_ck:
|
||||||
if (rtc->data->has_pclk)
|
if (rtc->data->has_pclk)
|
||||||
clk_disable_unprepare(rtc->pclk);
|
clk_disable_unprepare(rtc->pclk);
|
||||||
clk_disable_unprepare(rtc->rtc_ck);
|
|
||||||
|
|
||||||
if (rtc->data->need_dbp)
|
if (rtc->data->need_dbp)
|
||||||
regmap_update_bits(rtc->dbp, rtc->dbp_reg, rtc->dbp_mask, 0);
|
regmap_update_bits(rtc->dbp, rtc->dbp_reg, rtc->dbp_mask, 0);
|
||||||
|
|
|
@ -1,23 +1,10 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
/*
|
/*
|
||||||
* rtc-tps6586x.c: RTC driver for TI PMIC TPS6586X
|
* rtc-tps6586x.c: RTC driver for TI PMIC TPS6586X
|
||||||
*
|
*
|
||||||
* Copyright (c) 2012, NVIDIA Corporation.
|
* Copyright (c) 2012, NVIDIA Corporation.
|
||||||
*
|
*
|
||||||
* Author: Laxman Dewangan <ldewangan@nvidia.com>
|
* Author: Laxman Dewangan <ldewangan@nvidia.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 version 2.
|
|
||||||
*
|
|
||||||
* This program is distributed "as is" WITHOUT ANY WARRANTY of any kind,
|
|
||||||
* whether express or implied; 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, write to the Free Software
|
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
|
||||||
* 02111-1307, USA
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
/*
|
/*
|
||||||
* rtc-tps80031.c -- TI TPS80031/TPS80032 RTC driver
|
* rtc-tps80031.c -- TI TPS80031/TPS80032 RTC driver
|
||||||
*
|
*
|
||||||
|
@ -7,20 +8,6 @@
|
||||||
* Copyright (c) 2012, NVIDIA Corporation.
|
* Copyright (c) 2012, NVIDIA Corporation.
|
||||||
*
|
*
|
||||||
* Author: Laxman Dewangan <ldewangan@nvidia.com>
|
* Author: Laxman Dewangan <ldewangan@nvidia.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 version 2.
|
|
||||||
*
|
|
||||||
* This program is distributed "as is" WITHOUT ANY WARRANTY of any kind,
|
|
||||||
* whether express or implied; 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, write to the Free Software
|
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
|
||||||
* 02111-1307, USA
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/bcd.h>
|
#include <linux/bcd.h>
|
||||||
|
|
|
@ -282,7 +282,7 @@ static int rtc_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct v3020_platform_data *pdata = dev_get_platdata(&pdev->dev);
|
struct v3020_platform_data *pdata = dev_get_platdata(&pdev->dev);
|
||||||
struct v3020 *chip;
|
struct v3020 *chip;
|
||||||
int retval = -EBUSY;
|
int retval;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
|
chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
|
||||||
|
|
|
@ -102,7 +102,7 @@ max_user_freq_store(struct device *dev, struct device_attribute *attr,
|
||||||
static DEVICE_ATTR_RW(max_user_freq);
|
static DEVICE_ATTR_RW(max_user_freq);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* rtc_sysfs_show_hctosys - indicate if the given RTC set the system time
|
* hctosys_show - indicate if the given RTC set the system time
|
||||||
* @dev: The device that the attribute belongs to.
|
* @dev: The device that the attribute belongs to.
|
||||||
* @attr: The attribute being read.
|
* @attr: The attribute being read.
|
||||||
* @buf: The result buffer.
|
* @buf: The result buffer.
|
||||||
|
|
Loading…
Reference in New Issue