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:
Linus Torvalds
2017-05-10 19:37:14 -07:00
28 changed files with 721 additions and 46 deletions
@@ -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.
+1
View File
@@ -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)
{
+9 -2
View File
@@ -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
+1
View File
@@ -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
+7
View File
@@ -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,
+13 -4
View File
@@ -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)
+330
View File
@@ -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");
+84 -1
View File
@@ -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 @@ read_rtc:
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 @@ read_rtc:
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,
+9 -2
View File
@@ -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,
+8 -1
View File
@@ -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,
};
+7
View File
@@ -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,
+2
View File
@@ -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);
+2 -2
View File
@@ -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;
+10 -2
View File
@@ -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,
+66 -2
View File
@@ -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,
+6 -16
View File
@@ -844,7 +844,7 @@ err:
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",
+36 -1
View File
@@ -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,
+9
View File
@@ -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,
+20 -1
View File
@@ -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,
+7
View File
@@ -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,
+7
View File
@@ -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,
+8
View File
@@ -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,
+30 -9
View File
@@ -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),
};
+1 -1
View File
@@ -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;
}
-2
View File
@@ -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
*/