Commit 378de6df authored by Linus Torvalds's avatar Linus Torvalds

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

Pull RTC updates from Alexandre Belloni:
 "There are three new drivers this cycle. Also the cmos driver is
  getting fixes for longstanding wakeup issues on AMD.

  New drivers:
   - Analog Devices MAX31335
   - Nuvoton ma35d1
   - Texas Instrument TPS6594 PMIC RTC

  Drivers:
   - cmos: use ACPI alarm instead of HPET on recent AMD platforms
   - nuvoton: add NCT3015Y-R and NCT3018Y-R support
   - rv8803: proper suspend/resume and wakeup-source support"

* tag 'rtc-6.8' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux: (26 commits)
  rtc: nuvoton: Compatible with NCT3015Y-R and NCT3018Y-R
  rtc: da9063: Use dev_err_probe()
  rtc: da9063: Use device_get_match_data()
  rtc: da9063: Make IRQ as optional
  rtc: max31335: Fix comparison in max31335_volatile_reg()
  rtc: max31335: use regmap_update_bits_check
  rtc: max31335: remove unecessary locking
  rtc: max31335: add driver support
  dt-bindings: rtc: max31335: add max31335 bindings
  rtc: rv8803: add wakeup-source support
  rtc: ac100: remove misuses of kernel-doc
  rtc: class: Remove usage of the deprecated ida_simple_xx() API
  rtc: MAINTAINERS: drop Alessandro Zummo
  rtc: ma35d1: remove hardcoded UIE support
  dt-bindings: rtc: qcom-pm8xxx: fix inconsistent example
  rtc: rv8803: Add power management support
  rtc: ds3232: avoid unused-const-variable warning
  rtc: lpc24xx: add missing dependency
  rtc: tps6594: Add driver for TPS6594 RTC
  rtc: Add driver for Nuvoton ma35d1 rtc controller
  ...
parents 0f289bdd 14688f1a
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/rtc/adi,max31335.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Analog Devices MAX31335 RTC
maintainers:
- Antoniu Miclaus <antoniu.miclaus@analog.com>
description:
Analog Devices MAX31335 I2C RTC ±2ppm Automotive Real-Time Clock with
Integrated MEMS Resonator.
allOf:
- $ref: rtc.yaml#
properties:
compatible:
const: adi,max31335
reg:
maxItems: 1
interrupts:
maxItems: 1
"#clock-cells":
description:
RTC can be used as a clock source through its clock output pin.
const: 0
adi,tc-diode:
description:
Select the diode configuration for the trickle charger.
schottky - Schottky diode in series.
standard+schottky - standard diode + Schottky diode in series.
enum: [schottky, standard+schottky]
trickle-resistor-ohms:
description:
Selected resistor for trickle charger. Should be specified if trickle
charger should be enabled.
enum: [3000, 6000, 11000]
required:
- compatible
- reg
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
rtc@68 {
compatible = "adi,max31335";
reg = <0x68>;
pinctrl-0 = <&rtc_nint_pins>;
interrupts-extended = <&gpio1 16 IRQ_TYPE_LEVEL_HIGH>;
aux-voltage-chargeable = <1>;
trickle-resistor-ohms = <6000>;
adi,tc-diode = "schottky";
};
};
...
......@@ -29,6 +29,8 @@ properties:
trickle-diode-disable: true
wakeup-source: true
required:
- compatible
- reg
......
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/rtc/nuvoton,ma35d1-rtc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Nuvoton MA35D1 Real Time Clock
maintainers:
- Min-Jen Chen <mjchen@nuvoton.com>
allOf:
- $ref: rtc.yaml#
properties:
compatible:
enum:
- nuvoton,ma35d1-rtc
reg:
maxItems: 1
interrupts:
maxItems: 1
clocks:
maxItems: 1
required:
- compatible
- reg
- interrupts
- clocks
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/clock/nuvoton,ma35d1-clk.h>
rtc@40410000 {
compatible = "nuvoton,ma35d1-rtc";
reg = <0x40410000 0x200>;
interrupts = <GIC_SPI 5 IRQ_TYPE_EDGE_RISING>;
clocks = <&clk RTC_GATE>;
};
...
......@@ -61,27 +61,27 @@ additionalProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/spmi/spmi.h>
spmi_bus: spmi@c440000 {
reg = <0x0c440000 0x1100>;
#address-cells = <2>;
#size-cells = <0>;
pmicintc: pmic@0 {
reg = <0x0 SPMI_USID>;
compatible = "qcom,pm8921";
interrupts = <104 8>;
#interrupt-cells = <2>;
interrupt-controller;
#address-cells = <1>;
spmi {
#address-cells = <2>;
#size-cells = <0>;
pm8921_rtc: rtc@11d {
compatible = "qcom,pm8921-rtc";
reg = <0x11d>;
interrupts = <0x27 0>;
nvmem-cells = <&rtc_offset>;
nvmem-cell-names = "offset";
pmic@0 {
compatible = "qcom,pm8941", "qcom,spmi-pmic";
reg = <0x0 SPMI_USID>;
#address-cells = <1>;
#size-cells = <0>;
rtc@6000 {
compatible = "qcom,pm8941-rtc";
reg = <0x6000>, <0x6100>;
reg-names = "rtc", "alarm";
interrupts = <0x0 0x61 0x1 IRQ_TYPE_EDGE_RISING>;
nvmem-cells = <&rtc_offset>;
nvmem-cell-names = "offset";
};
};
};
};
...
......@@ -13126,6 +13126,14 @@ F: Documentation/devicetree/bindings/hwmon/adi,max31827.yaml
F: Documentation/hwmon/max31827.rst
F: drivers/hwmon/max31827.c
MAX31335 RTC DRIVER
M: Antoniu Miclaus <antoniu.miclaus@analog.com>
L: linux-rtc@vger.kernel.org
S: Supported
W: https://ez.analog.com/linux-software-drivers
F: Documentation/devicetree/bindings/rtc/adi,max31335.yaml
F: drivers/rtc/rtc-max31335.c
MAX6650 HARDWARE MONITOR AND FAN CONTROLLER DRIVER
L: linux-hwmon@vger.kernel.org
S: Orphan
......@@ -18451,7 +18459,6 @@ X: include/linux/srcu*.h
X: kernel/rcu/srcu*.c
REAL TIME CLOCK (RTC) SUBSYSTEM
M: Alessandro Zummo <a.zummo@towertech.it>
M: Alexandre Belloni <alexandre.belloni@bootlin.com>
L: linux-rtc@vger.kernel.org
S: Maintained
......
......@@ -80,7 +80,7 @@ init_rtc_epoch(void)
static int
alpha_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
int ret = mc146818_get_time(tm);
int ret = mc146818_get_time(tm, 10);
if (ret < 0) {
dev_err_ratelimited(dev, "unable to read current time\n");
......
......@@ -1438,7 +1438,7 @@ irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id)
memset(&curr_time, 0, sizeof(struct rtc_time));
if (hpet_rtc_flags & (RTC_UIE | RTC_AIE)) {
if (unlikely(mc146818_get_time(&curr_time) < 0)) {
if (unlikely(mc146818_get_time(&curr_time, 10) < 0)) {
pr_err_ratelimited("unable to read current time from RTC\n");
return IRQ_HANDLED;
}
......
......@@ -67,7 +67,7 @@ void mach_get_cmos_time(struct timespec64 *now)
return;
}
if (mc146818_get_time(&tm)) {
if (mc146818_get_time(&tm, 1000)) {
pr_err("Unable to read current time from RTC\n");
now->tv_sec = now->tv_nsec = 0;
return;
......
......@@ -120,7 +120,7 @@ static unsigned int read_magic_time(void)
struct rtc_time time;
unsigned int val;
if (mc146818_get_time(&time) < 0) {
if (mc146818_get_time(&time, 1000) < 0) {
pr_err("Unable to read current time from RTC\n");
return 0;
}
......
......@@ -373,6 +373,19 @@ config RTC_DRV_MAX8997
This driver can also be built as a module. If so, the module
will be called rtc-max8997.
config RTC_DRV_MAX31335
tristate "Analog Devices MAX31335"
depends on I2C
depends on COMMON_CLK
depends on HWMON || HWMON=n
select REGMAP_I2C
help
If you say yes here you get support for the Analog Devices
MAX31335.
This driver can also be built as a module. If so, the module
will be called rtc-max31335.
config RTC_DRV_MAX77686
tristate "Maxim MAX77686"
depends on MFD_MAX77686 || MFD_MAX77620 || MFD_MAX77714 || COMPILE_TEST
......@@ -578,6 +591,18 @@ config RTC_DRV_TPS6586X
along with alarm. This driver supports the RTC driver for
the TPS6586X RTC module.
config RTC_DRV_TPS6594
tristate "TI TPS6594 RTC driver"
depends on MFD_TPS6594
default MFD_TPS6594
help
TI Power Management IC TPS6594 supports RTC functionality
along with alarm. This driver supports the RTC driver for
the TPS6594 RTC module.
This driver can also be built as a module. If so, the module
will be called rtc-tps6594.
config RTC_DRV_TPS65910
tristate "TI TPS65910 RTC driver"
depends on MFD_TPS65910
......@@ -1705,6 +1730,7 @@ config RTC_DRV_LPC24XX
tristate "NXP RTC for LPC178x/18xx/408x/43xx"
depends on ARCH_LPC18XX || COMPILE_TEST
depends on OF && HAS_IOMEM
depends on COMMON_CLK
help
This enables support for the NXP RTC found which can be found on
NXP LPC178x/18xx/408x/43xx devices.
......@@ -1930,6 +1956,17 @@ config RTC_DRV_TI_K3
This driver can also be built as a module, if so, the module
will be called "rtc-ti-k3".
config RTC_DRV_MA35D1
tristate "Nuvoton MA35D1 RTC"
depends on ARCH_MA35 || COMPILE_TEST
select REGMAP_MMIO
help
If you say yes here you get support for the Nuvoton MA35D1
On-Chip Real Time Clock.
This driver can also be built as a module, if so, the module
will be called "rtc-ma35d1".
comment "HID Sensor RTC drivers"
config RTC_DRV_HID_SENSOR_TIME
......
......@@ -88,6 +88,8 @@ obj-$(CONFIG_RTC_DRV_M41T94) += rtc-m41t94.o
obj-$(CONFIG_RTC_DRV_M48T35) += rtc-m48t35.o
obj-$(CONFIG_RTC_DRV_M48T59) += rtc-m48t59.o
obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.o
obj-$(CONFIG_RTC_DRV_MA35D1) += rtc-ma35d1.o
obj-$(CONFIG_RTC_DRV_MAX31335) += rtc-max31335.o
obj-$(CONFIG_RTC_DRV_MAX6900) += rtc-max6900.o
obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o
obj-$(CONFIG_RTC_DRV_MAX6916) += rtc-max6916.o
......@@ -176,6 +178,7 @@ obj-$(CONFIG_RTC_DRV_TEGRA) += rtc-tegra.o
obj-$(CONFIG_RTC_DRV_TEST) += rtc-test.o
obj-$(CONFIG_RTC_DRV_TI_K3) += rtc-ti-k3.o
obj-$(CONFIG_RTC_DRV_TPS6586X) += rtc-tps6586x.o
obj-$(CONFIG_RTC_DRV_TPS6594) += rtc-tps6594.o
obj-$(CONFIG_RTC_DRV_TPS65910) += rtc-tps65910.o
obj-$(CONFIG_RTC_DRV_TWL4030) += rtc-twl.o
obj-$(CONFIG_RTC_DRV_VT8500) += rtc-vt8500.o
......
......@@ -256,7 +256,7 @@ static int rtc_device_get_id(struct device *dev)
of_id = of_alias_get_id(dev->parent->of_node, "rtc");
if (of_id >= 0) {
id = ida_simple_get(&rtc_ida, of_id, of_id + 1, GFP_KERNEL);
id = ida_alloc_range(&rtc_ida, of_id, of_id, GFP_KERNEL);
if (id < 0)
dev_warn(dev, "/aliases ID %d not available\n", of_id);
}
......
......@@ -99,7 +99,7 @@ struct ac100_rtc_dev {
struct clk_hw_onecell_data *clk_data;
};
/**
/*
* Clock controls for 3 clock output pins
*/
......@@ -378,7 +378,7 @@ static void ac100_rtc_unregister_clks(struct ac100_rtc_dev *chip)
clk_unregister_fixed_rate(chip->rtc_32k_clk->clk);
}
/**
/*
* RTC related bits
*/
static int ac100_rtc_get_time(struct device *dev, struct rtc_time *rtc_tm)
......
......@@ -231,7 +231,7 @@ static int cmos_read_time(struct device *dev, struct rtc_time *t)
if (!pm_trace_rtc_valid())
return -EIO;
ret = mc146818_get_time(t);
ret = mc146818_get_time(t, 1000);
if (ret < 0) {
dev_err_ratelimited(dev, "unable to read current time\n");
return ret;
......@@ -292,7 +292,7 @@ static int cmos_read_alarm(struct device *dev, struct rtc_wkalrm *t)
/* This not only a rtc_op, but also called directly */
if (!is_valid_irq(cmos->irq))
return -EIO;
return -ETIMEDOUT;
/* Basic alarms only support hour, minute, and seconds fields.
* Some also support day and month, for alarms up to a year in
......@@ -307,7 +307,7 @@ static int cmos_read_alarm(struct device *dev, struct rtc_wkalrm *t)
*
* Use the mc146818_avoid_UIP() function to avoid this.
*/
if (!mc146818_avoid_UIP(cmos_read_alarm_callback, &p))
if (!mc146818_avoid_UIP(cmos_read_alarm_callback, 10, &p))
return -EIO;
if (!(p.rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
......@@ -556,8 +556,8 @@ static int cmos_set_alarm(struct device *dev, struct rtc_wkalrm *t)
*
* Use mc146818_avoid_UIP() to avoid this.
*/
if (!mc146818_avoid_UIP(cmos_set_alarm_callback, &p))
return -EIO;
if (!mc146818_avoid_UIP(cmos_set_alarm_callback, 10, &p))
return -ETIMEDOUT;
cmos->alarm_expires = rtc_tm_to_time64(&t->time);
......@@ -818,18 +818,24 @@ static void rtc_wake_off(struct device *dev)
}
#ifdef CONFIG_X86
/* Enable use_acpi_alarm mode for Intel platforms no earlier than 2015 */
static void use_acpi_alarm_quirks(void)
{
if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL)
switch (boot_cpu_data.x86_vendor) {
case X86_VENDOR_INTEL:
if (dmi_get_bios_year() < 2015)
return;
break;
case X86_VENDOR_AMD:
case X86_VENDOR_HYGON:
if (dmi_get_bios_year() < 2021)
return;
break;
default:
return;
}
if (!is_hpet_enabled())
return;
if (dmi_get_bios_year() < 2015)
return;
use_acpi_alarm = true;
}
#else
......
......@@ -377,7 +377,6 @@ static int da9063_rtc_probe(struct platform_device *pdev)
{
struct da9063_compatible_rtc *rtc;
const struct da9063_compatible_rtc_regmap *config;
const struct of_device_id *match;
int irq_alarm;
u8 data[RTC_DATA_LEN];
int ret;
......@@ -385,14 +384,11 @@ static int da9063_rtc_probe(struct platform_device *pdev)
if (!pdev->dev.of_node)
return -ENXIO;
match = of_match_node(da9063_compatible_reg_id_table,
pdev->dev.of_node);
rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL);
if (!rtc)
return -ENOMEM;
rtc->config = match->data;
rtc->config = device_get_match_data(&pdev->dev);
if (of_device_is_compatible(pdev->dev.of_node, "dlg,da9063-rtc")) {
struct da9063 *chip = dev_get_drvdata(pdev->dev.parent);
......@@ -411,57 +407,49 @@ static int da9063_rtc_probe(struct platform_device *pdev)
config->rtc_enable_reg,
config->rtc_enable_mask,
config->rtc_enable_mask);
if (ret < 0) {
dev_err(&pdev->dev, "Failed to enable RTC\n");
return ret;
}
if (ret < 0)
return dev_err_probe(&pdev->dev, ret, "Failed to enable RTC\n");
ret = regmap_update_bits(rtc->regmap,
config->rtc_enable_32k_crystal_reg,
config->rtc_crystal_mask,
config->rtc_crystal_mask);
if (ret < 0) {
dev_err(&pdev->dev, "Failed to run 32kHz oscillator\n");
return ret;
}
if (ret < 0)
return dev_err_probe(&pdev->dev, ret,
"Failed to run 32kHz oscillator\n");
ret = regmap_update_bits(rtc->regmap,
config->rtc_alarm_secs_reg,
config->rtc_alarm_status_mask,
0);
if (ret < 0) {
dev_err(&pdev->dev, "Failed to access RTC alarm register\n");
return ret;
}
if (ret < 0)
return dev_err_probe(&pdev->dev, ret,
"Failed to access RTC alarm register\n");
ret = regmap_update_bits(rtc->regmap,
config->rtc_alarm_secs_reg,
DA9063_ALARM_STATUS_ALARM,
DA9063_ALARM_STATUS_ALARM);
if (ret < 0) {
dev_err(&pdev->dev, "Failed to access RTC alarm register\n");
return ret;
}
if (ret < 0)
return dev_err_probe(&pdev->dev, ret,
"Failed to access RTC alarm register\n");
ret = regmap_update_bits(rtc->regmap,
config->rtc_alarm_year_reg,
config->rtc_tick_on_mask,
0);
if (ret < 0) {
dev_err(&pdev->dev, "Failed to disable TICKs\n");
return ret;
}
if (ret < 0)
return dev_err_probe(&pdev->dev, ret,
"Failed to disable TICKs\n");
data[RTC_SEC] = 0;
ret = regmap_bulk_read(rtc->regmap,
config->rtc_alarm_secs_reg,
&data[config->rtc_data_start],
config->rtc_alarm_len);
if (ret < 0) {
dev_err(&pdev->dev, "Failed to read initial alarm data: %d\n",
ret);
return ret;
}
if (ret < 0)
return dev_err_probe(&pdev->dev, ret,
"Failed to read initial alarm data\n");
platform_set_drvdata(pdev, rtc);
......@@ -485,25 +473,29 @@ static int da9063_rtc_probe(struct platform_device *pdev)
clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, rtc->rtc_dev->features);
}
irq_alarm = platform_get_irq_byname(pdev, "ALARM");
if (irq_alarm < 0)
irq_alarm = platform_get_irq_byname_optional(pdev, "ALARM");
if (irq_alarm >= 0) {
ret = devm_request_threaded_irq(&pdev->dev, irq_alarm, NULL,
da9063_alarm_event,
IRQF_TRIGGER_LOW | IRQF_ONESHOT,
"ALARM", rtc);
if (ret)
dev_err(&pdev->dev,
"Failed to request ALARM IRQ %d: %d\n",
irq_alarm, ret);
ret = dev_pm_set_wake_irq(&pdev->dev, irq_alarm);
if (ret)
dev_warn(&pdev->dev,
"Failed to set IRQ %d as a wake IRQ: %d\n",
irq_alarm, ret);
device_init_wakeup(&pdev->dev, true);
} else if (irq_alarm != -ENXIO) {
return irq_alarm;
ret = devm_request_threaded_irq(&pdev->dev, irq_alarm, NULL,
da9063_alarm_event,
IRQF_TRIGGER_LOW | IRQF_ONESHOT,
"ALARM", rtc);
if (ret)
dev_err(&pdev->dev, "Failed to request ALARM IRQ %d: %d\n",
irq_alarm, ret);
ret = dev_pm_set_wake_irq(&pdev->dev, irq_alarm);
if (ret)
dev_warn(&pdev->dev,
"Failed to set IRQ %d as a wake IRQ: %d\n",
irq_alarm, ret);
device_init_wakeup(&pdev->dev, true);
} else {
clear_bit(RTC_FEATURE_ALARM, rtc->rtc_dev->features);
}
return devm_rtc_register_device(rtc->rtc_dev);
}
......
......@@ -536,6 +536,8 @@ static int ds3232_probe(struct device *dev, struct regmap *regmap, int irq,
return 0;
}
#if IS_ENABLED(CONFIG_I2C)
#ifdef CONFIG_PM_SLEEP
static int ds3232_suspend(struct device *dev)
{
......@@ -564,8 +566,6 @@ static const struct dev_pm_ops ds3232_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(ds3232_suspend, ds3232_resume)
};
#if IS_ENABLED(CONFIG_I2C)
static int ds3232_i2c_probe(struct i2c_client *client)
{
struct regmap *regmap;
......
// SPDX-License-Identifier: GPL-2.0
/*
* RTC driver for Nuvoton MA35D1
*
* Copyright (C) 2023 Nuvoton Technology Corp.
*/
#include <linux/bcd.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/rtc.h>
/* MA35D1 RTC Control Registers */
#define MA35_REG_RTC_INIT 0x00
#define MA35_REG_RTC_SINFASTS 0x04
#define MA35_REG_RTC_FREQADJ 0x08
#define MA35_REG_RTC_TIME 0x0c
#define MA35_REG_RTC_CAL 0x10
#define MA35_REG_RTC_CLKFMT 0x14
#define MA35_REG_RTC_WEEKDAY 0x18
#define MA35_REG_RTC_TALM 0x1c
#define MA35_REG_RTC_CALM 0x20
#define MA35_REG_RTC_LEAPYEAR 0x24
#define MA35_REG_RTC_INTEN 0x28
#define MA35_REG_RTC_INTSTS 0x2c
/* register MA35_REG_RTC_INIT */
#define RTC_INIT_ACTIVE BIT(0)
#define RTC_INIT_MAGIC_CODE 0xa5eb1357
/* register MA35_REG_RTC_CLKFMT */
#define RTC_CLKFMT_24HEN BIT(0)
#define RTC_CLKFMT_DCOMPEN BIT(16)
/* register MA35_REG_RTC_INTEN */
#define RTC_INTEN_ALMIEN BIT(0)
#define RTC_INTEN_UIEN BIT(1)
#define RTC_INTEN_CLKFIEN BIT(24)
#define RTC_INTEN_CLKSTIEN BIT(25)
/* register MA35_REG_RTC_INTSTS */
#define RTC_INTSTS_ALMIF BIT(0)
#define RTC_INTSTS_UIF BIT(1)
#define RTC_INTSTS_CLKFIF BIT(24)
#define RTC_INTSTS_CLKSTIF BIT(25)
#define RTC_INIT_TIMEOUT 250
struct ma35_rtc {
int irq_num;
void __iomem *rtc_reg;
struct rtc_device *rtcdev;
};
static u32 rtc_reg_read(struct ma35_rtc *p, u32 offset)
{
return __raw_readl(p->rtc_reg + offset);
}
static inline void rtc_reg_write(struct ma35_rtc *p, u32 offset, u32 value)
{
__raw_writel(value, p->rtc_reg + offset);
}
static irqreturn_t ma35d1_rtc_interrupt(int irq, void *data)
{
struct ma35_rtc *rtc = (struct ma35_rtc *)data;
unsigned long events = 0, rtc_irq;
rtc_irq = rtc_reg_read(rtc, MA35_REG_RTC_INTSTS);
if (rtc_irq & RTC_INTSTS_ALMIF) {
rtc_reg_write(rtc, MA35_REG_RTC_INTSTS, RTC_INTSTS_ALMIF);
events |= RTC_AF | RTC_IRQF;
}
rtc_update_irq(rtc->rtcdev, 1, events);
return IRQ_HANDLED;
}
static int ma35d1_rtc_init(struct ma35_rtc *rtc, u32 ms_timeout)
{
const unsigned long timeout = jiffies + msecs_to_jiffies(ms_timeout);
do {
if (rtc_reg_read(rtc, MA35_REG_RTC_INIT) & RTC_INIT_ACTIVE)
return 0;
rtc_reg_write(rtc, MA35_REG_RTC_INIT, RTC_INIT_MAGIC_CODE);
mdelay(1);
} while (time_before(jiffies, timeout));
return -ETIMEDOUT;
}
static int ma35d1_alarm_irq_enable(struct device *dev, u32 enabled)
{
struct ma35_rtc *rtc = dev_get_drvdata(dev);
u32 reg_ien;
reg_ien = rtc_reg_read(rtc, MA35_REG_RTC_INTEN);
if (enabled)
rtc_reg_write(rtc, MA35_REG_RTC_INTEN, reg_ien | RTC_INTEN_ALMIEN);
else
rtc_reg_write(rtc, MA35_REG_RTC_INTEN, reg_ien & ~RTC_INTEN_ALMIEN);
return 0;
}
static int ma35d1_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
struct ma35_rtc *rtc = dev_get_drvdata(dev);
u32 time, cal, wday;
do {
time = rtc_reg_read(rtc, MA35_REG_RTC_TIME);
cal = rtc_reg_read(rtc, MA35_REG_RTC_CAL);
wday = rtc_reg_read(rtc, MA35_REG_RTC_WEEKDAY);
} while (time != rtc_reg_read(rtc, MA35_REG_RTC_TIME) ||
cal != rtc_reg_read(rtc, MA35_REG_RTC_CAL));
tm->tm_mday = bcd2bin(cal >> 0);
tm->tm_wday = wday;
tm->tm_mon = bcd2bin(cal >> 8);
tm->tm_mon = tm->tm_mon - 1;
tm->tm_year = bcd2bin(cal >> 16) + 100;
tm->tm_sec = bcd2bin(time >> 0);
tm->tm_min = bcd2bin(time >> 8);
tm->tm_hour = bcd2bin(time >> 16);
return rtc_valid_tm(tm);
}
static int ma35d1_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
struct ma35_rtc *rtc = dev_get_drvdata(dev);
u32 val;
val = bin2bcd(tm->tm_mday) << 0 | bin2bcd(tm->tm_mon + 1) << 8 |
bin2bcd(tm->tm_year - 100) << 16;
rtc_reg_write(rtc, MA35_REG_RTC_CAL, val);
val = bin2bcd(tm->tm_sec) << 0 | bin2bcd(tm->tm_min) << 8 |
bin2bcd(tm->tm_hour) << 16;
rtc_reg_write(rtc, MA35_REG_RTC_TIME, val);
val = tm->tm_wday;
rtc_reg_write(rtc, MA35_REG_RTC_WEEKDAY, val);
return 0;
}
static int ma35d1_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
struct ma35_rtc *rtc = dev_get_drvdata(dev);
u32 talm, calm;
talm = rtc_reg_read(rtc, MA35_REG_RTC_TALM);
calm = rtc_reg_read(rtc, MA35_REG_RTC_CALM);
alrm->time.tm_mday = bcd2bin(calm >> 0);
alrm->time.tm_mon = bcd2bin(calm >> 8);
alrm->time.tm_mon = alrm->time.tm_mon - 1;
alrm->time.tm_year = bcd2bin(calm >> 16) + 100;
alrm->time.tm_sec = bcd2bin(talm >> 0);
alrm->time.tm_min = bcd2bin(talm >> 8);
alrm->time.tm_hour = bcd2bin(talm >> 16);
return rtc_valid_tm(&alrm->time);
}
static int ma35d1_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
struct ma35_rtc *rtc = dev_get_drvdata(dev);
unsigned long val;
val = bin2bcd(alrm->time.tm_mday) << 0 | bin2bcd(alrm->time.tm_mon + 1) << 8 |
bin2bcd(alrm->time.tm_year - 100) << 16;
rtc_reg_write(rtc, MA35_REG_RTC_CALM, val);
val = bin2bcd(alrm->time.tm_sec) << 0 | bin2bcd(alrm->time.tm_min) << 8 |
bin2bcd(alrm->time.tm_hour) << 16;
rtc_reg_write(rtc, MA35_REG_RTC_TALM, val);
ma35d1_alarm_irq_enable(dev, alrm->enabled);
return 0;
}
static const struct rtc_class_ops ma35d1_rtc_ops = {
.read_time = ma35d1_rtc_read_time,
.set_time = ma35d1_rtc_set_time,
.read_alarm = ma35d1_rtc_read_alarm,
.set_alarm = ma35d1_rtc_set_alarm,
.alarm_irq_enable = ma35d1_alarm_irq_enable,
};
static int ma35d1_rtc_probe(struct platform_device *pdev)
{
struct ma35_rtc *rtc;
struct clk *clk;
int ret;
rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL);
if (!rtc)
return -ENOMEM;
rtc->rtc_reg = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(rtc->rtc_reg))
return PTR_ERR(rtc->rtc_reg);
clk = of_clk_get(pdev->dev.of_node, 0);
if (IS_ERR(clk))
return dev_err_probe(&pdev->dev, PTR_ERR(clk), "failed to find rtc clock\n");
ret = clk_prepare_enable(clk);
if (ret)
return ret;
if (!(rtc_reg_read(rtc, MA35_REG_RTC_INIT) & RTC_INIT_ACTIVE)) {
ret = ma35d1_rtc_init(rtc, RTC_INIT_TIMEOUT);
if (ret)
return dev_err_probe(&pdev->dev, ret, "rtc init failed\n");
}
rtc->irq_num = platform_get_irq(pdev, 0);
ret = devm_request_irq(&pdev->dev, rtc->irq_num, ma35d1_rtc_interrupt,
IRQF_NO_SUSPEND, "ma35d1rtc", rtc);
if (ret)
return dev_err_probe(&pdev->dev, ret, "Failed to request rtc irq\n");
platform_set_drvdata(pdev, rtc);
device_init_wakeup(&pdev->dev, true);
rtc->rtcdev = devm_rtc_allocate_device(&pdev->dev);
if (IS_ERR(rtc->rtcdev))
return PTR_ERR(rtc->rtcdev);
rtc->rtcdev->ops = &ma35d1_rtc_ops;
rtc->rtcdev->range_min = RTC_TIMESTAMP_BEGIN_2000;
rtc->rtcdev->range_max = RTC_TIMESTAMP_END_2099;
ret = devm_rtc_register_device(rtc->rtcdev);
if (ret)
return dev_err_probe(&pdev->dev, ret, "Failed to register rtc device\n");
return 0;
}
static int ma35d1_rtc_suspend(struct platform_device *pdev, pm_message_t state)
{
struct ma35_rtc *rtc = platform_get_drvdata(pdev);
if (device_may_wakeup(&pdev->dev))
enable_irq_wake(rtc->irq_num);
return 0;
}
static int ma35d1_rtc_resume(struct platform_device *pdev)
{
struct ma35_rtc *rtc = platform_get_drvdata(pdev);
if (device_may_wakeup(&pdev->dev))
disable_irq_wake(rtc->irq_num);
return 0;
}
static const struct of_device_id ma35d1_rtc_of_match[] = {
{ .compatible = "nuvoton,ma35d1-rtc", },
{},
};
MODULE_DEVICE_TABLE(of, ma35d1_rtc_of_match);
static struct platform_driver ma35d1_rtc_driver = {
.suspend = ma35d1_rtc_suspend,
.resume = ma35d1_rtc_resume,
.probe = ma35d1_rtc_probe,
.driver = {
.name = "rtc-ma35d1",
.of_match_table = ma35d1_rtc_of_match,
},
};
module_platform_driver(ma35d1_rtc_driver);
MODULE_AUTHOR("Ming-Jen Chen <mjchen@nuvoton.com>");
MODULE_DESCRIPTION("MA35D1 RTC driver");
MODULE_LICENSE("GPL");
This diff is collapsed.
......@@ -8,26 +8,31 @@
#include <linux/acpi.h>
#endif
#define UIP_RECHECK_DELAY 100 /* usec */
#define UIP_RECHECK_DELAY_MS (USEC_PER_MSEC / UIP_RECHECK_DELAY)
#define UIP_RECHECK_LOOPS_MS(x) (x / UIP_RECHECK_DELAY_MS)
/*
* Execute a function while the UIP (Update-in-progress) bit of the RTC is
* unset.
* unset. The timeout is configurable by the caller in ms.
*
* Warning: callback may be executed more then once.
*/
bool mc146818_avoid_UIP(void (*callback)(unsigned char seconds, void *param),
int timeout,
void *param)
{
int i;
unsigned long flags;
unsigned char seconds;
for (i = 0; i < 100; i++) {
for (i = 0; UIP_RECHECK_LOOPS_MS(i) < timeout; i++) {
spin_lock_irqsave(&rtc_lock, flags);
/*
* Check whether there is an update in progress during which the
* readout is unspecified. The maximum update time is ~2ms. Poll
* every 100 usec for completion.
* for completion.
*
* Store the second value before checking UIP so a long lasting
* NMI which happens to hit after the UIP check cannot make
......@@ -37,7 +42,7 @@ bool mc146818_avoid_UIP(void (*callback)(unsigned char seconds, void *param),
if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP) {
spin_unlock_irqrestore(&rtc_lock, flags);
udelay(100);
udelay(UIP_RECHECK_DELAY);
continue;
}
......@@ -56,7 +61,7 @@ bool mc146818_avoid_UIP(void (*callback)(unsigned char seconds, void *param),
*/
if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP) {
spin_unlock_irqrestore(&rtc_lock, flags);
udelay(100);
udelay(UIP_RECHECK_DELAY);
continue;
}
......@@ -72,6 +77,10 @@ bool mc146818_avoid_UIP(void (*callback)(unsigned char seconds, void *param),
}
spin_unlock_irqrestore(&rtc_lock, flags);
if (UIP_RECHECK_LOOPS_MS(i) >= 100)
pr_warn("Reading current time from RTC took around %li ms\n",
UIP_RECHECK_LOOPS_MS(i));
return true;
}
return false;
......@@ -84,7 +93,7 @@ EXPORT_SYMBOL_GPL(mc146818_avoid_UIP);
*/
bool mc146818_does_rtc_work(void)
{
return mc146818_avoid_UIP(NULL, NULL);
return mc146818_avoid_UIP(NULL, 1000, NULL);
}
EXPORT_SYMBOL_GPL(mc146818_does_rtc_work);
......@@ -130,15 +139,27 @@ static void mc146818_get_time_callback(unsigned char seconds, void *param_in)
p->ctrl = CMOS_READ(RTC_CONTROL);
}
int mc146818_get_time(struct rtc_time *time)
/**
* mc146818_get_time - Get the current time from the RTC
* @time: pointer to struct rtc_time to store the current time
* @timeout: timeout value in ms
*
* This function reads the current time from the RTC and stores it in the
* provided struct rtc_time. The timeout parameter specifies the maximum
* time to wait for the RTC to become ready.
*
* Return: 0 on success, -ETIMEDOUT if the RTC did not become ready within
* the specified timeout, or another error code if an error occurred.
*/
int mc146818_get_time(struct rtc_time *time, int timeout)
{
struct mc146818_get_time_callback_param p = {
.time = time
};
if (!mc146818_avoid_UIP(mc146818_get_time_callback, &p)) {
if (!mc146818_avoid_UIP(mc146818_get_time_callback, timeout, &p)) {
memset(time, 0, sizeof(*time));
return -EIO;
return -ETIMEDOUT;
}
if (!(p.ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
......
......@@ -23,6 +23,7 @@
#define NCT3018Y_REG_CTRL 0x0A /* timer control */
#define NCT3018Y_REG_ST 0x0B /* status */
#define NCT3018Y_REG_CLKO 0x0C /* clock out */
#define NCT3018Y_REG_PART 0x21 /* part info */
#define NCT3018Y_BIT_AF BIT(7)
#define NCT3018Y_BIT_ST BIT(7)
......@@ -37,10 +38,12 @@
#define NCT3018Y_REG_BAT_MASK 0x07
#define NCT3018Y_REG_CLKO_F_MASK 0x03 /* frequenc mask */
#define NCT3018Y_REG_CLKO_CKE 0x80 /* clock out enabled */
#define NCT3018Y_REG_PART_NCT3018Y 0x02
struct nct3018y {
struct rtc_device *rtc;
struct i2c_client *client;
int part_num;
#ifdef CONFIG_COMMON_CLK
struct clk_hw clkout_hw;
#endif
......@@ -177,8 +180,27 @@ static int nct3018y_rtc_read_time(struct device *dev, struct rtc_time *tm)
static int nct3018y_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
struct i2c_client *client = to_i2c_client(dev);
struct nct3018y *nct3018y = dev_get_drvdata(dev);
unsigned char buf[4] = {0};
int err;
int err, flags;
int restore_flags = 0;
flags = i2c_smbus_read_byte_data(client, NCT3018Y_REG_CTRL);
if (flags < 0) {
dev_dbg(&client->dev, "Failed to read NCT3018Y_REG_CTRL.\n");
return flags;
}
/* Check and set TWO bit */
if (nct3018y->part_num == NCT3018Y_REG_PART_NCT3018Y && !(flags & NCT3018Y_BIT_TWO)) {
restore_flags = 1;
flags |= NCT3018Y_BIT_TWO;
err = i2c_smbus_write_byte_data(client, NCT3018Y_REG_CTRL, flags);
if (err < 0) {
dev_dbg(&client->dev, "Unable to write NCT3018Y_REG_CTRL.\n");
return err;
}
}
buf[0] = bin2bcd(tm->tm_sec);
err = i2c_smbus_write_byte_data(client, NCT3018Y_REG_SC, buf[0]);
......@@ -212,6 +234,18 @@ static int nct3018y_rtc_set_time(struct device *dev, struct rtc_time *tm)
return -EIO;
}
/* Restore TWO bit */
if (restore_flags) {
if (nct3018y->part_num == NCT3018Y_REG_PART_NCT3018Y)
flags &= ~NCT3018Y_BIT_TWO;
err = i2c_smbus_write_byte_data(client, NCT3018Y_REG_CTRL, flags);
if (err < 0) {
dev_dbg(&client->dev, "Unable to write NCT3018Y_REG_CTRL.\n");
return err;
}
}
return err;
}
......@@ -479,11 +513,17 @@ static int nct3018y_probe(struct i2c_client *client)
dev_dbg(&client->dev, "%s: NCT3018Y_BIT_TWO is set\n", __func__);
}
flags = NCT3018Y_BIT_TWO;
err = i2c_smbus_write_byte_data(client, NCT3018Y_REG_CTRL, flags);
if (err < 0) {
dev_dbg(&client->dev, "Unable to write NCT3018Y_REG_CTRL\n");
return err;
nct3018y->part_num = i2c_smbus_read_byte_data(client, NCT3018Y_REG_PART);
if (nct3018y->part_num < 0) {
dev_dbg(&client->dev, "Failed to read NCT3018Y_REG_PART.\n");
return nct3018y->part_num;
} else if (nct3018y->part_num == NCT3018Y_REG_PART_NCT3018Y) {
flags = NCT3018Y_BIT_HF;
err = i2c_smbus_write_byte_data(client, NCT3018Y_REG_CTRL, flags);
if (err < 0) {
dev_dbg(&client->dev, "Unable to write NCT3018Y_REG_CTRL.\n");
return err;
}
}
flags = 0;
......
......@@ -17,6 +17,7 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/rtc.h>
#include <linux/pm_wakeirq.h>
#define RV8803_I2C_TRY_COUNT 4
......@@ -607,6 +608,28 @@ static int rv8803_regs_configure(struct rv8803_data *rv8803)
return 0;
}
static int rv8803_resume(struct device *dev)
{
struct rv8803_data *rv8803 = dev_get_drvdata(dev);
if (rv8803->client->irq > 0 && device_may_wakeup(dev))
disable_irq_wake(rv8803->client->irq);
return 0;
}
static int rv8803_suspend(struct device *dev)
{
struct rv8803_data *rv8803 = dev_get_drvdata(dev);
if (rv8803->client->irq > 0 && device_may_wakeup(dev))
enable_irq_wake(rv8803->client->irq);
return 0;
}
static DEFINE_SIMPLE_DEV_PM_OPS(rv8803_pm_ops, rv8803_suspend, rv8803_resume);
static const struct i2c_device_id rv8803_id[] = {
{ "rv8803", rv_8803 },
{ "rv8804", rx_8804 },
......@@ -683,10 +706,18 @@ static int rv8803_probe(struct i2c_client *client)
if (err) {
dev_warn(&client->dev, "unable to request IRQ, alarms disabled\n");
client->irq = 0;
} else {
device_init_wakeup(&client->dev, true);
err = dev_pm_set_wake_irq(&client->dev, client->irq);
if (err)
dev_err(&client->dev, "failed to set wake IRQ\n");
}
} else {
if (device_property_read_bool(&client->dev, "wakeup-source"))
device_init_wakeup(&client->dev, true);
else
clear_bit(RTC_FEATURE_ALARM, rv8803->rtc->features);
}
if (!client->irq)
clear_bit(RTC_FEATURE_ALARM, rv8803->rtc->features);
if (of_property_read_bool(client->dev.of_node, "epson,vdet-disable"))
rv8803->backup |= RX8900_FLAG_VDETOFF;
......@@ -737,6 +768,7 @@ static struct i2c_driver rv8803_driver = {
.driver = {
.name = "rtc-rv8803",
.of_match_table = of_match_ptr(rv8803_of_match),
.pm = &rv8803_pm_ops,
},
.probe = rv8803_probe,
.id_table = rv8803_id,
......
This diff is collapsed.
......@@ -126,10 +126,11 @@ struct cmos_rtc_board_info {
#endif /* ARCH_RTC_LOCATION */
bool mc146818_does_rtc_work(void);
int mc146818_get_time(struct rtc_time *time);
int mc146818_get_time(struct rtc_time *time, int timeout);
int mc146818_set_time(struct rtc_time *time);
bool mc146818_avoid_UIP(void (*callback)(unsigned char seconds, void *param),
int timeout,
void *param);
#endif /* _MC146818RTC_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment