RTC for 5.8

Subsystem:
  - new VL flag for backup switch over
 
 Drivers:
  - ingenic: only support device tree
  - pcf2127: report battery switch over, handle nowayout
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEycoQi/giopmpPgB12wIijOdRNOUFAl7dWSkACgkQ2wIijOdR
 NOXGbQ//cSTxUJbuYBNi/VCV7J3/khGlyoQQqDsru/tzuEwXHGBoG2LRNQMOauWd
 2Osg61VQj4IY+WCqp4+ivn5H0K26y1PPKkt+UmrlRgkl0eeDFWmY4ejpziZ85D7Z
 kDlzcUi3YWkd6m4YSJJrtdCcKljBMIEXb/PEKKK9y6dkrcG5990N8JchpmkCzrjx
 fTPVIOfxu43msDc5b8egUDzPYnNbFw3ERAeasr6/EGTz+ksCspXtvWDk/mJzum0G
 FiermTkO499Dr66Nf0AS3ex9SvEoqH+kd9KA1CKii5OlYEl7K9sI+eSmTQ1EutZO
 L5WAvvQdW8UkARo6R4HAobhwK27pL+wpzUljbyXxt940/RTeqp82kl7rnH+0ihU7
 tTbR2Vu+uwWrfQbPkCCj0TJmqIHgam5/Vhn1+ZR2f4U2JIlPvvHoLRVKO0oP7XKK
 1ZDcP8zc9V2LQ2G2M1/ec6eOmoGW3EZDnKp4hcv9mnEiePSvVn04t5sa83NjNs4R
 e+awVY1x5pFwoXu99gjlfQTV2kTyaA7Jywp6gIO7BKaw/Ci3+d3tlpowfsDH+UVI
 WwKxNNqmuNXqoIep0zqUhqXHNIizKxGEk8wE4mr8HP2SlGJ+lUHAyrTTdpLeinN1
 5qTEPT3BhjExSFfDZQyWV3+CzKMvxtfFA4/Ca/0iSoaqzMZpm1E=
 =dsKr
 -----END PGP SIGNATURE-----

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

Pull RTC updates from Alexandre Belloni:
 "Not much this cycle apart from the ingenic rtc driver rework.

  The fixes are mainly minor issues reported by coccinelle rather than
  real world issues.

  Subsystem:

   - new VL flag for backup switch over

  Drivers:

   - ingenic: only support device tree

   - pcf2127: report battery switch over, handle nowayout"

* tag 'rtc-5.8' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux: (29 commits)
  rtc: pcf2127: watchdog: handle nowayout feature
  rtc: fsl-ftm-alarm: fix freeze(s2idle) failed to wake
  rtc: abx80x: Provide debug feedback for invalid dt properties
  rtc: abx80x: Add Device Tree matching table
  rtc: rv3028: Add missed check for devm_regmap_init_i2c()
  rtc: mpc5121: Use correct return value for mpc5121_rtc_probe()
  rtc: goldfish: Use correct return value for goldfish_rtc_probe()
  rtc: snvs: Add necessary clock operations for RTC APIs
  rtc: snvs: Make SNVS clock always prepared
  rtc: ingenic: Reset regulator register in probe
  rtc: ingenic: Fix masking of error code
  rtc: ingenic: Remove unused fields from private structure
  rtc: ingenic: Set wakeup params in probe
  rtc: ingenic: Enable clock in probe
  rtc: ingenic: Use local 'dev' variable in probe
  rtc: ingenic: Only support probing from devicetree
  rtc: mc13xxx: fix a double-unlock issue
  rtc: stmp3xxx: update contact email
  rtc: max77686: Use single-byte writes on MAX77620
  rtc: pcf2127: report battery switch over
  ...
This commit is contained in:
Linus Torvalds 2020-06-07 16:11:23 -07:00
commit e8dff03aef
17 changed files with 259 additions and 152 deletions

View File

@ -1680,6 +1680,7 @@ config RTC_DRV_MPC5121
config RTC_DRV_JZ4740 config RTC_DRV_JZ4740
tristate "Ingenic JZ4740 SoC" tristate "Ingenic JZ4740 SoC"
depends on MIPS || COMPILE_TEST depends on MIPS || COMPILE_TEST
depends on OF
help help
If you say yes here you get support for the Ingenic JZ47xx SoCs RTC If you say yes here you get support for the Ingenic JZ47xx SoCs RTC
controllers. controllers.

View File

@ -106,12 +106,6 @@ static int pm860x_rtc_set_time(struct device *dev, struct rtc_time *tm)
unsigned char buf[4]; unsigned char buf[4];
unsigned long ticks, base, data; unsigned long ticks, base, data;
if (tm->tm_year > 206) {
dev_dbg(info->dev, "Set time %d out of range. "
"Please set time between 1970 to 2106.\n",
1900 + tm->tm_year);
return -EINVAL;
}
ticks = rtc_tm_to_time64(tm); ticks = rtc_tm_to_time64(tm);
/* load 32-bit read-only counter */ /* load 32-bit read-only counter */

View File

@ -13,6 +13,7 @@
#include <linux/bcd.h> #include <linux/bcd.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of_device.h>
#include <linux/rtc.h> #include <linux/rtc.h>
#include <linux/watchdog.h> #include <linux/watchdog.h>
@ -554,8 +555,9 @@ static const struct rtc_class_ops abx80x_rtc_ops = {
.ioctl = abx80x_ioctl, .ioctl = abx80x_ioctl,
}; };
static int abx80x_dt_trickle_cfg(struct device_node *np) static int abx80x_dt_trickle_cfg(struct i2c_client *client)
{ {
struct device_node *np = client->dev.of_node;
const char *diode; const char *diode;
int trickle_cfg = 0; int trickle_cfg = 0;
int i, ret; int i, ret;
@ -565,12 +567,14 @@ static int abx80x_dt_trickle_cfg(struct device_node *np)
if (ret) if (ret)
return ret; return ret;
if (!strcmp(diode, "standard")) if (!strcmp(diode, "standard")) {
trickle_cfg |= ABX8XX_TRICKLE_STANDARD_DIODE; trickle_cfg |= ABX8XX_TRICKLE_STANDARD_DIODE;
else if (!strcmp(diode, "schottky")) } else if (!strcmp(diode, "schottky")) {
trickle_cfg |= ABX8XX_TRICKLE_SCHOTTKY_DIODE; trickle_cfg |= ABX8XX_TRICKLE_SCHOTTKY_DIODE;
else } else {
dev_dbg(&client->dev, "Invalid tc-diode value: %s\n", diode);
return -EINVAL; return -EINVAL;
}
ret = of_property_read_u32(np, "abracon,tc-resistor", &tmp); ret = of_property_read_u32(np, "abracon,tc-resistor", &tmp);
if (ret) if (ret)
@ -580,8 +584,10 @@ static int abx80x_dt_trickle_cfg(struct device_node *np)
if (trickle_resistors[i] == tmp) if (trickle_resistors[i] == tmp)
break; break;
if (i == sizeof(trickle_resistors)) if (i == sizeof(trickle_resistors)) {
dev_dbg(&client->dev, "Invalid tc-resistor value: %u\n", tmp);
return -EINVAL; return -EINVAL;
}
return (trickle_cfg | i); return (trickle_cfg | i);
} }
@ -793,7 +799,7 @@ static int abx80x_probe(struct i2c_client *client,
} }
if (np && abx80x_caps[part].has_tc) if (np && abx80x_caps[part].has_tc)
trickle_cfg = abx80x_dt_trickle_cfg(np); trickle_cfg = abx80x_dt_trickle_cfg(client);
if (trickle_cfg > 0) { if (trickle_cfg > 0) {
dev_info(&client->dev, "Enabling trickle charger: %02x\n", dev_info(&client->dev, "Enabling trickle charger: %02x\n",
@ -863,9 +869,57 @@ static const struct i2c_device_id abx80x_id[] = {
}; };
MODULE_DEVICE_TABLE(i2c, abx80x_id); MODULE_DEVICE_TABLE(i2c, abx80x_id);
#ifdef CONFIG_OF
static const struct of_device_id abx80x_of_match[] = {
{
.compatible = "abracon,abx80x",
.data = (void *)ABX80X
},
{
.compatible = "abracon,ab0801",
.data = (void *)AB0801
},
{
.compatible = "abracon,ab0803",
.data = (void *)AB0803
},
{
.compatible = "abracon,ab0804",
.data = (void *)AB0804
},
{
.compatible = "abracon,ab0805",
.data = (void *)AB0805
},
{
.compatible = "abracon,ab1801",
.data = (void *)AB1801
},
{
.compatible = "abracon,ab1803",
.data = (void *)AB1803
},
{
.compatible = "abracon,ab1804",
.data = (void *)AB1804
},
{
.compatible = "abracon,ab1805",
.data = (void *)AB1805
},
{
.compatible = "microcrystal,rv1805",
.data = (void *)RV1805
},
{ }
};
MODULE_DEVICE_TABLE(of, abx80x_of_match);
#endif
static struct i2c_driver abx80x_driver = { static struct i2c_driver abx80x_driver = {
.driver = { .driver = {
.name = "rtc-abx80x", .name = "rtc-abx80x",
.of_match_table = of_match_ptr(abx80x_of_match),
}, },
.probe = abx80x_probe, .probe = abx80x_probe,
.id_table = abx80x_id, .id_table = abx80x_id,

View File

@ -21,6 +21,7 @@
#include <linux/rtc.h> #include <linux/rtc.h>
#include <linux/time.h> #include <linux/time.h>
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/pm_wakeirq.h>
#define FTM_SC_CLK(c) ((c) << FTM_SC_CLK_MASK_SHIFT) #define FTM_SC_CLK(c) ((c) << FTM_SC_CLK_MASK_SHIFT)
@ -268,13 +269,11 @@ static int ftm_rtc_probe(struct platform_device *pdev)
} }
irq = platform_get_irq(pdev, 0); irq = platform_get_irq(pdev, 0);
if (irq < 0) { if (irq < 0)
dev_err(&pdev->dev, "can't get irq number\n");
return irq; return irq;
}
ret = devm_request_irq(&pdev->dev, irq, ftm_rtc_alarm_interrupt, ret = devm_request_irq(&pdev->dev, irq, ftm_rtc_alarm_interrupt,
IRQF_NO_SUSPEND, dev_name(&pdev->dev), rtc); 0, dev_name(&pdev->dev), rtc);
if (ret < 0) { if (ret < 0) {
dev_err(&pdev->dev, "failed to request irq\n"); dev_err(&pdev->dev, "failed to request irq\n");
return ret; return ret;
@ -287,6 +286,9 @@ static int ftm_rtc_probe(struct platform_device *pdev)
rtc->rtc_dev->ops = &ftm_rtc_ops; rtc->rtc_dev->ops = &ftm_rtc_ops;
device_init_wakeup(&pdev->dev, true); device_init_wakeup(&pdev->dev, true);
ret = dev_pm_set_wake_irq(&pdev->dev, irq);
if (ret)
dev_err(&pdev->dev, "failed to enable irq wake\n");
ret = rtc_register_device(rtc->rtc_dev); ret = rtc_register_device(rtc->rtc_dev);
if (ret) { if (ret) {

View File

@ -174,7 +174,7 @@ static int goldfish_rtc_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, rtcdrv); platform_set_drvdata(pdev, rtcdrv);
rtcdrv->base = devm_platform_ioremap_resource(pdev, 0); rtcdrv->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(rtcdrv->base)) if (IS_ERR(rtcdrv->base))
return -ENODEV; return PTR_ERR(rtcdrv->base);
rtcdrv->irq = platform_get_irq(pdev, 0); rtcdrv->irq = platform_get_irq(pdev, 0);
if (rtcdrv->irq < 0) if (rtcdrv->irq < 0)

View File

@ -55,14 +55,8 @@ struct jz4740_rtc {
enum jz4740_rtc_type type; enum jz4740_rtc_type type;
struct rtc_device *rtc; struct rtc_device *rtc;
struct clk *clk;
int irq;
spinlock_t lock; spinlock_t lock;
unsigned int min_wakeup_pin_assert_time;
unsigned int reset_pin_assert_time;
}; };
static struct device *dev_for_power_off; static struct device *dev_for_power_off;
@ -259,44 +253,15 @@ static void jz4740_rtc_poweroff(struct device *dev)
static void jz4740_rtc_power_off(void) static void jz4740_rtc_power_off(void)
{ {
struct jz4740_rtc *rtc = dev_get_drvdata(dev_for_power_off);
unsigned long rtc_rate;
unsigned long wakeup_filter_ticks;
unsigned long reset_counter_ticks;
clk_prepare_enable(rtc->clk);
rtc_rate = clk_get_rate(rtc->clk);
/*
* Set minimum wakeup pin assertion time: 100 ms.
* Range is 0 to 2 sec if RTC is clocked at 32 kHz.
*/
wakeup_filter_ticks =
(rtc->min_wakeup_pin_assert_time * rtc_rate) / 1000;
if (wakeup_filter_ticks < JZ_RTC_WAKEUP_FILTER_MASK)
wakeup_filter_ticks &= JZ_RTC_WAKEUP_FILTER_MASK;
else
wakeup_filter_ticks = JZ_RTC_WAKEUP_FILTER_MASK;
jz4740_rtc_reg_write(rtc,
JZ_REG_RTC_WAKEUP_FILTER, wakeup_filter_ticks);
/*
* Set reset pin low-level assertion time after wakeup: 60 ms.
* Range is 0 to 125 ms if RTC is clocked at 32 kHz.
*/
reset_counter_ticks = (rtc->reset_pin_assert_time * rtc_rate) / 1000;
if (reset_counter_ticks < JZ_RTC_RESET_COUNTER_MASK)
reset_counter_ticks &= JZ_RTC_RESET_COUNTER_MASK;
else
reset_counter_ticks = JZ_RTC_RESET_COUNTER_MASK;
jz4740_rtc_reg_write(rtc,
JZ_REG_RTC_RESET_COUNTER, reset_counter_ticks);
jz4740_rtc_poweroff(dev_for_power_off); jz4740_rtc_poweroff(dev_for_power_off);
kernel_halt(); kernel_halt();
} }
static void jz4740_rtc_clk_disable(void *data)
{
clk_disable_unprepare(data);
}
static const struct of_device_id jz4740_rtc_of_match[] = { static const struct of_device_id jz4740_rtc_of_match[] = {
{ .compatible = "ingenic,jz4740-rtc", .data = (void *)ID_JZ4740 }, { .compatible = "ingenic,jz4740-rtc", .data = (void *)ID_JZ4740 },
{ .compatible = "ingenic,jz4760-rtc", .data = (void *)ID_JZ4760 }, { .compatible = "ingenic,jz4760-rtc", .data = (void *)ID_JZ4760 },
@ -305,110 +270,140 @@ static const struct of_device_id jz4740_rtc_of_match[] = {
}; };
MODULE_DEVICE_TABLE(of, jz4740_rtc_of_match); MODULE_DEVICE_TABLE(of, jz4740_rtc_of_match);
static void jz4740_rtc_set_wakeup_params(struct jz4740_rtc *rtc,
struct device_node *np,
unsigned long rate)
{
unsigned long wakeup_ticks, reset_ticks;
unsigned int min_wakeup_pin_assert_time = 60; /* Default: 60ms */
unsigned int reset_pin_assert_time = 100; /* Default: 100ms */
of_property_read_u32(np, "ingenic,reset-pin-assert-time-ms",
&reset_pin_assert_time);
of_property_read_u32(np, "ingenic,min-wakeup-pin-assert-time-ms",
&min_wakeup_pin_assert_time);
/*
* Set minimum wakeup pin assertion time: 100 ms.
* Range is 0 to 2 sec if RTC is clocked at 32 kHz.
*/
wakeup_ticks = (min_wakeup_pin_assert_time * rate) / 1000;
if (wakeup_ticks < JZ_RTC_WAKEUP_FILTER_MASK)
wakeup_ticks &= JZ_RTC_WAKEUP_FILTER_MASK;
else
wakeup_ticks = JZ_RTC_WAKEUP_FILTER_MASK;
jz4740_rtc_reg_write(rtc, JZ_REG_RTC_WAKEUP_FILTER, wakeup_ticks);
/*
* Set reset pin low-level assertion time after wakeup: 60 ms.
* Range is 0 to 125 ms if RTC is clocked at 32 kHz.
*/
reset_ticks = (reset_pin_assert_time * rate) / 1000;
if (reset_ticks < JZ_RTC_RESET_COUNTER_MASK)
reset_ticks &= JZ_RTC_RESET_COUNTER_MASK;
else
reset_ticks = JZ_RTC_RESET_COUNTER_MASK;
jz4740_rtc_reg_write(rtc, JZ_REG_RTC_RESET_COUNTER, reset_ticks);
}
static int jz4740_rtc_probe(struct platform_device *pdev) static int jz4740_rtc_probe(struct platform_device *pdev)
{ {
int ret; struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
struct jz4740_rtc *rtc; struct jz4740_rtc *rtc;
const struct platform_device_id *id = platform_get_device_id(pdev); unsigned long rate;
const struct of_device_id *of_id = of_match_device( struct clk *clk;
jz4740_rtc_of_match, &pdev->dev); int ret, irq;
struct device_node *np = pdev->dev.of_node;
rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL); rtc = devm_kzalloc(dev, sizeof(*rtc), GFP_KERNEL);
if (!rtc) if (!rtc)
return -ENOMEM; return -ENOMEM;
if (of_id) rtc->type = (enum jz4740_rtc_type)device_get_match_data(dev);
rtc->type = (enum jz4740_rtc_type)of_id->data;
else
rtc->type = id->driver_data;
rtc->irq = platform_get_irq(pdev, 0); irq = platform_get_irq(pdev, 0);
if (rtc->irq < 0) if (irq < 0)
return -ENOENT; return irq;
rtc->base = devm_platform_ioremap_resource(pdev, 0); rtc->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(rtc->base)) if (IS_ERR(rtc->base))
return PTR_ERR(rtc->base); return PTR_ERR(rtc->base);
rtc->clk = devm_clk_get(&pdev->dev, "rtc"); clk = devm_clk_get(dev, "rtc");
if (IS_ERR(rtc->clk)) { if (IS_ERR(clk)) {
dev_err(&pdev->dev, "Failed to get RTC clock\n"); dev_err(dev, "Failed to get RTC clock\n");
return PTR_ERR(rtc->clk); return PTR_ERR(clk);
}
ret = clk_prepare_enable(clk);
if (ret) {
dev_err(dev, "Failed to enable clock\n");
return ret;
}
ret = devm_add_action_or_reset(dev, jz4740_rtc_clk_disable, clk);
if (ret) {
dev_err(dev, "Failed to register devm action\n");
return ret;
} }
spin_lock_init(&rtc->lock); spin_lock_init(&rtc->lock);
platform_set_drvdata(pdev, rtc); platform_set_drvdata(pdev, rtc);
device_init_wakeup(&pdev->dev, 1); device_init_wakeup(dev, 1);
ret = dev_pm_set_wake_irq(&pdev->dev, rtc->irq); ret = dev_pm_set_wake_irq(dev, irq);
if (ret) { if (ret) {
dev_err(&pdev->dev, "Failed to set wake irq: %d\n", ret); dev_err(dev, "Failed to set wake irq: %d\n", ret);
return ret; return ret;
} }
rtc->rtc = devm_rtc_allocate_device(&pdev->dev); rtc->rtc = devm_rtc_allocate_device(dev);
if (IS_ERR(rtc->rtc)) { if (IS_ERR(rtc->rtc)) {
ret = PTR_ERR(rtc->rtc); ret = PTR_ERR(rtc->rtc);
dev_err(&pdev->dev, "Failed to allocate rtc device: %d\n", ret); dev_err(dev, "Failed to allocate rtc device: %d\n", ret);
return ret; return ret;
} }
rtc->rtc->ops = &jz4740_rtc_ops; rtc->rtc->ops = &jz4740_rtc_ops;
rtc->rtc->range_max = U32_MAX; rtc->rtc->range_max = U32_MAX;
rate = clk_get_rate(clk);
jz4740_rtc_set_wakeup_params(rtc, np, rate);
/* Each 1 Hz pulse should happen after (rate) ticks */
jz4740_rtc_reg_write(rtc, JZ_REG_RTC_REGULATOR, rate - 1);
ret = rtc_register_device(rtc->rtc); ret = rtc_register_device(rtc->rtc);
if (ret) if (ret)
return ret; return ret;
ret = devm_request_irq(&pdev->dev, rtc->irq, jz4740_rtc_irq, 0, ret = devm_request_irq(dev, irq, jz4740_rtc_irq, 0,
pdev->name, rtc); pdev->name, rtc);
if (ret) { if (ret) {
dev_err(&pdev->dev, "Failed to request rtc irq: %d\n", ret); dev_err(dev, "Failed to request rtc irq: %d\n", ret);
return ret; return ret;
} }
if (np && of_device_is_system_power_controller(np)) { if (of_device_is_system_power_controller(np)) {
if (!pm_power_off) { dev_for_power_off = dev;
/* Default: 60ms */
rtc->reset_pin_assert_time = 60;
of_property_read_u32(np,
"ingenic,reset-pin-assert-time-ms",
&rtc->reset_pin_assert_time);
/* Default: 100ms */ if (!pm_power_off)
rtc->min_wakeup_pin_assert_time = 100;
of_property_read_u32(np,
"ingenic,min-wakeup-pin-assert-time-ms",
&rtc->min_wakeup_pin_assert_time);
dev_for_power_off = &pdev->dev;
pm_power_off = jz4740_rtc_power_off; pm_power_off = jz4740_rtc_power_off;
} else { else
dev_warn(&pdev->dev, dev_warn(dev, "Poweroff handler already present!\n");
"Poweroff handler already present!\n");
}
} }
return 0; return 0;
} }
static const struct platform_device_id jz4740_rtc_ids[] = {
{ "jz4740-rtc", ID_JZ4740 },
{ "jz4780-rtc", ID_JZ4780 },
{}
};
MODULE_DEVICE_TABLE(platform, jz4740_rtc_ids);
static struct platform_driver jz4740_rtc_driver = { static struct platform_driver jz4740_rtc_driver = {
.probe = jz4740_rtc_probe, .probe = jz4740_rtc_probe,
.driver = { .driver = {
.name = "jz4740-rtc", .name = "jz4740-rtc",
.of_match_table = of_match_ptr(jz4740_rtc_of_match), .of_match_table = jz4740_rtc_of_match,
}, },
.id_table = jz4740_rtc_ids,
}; };
module_platform_driver(jz4740_rtc_driver); module_platform_driver(jz4740_rtc_driver);

View File

@ -205,10 +205,8 @@ static int lpc24xx_rtc_probe(struct platform_device *pdev)
return PTR_ERR(rtc->rtc_base); return PTR_ERR(rtc->rtc_base);
irq = platform_get_irq(pdev, 0); irq = platform_get_irq(pdev, 0);
if (irq < 0) { if (irq < 0)
dev_warn(&pdev->dev, "can't get interrupt resource\n");
return irq; return irq;
}
rtc->clk_rtc = devm_clk_get(&pdev->dev, "rtc"); rtc->clk_rtc = devm_clk_get(&pdev->dev, "rtc");
if (IS_ERR(rtc->clk_rtc)) { if (IS_ERR(rtc->clk_rtc)) {

View File

@ -78,6 +78,8 @@ struct max77686_rtc_driver_data {
int alarm_pending_status_reg; int alarm_pending_status_reg;
/* RTC IRQ CHIP for regmap */ /* RTC IRQ CHIP for regmap */
const struct regmap_irq_chip *rtc_irq_chip; const struct regmap_irq_chip *rtc_irq_chip;
/* regmap configuration for the chip */
const struct regmap_config *regmap_config;
}; };
struct max77686_rtc_info { struct max77686_rtc_info {
@ -182,6 +184,11 @@ static const struct regmap_irq_chip max77686_rtc_irq_chip = {
.num_irqs = ARRAY_SIZE(max77686_rtc_irqs), .num_irqs = ARRAY_SIZE(max77686_rtc_irqs),
}; };
static const struct regmap_config max77686_rtc_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
};
static const struct max77686_rtc_driver_data max77686_drv_data = { static const struct max77686_rtc_driver_data max77686_drv_data = {
.delay = 16000, .delay = 16000,
.mask = 0x7f, .mask = 0x7f,
@ -191,6 +198,13 @@ static const struct max77686_rtc_driver_data max77686_drv_data = {
.alarm_pending_status_reg = MAX77686_REG_STATUS2, .alarm_pending_status_reg = MAX77686_REG_STATUS2,
.rtc_i2c_addr = MAX77686_I2C_ADDR_RTC, .rtc_i2c_addr = MAX77686_I2C_ADDR_RTC,
.rtc_irq_chip = &max77686_rtc_irq_chip, .rtc_irq_chip = &max77686_rtc_irq_chip,
.regmap_config = &max77686_rtc_regmap_config,
};
static const struct regmap_config max77620_rtc_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.use_single_write = true,
}; };
static const struct max77686_rtc_driver_data max77620_drv_data = { static const struct max77686_rtc_driver_data max77620_drv_data = {
@ -202,6 +216,7 @@ static const struct max77686_rtc_driver_data max77620_drv_data = {
.alarm_pending_status_reg = MAX77686_INVALID_REG, .alarm_pending_status_reg = MAX77686_INVALID_REG,
.rtc_i2c_addr = MAX77620_I2C_ADDR_RTC, .rtc_i2c_addr = MAX77620_I2C_ADDR_RTC,
.rtc_irq_chip = &max77686_rtc_irq_chip, .rtc_irq_chip = &max77686_rtc_irq_chip,
.regmap_config = &max77620_rtc_regmap_config,
}; };
static const unsigned int max77802_map[REG_RTC_END] = { static const unsigned int max77802_map[REG_RTC_END] = {
@ -658,11 +673,6 @@ static int max77686_rtc_init_reg(struct max77686_rtc_info *info)
return ret; return ret;
} }
static const struct regmap_config max77686_rtc_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
};
static int max77686_init_rtc_regmap(struct max77686_rtc_info *info) static int max77686_init_rtc_regmap(struct max77686_rtc_info *info)
{ {
struct device *parent = info->dev->parent; struct device *parent = info->dev->parent;
@ -698,7 +708,7 @@ static int max77686_init_rtc_regmap(struct max77686_rtc_info *info)
} }
info->rtc_regmap = devm_regmap_init_i2c(info->rtc, info->rtc_regmap = devm_regmap_init_i2c(info->rtc,
&max77686_rtc_regmap_config); info->drv_data->regmap_config);
if (IS_ERR(info->rtc_regmap)) { if (IS_ERR(info->rtc_regmap)) {
ret = PTR_ERR(info->rtc_regmap); ret = PTR_ERR(info->rtc_regmap);
dev_err(info->dev, "Failed to allocate RTC regmap: %d\n", ret); dev_err(info->dev, "Failed to allocate RTC regmap: %d\n", ret);

View File

@ -308,8 +308,10 @@ static int __init mc13xxx_rtc_probe(struct platform_device *pdev)
mc13xxx_unlock(mc13xxx); mc13xxx_unlock(mc13xxx);
ret = rtc_register_device(priv->rtc); ret = rtc_register_device(priv->rtc);
if (ret) if (ret) {
mc13xxx_lock(mc13xxx);
goto err_irq_request; goto err_irq_request;
}
return 0; return 0;

View File

@ -316,7 +316,7 @@ static int mpc5121_rtc_probe(struct platform_device *op)
rtc->regs = devm_platform_ioremap_resource(op, 0); rtc->regs = devm_platform_ioremap_resource(op, 0);
if (IS_ERR(rtc->regs)) { if (IS_ERR(rtc->regs)) {
dev_err(&op->dev, "%s: couldn't map io space\n", __func__); dev_err(&op->dev, "%s: couldn't map io space\n", __func__);
return -ENOSYS; return PTR_ERR(rtc->regs);
} }
device_init_wakeup(&op->dev, 1); device_init_wakeup(&op->dev, 1);

View File

@ -310,7 +310,6 @@ static const struct rtc_class_ops mt2712_rtc_ops = {
static int mt2712_rtc_probe(struct platform_device *pdev) static int mt2712_rtc_probe(struct platform_device *pdev)
{ {
struct resource *res;
struct mt2712_rtc *mt2712_rtc; struct mt2712_rtc *mt2712_rtc;
int ret; int ret;
@ -319,8 +318,7 @@ static int mt2712_rtc_probe(struct platform_device *pdev)
if (!mt2712_rtc) if (!mt2712_rtc)
return -ENOMEM; return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); mt2712_rtc->base = devm_platform_ioremap_resource(pdev, 0);
mt2712_rtc->base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(mt2712_rtc->base)) if (IS_ERR(mt2712_rtc->base))
return PTR_ERR(mt2712_rtc->base); return PTR_ERR(mt2712_rtc->base);
@ -328,10 +326,8 @@ static int mt2712_rtc_probe(struct platform_device *pdev)
mt2712_rtc_hw_init(mt2712_rtc); mt2712_rtc_hw_init(mt2712_rtc);
mt2712_rtc->irq = platform_get_irq(pdev, 0); mt2712_rtc->irq = platform_get_irq(pdev, 0);
if (mt2712_rtc->irq < 0) { if (mt2712_rtc->irq < 0)
dev_err(&pdev->dev, "No IRQ resource\n");
return mt2712_rtc->irq; return mt2712_rtc->irq;
}
platform_set_drvdata(pdev, mt2712_rtc); platform_set_drvdata(pdev, mt2712_rtc);
@ -356,13 +352,7 @@ static int mt2712_rtc_probe(struct platform_device *pdev)
mt2712_rtc->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000; mt2712_rtc->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
mt2712_rtc->rtc->range_max = MT2712_RTC_TIMESTAMP_END_2127; mt2712_rtc->rtc->range_max = MT2712_RTC_TIMESTAMP_END_2127;
ret = rtc_register_device(mt2712_rtc->rtc); return rtc_register_device(mt2712_rtc->rtc);
if (ret) {
dev_err(&pdev->dev, "register rtc device failed\n");
return ret;
}
return 0;
} }
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP

View File

@ -137,8 +137,7 @@ static int pcf2127_rtc_read_time(struct device *dev, struct rtc_time *tm)
tm->tm_wday = buf[PCF2127_REG_DW] & 0x07; tm->tm_wday = buf[PCF2127_REG_DW] & 0x07;
tm->tm_mon = bcd2bin(buf[PCF2127_REG_MO] & 0x1F) - 1; /* rtc mn 1-12 */ tm->tm_mon = bcd2bin(buf[PCF2127_REG_MO] & 0x1F) - 1; /* rtc mn 1-12 */
tm->tm_year = bcd2bin(buf[PCF2127_REG_YR]); tm->tm_year = bcd2bin(buf[PCF2127_REG_YR]);
if (tm->tm_year < 70) tm->tm_year += 100;
tm->tm_year += 100; /* assume we are in 1970...2069 */
dev_dbg(dev, "%s: tm is secs=%d, mins=%d, hours=%d, " dev_dbg(dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
"mday=%d, mon=%d, year=%d, wday=%d\n", "mday=%d, mon=%d, year=%d, wday=%d\n",
@ -172,7 +171,7 @@ static int pcf2127_rtc_set_time(struct device *dev, struct rtc_time *tm)
buf[i++] = bin2bcd(tm->tm_mon + 1); buf[i++] = bin2bcd(tm->tm_mon + 1);
/* year */ /* year */
buf[i++] = bin2bcd(tm->tm_year % 100); buf[i++] = bin2bcd(tm->tm_year - 100);
/* write register's data */ /* write register's data */
err = regmap_bulk_write(pcf2127->regmap, PCF2127_REG_SC, buf, i); err = regmap_bulk_write(pcf2127->regmap, PCF2127_REG_SC, buf, i);
@ -185,30 +184,35 @@ static int pcf2127_rtc_set_time(struct device *dev, struct rtc_time *tm)
return 0; return 0;
} }
#ifdef CONFIG_RTC_INTF_DEV
static int pcf2127_rtc_ioctl(struct device *dev, static int pcf2127_rtc_ioctl(struct device *dev,
unsigned int cmd, unsigned long arg) unsigned int cmd, unsigned long arg)
{ {
struct pcf2127 *pcf2127 = dev_get_drvdata(dev); struct pcf2127 *pcf2127 = dev_get_drvdata(dev);
int touser; int val, touser = 0;
int ret; int ret;
switch (cmd) { switch (cmd) {
case RTC_VL_READ: case RTC_VL_READ:
ret = regmap_read(pcf2127->regmap, PCF2127_REG_CTRL3, &touser); ret = regmap_read(pcf2127->regmap, PCF2127_REG_CTRL3, &val);
if (ret) if (ret)
return ret; return ret;
touser = touser & PCF2127_BIT_CTRL3_BLF ? RTC_VL_BACKUP_LOW : 0; if (val & PCF2127_BIT_CTRL3_BLF)
touser |= RTC_VL_BACKUP_LOW;
if (val & PCF2127_BIT_CTRL3_BF)
touser |= RTC_VL_BACKUP_SWITCH;
return put_user(touser, (unsigned int __user *)arg); return put_user(touser, (unsigned int __user *)arg);
case RTC_VL_CLR:
return regmap_update_bits(pcf2127->regmap, PCF2127_REG_CTRL3,
PCF2127_BIT_CTRL3_BF, 0);
default: default:
return -ENOIOCTLCMD; return -ENOIOCTLCMD;
} }
} }
#else
#define pcf2127_rtc_ioctl NULL
#endif
static const struct rtc_class_ops pcf2127_rtc_ops = { static const struct rtc_class_ops pcf2127_rtc_ops = {
.ioctl = pcf2127_rtc_ioctl, .ioctl = pcf2127_rtc_ioctl,
@ -433,6 +437,9 @@ static int pcf2127_probe(struct device *dev, struct regmap *regmap,
return PTR_ERR(pcf2127->rtc); return PTR_ERR(pcf2127->rtc);
pcf2127->rtc->ops = &pcf2127_rtc_ops; pcf2127->rtc->ops = &pcf2127_rtc_ops;
pcf2127->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
pcf2127->rtc->range_max = RTC_TIMESTAMP_END_2099;
pcf2127->rtc->set_start_time = true; /* Sets actual start to 1970 */
pcf2127->wdd.parent = dev; pcf2127->wdd.parent = dev;
pcf2127->wdd.info = &pcf2127_wdt_info; pcf2127->wdd.info = &pcf2127_wdt_info;
@ -441,6 +448,7 @@ static int pcf2127_probe(struct device *dev, struct regmap *regmap,
pcf2127->wdd.max_timeout = PCF2127_WD_VAL_MAX; pcf2127->wdd.max_timeout = PCF2127_WD_VAL_MAX;
pcf2127->wdd.timeout = PCF2127_WD_VAL_DEFAULT; pcf2127->wdd.timeout = PCF2127_WD_VAL_DEFAULT;
pcf2127->wdd.min_hw_heartbeat_ms = 500; pcf2127->wdd.min_hw_heartbeat_ms = 500;
pcf2127->wdd.status = WATCHDOG_NOWAYOUT_INIT_STATUS;
watchdog_set_drvdata(&pcf2127->wdd, pcf2127); watchdog_set_drvdata(&pcf2127->wdd, pcf2127);
@ -495,7 +503,6 @@ static int pcf2127_probe(struct device *dev, struct regmap *regmap,
*/ */
ret = regmap_update_bits(pcf2127->regmap, PCF2127_REG_CTRL3, ret = regmap_update_bits(pcf2127->regmap, PCF2127_REG_CTRL3,
PCF2127_BIT_CTRL3_BTSE | PCF2127_BIT_CTRL3_BTSE |
PCF2127_BIT_CTRL3_BF |
PCF2127_BIT_CTRL3_BIE | PCF2127_BIT_CTRL3_BIE |
PCF2127_BIT_CTRL3_BLIE, 0); PCF2127_BIT_CTRL3_BLIE, 0);
if (ret) { if (ret) {
@ -636,6 +643,7 @@ static int pcf2127_i2c_probe(struct i2c_client *client,
static const struct regmap_config config = { static const struct regmap_config config = {
.reg_bits = 8, .reg_bits = 8,
.val_bits = 8, .val_bits = 8,
.max_register = 0x1d,
}; };
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
@ -703,6 +711,7 @@ static int pcf2127_spi_probe(struct spi_device *spi)
.val_bits = 8, .val_bits = 8,
.read_flag_mask = 0xa0, .read_flag_mask = 0xa0,
.write_flag_mask = 0x20, .write_flag_mask = 0x20,
.max_register = 0x1d,
}; };
struct regmap *regmap; struct regmap *regmap;

View File

@ -356,10 +356,8 @@ static int rc5t619_rtc_probe(struct platform_device *pdev)
int err; int err;
rtc = devm_kzalloc(dev, sizeof(*rtc), GFP_KERNEL); rtc = devm_kzalloc(dev, sizeof(*rtc), GFP_KERNEL);
if (IS_ERR(rtc)) { if (!rtc)
err = PTR_ERR(rtc);
return -ENOMEM; return -ENOMEM;
}
rtc->rn5t618 = rn5t618; rtc->rn5t618 = rn5t618;

View File

@ -755,6 +755,8 @@ static int rv3028_probe(struct i2c_client *client)
return -ENOMEM; return -ENOMEM;
rv3028->regmap = devm_regmap_init_i2c(client, &regmap_config); rv3028->regmap = devm_regmap_init_i2c(client, &regmap_config);
if (IS_ERR(rv3028->regmap))
return PTR_ERR(rv3028->regmap);
i2c_set_clientdata(client, rv3028); i2c_set_clientdata(client, rv3028);

View File

@ -148,10 +148,21 @@ static int snvs_rtc_enable(struct snvs_rtc_data *data, bool enable)
static int snvs_rtc_read_time(struct device *dev, struct rtc_time *tm) static int snvs_rtc_read_time(struct device *dev, struct rtc_time *tm)
{ {
struct snvs_rtc_data *data = dev_get_drvdata(dev); struct snvs_rtc_data *data = dev_get_drvdata(dev);
unsigned long time = rtc_read_lp_counter(data); unsigned long time;
int ret;
if (data->clk) {
ret = clk_enable(data->clk);
if (ret)
return ret;
}
time = rtc_read_lp_counter(data);
rtc_time64_to_tm(time, tm); rtc_time64_to_tm(time, tm);
if (data->clk)
clk_disable(data->clk);
return 0; return 0;
} }
@ -161,6 +172,12 @@ static int snvs_rtc_set_time(struct device *dev, struct rtc_time *tm)
unsigned long time = rtc_tm_to_time64(tm); unsigned long time = rtc_tm_to_time64(tm);
int ret; int ret;
if (data->clk) {
ret = clk_enable(data->clk);
if (ret)
return ret;
}
/* Disable RTC first */ /* Disable RTC first */
ret = snvs_rtc_enable(data, false); ret = snvs_rtc_enable(data, false);
if (ret) if (ret)
@ -173,6 +190,9 @@ static int snvs_rtc_set_time(struct device *dev, struct rtc_time *tm)
/* Enable RTC again */ /* Enable RTC again */
ret = snvs_rtc_enable(data, true); ret = snvs_rtc_enable(data, true);
if (data->clk)
clk_disable(data->clk);
return ret; return ret;
} }
@ -180,6 +200,13 @@ static int snvs_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{ {
struct snvs_rtc_data *data = dev_get_drvdata(dev); struct snvs_rtc_data *data = dev_get_drvdata(dev);
u32 lptar, lpsr; u32 lptar, lpsr;
int ret;
if (data->clk) {
ret = clk_enable(data->clk);
if (ret)
return ret;
}
regmap_read(data->regmap, data->offset + SNVS_LPTAR, &lptar); regmap_read(data->regmap, data->offset + SNVS_LPTAR, &lptar);
rtc_time64_to_tm(lptar, &alrm->time); rtc_time64_to_tm(lptar, &alrm->time);
@ -187,18 +214,33 @@ static int snvs_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
regmap_read(data->regmap, data->offset + SNVS_LPSR, &lpsr); regmap_read(data->regmap, data->offset + SNVS_LPSR, &lpsr);
alrm->pending = (lpsr & SNVS_LPSR_LPTA) ? 1 : 0; alrm->pending = (lpsr & SNVS_LPSR_LPTA) ? 1 : 0;
if (data->clk)
clk_disable(data->clk);
return 0; return 0;
} }
static int snvs_rtc_alarm_irq_enable(struct device *dev, unsigned int enable) static int snvs_rtc_alarm_irq_enable(struct device *dev, unsigned int enable)
{ {
struct snvs_rtc_data *data = dev_get_drvdata(dev); struct snvs_rtc_data *data = dev_get_drvdata(dev);
int ret;
if (data->clk) {
ret = clk_enable(data->clk);
if (ret)
return ret;
}
regmap_update_bits(data->regmap, data->offset + SNVS_LPCR, regmap_update_bits(data->regmap, data->offset + SNVS_LPCR,
(SNVS_LPCR_LPTA_EN | SNVS_LPCR_LPWUI_EN), (SNVS_LPCR_LPTA_EN | SNVS_LPCR_LPWUI_EN),
enable ? (SNVS_LPCR_LPTA_EN | SNVS_LPCR_LPWUI_EN) : 0); enable ? (SNVS_LPCR_LPTA_EN | SNVS_LPCR_LPWUI_EN) : 0);
return rtc_write_sync_lp(data); ret = rtc_write_sync_lp(data);
if (data->clk)
clk_disable(data->clk);
return ret;
} }
static int snvs_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) static int snvs_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
@ -207,6 +249,12 @@ static int snvs_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
unsigned long time = rtc_tm_to_time64(&alrm->time); unsigned long time = rtc_tm_to_time64(&alrm->time);
int ret; int ret;
if (data->clk) {
ret = clk_enable(data->clk);
if (ret)
return ret;
}
regmap_update_bits(data->regmap, data->offset + SNVS_LPCR, SNVS_LPCR_LPTA_EN, 0); regmap_update_bits(data->regmap, data->offset + SNVS_LPCR, SNVS_LPCR_LPTA_EN, 0);
ret = rtc_write_sync_lp(data); ret = rtc_write_sync_lp(data);
if (ret) if (ret)
@ -216,6 +264,9 @@ static int snvs_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
/* Clear alarm interrupt status bit */ /* Clear alarm interrupt status bit */
regmap_write(data->regmap, data->offset + SNVS_LPSR, SNVS_LPSR_LPTA); regmap_write(data->regmap, data->offset + SNVS_LPSR, SNVS_LPSR_LPTA);
if (data->clk)
clk_disable(data->clk);
return snvs_rtc_alarm_irq_enable(dev, alrm->enabled); return snvs_rtc_alarm_irq_enable(dev, alrm->enabled);
} }
@ -362,7 +413,7 @@ static int __maybe_unused snvs_rtc_suspend_noirq(struct device *dev)
struct snvs_rtc_data *data = dev_get_drvdata(dev); struct snvs_rtc_data *data = dev_get_drvdata(dev);
if (data->clk) if (data->clk)
clk_disable_unprepare(data->clk); clk_disable(data->clk);
return 0; return 0;
} }
@ -372,7 +423,7 @@ static int __maybe_unused snvs_rtc_resume_noirq(struct device *dev)
struct snvs_rtc_data *data = dev_get_drvdata(dev); struct snvs_rtc_data *data = dev_get_drvdata(dev);
if (data->clk) if (data->clk)
return clk_prepare_enable(data->clk); return clk_enable(data->clk);
return 0; return 0;
} }

View File

@ -416,5 +416,5 @@ module_platform_driver(stmp3xxx_rtcdrv);
MODULE_DESCRIPTION("STMP3xxx RTC Driver"); MODULE_DESCRIPTION("STMP3xxx RTC Driver");
MODULE_AUTHOR("dmitry pervushin <dpervushin@embeddedalley.com> and " MODULE_AUTHOR("dmitry pervushin <dpervushin@embeddedalley.com> and "
"Wolfram Sang <w.sang@pengutronix.de>"); "Wolfram Sang <kernel@pengutronix.de>");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");

View File

@ -99,6 +99,7 @@ struct rtc_pll_info {
#define RTC_VL_BACKUP_LOW _BITUL(1) /* Backup voltage is low */ #define RTC_VL_BACKUP_LOW _BITUL(1) /* Backup voltage is low */
#define RTC_VL_BACKUP_EMPTY _BITUL(2) /* Backup empty or not present */ #define RTC_VL_BACKUP_EMPTY _BITUL(2) /* Backup empty or not present */
#define RTC_VL_ACCURACY_LOW _BITUL(3) /* Voltage is low, RTC accuracy is reduced */ #define RTC_VL_ACCURACY_LOW _BITUL(3) /* Voltage is low, RTC accuracy is reduced */
#define RTC_VL_BACKUP_SWITCH _BITUL(4) /* Backup switchover happened */
#define RTC_VL_READ _IOR('p', 0x13, unsigned int) /* Voltage low detection */ #define RTC_VL_READ _IOR('p', 0x13, unsigned int) /* Voltage low detection */
#define RTC_VL_CLR _IO('p', 0x14) /* Clear voltage low information */ #define RTC_VL_CLR _IO('p', 0x14) /* Clear voltage low information */