mirror of https://gitee.com/openkylin/linux.git
RTC for 4.12
Subsystem: - Add OF device ID table for i2c drivers New driver: - Motorola CPCAP PMIC RTC Drivers: - cmos: fix IRQ selection - ds1307: Add ST m41t0 support - ds1374: fix watchdog configuration - sh: Add rza series support -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEXx9Viay1+e7J/aM4AyWl4gNJNJIFAlkTf2sACgkQAyWl4gNJ NJLPvw//dGzo6oD3C96QIurfrgFx9512ZurEiJpGPIO15obTVLF0SNuswaMj7knm ezqQ23qX9VBEmu3si7LvkQVbE60giB3XnlJ/wpFi/LhtlM7SQ4o2Z8Go3rkL8tCw iPcj5l3ShbHgSF+TBK+jK5C/8ahR7RE32l2rtSi9xwzxOmKRySmSWg2iGmGJMNUU 7UHR4DRHVPS/h1ffM/rOWV+d3GVK9laNmeoIORhsWCa+iYwGRZr3XL3GXQzhehBO H5uFYewMVBHREADiqMNQ/ogHZI+ghXt1OSK7vhUFkYxosqU56P0YtU6SPH6UuFsH ryoiUmCgQQjjhptlvVv71D7Wj1txSCT6rByQU1YyVZ0yw9XpVuGTYBjFBY+D7nxb e3sR+Poe3diVLWDwFTXStrY0TtVlCTTCjs5T2kwUdYOJ188expQGHgj6wVl7PPTs gpeSIunekbop13KCPWV01TzmRLB8ne9ZiomsuiNnuAKhXP7KRf6AfuQd6kpyvpmH vhGcEIe7O0i4TwUIuB/dmdhLHmlOqCpLJpGQihNc+f0jJAxHv+akXEQ06H84FkJD kPkBYSVDp/2pEBdf7ig2mlpPEqANgoQY8GCu9SbEg976g0v8k6m+i9IlbR0m7hwE 0XF+8W45iNsaEIzoXcyHuB/lrUy1/0eNoG4KX8vyWIjITo5HQWg= =40TA -----END PGP SIGNATURE----- Merge tag 'rtc-4.12' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux Pull RTC updates from Alexandre Belloni: "RTC subsystem update: - Add OF device ID table for i2c drivers New RTC driver: - Motorola CPCAP PMIC RTC RTC driver updates: - cmos: fix IRQ selection - ds1307: Add ST m41t0 support - ds1374: fix watchdog configuration - sh: Add rza series support" * tag 'rtc-4.12' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux: (33 commits) rtc: gemini: add return value validation rtc: snvs: fix an incorrect check of return value rtc: ds1374: wdt: Fix stop/start ioctl always returning -EINVAL rtc: ds1374: wdt: Fix issue with timeout scaling from secs to wdt ticks rtc: sh: mark PM functions as unused rtc: hid-sensor-time: remove some dead code rtc: m41t80: Add proper compatible for rv4162 rtc: ds1307: Add m41t0 to OF device ID table rtc: ds1307: support m41t0 variant rtc: cpcap: fix improper use of IRQ_NONE for request_threaded_irq rtc: cmos: Do not assume irq 8 for rtc when there are no legacy irqs x86: i8259: export legacy_pic symbol dt-bindings: rtc: document the rtc-sh bindings rtc: sh: add support for rza series rtc: cpcap: kfreeing devm allocated memory rtc: wm8350: Remove unused to_wm8350_from_rtc_dev rtc: cpcap: new rtc driver dt-bindings: Add vendor prefix for Motorola rtc: omap: mark PM methods as __maybe_unused rtc: omap: remove incorrect __exit markups ...
This commit is contained in:
commit
556d994a75
|
@ -0,0 +1,18 @@
|
|||
Motorola CPCAP PMIC RTC
|
||||
-----------------------
|
||||
|
||||
This module is part of the CPCAP. For more details about the whole
|
||||
chip see Documentation/devicetree/bindings/mfd/motorola-cpcap.txt.
|
||||
|
||||
Requires node properties:
|
||||
- compatible: should contain "motorola,cpcap-rtc"
|
||||
- interrupts: An interrupt specifier for alarm and 1 Hz irq
|
||||
|
||||
Example:
|
||||
|
||||
&cpcap {
|
||||
cpcap_rtc: rtc {
|
||||
compatible = "motorola,cpcap-rtc";
|
||||
interrupts = <39 IRQ_TYPE_NONE>, <26 IRQ_TYPE_NONE>;
|
||||
};
|
||||
};
|
|
@ -0,0 +1,28 @@
|
|||
* Real Time Clock for Renesas SH and ARM SoCs
|
||||
|
||||
Required properties:
|
||||
- compatible: Should be "renesas,r7s72100-rtc" and "renesas,sh-rtc" as a
|
||||
fallback.
|
||||
- reg: physical base address and length of memory mapped region.
|
||||
- interrupts: 3 interrupts for alarm, period, and carry.
|
||||
- interrupt-names: The interrupts should be labeled as "alarm", "period", and
|
||||
"carry".
|
||||
- clocks: The functional clock source for the RTC controller must be listed
|
||||
first (if exists). Additionally, potential clock counting sources are to be
|
||||
listed.
|
||||
- clock-names: The functional clock must be labeled as "fck". Other clocks
|
||||
may be named in accordance to the SoC hardware manuals.
|
||||
|
||||
|
||||
Example:
|
||||
rtc: rtc@fcff1000 {
|
||||
compatible = "renesas,r7s72100-rtc", "renesas,sh-rtc";
|
||||
reg = <0xfcff1000 0x2e>;
|
||||
interrupts = <GIC_SPI 276 IRQ_TYPE_EDGE_RISING
|
||||
GIC_SPI 277 IRQ_TYPE_EDGE_RISING
|
||||
GIC_SPI 278 IRQ_TYPE_EDGE_RISING>;
|
||||
interrupt-names = "alarm", "period", "carry";
|
||||
clocks = <&mstp6_clks R7S72100_CLK_RTC>, <&rtc_x1_clk>,
|
||||
<&rtc_x3_clk>, <&extal_clk>;
|
||||
clock-names = "fck", "rtc_x1", "rtc_x3", "extal";
|
||||
};
|
|
@ -160,6 +160,7 @@ sii,s35390a 2-wire CMOS real-time clock
|
|||
silabs,si7020 Relative Humidity and Temperature Sensors
|
||||
skyworks,sky81452 Skyworks SKY81452: Six-Channel White LED Driver with Touch Panel Bias Supply
|
||||
st,24c256 i2c serial eeprom (24cxx)
|
||||
st,m41t0 Serial real-time clock (RTC)
|
||||
st,m41t00 Serial real-time clock (RTC)
|
||||
st,m41t62 Serial real-time clock (RTC) with alarm
|
||||
st,m41t80 M41T80 - SERIAL ACCESS RTC WITH ALARMS
|
||||
|
|
|
@ -197,6 +197,7 @@ minix MINIX Technology Ltd.
|
|||
miramems MiraMEMS Sensing Technology Co., Ltd.
|
||||
mitsubishi Mitsubishi Electric Corporation
|
||||
mosaixtech Mosaix Technologies, Inc.
|
||||
motorola Motorola, Inc.
|
||||
moxa Moxa
|
||||
mpl MPL AG
|
||||
mqmaker mqmaker Inc.
|
||||
|
|
|
@ -418,6 +418,7 @@ struct legacy_pic default_legacy_pic = {
|
|||
};
|
||||
|
||||
struct legacy_pic *legacy_pic = &default_legacy_pic;
|
||||
EXPORT_SYMBOL(legacy_pic);
|
||||
|
||||
static int __init i8259A_init_ops(void)
|
||||
{
|
||||
|
|
|
@ -1303,10 +1303,10 @@ config RTC_DRV_SA1100
|
|||
|
||||
config RTC_DRV_SH
|
||||
tristate "SuperH On-Chip RTC"
|
||||
depends on SUPERH && HAVE_CLK
|
||||
depends on SUPERH || ARCH_RENESAS
|
||||
help
|
||||
Say Y here to enable support for the on-chip RTC found in
|
||||
most SuperH processors.
|
||||
most SuperH processors. This RTC is also found in RZ/A SoCs.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called rtc-sh.
|
||||
|
@ -1731,6 +1731,13 @@ config RTC_DRV_STM32
|
|||
This driver can also be built as a module, if so, the module
|
||||
will be called "rtc-stm32".
|
||||
|
||||
config RTC_DRV_CPCAP
|
||||
depends on MFD_CPCAP
|
||||
tristate "Motorola CPCAP RTC"
|
||||
help
|
||||
Say y here for CPCAP rtc found on some Motorola phones
|
||||
and tablets such as Droid 4.
|
||||
|
||||
comment "HID Sensor RTC drivers"
|
||||
|
||||
config RTC_DRV_HID_SENSOR_TIME
|
||||
|
|
|
@ -40,6 +40,7 @@ obj-$(CONFIG_RTC_DRV_BQ32K) += rtc-bq32k.o
|
|||
obj-$(CONFIG_RTC_DRV_BQ4802) += rtc-bq4802.o
|
||||
obj-$(CONFIG_RTC_DRV_CMOS) += rtc-cmos.o
|
||||
obj-$(CONFIG_RTC_DRV_COH901331) += rtc-coh901331.o
|
||||
obj-$(CONFIG_RTC_DRV_CPCAP) += rtc-cpcap.o
|
||||
obj-$(CONFIG_RTC_DRV_DA9052) += rtc-da9052.o
|
||||
obj-$(CONFIG_RTC_DRV_DA9055) += rtc-da9055.o
|
||||
obj-$(CONFIG_RTC_DRV_DA9063) += rtc-da9063.o
|
||||
|
|
|
@ -310,9 +310,16 @@ static const struct i2c_device_id bq32k_id[] = {
|
|||
};
|
||||
MODULE_DEVICE_TABLE(i2c, bq32k_id);
|
||||
|
||||
static const struct of_device_id bq32k_of_match[] = {
|
||||
{ .compatible = "ti,bq32000" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, bq32k_of_match);
|
||||
|
||||
static struct i2c_driver bq32k_driver = {
|
||||
.driver = {
|
||||
.name = "bq32k",
|
||||
.of_match_table = of_match_ptr(bq32k_of_match),
|
||||
},
|
||||
.probe = bq32k_probe,
|
||||
.remove = bq32k_remove,
|
||||
|
|
|
@ -41,6 +41,9 @@
|
|||
#include <linux/pm.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_platform.h>
|
||||
#ifdef CONFIG_X86
|
||||
#include <asm/i8259.h>
|
||||
#endif
|
||||
|
||||
/* this is for "generic access to PC-style RTC" using CMOS_READ/CMOS_WRITE */
|
||||
#include <linux/mc146818rtc.h>
|
||||
|
@ -1193,17 +1196,23 @@ static int cmos_pnp_probe(struct pnp_dev *pnp, const struct pnp_device_id *id)
|
|||
{
|
||||
cmos_wake_setup(&pnp->dev);
|
||||
|
||||
if (pnp_port_start(pnp, 0) == 0x70 && !pnp_irq_valid(pnp, 0))
|
||||
if (pnp_port_start(pnp, 0) == 0x70 && !pnp_irq_valid(pnp, 0)) {
|
||||
unsigned int irq = 0;
|
||||
#ifdef CONFIG_X86
|
||||
/* Some machines contain a PNP entry for the RTC, but
|
||||
* don't define the IRQ. It should always be safe to
|
||||
* hardcode it in these cases
|
||||
* hardcode it on systems with a legacy PIC.
|
||||
*/
|
||||
if (nr_legacy_irqs())
|
||||
irq = 8;
|
||||
#endif
|
||||
return cmos_do_probe(&pnp->dev,
|
||||
pnp_get_resource(pnp, IORESOURCE_IO, 0), 8);
|
||||
else
|
||||
pnp_get_resource(pnp, IORESOURCE_IO, 0), irq);
|
||||
} else {
|
||||
return cmos_do_probe(&pnp->dev,
|
||||
pnp_get_resource(pnp, IORESOURCE_IO, 0),
|
||||
pnp_irq(pnp, 0));
|
||||
}
|
||||
}
|
||||
|
||||
static void cmos_pnp_remove(struct pnp_dev *pnp)
|
||||
|
|
|
@ -0,0 +1,330 @@
|
|||
/*
|
||||
* Motorola CPCAP PMIC RTC driver
|
||||
*
|
||||
* Based on cpcap-regulator.c from Motorola Linux kernel tree
|
||||
* Copyright (C) 2009 Motorola, Inc.
|
||||
*
|
||||
* Rewritten for mainline kernel
|
||||
* - use DT
|
||||
* - use regmap
|
||||
* - use standard interrupt framework
|
||||
* - use managed device resources
|
||||
* - remove custom "secure clock daemon" helpers
|
||||
*
|
||||
* Copyright (C) 2017 Sebastian Reichel <sre@kernel.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/rtc.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/mfd/motorola-cpcap.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/sched.h>
|
||||
|
||||
#define SECS_PER_DAY 86400
|
||||
#define DAY_MASK 0x7FFF
|
||||
#define TOD1_MASK 0x00FF
|
||||
#define TOD2_MASK 0x01FF
|
||||
|
||||
struct cpcap_time {
|
||||
int day;
|
||||
int tod1;
|
||||
int tod2;
|
||||
};
|
||||
|
||||
struct cpcap_rtc {
|
||||
struct regmap *regmap;
|
||||
struct rtc_device *rtc_dev;
|
||||
u16 vendor;
|
||||
int alarm_irq;
|
||||
bool alarm_enabled;
|
||||
int update_irq;
|
||||
bool update_enabled;
|
||||
};
|
||||
|
||||
static void cpcap2rtc_time(struct rtc_time *rtc, struct cpcap_time *cpcap)
|
||||
{
|
||||
unsigned long int tod;
|
||||
unsigned long int time;
|
||||
|
||||
tod = (cpcap->tod1 & TOD1_MASK) | ((cpcap->tod2 & TOD2_MASK) << 8);
|
||||
time = tod + ((cpcap->day & DAY_MASK) * SECS_PER_DAY);
|
||||
|
||||
rtc_time_to_tm(time, rtc);
|
||||
}
|
||||
|
||||
static void rtc2cpcap_time(struct cpcap_time *cpcap, struct rtc_time *rtc)
|
||||
{
|
||||
unsigned long time;
|
||||
|
||||
rtc_tm_to_time(rtc, &time);
|
||||
|
||||
cpcap->day = time / SECS_PER_DAY;
|
||||
time %= SECS_PER_DAY;
|
||||
cpcap->tod2 = (time >> 8) & TOD2_MASK;
|
||||
cpcap->tod1 = time & TOD1_MASK;
|
||||
}
|
||||
|
||||
static int cpcap_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
|
||||
{
|
||||
struct cpcap_rtc *rtc = dev_get_drvdata(dev);
|
||||
|
||||
if (rtc->alarm_enabled == enabled)
|
||||
return 0;
|
||||
|
||||
if (enabled)
|
||||
enable_irq(rtc->alarm_irq);
|
||||
else
|
||||
disable_irq(rtc->alarm_irq);
|
||||
|
||||
rtc->alarm_enabled = !!enabled;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cpcap_rtc_read_time(struct device *dev, struct rtc_time *tm)
|
||||
{
|
||||
struct cpcap_rtc *rtc;
|
||||
struct cpcap_time cpcap_tm;
|
||||
int temp_tod2;
|
||||
int ret;
|
||||
|
||||
rtc = dev_get_drvdata(dev);
|
||||
|
||||
ret = regmap_read(rtc->regmap, CPCAP_REG_TOD2, &temp_tod2);
|
||||
ret |= regmap_read(rtc->regmap, CPCAP_REG_DAY, &cpcap_tm.day);
|
||||
ret |= regmap_read(rtc->regmap, CPCAP_REG_TOD1, &cpcap_tm.tod1);
|
||||
ret |= regmap_read(rtc->regmap, CPCAP_REG_TOD2, &cpcap_tm.tod2);
|
||||
|
||||
if (temp_tod2 > cpcap_tm.tod2)
|
||||
ret |= regmap_read(rtc->regmap, CPCAP_REG_DAY, &cpcap_tm.day);
|
||||
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to read time\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
cpcap2rtc_time(tm, &cpcap_tm);
|
||||
|
||||
return rtc_valid_tm(tm);
|
||||
}
|
||||
|
||||
static int cpcap_rtc_set_time(struct device *dev, struct rtc_time *tm)
|
||||
{
|
||||
struct cpcap_rtc *rtc;
|
||||
struct cpcap_time cpcap_tm;
|
||||
int ret = 0;
|
||||
|
||||
rtc = dev_get_drvdata(dev);
|
||||
|
||||
rtc2cpcap_time(&cpcap_tm, tm);
|
||||
|
||||
if (rtc->alarm_enabled)
|
||||
disable_irq(rtc->alarm_irq);
|
||||
if (rtc->update_enabled)
|
||||
disable_irq(rtc->update_irq);
|
||||
|
||||
if (rtc->vendor == CPCAP_VENDOR_ST) {
|
||||
/* The TOD1 and TOD2 registers MUST be written in this order
|
||||
* for the change to properly set.
|
||||
*/
|
||||
ret |= regmap_update_bits(rtc->regmap, CPCAP_REG_TOD1,
|
||||
TOD1_MASK, cpcap_tm.tod1);
|
||||
ret |= regmap_update_bits(rtc->regmap, CPCAP_REG_TOD2,
|
||||
TOD2_MASK, cpcap_tm.tod2);
|
||||
ret |= regmap_update_bits(rtc->regmap, CPCAP_REG_DAY,
|
||||
DAY_MASK, cpcap_tm.day);
|
||||
} else {
|
||||
/* Clearing the upper lower 8 bits of the TOD guarantees that
|
||||
* the upper half of TOD (TOD2) will not increment for 0xFF RTC
|
||||
* ticks (255 seconds). During this time we can safely write
|
||||
* to DAY, TOD2, then TOD1 (in that order) and expect RTC to be
|
||||
* synchronized to the exact time requested upon the final write
|
||||
* to TOD1.
|
||||
*/
|
||||
ret |= regmap_update_bits(rtc->regmap, CPCAP_REG_TOD1,
|
||||
TOD1_MASK, 0);
|
||||
ret |= regmap_update_bits(rtc->regmap, CPCAP_REG_DAY,
|
||||
DAY_MASK, cpcap_tm.day);
|
||||
ret |= regmap_update_bits(rtc->regmap, CPCAP_REG_TOD2,
|
||||
TOD2_MASK, cpcap_tm.tod2);
|
||||
ret |= regmap_update_bits(rtc->regmap, CPCAP_REG_TOD1,
|
||||
TOD1_MASK, cpcap_tm.tod1);
|
||||
}
|
||||
|
||||
if (rtc->update_enabled)
|
||||
enable_irq(rtc->update_irq);
|
||||
if (rtc->alarm_enabled)
|
||||
enable_irq(rtc->alarm_irq);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int cpcap_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
|
||||
{
|
||||
struct cpcap_rtc *rtc;
|
||||
struct cpcap_time cpcap_tm;
|
||||
int ret;
|
||||
|
||||
rtc = dev_get_drvdata(dev);
|
||||
|
||||
alrm->enabled = rtc->alarm_enabled;
|
||||
|
||||
ret = regmap_read(rtc->regmap, CPCAP_REG_DAYA, &cpcap_tm.day);
|
||||
ret |= regmap_read(rtc->regmap, CPCAP_REG_TODA2, &cpcap_tm.tod2);
|
||||
ret |= regmap_read(rtc->regmap, CPCAP_REG_TODA1, &cpcap_tm.tod1);
|
||||
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to read time\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
cpcap2rtc_time(&alrm->time, &cpcap_tm);
|
||||
return rtc_valid_tm(&alrm->time);
|
||||
}
|
||||
|
||||
static int cpcap_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
|
||||
{
|
||||
struct cpcap_rtc *rtc;
|
||||
struct cpcap_time cpcap_tm;
|
||||
int ret;
|
||||
|
||||
rtc = dev_get_drvdata(dev);
|
||||
|
||||
rtc2cpcap_time(&cpcap_tm, &alrm->time);
|
||||
|
||||
if (rtc->alarm_enabled)
|
||||
disable_irq(rtc->alarm_irq);
|
||||
|
||||
ret = regmap_update_bits(rtc->regmap, CPCAP_REG_DAYA, DAY_MASK,
|
||||
cpcap_tm.day);
|
||||
ret |= regmap_update_bits(rtc->regmap, CPCAP_REG_TODA2, TOD2_MASK,
|
||||
cpcap_tm.tod2);
|
||||
ret |= regmap_update_bits(rtc->regmap, CPCAP_REG_TODA1, TOD1_MASK,
|
||||
cpcap_tm.tod1);
|
||||
|
||||
if (!ret) {
|
||||
enable_irq(rtc->alarm_irq);
|
||||
rtc->alarm_enabled = true;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct rtc_class_ops cpcap_rtc_ops = {
|
||||
.read_time = cpcap_rtc_read_time,
|
||||
.set_time = cpcap_rtc_set_time,
|
||||
.read_alarm = cpcap_rtc_read_alarm,
|
||||
.set_alarm = cpcap_rtc_set_alarm,
|
||||
.alarm_irq_enable = cpcap_rtc_alarm_irq_enable,
|
||||
};
|
||||
|
||||
static irqreturn_t cpcap_rtc_alarm_irq(int irq, void *data)
|
||||
{
|
||||
struct cpcap_rtc *rtc = data;
|
||||
|
||||
rtc_update_irq(rtc->rtc_dev, 1, RTC_AF | RTC_IRQF);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t cpcap_rtc_update_irq(int irq, void *data)
|
||||
{
|
||||
struct cpcap_rtc *rtc = data;
|
||||
|
||||
rtc_update_irq(rtc->rtc_dev, 1, RTC_UF | RTC_IRQF);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int cpcap_rtc_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct cpcap_rtc *rtc;
|
||||
int err;
|
||||
|
||||
rtc = devm_kzalloc(dev, sizeof(*rtc), GFP_KERNEL);
|
||||
if (!rtc)
|
||||
return -ENOMEM;
|
||||
|
||||
rtc->regmap = dev_get_regmap(dev->parent, NULL);
|
||||
if (!rtc->regmap)
|
||||
return -ENODEV;
|
||||
|
||||
platform_set_drvdata(pdev, rtc);
|
||||
rtc->rtc_dev = devm_rtc_device_register(dev, "cpcap_rtc",
|
||||
&cpcap_rtc_ops, THIS_MODULE);
|
||||
|
||||
if (IS_ERR(rtc->rtc_dev))
|
||||
return PTR_ERR(rtc->rtc_dev);
|
||||
|
||||
err = cpcap_get_vendor(dev, rtc->regmap, &rtc->vendor);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
rtc->alarm_irq = platform_get_irq(pdev, 0);
|
||||
err = devm_request_threaded_irq(dev, rtc->alarm_irq, NULL,
|
||||
cpcap_rtc_alarm_irq, IRQF_TRIGGER_NONE,
|
||||
"rtc_alarm", rtc);
|
||||
if (err) {
|
||||
dev_err(dev, "Could not request alarm irq: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
disable_irq(rtc->alarm_irq);
|
||||
|
||||
/* Stock Android uses the 1 Hz interrupt for "secure clock daemon",
|
||||
* which is not supported by the mainline kernel. The mainline kernel
|
||||
* does not use the irq at the moment, but we explicitly request and
|
||||
* disable it, so that its masked and does not wake up the processor
|
||||
* every second.
|
||||
*/
|
||||
rtc->update_irq = platform_get_irq(pdev, 1);
|
||||
err = devm_request_threaded_irq(dev, rtc->update_irq, NULL,
|
||||
cpcap_rtc_update_irq, IRQF_TRIGGER_NONE,
|
||||
"rtc_1hz", rtc);
|
||||
if (err) {
|
||||
dev_err(dev, "Could not request update irq: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
disable_irq(rtc->update_irq);
|
||||
|
||||
err = device_init_wakeup(dev, 1);
|
||||
if (err) {
|
||||
dev_err(dev, "wakeup initialization failed (%d)\n", err);
|
||||
/* ignore error and continue without wakeup support */
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id cpcap_rtc_of_match[] = {
|
||||
{ .compatible = "motorola,cpcap-rtc", },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, cpcap_rtc_of_match);
|
||||
|
||||
static struct platform_driver cpcap_rtc_driver = {
|
||||
.probe = cpcap_rtc_probe,
|
||||
.driver = {
|
||||
.name = "cpcap-rtc",
|
||||
.of_match_table = cpcap_rtc_of_match,
|
||||
},
|
||||
};
|
||||
|
||||
module_platform_driver(cpcap_rtc_driver);
|
||||
|
||||
MODULE_ALIAS("platform:cpcap-rtc");
|
||||
MODULE_DESCRIPTION("CPCAP RTC driver");
|
||||
MODULE_AUTHOR("Sebastian Reichel <sre@kernel.org>");
|
||||
MODULE_LICENSE("GPL");
|
|
@ -16,6 +16,7 @@
|
|||
#include <linux/i2c.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/rtc/ds1307.h>
|
||||
#include <linux/rtc.h>
|
||||
#include <linux/slab.h>
|
||||
|
@ -38,6 +39,7 @@ enum ds_type {
|
|||
ds_1340,
|
||||
ds_1388,
|
||||
ds_3231,
|
||||
m41t0,
|
||||
m41t00,
|
||||
mcp794xx,
|
||||
rx_8025,
|
||||
|
@ -52,6 +54,7 @@ enum ds_type {
|
|||
# define DS1340_BIT_nEOSC 0x80
|
||||
# define MCP794XX_BIT_ST 0x80
|
||||
#define DS1307_REG_MIN 0x01 /* 00-59 */
|
||||
# define M41T0_BIT_OF 0x80
|
||||
#define DS1307_REG_HOUR 0x02 /* 00-23, or 1-12{am,pm} */
|
||||
# define DS1307_BIT_12HR 0x40 /* in REG_HOUR */
|
||||
# define DS1307_BIT_PM 0x20 /* in REG_HOUR */
|
||||
|
@ -182,6 +185,7 @@ static const struct i2c_device_id ds1307_id[] = {
|
|||
{ "ds1388", ds_1388 },
|
||||
{ "ds1340", ds_1340 },
|
||||
{ "ds3231", ds_3231 },
|
||||
{ "m41t0", m41t0 },
|
||||
{ "m41t00", m41t00 },
|
||||
{ "mcp7940x", mcp794xx },
|
||||
{ "mcp7941x", mcp794xx },
|
||||
|
@ -192,6 +196,69 @@ static const struct i2c_device_id ds1307_id[] = {
|
|||
};
|
||||
MODULE_DEVICE_TABLE(i2c, ds1307_id);
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static const struct of_device_id ds1307_of_match[] = {
|
||||
{
|
||||
.compatible = "dallas,ds1307",
|
||||
.data = (void *)ds_1307
|
||||
},
|
||||
{
|
||||
.compatible = "dallas,ds1337",
|
||||
.data = (void *)ds_1337
|
||||
},
|
||||
{
|
||||
.compatible = "dallas,ds1338",
|
||||
.data = (void *)ds_1338
|
||||
},
|
||||
{
|
||||
.compatible = "dallas,ds1339",
|
||||
.data = (void *)ds_1339
|
||||
},
|
||||
{
|
||||
.compatible = "dallas,ds1388",
|
||||
.data = (void *)ds_1388
|
||||
},
|
||||
{
|
||||
.compatible = "dallas,ds1340",
|
||||
.data = (void *)ds_1340
|
||||
},
|
||||
{
|
||||
.compatible = "maxim,ds3231",
|
||||
.data = (void *)ds_3231
|
||||
},
|
||||
{
|
||||
.compatible = "st,m41t0",
|
||||
.data = (void *)m41t00
|
||||
},
|
||||
{
|
||||
.compatible = "st,m41t00",
|
||||
.data = (void *)m41t00
|
||||
},
|
||||
{
|
||||
.compatible = "microchip,mcp7940x",
|
||||
.data = (void *)mcp794xx
|
||||
},
|
||||
{
|
||||
.compatible = "microchip,mcp7941x",
|
||||
.data = (void *)mcp794xx
|
||||
},
|
||||
{
|
||||
.compatible = "pericom,pt7c4338",
|
||||
.data = (void *)ds_1307
|
||||
},
|
||||
{
|
||||
.compatible = "epson,rx8025",
|
||||
.data = (void *)rx_8025
|
||||
},
|
||||
{
|
||||
.compatible = "isil,isl12057",
|
||||
.data = (void *)ds_1337
|
||||
},
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, ds1307_of_match);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
static const struct acpi_device_id ds1307_acpi_ids[] = {
|
||||
{ .id = "DS1307", .driver_data = ds_1307 },
|
||||
|
@ -201,6 +268,7 @@ static const struct acpi_device_id ds1307_acpi_ids[] = {
|
|||
{ .id = "DS1388", .driver_data = ds_1388 },
|
||||
{ .id = "DS1340", .driver_data = ds_1340 },
|
||||
{ .id = "DS3231", .driver_data = ds_3231 },
|
||||
{ .id = "M41T0", .driver_data = m41t0 },
|
||||
{ .id = "M41T00", .driver_data = m41t00 },
|
||||
{ .id = "MCP7940X", .driver_data = mcp794xx },
|
||||
{ .id = "MCP7941X", .driver_data = mcp794xx },
|
||||
|
@ -396,6 +464,13 @@ static int ds1307_get_time(struct device *dev, struct rtc_time *t)
|
|||
|
||||
dev_dbg(dev, "%s: %7ph\n", "read", ds1307->regs);
|
||||
|
||||
/* if oscillator fail bit is set, no data can be trusted */
|
||||
if (ds1307->type == m41t0 &&
|
||||
ds1307->regs[DS1307_REG_MIN] & M41T0_BIT_OF) {
|
||||
dev_warn_once(dev, "oscillator failed, set time!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
t->tm_sec = bcd2bin(ds1307->regs[DS1307_REG_SECS] & 0x7f);
|
||||
t->tm_min = bcd2bin(ds1307->regs[DS1307_REG_MIN] & 0x7f);
|
||||
tmp = ds1307->regs[DS1307_REG_HOUR] & 0x3f;
|
||||
|
@ -1318,7 +1393,12 @@ static int ds1307_probe(struct i2c_client *client,
|
|||
i2c_set_clientdata(client, ds1307);
|
||||
|
||||
ds1307->client = client;
|
||||
if (id) {
|
||||
|
||||
if (client->dev.of_node) {
|
||||
ds1307->type = (enum ds_type)
|
||||
of_device_get_match_data(&client->dev);
|
||||
chip = &chips[ds1307->type];
|
||||
} else if (id) {
|
||||
chip = &chips[id->driver_data];
|
||||
ds1307->type = id->driver_data;
|
||||
} else {
|
||||
|
@ -1513,6 +1593,7 @@ static int ds1307_probe(struct i2c_client *client,
|
|||
tmp = ds1307->regs[DS1307_REG_SECS];
|
||||
switch (ds1307->type) {
|
||||
case ds_1307:
|
||||
case m41t0:
|
||||
case m41t00:
|
||||
/* clock halted? turn it on, so clock can tick. */
|
||||
if (tmp & DS1307_BIT_CH) {
|
||||
|
@ -1577,6 +1658,7 @@ static int ds1307_probe(struct i2c_client *client,
|
|||
tmp = ds1307->regs[DS1307_REG_HOUR];
|
||||
switch (ds1307->type) {
|
||||
case ds_1340:
|
||||
case m41t0:
|
||||
case m41t00:
|
||||
/*
|
||||
* NOTE: ignores century bits; fix before deploying
|
||||
|
@ -1711,6 +1793,7 @@ static int ds1307_remove(struct i2c_client *client)
|
|||
static struct i2c_driver ds1307_driver = {
|
||||
.driver = {
|
||||
.name = "rtc-ds1307",
|
||||
.of_match_table = of_match_ptr(ds1307_of_match),
|
||||
.acpi_match_table = ACPI_PTR(ds1307_acpi_ids),
|
||||
},
|
||||
.probe = ds1307_probe,
|
||||
|
|
|
@ -525,6 +525,10 @@ static long ds1374_wdt_ioctl(struct file *file, unsigned int cmd,
|
|||
if (get_user(new_margin, (int __user *)arg))
|
||||
return -EFAULT;
|
||||
|
||||
/* the hardware's tick rate is 4096 Hz, so
|
||||
* the counter value needs to be scaled accordingly
|
||||
*/
|
||||
new_margin <<= 12;
|
||||
if (new_margin < 1 || new_margin > 16777216)
|
||||
return -EINVAL;
|
||||
|
||||
|
@ -533,7 +537,8 @@ static long ds1374_wdt_ioctl(struct file *file, unsigned int cmd,
|
|||
ds1374_wdt_ping();
|
||||
/* fallthrough */
|
||||
case WDIOC_GETTIMEOUT:
|
||||
return put_user(wdt_margin, (int __user *)arg);
|
||||
/* when returning ... inverse is true */
|
||||
return put_user((wdt_margin >> 12), (int __user *)arg);
|
||||
case WDIOC_SETOPTIONS:
|
||||
if (copy_from_user(&options, (int __user *)arg, sizeof(int)))
|
||||
return -EFAULT;
|
||||
|
@ -541,14 +546,15 @@ static long ds1374_wdt_ioctl(struct file *file, unsigned int cmd,
|
|||
if (options & WDIOS_DISABLECARD) {
|
||||
pr_info("disable watchdog\n");
|
||||
ds1374_wdt_disable();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (options & WDIOS_ENABLECARD) {
|
||||
pr_info("enable watchdog\n");
|
||||
ds1374_wdt_settimeout(wdt_margin);
|
||||
ds1374_wdt_ping();
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
return -ENOTTY;
|
||||
|
@ -704,6 +710,7 @@ static SIMPLE_DEV_PM_OPS(ds1374_pm, ds1374_suspend, ds1374_resume);
|
|||
static struct i2c_driver ds1374_driver = {
|
||||
.driver = {
|
||||
.name = "rtc-ds1374",
|
||||
.of_match_table = of_match_ptr(ds1374_of_match),
|
||||
.pm = &ds1374_pm,
|
||||
},
|
||||
.probe = ds1374_probe,
|
||||
|
|
|
@ -196,10 +196,17 @@ static struct i2c_device_id ds1672_id[] = {
|
|||
};
|
||||
MODULE_DEVICE_TABLE(i2c, ds1672_id);
|
||||
|
||||
static const struct of_device_id ds1672_of_match[] = {
|
||||
{ .compatible = "dallas,ds1672" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, ds1672_of_match);
|
||||
|
||||
static struct i2c_driver ds1672_driver = {
|
||||
.driver = {
|
||||
.name = "rtc-ds1672",
|
||||
},
|
||||
.of_match_table = of_match_ptr(ds1672_of_match),
|
||||
},
|
||||
.probe = &ds1672_probe,
|
||||
.id_table = ds1672_id,
|
||||
};
|
||||
|
|
|
@ -442,9 +442,16 @@ static const struct i2c_device_id ds3232_id[] = {
|
|||
};
|
||||
MODULE_DEVICE_TABLE(i2c, ds3232_id);
|
||||
|
||||
static const struct of_device_id ds3232_of_match[] = {
|
||||
{ .compatible = "dallas,ds3232" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, ds3232_of_match);
|
||||
|
||||
static struct i2c_driver ds3232_driver = {
|
||||
.driver = {
|
||||
.name = "rtc-ds3232",
|
||||
.of_match_table = of_match_ptr(ds3232_of_match),
|
||||
.pm = &ds3232_pm_ops,
|
||||
},
|
||||
.probe = ds3232_i2c_probe,
|
||||
|
|
|
@ -139,6 +139,8 @@ static int gemini_rtc_probe(struct platform_device *pdev)
|
|||
|
||||
rtc->rtc_base = devm_ioremap(dev, res->start,
|
||||
resource_size(res));
|
||||
if (!rtc->rtc_base)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = devm_request_irq(dev, rtc->rtc_irq, gemini_rtc_interrupt,
|
||||
IRQF_SHARED, pdev->name, dev);
|
||||
|
|
|
@ -291,9 +291,9 @@ static int hid_time_probe(struct platform_device *pdev)
|
|||
"hid-sensor-time", &hid_time_rtc_ops,
|
||||
THIS_MODULE);
|
||||
|
||||
if (IS_ERR_OR_NULL(time_state->rtc)) {
|
||||
if (IS_ERR(time_state->rtc)) {
|
||||
hid_device_io_stop(hsdev->hdev);
|
||||
ret = time_state->rtc ? PTR_ERR(time_state->rtc) : -ENODEV;
|
||||
ret = PTR_ERR(time_state->rtc);
|
||||
time_state->rtc = NULL;
|
||||
dev_err(&pdev->dev, "rtc device register failed!\n");
|
||||
goto err_rtc;
|
||||
|
|
|
@ -687,10 +687,18 @@ static const struct i2c_device_id isl1208_id[] = {
|
|||
};
|
||||
MODULE_DEVICE_TABLE(i2c, isl1208_id);
|
||||
|
||||
static const struct of_device_id isl1208_of_match[] = {
|
||||
{ .compatible = "isil,isl1208" },
|
||||
{ .compatible = "isil,isl1218" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, isl1208_of_match);
|
||||
|
||||
static struct i2c_driver isl1208_driver = {
|
||||
.driver = {
|
||||
.name = "rtc-isl1208",
|
||||
},
|
||||
.name = "rtc-isl1208",
|
||||
.of_match_table = of_match_ptr(isl1208_of_match),
|
||||
},
|
||||
.probe = isl1208_probe,
|
||||
.remove = isl1208_remove,
|
||||
.id_table = isl1208_id,
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/rtc.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/mutex.h>
|
||||
|
@ -86,8 +87,66 @@ static const struct i2c_device_id m41t80_id[] = {
|
|||
};
|
||||
MODULE_DEVICE_TABLE(i2c, m41t80_id);
|
||||
|
||||
static const struct of_device_id m41t80_of_match[] = {
|
||||
{
|
||||
.compatible = "st,m41t62",
|
||||
.data = (void *)(M41T80_FEATURE_SQ | M41T80_FEATURE_SQ_ALT)
|
||||
},
|
||||
{
|
||||
.compatible = "st,m41t65",
|
||||
.data = (void *)(M41T80_FEATURE_HT | M41T80_FEATURE_WD)
|
||||
},
|
||||
{
|
||||
.compatible = "st,m41t80",
|
||||
.data = (void *)(M41T80_FEATURE_SQ)
|
||||
},
|
||||
{
|
||||
.compatible = "st,m41t81",
|
||||
.data = (void *)(M41T80_FEATURE_HT | M41T80_FEATURE_SQ)
|
||||
},
|
||||
{
|
||||
.compatible = "st,m41t81s",
|
||||
.data = (void *)(M41T80_FEATURE_HT | M41T80_FEATURE_BL | M41T80_FEATURE_SQ)
|
||||
},
|
||||
{
|
||||
.compatible = "st,m41t82",
|
||||
.data = (void *)(M41T80_FEATURE_HT | M41T80_FEATURE_BL | M41T80_FEATURE_SQ)
|
||||
},
|
||||
{
|
||||
.compatible = "st,m41t83",
|
||||
.data = (void *)(M41T80_FEATURE_HT | M41T80_FEATURE_BL | M41T80_FEATURE_SQ)
|
||||
},
|
||||
{
|
||||
.compatible = "st,m41t84",
|
||||
.data = (void *)(M41T80_FEATURE_HT | M41T80_FEATURE_BL | M41T80_FEATURE_SQ)
|
||||
},
|
||||
{
|
||||
.compatible = "st,m41t85",
|
||||
.data = (void *)(M41T80_FEATURE_HT | M41T80_FEATURE_BL | M41T80_FEATURE_SQ)
|
||||
},
|
||||
{
|
||||
.compatible = "st,m41t87",
|
||||
.data = (void *)(M41T80_FEATURE_HT | M41T80_FEATURE_BL | M41T80_FEATURE_SQ)
|
||||
},
|
||||
{
|
||||
.compatible = "microcrystal,rv4162",
|
||||
.data = (void *)(M41T80_FEATURE_SQ | M41T80_FEATURE_WD | M41T80_FEATURE_SQ_ALT)
|
||||
},
|
||||
/* DT compatibility only, do not use compatibles below: */
|
||||
{
|
||||
.compatible = "st,rv4162",
|
||||
.data = (void *)(M41T80_FEATURE_SQ | M41T80_FEATURE_WD | M41T80_FEATURE_SQ_ALT)
|
||||
},
|
||||
{
|
||||
.compatible = "rv4162",
|
||||
.data = (void *)(M41T80_FEATURE_SQ | M41T80_FEATURE_WD | M41T80_FEATURE_SQ_ALT)
|
||||
},
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, m41t80_of_match);
|
||||
|
||||
struct m41t80_data {
|
||||
u8 features;
|
||||
unsigned long features;
|
||||
struct rtc_device *rtc;
|
||||
};
|
||||
|
||||
|
@ -786,7 +845,11 @@ static int m41t80_probe(struct i2c_client *client,
|
|||
if (!m41t80_data)
|
||||
return -ENOMEM;
|
||||
|
||||
m41t80_data->features = id->driver_data;
|
||||
if (client->dev.of_node)
|
||||
m41t80_data->features = (unsigned long)
|
||||
of_device_get_match_data(&client->dev);
|
||||
else
|
||||
m41t80_data->features = id->driver_data;
|
||||
i2c_set_clientdata(client, m41t80_data);
|
||||
|
||||
if (client->irq > 0) {
|
||||
|
@ -894,6 +957,7 @@ static int m41t80_remove(struct i2c_client *client)
|
|||
static struct i2c_driver m41t80_driver = {
|
||||
.driver = {
|
||||
.name = "rtc-m41t80",
|
||||
.of_match_table = of_match_ptr(m41t80_of_match),
|
||||
.pm = &m41t80_pm,
|
||||
},
|
||||
.probe = m41t80_probe,
|
||||
|
|
|
@ -844,7 +844,7 @@ static int omap_rtc_probe(struct platform_device *pdev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int __exit omap_rtc_remove(struct platform_device *pdev)
|
||||
static int omap_rtc_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct omap_rtc *rtc = platform_get_drvdata(pdev);
|
||||
u8 reg;
|
||||
|
@ -882,8 +882,7 @@ static int __exit omap_rtc_remove(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int omap_rtc_suspend(struct device *dev)
|
||||
static int __maybe_unused omap_rtc_suspend(struct device *dev)
|
||||
{
|
||||
struct omap_rtc *rtc = dev_get_drvdata(dev);
|
||||
|
||||
|
@ -906,7 +905,7 @@ static int omap_rtc_suspend(struct device *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int omap_rtc_resume(struct device *dev)
|
||||
static int __maybe_unused omap_rtc_resume(struct device *dev)
|
||||
{
|
||||
struct omap_rtc *rtc = dev_get_drvdata(dev);
|
||||
|
||||
|
@ -921,10 +920,8 @@ static int omap_rtc_resume(struct device *dev)
|
|||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int omap_rtc_runtime_suspend(struct device *dev)
|
||||
static int __maybe_unused omap_rtc_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct omap_rtc *rtc = dev_get_drvdata(dev);
|
||||
|
||||
|
@ -934,16 +931,9 @@ static int omap_rtc_runtime_suspend(struct device *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int omap_rtc_runtime_resume(struct device *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const struct dev_pm_ops omap_rtc_pm_ops = {
|
||||
SET_SYSTEM_SLEEP_PM_OPS(omap_rtc_suspend, omap_rtc_resume)
|
||||
SET_RUNTIME_PM_OPS(omap_rtc_runtime_suspend,
|
||||
omap_rtc_runtime_resume, NULL)
|
||||
SET_RUNTIME_PM_OPS(omap_rtc_runtime_suspend, NULL, NULL)
|
||||
};
|
||||
|
||||
static void omap_rtc_shutdown(struct platform_device *pdev)
|
||||
|
@ -964,7 +954,7 @@ static void omap_rtc_shutdown(struct platform_device *pdev)
|
|||
|
||||
static struct platform_driver omap_rtc_driver = {
|
||||
.probe = omap_rtc_probe,
|
||||
.remove = __exit_p(omap_rtc_remove),
|
||||
.remove = omap_rtc_remove,
|
||||
.shutdown = omap_rtc_shutdown,
|
||||
.driver = {
|
||||
.name = "omap_rtc",
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include <linux/bcd.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
|
||||
/*
|
||||
* Ricoh has a family of I2C based RTCs, which differ only slightly from
|
||||
|
@ -83,6 +84,35 @@ static const struct i2c_device_id rs5c372_id[] = {
|
|||
};
|
||||
MODULE_DEVICE_TABLE(i2c, rs5c372_id);
|
||||
|
||||
static const struct of_device_id rs5c372_of_match[] = {
|
||||
{
|
||||
.compatible = "ricoh,r2025sd",
|
||||
.data = (void *)rtc_r2025sd
|
||||
},
|
||||
{
|
||||
.compatible = "ricoh,r2221tl",
|
||||
.data = (void *)rtc_r2221tl
|
||||
},
|
||||
{
|
||||
.compatible = "ricoh,rs5c372a",
|
||||
.data = (void *)rtc_rs5c372a
|
||||
},
|
||||
{
|
||||
.compatible = "ricoh,rs5c372b",
|
||||
.data = (void *)rtc_rs5c372b
|
||||
},
|
||||
{
|
||||
.compatible = "ricoh,rv5c386",
|
||||
.data = (void *)rtc_rv5c386
|
||||
},
|
||||
{
|
||||
.compatible = "ricoh,rv5c387a",
|
||||
.data = (void *)rtc_rv5c387a
|
||||
},
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, rs5c372_of_match);
|
||||
|
||||
/* REVISIT: this assumes that:
|
||||
* - we're in the 21st century, so it's safe to ignore the century
|
||||
* bit for rv5c38[67] (REG_MONTH bit 7);
|
||||
|
@ -581,7 +611,11 @@ static int rs5c372_probe(struct i2c_client *client,
|
|||
|
||||
rs5c372->client = client;
|
||||
i2c_set_clientdata(client, rs5c372);
|
||||
rs5c372->type = id->driver_data;
|
||||
if (client->dev.of_node)
|
||||
rs5c372->type = (enum rtc_type)
|
||||
of_device_get_match_data(&client->dev);
|
||||
else
|
||||
rs5c372->type = id->driver_data;
|
||||
|
||||
/* we read registers 0x0f then 0x00-0x0f; skip the first one */
|
||||
rs5c372->regs = &rs5c372->buf[1];
|
||||
|
@ -673,6 +707,7 @@ static int rs5c372_remove(struct i2c_client *client)
|
|||
static struct i2c_driver rs5c372_driver = {
|
||||
.driver = {
|
||||
.name = "rtc-rs5c372",
|
||||
.of_match_table = of_match_ptr(rs5c372_of_match),
|
||||
},
|
||||
.probe = rs5c372_probe,
|
||||
.remove = rs5c372_remove,
|
||||
|
|
|
@ -875,9 +875,18 @@ static struct i2c_device_id rv3029_id[] = {
|
|||
};
|
||||
MODULE_DEVICE_TABLE(i2c, rv3029_id);
|
||||
|
||||
static const struct of_device_id rv3029_of_match[] = {
|
||||
{ .compatible = "rv3029" },
|
||||
{ .compatible = "rv3029c2" },
|
||||
{ .compatible = "mc,rv3029c2" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, rv3029_of_match);
|
||||
|
||||
static struct i2c_driver rv3029_driver = {
|
||||
.driver = {
|
||||
.name = "rtc-rv3029c2",
|
||||
.of_match_table = of_match_ptr(rv3029_of_match),
|
||||
},
|
||||
.probe = rv3029_i2c_probe,
|
||||
.id_table = rv3029_id,
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <linux/interrupt.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/rtc.h>
|
||||
|
||||
#define RV8803_I2C_TRY_COUNT 4
|
||||
|
@ -556,7 +557,11 @@ static int rv8803_probe(struct i2c_client *client,
|
|||
|
||||
mutex_init(&rv8803->flags_lock);
|
||||
rv8803->client = client;
|
||||
rv8803->type = id->driver_data;
|
||||
if (client->dev.of_node)
|
||||
rv8803->type = (enum rv8803_type)
|
||||
of_device_get_match_data(&client->dev);
|
||||
else
|
||||
rv8803->type = id->driver_data;
|
||||
i2c_set_clientdata(client, rv8803);
|
||||
|
||||
flags = rv8803_read_reg(client, RV8803_FLAG);
|
||||
|
@ -627,9 +632,23 @@ static const struct i2c_device_id rv8803_id[] = {
|
|||
};
|
||||
MODULE_DEVICE_TABLE(i2c, rv8803_id);
|
||||
|
||||
static const struct of_device_id rv8803_of_match[] = {
|
||||
{
|
||||
.compatible = "microcrystal,rv8803",
|
||||
.data = (void *)rx_8900
|
||||
},
|
||||
{
|
||||
.compatible = "epson,rx8900",
|
||||
.data = (void *)rx_8900
|
||||
},
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, rv8803_of_match);
|
||||
|
||||
static struct i2c_driver rv8803_driver = {
|
||||
.driver = {
|
||||
.name = "rtc-rv8803",
|
||||
.of_match_table = of_match_ptr(rv8803_of_match),
|
||||
},
|
||||
.probe = rv8803_probe,
|
||||
.remove = rv8803_remove,
|
||||
|
|
|
@ -59,6 +59,12 @@ static const struct i2c_device_id rx8010_id[] = {
|
|||
};
|
||||
MODULE_DEVICE_TABLE(i2c, rx8010_id);
|
||||
|
||||
static const struct of_device_id rx8010_of_match[] = {
|
||||
{ .compatible = "epson,rx8010" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, rx8010_of_match);
|
||||
|
||||
struct rx8010_data {
|
||||
struct i2c_client *client;
|
||||
struct rtc_device *rtc;
|
||||
|
@ -487,6 +493,7 @@ static int rx8010_probe(struct i2c_client *client,
|
|||
static struct i2c_driver rx8010_driver = {
|
||||
.driver = {
|
||||
.name = "rtc-rx8010",
|
||||
.of_match_table = of_match_ptr(rx8010_of_match),
|
||||
},
|
||||
.probe = rx8010_probe,
|
||||
.id_table = rx8010_id,
|
||||
|
|
|
@ -308,9 +308,16 @@ static const struct i2c_device_id rx8581_id[] = {
|
|||
};
|
||||
MODULE_DEVICE_TABLE(i2c, rx8581_id);
|
||||
|
||||
static const struct of_device_id rx8581_of_match[] = {
|
||||
{ .compatible = "epson,rx8581" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, rx8581_of_match);
|
||||
|
||||
static struct i2c_driver rx8581_driver = {
|
||||
.driver = {
|
||||
.name = "rtc-rx8581",
|
||||
.of_match_table = of_match_ptr(rx8581_of_match),
|
||||
},
|
||||
.probe = rx8581_probe,
|
||||
.id_table = rx8581_id,
|
||||
|
|
|
@ -58,6 +58,13 @@ static const struct i2c_device_id s35390a_id[] = {
|
|||
};
|
||||
MODULE_DEVICE_TABLE(i2c, s35390a_id);
|
||||
|
||||
static const struct of_device_id s35390a_of_match[] = {
|
||||
{ .compatible = "s35390a" },
|
||||
{ .compatible = "sii,s35390a" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, s35390a_of_match);
|
||||
|
||||
struct s35390a {
|
||||
struct i2c_client *client[8];
|
||||
struct rtc_device *rtc;
|
||||
|
@ -502,6 +509,7 @@ static int s35390a_remove(struct i2c_client *client)
|
|||
static struct i2c_driver s35390a_driver = {
|
||||
.driver = {
|
||||
.name = "rtc-s35390a",
|
||||
.of_match_table = of_match_ptr(s35390a_of_match),
|
||||
},
|
||||
.probe = s35390a_probe,
|
||||
.remove = s35390a_remove,
|
||||
|
|
|
@ -27,7 +27,15 @@
|
|||
#include <linux/log2.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/slab.h>
|
||||
#ifdef CONFIG_SUPERH
|
||||
#include <asm/rtc.h>
|
||||
#else
|
||||
/* Default values for RZ/A RTC */
|
||||
#define rtc_reg_size sizeof(u16)
|
||||
#define RTC_BIT_INVERTED 0 /* no chip bugs */
|
||||
#define RTC_CAP_4_DIGIT_YEAR (1 << 0)
|
||||
#define RTC_DEF_CAPABILITIES RTC_CAP_4_DIGIT_YEAR
|
||||
#endif
|
||||
|
||||
#define DRV_NAME "sh-rtc"
|
||||
|
||||
|
@ -570,6 +578,8 @@ static int __init sh_rtc_probe(struct platform_device *pdev)
|
|||
rtc->alarm_irq = platform_get_irq(pdev, 2);
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_IO, 0);
|
||||
if (!res)
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (unlikely(res == NULL)) {
|
||||
dev_err(&pdev->dev, "No IO resource\n");
|
||||
return -ENOENT;
|
||||
|
@ -587,12 +597,15 @@ static int __init sh_rtc_probe(struct platform_device *pdev)
|
|||
if (unlikely(!rtc->regbase))
|
||||
return -EINVAL;
|
||||
|
||||
clk_id = pdev->id;
|
||||
/* With a single device, the clock id is still "rtc0" */
|
||||
if (clk_id < 0)
|
||||
clk_id = 0;
|
||||
if (!pdev->dev.of_node) {
|
||||
clk_id = pdev->id;
|
||||
/* With a single device, the clock id is still "rtc0" */
|
||||
if (clk_id < 0)
|
||||
clk_id = 0;
|
||||
|
||||
snprintf(clk_name, sizeof(clk_name), "rtc%d", clk_id);
|
||||
snprintf(clk_name, sizeof(clk_name), "rtc%d", clk_id);
|
||||
} else
|
||||
snprintf(clk_name, sizeof(clk_name), "fck");
|
||||
|
||||
rtc->clk = devm_clk_get(&pdev->dev, clk_name);
|
||||
if (IS_ERR(rtc->clk)) {
|
||||
|
@ -608,6 +621,8 @@ static int __init sh_rtc_probe(struct platform_device *pdev)
|
|||
clk_enable(rtc->clk);
|
||||
|
||||
rtc->capabilities = RTC_DEF_CAPABILITIES;
|
||||
|
||||
#ifdef CONFIG_SUPERH
|
||||
if (dev_get_platdata(&pdev->dev)) {
|
||||
struct sh_rtc_platform_info *pinfo =
|
||||
dev_get_platdata(&pdev->dev);
|
||||
|
@ -618,6 +633,7 @@ static int __init sh_rtc_probe(struct platform_device *pdev)
|
|||
*/
|
||||
rtc->capabilities |= pinfo->capabilities;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (rtc->carry_irq <= 0) {
|
||||
/* register shared periodic/carry/alarm irq */
|
||||
|
@ -718,8 +734,7 @@ static void sh_rtc_set_irq_wake(struct device *dev, int enabled)
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int sh_rtc_suspend(struct device *dev)
|
||||
static int __maybe_unused sh_rtc_suspend(struct device *dev)
|
||||
{
|
||||
if (device_may_wakeup(dev))
|
||||
sh_rtc_set_irq_wake(dev, 1);
|
||||
|
@ -727,21 +742,27 @@ static int sh_rtc_suspend(struct device *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int sh_rtc_resume(struct device *dev)
|
||||
static int __maybe_unused sh_rtc_resume(struct device *dev)
|
||||
{
|
||||
if (device_may_wakeup(dev))
|
||||
sh_rtc_set_irq_wake(dev, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(sh_rtc_pm_ops, sh_rtc_suspend, sh_rtc_resume);
|
||||
|
||||
static const struct of_device_id sh_rtc_of_match[] = {
|
||||
{ .compatible = "renesas,sh-rtc", },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, sh_rtc_of_match);
|
||||
|
||||
static struct platform_driver sh_rtc_platform_driver = {
|
||||
.driver = {
|
||||
.name = DRV_NAME,
|
||||
.pm = &sh_rtc_pm_ops,
|
||||
.of_match_table = sh_rtc_of_match,
|
||||
},
|
||||
.remove = __exit_p(sh_rtc_remove),
|
||||
};
|
||||
|
|
|
@ -258,7 +258,7 @@ static int snvs_rtc_probe(struct platform_device *pdev)
|
|||
of_property_read_u32(pdev->dev.of_node, "offset", &data->offset);
|
||||
}
|
||||
|
||||
if (!data->regmap) {
|
||||
if (IS_ERR(data->regmap)) {
|
||||
dev_err(&pdev->dev, "Can't find snvs syscon\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
|
|
@ -30,8 +30,6 @@
|
|||
#define WM8350_SET_TIME_RETRIES 5
|
||||
#define WM8350_GET_TIME_RETRIES 5
|
||||
|
||||
#define to_wm8350_from_rtc_dev(d) container_of(d, struct wm8350, rtc.pdev.dev)
|
||||
|
||||
/*
|
||||
* Read current time and date in RTC
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue