RTC for 5.16

Subsystem:
  - Add new ioctl to get and set extra RTC parameters, this includes backup
    switch mode
  - Expose available features to userspace, in particular, when alarmas have a
    resolution of one minute instead of a second.
  - Let the core handle those alarms with a minute resolution
 
 New driver:
  - MSTAR MSC313 RTC
 
 Drivers:
  - Add SPI ID table where necessary
  - Add BSM support for rv3028, rv3032 and pcf8523
  - s3c: set RTC range
  - rx8025: set range, implement .set_offset and .read_offset
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEEBqsFVZXh8s/0O5JiY6TcMGxwOjIFAmGNm7AACgkQY6TcMGxw
 OjJBeA/+PHmLq0v1olnG2kx0Ch7nzYzonCO+3tvPi5xoPKUZln5TpdSqAECqDC6g
 PizHUdJaBNTc3Y7GMUkryuuWq67kYlzx1N7EHZqgARk7s6hus+SJmQb7kiCbiawD
 pP62na7ZJDCs6S70WD9VMCJQ21xokwwTWzL7nVD98LN1qkQCj4cSuoDPBEJQyeG2
 S5Xi1CePW84c9eKx4Sy//bzLnCpSqb6tDHfsexwmLFTk5WN0onZRZSYD0/loY8N+
 EEMX0Ts/9ERqM5QALDMB4YQNWvRCtGP7Fl0QPtVRXC2MXyg/GYhdC2F2SvQmYCRC
 VZoZwCJ82x4Pa2UTdg2L3WD0uKrvycnRaAYV71CME5PkAw1hQqLz3HZwjYXkITvp
 crhZQvCGHn9w2UOEAKnWWnCLsl3paWXkN0zGeFhYYGeAIf79fRnIGc3cGubjSgiv
 9WU9oRL8EzY5bL07fP5P81leknzROZmK3Re6vefI5o2A4qY0qP9mU6zVKxZy/iHd
 7GiE5jNact0oUB7Vhakh4wUchyOJCPZSFxfeNqPJzs6FlVUR74Ulw05Sywnz+W7a
 oXtODF0cmJPVeUJYmo5EKfLAId4iPmcq8Fh16ayw4595pwc6iHE+GRL6j7Zjk+AX
 u9UA2qXqYhE5PgcxC6pd/hMV29p1S81BKdjyf0HF7oxWgBoT1lc=
 =pTlj
 -----END PGP SIGNATURE-----

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

Pull RTC updates from Alexandre Belloni:
 "This includes new ioctls to get and set parameters and in particular
  the backup switch mode that is needed for some RTCs to actually enable
  the backup voltage (and have a useful RTC).

  The same interface can also be used to get the actual features
  supported by the RTC so userspace has a better way than trying and
  failing.

  Summary:

  Subsystem:
   - Add new ioctl to get and set extra RTC parameters, this includes
     backup switch mode
   - Expose available features to userspace, in particular, when alarmas
     have a resolution of one minute instead of a second.
   - Let the core handle those alarms with a minute resolution

  New driver:
   - MSTAR MSC313 RTC

  Drivers:
   - Add SPI ID table where necessary
   - Add BSM support for rv3028, rv3032 and pcf8523
   - s3c: set RTC range
   - rx8025: set range, implement .set_offset and .read_offset"

* tag 'rtc-5.16' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux: (50 commits)
  rtc: rx8025: use .set_offset/.read_offset
  rtc: rx8025: use rtc_add_group
  rtc: rx8025: clear RTC_FEATURE_ALARM when alarm are not supported
  rtc: rx8025: set range
  rtc: rx8025: let the core handle the alarm resolution
  rtc: rx8025: switch to devm_rtc_allocate_device
  rtc: ab8500: let the core handle the alarm resolution
  rtc: ab-eoz9: support UIE when available
  rtc: ab-eoz9: use RTC_FEATURE_UPDATE_INTERRUPT
  rtc: rv3032: let the core handle the alarm resolution
  rtc: s35390a: let the core handle the alarm resolution
  rtc: handle alarms with a minute resolution
  rtc: pcf85063: silence cppcheck warning
  rtc: rv8803: fix writing back ctrl in flag register
  rtc: s3c: Add time range
  rtc: s3c: Extract read/write IO into separate functions
  rtc: s3c: Remove usage of devm_rtc_device_register()
  rtc: tps80031: Remove driver
  rtc: sun6i: Allow probing without an early clock provider
  rtc: pcf8523: add BSM support
  ...
This commit is contained in:
Linus Torvalds 2021-11-12 11:44:31 -08:00
commit 3b81bf78b7
31 changed files with 984 additions and 763 deletions

View File

@ -0,0 +1,49 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/rtc/mstar,msc313-rtc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Mstar MSC313e RTC Device Tree Bindings
allOf:
- $ref: "rtc.yaml#"
maintainers:
- Daniel Palmer <daniel@0x0f.com>
- Romain Perier <romain.perier@gmail.com>
properties:
compatible:
enum:
- mstar,msc313-rtc
reg:
maxItems: 1
interrupts:
maxItems: 1
start-year: true
clocks:
maxItems: 1
required:
- compatible
- reg
- interrupts
- clocks
additionalProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
rtc@2400 {
compatible = "mstar,msc313-rtc";
reg = <0x2400 0x40>;
clocks = <&xtal_div2>;
interrupts-extended = <&intc_irq GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
};
...

View File

@ -13,10 +13,19 @@ Optional property:
expressed in femto Farad (fF). Valid values are 7000 and 12500. expressed in femto Farad (fF). Valid values are 7000 and 12500.
Default value (if no value is specified) is 7000fF. Default value (if no value is specified) is 7000fF.
Optional child node:
- clock: Provide this if the square wave pin is used as boot-enabled fixed clock.
Example: Example:
pcf85063: rtc@51 { pcf85063: rtc@51 {
compatible = "nxp,pcf85063"; compatible = "nxp,pcf85063";
reg = <0x51>; reg = <0x51>;
quartz-load-femtofarads = <12500>; quartz-load-femtofarads = <12500>;
clock {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <32768>;
};
}; };

View File

@ -2283,6 +2283,7 @@ F: arch/arm/boot/dts/mstar-*
F: arch/arm/mach-mstar/ F: arch/arm/mach-mstar/
F: drivers/clk/mstar/ F: drivers/clk/mstar/
F: drivers/gpio/gpio-msc313.c F: drivers/gpio/gpio-msc313.c
F: drivers/rtc/rtc-msc313.c
F: drivers/watchdog/msc313e_wdt.c F: drivers/watchdog/msc313e_wdt.c
F: include/dt-bindings/clock/mstar-* F: include/dt-bindings/clock/mstar-*
F: include/dt-bindings/gpio/msc313-gpio.h F: include/dt-bindings/gpio/msc313-gpio.h

View File

@ -441,6 +441,7 @@ config RTC_DRV_X1205
config RTC_DRV_PCF8523 config RTC_DRV_PCF8523
tristate "NXP PCF8523" tristate "NXP PCF8523"
select REGMAP_I2C
help help
If you say yes here you get support for the NXP PCF8523 RTC If you say yes here you get support for the NXP PCF8523 RTC
chips. chips.
@ -582,14 +583,6 @@ config RTC_DRV_TPS65910
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called rtc-tps65910. will be called rtc-tps65910.
config RTC_DRV_TPS80031
tristate "TI TPS80031/TPS80032 RTC driver"
depends on MFD_TPS80031
help
TI Power Management IC TPS80031 supports RTC functionality
along with alarm. This driver supports the RTC driver for
the TPS80031 RTC module.
config RTC_DRV_RC5T583 config RTC_DRV_RC5T583
tristate "RICOH 5T583 RTC driver" tristate "RICOH 5T583 RTC driver"
depends on MFD_RC5T583 depends on MFD_RC5T583
@ -1929,4 +1922,14 @@ config RTC_DRV_WILCO_EC
This can also be built as a module. If so, the module will This can also be built as a module. If so, the module will
be named "rtc_wilco_ec". be named "rtc_wilco_ec".
config RTC_DRV_MSC313
tristate "MStar MSC313 RTC"
depends on ARCH_MSTARV7 || COMPILE_TEST
help
If you say yes here you get support for the Mstar MSC313e On-Chip
Real Time Clock.
This driver can also be built as a module, if so, the module
will be called "rtc-msc313".
endif # RTC_CLASS endif # RTC_CLASS

View File

@ -103,6 +103,7 @@ obj-$(CONFIG_RTC_DRV_MCP795) += rtc-mcp795.o
obj-$(CONFIG_RTC_DRV_MESON) += rtc-meson.o obj-$(CONFIG_RTC_DRV_MESON) += rtc-meson.o
obj-$(CONFIG_RTC_DRV_MOXART) += rtc-moxart.o obj-$(CONFIG_RTC_DRV_MOXART) += rtc-moxart.o
obj-$(CONFIG_RTC_DRV_MPC5121) += rtc-mpc5121.o obj-$(CONFIG_RTC_DRV_MPC5121) += rtc-mpc5121.o
obj-$(CONFIG_RTC_DRV_MSC313) += rtc-msc313.o
obj-$(CONFIG_RTC_DRV_MSM6242) += rtc-msm6242.o obj-$(CONFIG_RTC_DRV_MSM6242) += rtc-msm6242.o
obj-$(CONFIG_RTC_DRV_MT2712) += rtc-mt2712.o obj-$(CONFIG_RTC_DRV_MT2712) += rtc-mt2712.o
obj-$(CONFIG_RTC_DRV_MT6397) += rtc-mt6397.o obj-$(CONFIG_RTC_DRV_MT6397) += rtc-mt6397.o
@ -169,7 +170,6 @@ obj-$(CONFIG_RTC_DRV_TEGRA) += rtc-tegra.o
obj-$(CONFIG_RTC_DRV_TEST) += rtc-test.o obj-$(CONFIG_RTC_DRV_TEST) += rtc-test.o
obj-$(CONFIG_RTC_DRV_TPS6586X) += rtc-tps6586x.o obj-$(CONFIG_RTC_DRV_TPS6586X) += rtc-tps6586x.o
obj-$(CONFIG_RTC_DRV_TPS65910) += rtc-tps65910.o obj-$(CONFIG_RTC_DRV_TPS65910) += rtc-tps65910.o
obj-$(CONFIG_RTC_DRV_TPS80031) += rtc-tps80031.o
obj-$(CONFIG_RTC_DRV_TWL4030) += rtc-twl.o obj-$(CONFIG_RTC_DRV_TWL4030) += rtc-twl.o
obj-$(CONFIG_RTC_DRV_V3020) += rtc-v3020.o obj-$(CONFIG_RTC_DRV_V3020) += rtc-v3020.o
obj-$(CONFIG_RTC_DRV_VR41XX) += rtc-vr41xx.o obj-$(CONFIG_RTC_DRV_VR41XX) += rtc-vr41xx.o

View File

@ -232,6 +232,7 @@ static struct rtc_device *rtc_allocate_device(void)
rtc->pie_enabled = 0; rtc->pie_enabled = 0;
set_bit(RTC_FEATURE_ALARM, rtc->features); set_bit(RTC_FEATURE_ALARM, rtc->features);
set_bit(RTC_FEATURE_UPDATE_INTERRUPT, rtc->features);
return rtc; return rtc;
} }
@ -334,7 +335,8 @@ static void devm_rtc_unregister_device(void *data)
* letting any rtc_class_open() users access it again * letting any rtc_class_open() users access it again
*/ */
rtc_proc_del_device(rtc); rtc_proc_del_device(rtc);
cdev_device_del(&rtc->char_dev, &rtc->dev); if (!test_bit(RTC_NO_CDEV, &rtc->flags))
cdev_device_del(&rtc->char_dev, &rtc->dev);
rtc->ops = NULL; rtc->ops = NULL;
mutex_unlock(&rtc->ops_lock); mutex_unlock(&rtc->ops_lock);
} }
@ -363,7 +365,9 @@ struct rtc_device *devm_rtc_allocate_device(struct device *dev)
rtc->id = id; rtc->id = id;
rtc->dev.parent = dev; rtc->dev.parent = dev;
dev_set_name(&rtc->dev, "rtc%d", id); err = dev_set_name(&rtc->dev, "rtc%d", id);
if (err)
return ERR_PTR(err);
err = devm_add_action_or_reset(dev, devm_rtc_release_device, rtc); err = devm_add_action_or_reset(dev, devm_rtc_release_device, rtc);
if (err) if (err)
@ -386,6 +390,12 @@ int __devm_rtc_register_device(struct module *owner, struct rtc_device *rtc)
if (!rtc->ops->set_alarm) if (!rtc->ops->set_alarm)
clear_bit(RTC_FEATURE_ALARM, rtc->features); clear_bit(RTC_FEATURE_ALARM, rtc->features);
if (rtc->uie_unsupported)
clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, rtc->features);
if (rtc->ops->set_offset)
set_bit(RTC_FEATURE_CORRECTION, rtc->features);
rtc->owner = owner; rtc->owner = owner;
rtc_device_get_offset(rtc); rtc_device_get_offset(rtc);
@ -397,12 +407,14 @@ int __devm_rtc_register_device(struct module *owner, struct rtc_device *rtc)
rtc_dev_prepare(rtc); rtc_dev_prepare(rtc);
err = cdev_device_add(&rtc->char_dev, &rtc->dev); err = cdev_device_add(&rtc->char_dev, &rtc->dev);
if (err) if (err) {
set_bit(RTC_NO_CDEV, &rtc->flags);
dev_warn(rtc->dev.parent, "failed to add char device %d:%d\n", dev_warn(rtc->dev.parent, "failed to add char device %d:%d\n",
MAJOR(rtc->dev.devt), rtc->id); MAJOR(rtc->dev.devt), rtc->id);
else } else {
dev_dbg(rtc->dev.parent, "char device (%d:%d)\n", dev_dbg(rtc->dev.parent, "char device (%d:%d)\n",
MAJOR(rtc->dev.devt), rtc->id); MAJOR(rtc->dev.devt), rtc->id);
}
rtc_proc_add_device(rtc); rtc_proc_add_device(rtc);

View File

@ -208,6 +208,7 @@ static long rtc_dev_ioctl(struct file *file,
const struct rtc_class_ops *ops = rtc->ops; const struct rtc_class_ops *ops = rtc->ops;
struct rtc_time tm; struct rtc_time tm;
struct rtc_wkalrm alarm; struct rtc_wkalrm alarm;
struct rtc_param param;
void __user *uarg = (void __user *)arg; void __user *uarg = (void __user *)arg;
err = mutex_lock_interruptible(&rtc->ops_lock); err = mutex_lock_interruptible(&rtc->ops_lock);
@ -221,6 +222,7 @@ static long rtc_dev_ioctl(struct file *file,
switch (cmd) { switch (cmd) {
case RTC_EPOCH_SET: case RTC_EPOCH_SET:
case RTC_SET_TIME: case RTC_SET_TIME:
case RTC_PARAM_SET:
if (!capable(CAP_SYS_TIME)) if (!capable(CAP_SYS_TIME))
err = -EACCES; err = -EACCES;
break; break;
@ -382,6 +384,69 @@ static long rtc_dev_ioctl(struct file *file,
err = -EFAULT; err = -EFAULT;
return err; return err;
case RTC_PARAM_GET:
if (copy_from_user(&param, uarg, sizeof(param))) {
mutex_unlock(&rtc->ops_lock);
return -EFAULT;
}
switch(param.param) {
long offset;
case RTC_PARAM_FEATURES:
if (param.index != 0)
err = -EINVAL;
param.uvalue = rtc->features[0];
break;
case RTC_PARAM_CORRECTION:
mutex_unlock(&rtc->ops_lock);
if (param.index != 0)
return -EINVAL;
err = rtc_read_offset(rtc, &offset);
mutex_lock(&rtc->ops_lock);
if (err == 0)
param.svalue = offset;
break;
default:
if (rtc->ops->param_get)
err = rtc->ops->param_get(rtc->dev.parent, &param);
else
err = -EINVAL;
}
if (!err)
if (copy_to_user(uarg, &param, sizeof(param)))
err = -EFAULT;
break;
case RTC_PARAM_SET:
if (copy_from_user(&param, uarg, sizeof(param))) {
mutex_unlock(&rtc->ops_lock);
return -EFAULT;
}
switch(param.param) {
case RTC_PARAM_FEATURES:
err = -EINVAL;
break;
case RTC_PARAM_CORRECTION:
mutex_unlock(&rtc->ops_lock);
if (param.index != 0)
return -EINVAL;
return rtc_set_offset(rtc, param.svalue);
default:
if (rtc->ops->param_set)
err = rtc->ops->param_set(rtc->dev.parent, &param);
else
err = -EINVAL;
}
break;
default: default:
/* Finally try the driver's ioctl interface */ /* Finally try the driver's ioctl interface */
if (ops->ioctl) { if (ops->ioctl) {

View File

@ -423,6 +423,7 @@ static int __rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
if (err) if (err)
return err; return err;
now = rtc_tm_to_time64(&tm); now = rtc_tm_to_time64(&tm);
if (scheduled <= now) if (scheduled <= now)
return -ETIME; return -ETIME;
/* /*
@ -447,6 +448,7 @@ static int __rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
int rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) int rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
{ {
ktime_t alarm_time;
int err; int err;
if (!rtc->ops) if (!rtc->ops)
@ -468,7 +470,15 @@ int rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
if (rtc->aie_timer.enabled) if (rtc->aie_timer.enabled)
rtc_timer_remove(rtc, &rtc->aie_timer); rtc_timer_remove(rtc, &rtc->aie_timer);
rtc->aie_timer.node.expires = rtc_tm_to_ktime(alarm->time); alarm_time = rtc_tm_to_ktime(alarm->time);
/*
* Round down so we never miss a deadline, checking for past deadline is
* done in __rtc_set_alarm
*/
if (test_bit(RTC_FEATURE_ALARM_RES_MINUTE, rtc->features))
alarm_time = ktime_sub_ns(alarm_time, (u64)alarm->time.tm_sec * NSEC_PER_SEC);
rtc->aie_timer.node.expires = alarm_time;
rtc->aie_timer.period = 0; rtc->aie_timer.period = 0;
if (alarm->enabled) if (alarm->enabled)
err = rtc_timer_enqueue(rtc, &rtc->aie_timer); err = rtc_timer_enqueue(rtc, &rtc->aie_timer);
@ -561,7 +571,8 @@ int rtc_update_irq_enable(struct rtc_device *rtc, unsigned int enabled)
if (rtc->uie_rtctimer.enabled == enabled) if (rtc->uie_rtctimer.enabled == enabled)
goto out; goto out;
if (rtc->uie_unsupported || !test_bit(RTC_FEATURE_ALARM, rtc->features)) { if (!test_bit(RTC_FEATURE_UPDATE_INTERRUPT, rtc->features) ||
!test_bit(RTC_FEATURE_ALARM, rtc->features)) {
mutex_unlock(&rtc->ops_lock); mutex_unlock(&rtc->ops_lock);
#ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL #ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL
return rtc_dev_update_irq_enable_emul(rtc, enabled); return rtc_dev_update_irq_enable_emul(rtc, enabled);

View File

@ -534,7 +534,6 @@ static int abeoz9_probe(struct i2c_client *client,
data->rtc->ops = &rtc_ops; data->rtc->ops = &rtc_ops;
data->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000; data->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
data->rtc->range_max = RTC_TIMESTAMP_END_2099; data->rtc->range_max = RTC_TIMESTAMP_END_2099;
data->rtc->uie_unsupported = 1;
clear_bit(RTC_FEATURE_ALARM, data->rtc->features); clear_bit(RTC_FEATURE_ALARM, data->rtc->features);
if (client->irq > 0) { if (client->irq > 0) {
@ -546,6 +545,8 @@ static int abeoz9_probe(struct i2c_client *client,
dev_err(dev, "failed to request alarm irq\n"); dev_err(dev, "failed to request alarm irq\n");
return ret; return ret;
} }
} else {
clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, data->rtc->features);
} }
if (client->irq > 0 || device_property_read_bool(dev, "wakeup-source")) { if (client->irq > 0 || device_property_read_bool(dev, "wakeup-source")) {

View File

@ -184,25 +184,9 @@ static int ab8500_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
{ {
int retval, i; int retval, i;
unsigned char buf[ARRAY_SIZE(ab8500_rtc_alarm_regs)]; unsigned char buf[ARRAY_SIZE(ab8500_rtc_alarm_regs)];
unsigned long mins, secs = 0, cursec = 0; unsigned long mins;
struct rtc_time curtm;
/* Get the number of seconds since 1970 */ mins = (unsigned long)rtc_tm_to_time64(&alarm->time) / 60;
secs = rtc_tm_to_time64(&alarm->time);
/*
* Check whether alarm is set less than 1min.
* Since our RTC doesn't support alarm resolution less than 1min,
* return -EINVAL, so UIE EMUL can take it up, incase of UIE_ON
*/
ab8500_rtc_read_time(dev, &curtm); /* Read current time */
cursec = rtc_tm_to_time64(&curtm);
if ((secs - cursec) < 59) {
dev_dbg(dev, "Alarm less than 1 minute not supported\r\n");
return -EINVAL;
}
mins = secs / 60;
buf[2] = mins & 0xFF; buf[2] = mins & 0xFF;
buf[1] = (mins >> 8) & 0xFF; buf[1] = (mins >> 8) & 0xFF;
@ -394,7 +378,8 @@ static int ab8500_rtc_probe(struct platform_device *pdev)
dev_pm_set_wake_irq(&pdev->dev, irq); dev_pm_set_wake_irq(&pdev->dev, irq);
platform_set_drvdata(pdev, rtc); platform_set_drvdata(pdev, rtc);
rtc->uie_unsupported = 1; set_bit(RTC_FEATURE_ALARM_RES_MINUTE, rtc->features);
clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, rtc->features);
rtc->range_max = (1ULL << 24) * 60 - 1; // 24-bit minutes + 59 secs rtc->range_max = (1ULL << 24) * 60 - 1; // 24-bit minutes + 59 secs
rtc->start_secs = RTC_TIMESTAMP_BEGIN_2000; rtc->start_secs = RTC_TIMESTAMP_BEGIN_2000;

View File

@ -199,11 +199,18 @@ static const struct of_device_id ds1302_dt_ids[] = {
MODULE_DEVICE_TABLE(of, ds1302_dt_ids); MODULE_DEVICE_TABLE(of, ds1302_dt_ids);
#endif #endif
static const struct spi_device_id ds1302_spi_ids[] = {
{ .name = "ds1302", },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(spi, ds1302_spi_ids);
static struct spi_driver ds1302_driver = { static struct spi_driver ds1302_driver = {
.driver.name = "rtc-ds1302", .driver.name = "rtc-ds1302",
.driver.of_match_table = of_match_ptr(ds1302_dt_ids), .driver.of_match_table = of_match_ptr(ds1302_dt_ids),
.probe = ds1302_probe, .probe = ds1302_probe,
.remove = ds1302_remove, .remove = ds1302_remove,
.id_table = ds1302_spi_ids,
}; };
module_spi_driver(ds1302_driver); module_spi_driver(ds1302_driver);

View File

@ -219,12 +219,19 @@ static const struct of_device_id ds1390_of_match[] = {
}; };
MODULE_DEVICE_TABLE(of, ds1390_of_match); MODULE_DEVICE_TABLE(of, ds1390_of_match);
static const struct spi_device_id ds1390_spi_ids[] = {
{ .name = "ds1390" },
{}
};
MODULE_DEVICE_TABLE(spi, ds1390_spi_ids);
static struct spi_driver ds1390_driver = { static struct spi_driver ds1390_driver = {
.driver = { .driver = {
.name = "rtc-ds1390", .name = "rtc-ds1390",
.of_match_table = of_match_ptr(ds1390_of_match), .of_match_table = of_match_ptr(ds1390_of_match),
}, },
.probe = ds1390_probe, .probe = ds1390_probe,
.id_table = ds1390_spi_ids,
}; };
module_spi_driver(ds1390_driver); module_spi_driver(ds1390_driver);

View File

@ -557,7 +557,7 @@ static struct clk *m41t80_sqw_register_clk(struct m41t80_data *m41t80)
* registered automatically when being referenced. * registered automatically when being referenced.
*/ */
of_node_put(fixed_clock); of_node_put(fixed_clock);
return 0; return NULL;
} }
/* First disable the clock */ /* First disable the clock */

View File

@ -430,12 +430,19 @@ static const struct of_device_id mcp795_of_match[] = {
MODULE_DEVICE_TABLE(of, mcp795_of_match); MODULE_DEVICE_TABLE(of, mcp795_of_match);
#endif #endif
static const struct spi_device_id mcp795_spi_ids[] = {
{ .name = "mcp795" },
{ }
};
MODULE_DEVICE_TABLE(spi, mcp795_spi_ids);
static struct spi_driver mcp795_driver = { static struct spi_driver mcp795_driver = {
.driver = { .driver = {
.name = "rtc-mcp795", .name = "rtc-mcp795",
.of_match_table = of_match_ptr(mcp795_of_match), .of_match_table = of_match_ptr(mcp795_of_match),
}, },
.probe = mcp795_probe, .probe = mcp795_probe,
.id_table = mcp795_spi_ids,
}; };
module_spi_driver(mcp795_driver); module_spi_driver(mcp795_driver);

259
drivers/rtc/rtc-msc313.c Normal file
View File

@ -0,0 +1,259 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Real time clocks driver for MStar/SigmaStar ARMv7 SoCs.
* Based on "Real Time Clock driver for msb252x." that was contained
* in various MStar kernels.
*
* (C) 2019 Daniel Palmer
* (C) 2021 Romain Perier
*/
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/platform_device.h>
#include <linux/rtc.h>
/* Registers */
#define REG_RTC_CTRL 0x00
#define REG_RTC_FREQ_CW_L 0x04
#define REG_RTC_FREQ_CW_H 0x08
#define REG_RTC_LOAD_VAL_L 0x0C
#define REG_RTC_LOAD_VAL_H 0x10
#define REG_RTC_MATCH_VAL_L 0x14
#define REG_RTC_MATCH_VAL_H 0x18
#define REG_RTC_STATUS_INT 0x1C
#define REG_RTC_CNT_VAL_L 0x20
#define REG_RTC_CNT_VAL_H 0x24
/* Control bits for REG_RTC_CTRL */
#define SOFT_RSTZ_BIT BIT(0)
#define CNT_EN_BIT BIT(1)
#define WRAP_EN_BIT BIT(2)
#define LOAD_EN_BIT BIT(3)
#define READ_EN_BIT BIT(4)
#define INT_MASK_BIT BIT(5)
#define INT_FORCE_BIT BIT(6)
#define INT_CLEAR_BIT BIT(7)
/* Control bits for REG_RTC_STATUS_INT */
#define RAW_INT_BIT BIT(0)
#define ALM_INT_BIT BIT(1)
struct msc313_rtc {
struct rtc_device *rtc_dev;
void __iomem *rtc_base;
};
static int msc313_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
{
struct msc313_rtc *priv = dev_get_drvdata(dev);
unsigned long seconds;
seconds = readw(priv->rtc_base + REG_RTC_MATCH_VAL_L)
| ((unsigned long)readw(priv->rtc_base + REG_RTC_MATCH_VAL_H) << 16);
rtc_time64_to_tm(seconds, &alarm->time);
if (!(readw(priv->rtc_base + REG_RTC_CTRL) & INT_MASK_BIT))
alarm->enabled = 1;
return 0;
}
static int msc313_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
{
struct msc313_rtc *priv = dev_get_drvdata(dev);
u16 reg;
reg = readw(priv->rtc_base + REG_RTC_CTRL);
if (enabled)
reg &= ~INT_MASK_BIT;
else
reg |= INT_MASK_BIT;
writew(reg, priv->rtc_base + REG_RTC_CTRL);
return 0;
}
static int msc313_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
{
struct msc313_rtc *priv = dev_get_drvdata(dev);
unsigned long seconds;
seconds = rtc_tm_to_time64(&alarm->time);
writew((seconds & 0xFFFF), priv->rtc_base + REG_RTC_MATCH_VAL_L);
writew((seconds >> 16) & 0xFFFF, priv->rtc_base + REG_RTC_MATCH_VAL_H);
msc313_rtc_alarm_irq_enable(dev, alarm->enabled);
return 0;
}
static bool msc313_rtc_get_enabled(struct msc313_rtc *priv)
{
return readw(priv->rtc_base + REG_RTC_CTRL) & CNT_EN_BIT;
}
static void msc313_rtc_set_enabled(struct msc313_rtc *priv)
{
u16 reg;
reg = readw(priv->rtc_base + REG_RTC_CTRL);
reg |= CNT_EN_BIT;
writew(reg, priv->rtc_base + REG_RTC_CTRL);
}
static int msc313_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
struct msc313_rtc *priv = dev_get_drvdata(dev);
u32 seconds;
u16 reg;
if (!msc313_rtc_get_enabled(priv))
return -EINVAL;
reg = readw(priv->rtc_base + REG_RTC_CTRL);
writew(reg | READ_EN_BIT, priv->rtc_base + REG_RTC_CTRL);
/* Wait for HW latch done */
while (readw(priv->rtc_base + REG_RTC_CTRL) & READ_EN_BIT)
udelay(1);
seconds = readw(priv->rtc_base + REG_RTC_CNT_VAL_L)
| ((unsigned long)readw(priv->rtc_base + REG_RTC_CNT_VAL_H) << 16);
rtc_time64_to_tm(seconds, tm);
return 0;
}
static int msc313_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
struct msc313_rtc *priv = dev_get_drvdata(dev);
unsigned long seconds;
u16 reg;
seconds = rtc_tm_to_time64(tm);
writew(seconds & 0xFFFF, priv->rtc_base + REG_RTC_LOAD_VAL_L);
writew((seconds >> 16) & 0xFFFF, priv->rtc_base + REG_RTC_LOAD_VAL_H);
/* Enable load for loading value into internal RTC counter */
reg = readw(priv->rtc_base + REG_RTC_CTRL);
writew(reg | LOAD_EN_BIT, priv->rtc_base + REG_RTC_CTRL);
/* Wait for HW latch done */
while (readw(priv->rtc_base + REG_RTC_CTRL) & LOAD_EN_BIT)
udelay(1);
msc313_rtc_set_enabled(priv);
return 0;
}
static const struct rtc_class_ops msc313_rtc_ops = {
.read_time = msc313_rtc_read_time,
.set_time = msc313_rtc_set_time,
.read_alarm = msc313_rtc_read_alarm,
.set_alarm = msc313_rtc_set_alarm,
.alarm_irq_enable = msc313_rtc_alarm_irq_enable,
};
static irqreturn_t msc313_rtc_interrupt(s32 irq, void *dev_id)
{
struct msc313_rtc *priv = dev_get_drvdata(dev_id);
u16 reg;
reg = readw(priv->rtc_base + REG_RTC_STATUS_INT);
if (!(reg & ALM_INT_BIT))
return IRQ_NONE;
reg = readw(priv->rtc_base + REG_RTC_CTRL);
reg |= INT_CLEAR_BIT;
reg &= ~INT_FORCE_BIT;
writew(reg, priv->rtc_base + REG_RTC_CTRL);
rtc_update_irq(priv->rtc_dev, 1, RTC_IRQF | RTC_AF);
return IRQ_HANDLED;
}
static int msc313_rtc_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct msc313_rtc *priv;
unsigned long rate;
struct clk *clk;
int ret;
int irq;
priv = devm_kzalloc(&pdev->dev, sizeof(struct msc313_rtc), GFP_KERNEL);
if (!priv)
return -ENOMEM;
priv->rtc_base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(priv->rtc_base))
return PTR_ERR(priv->rtc_base);
irq = platform_get_irq(pdev, 0);
if (irq < 0)
return -EINVAL;
priv->rtc_dev = devm_rtc_allocate_device(dev);
if (IS_ERR(priv->rtc_dev))
return PTR_ERR(priv->rtc_dev);
priv->rtc_dev->ops = &msc313_rtc_ops;
priv->rtc_dev->range_max = U32_MAX;
ret = devm_request_irq(dev, irq, msc313_rtc_interrupt, IRQF_SHARED,
dev_name(&pdev->dev), &pdev->dev);
if (ret) {
dev_err(dev, "Could not request IRQ\n");
return ret;
}
clk = devm_clk_get(dev, NULL);
if (IS_ERR(clk)) {
dev_err(dev, "No input reference clock\n");
return PTR_ERR(clk);
}
ret = clk_prepare_enable(clk);
if (ret) {
dev_err(dev, "Failed to enable the reference clock, %d\n", ret);
return ret;
}
ret = devm_add_action_or_reset(dev, (void (*) (void *))clk_disable_unprepare, clk);
if (ret)
return ret;
rate = clk_get_rate(clk);
writew(rate & 0xFFFF, priv->rtc_base + REG_RTC_FREQ_CW_L);
writew((rate >> 16) & 0xFFFF, priv->rtc_base + REG_RTC_FREQ_CW_H);
platform_set_drvdata(pdev, priv);
return devm_rtc_register_device(priv->rtc_dev);
}
static const struct of_device_id msc313_rtc_of_match_table[] = {
{ .compatible = "mstar,msc313-rtc" },
{ }
};
MODULE_DEVICE_TABLE(of, msc313_rtc_of_match_table);
static struct platform_driver msc313_rtc_driver = {
.probe = msc313_rtc_probe,
.driver = {
.name = "msc313-rtc",
.of_match_table = msc313_rtc_of_match_table,
},
};
module_platform_driver(msc313_rtc_driver);
MODULE_AUTHOR("Daniel Palmer <daniel@thingy.jp>");
MODULE_AUTHOR("Romain Perier <romain.perier@gmail.com>");
MODULE_DESCRIPTION("MStar RTC Driver");
MODULE_LICENSE("GPL v2");

View File

@ -1029,6 +1029,5 @@ static struct platform_driver omap_rtc_driver = {
module_platform_driver(omap_rtc_driver); module_platform_driver(omap_rtc_driver);
MODULE_ALIAS("platform:omap_rtc");
MODULE_AUTHOR("George G. Davis (and others)"); MODULE_AUTHOR("George G. Davis (and others)");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");

View File

@ -451,12 +451,21 @@ static const struct of_device_id pcf2123_dt_ids[] = {
MODULE_DEVICE_TABLE(of, pcf2123_dt_ids); MODULE_DEVICE_TABLE(of, pcf2123_dt_ids);
#endif #endif
static const struct spi_device_id pcf2123_spi_ids[] = {
{ .name = "pcf2123", },
{ .name = "rv2123", },
{ .name = "rtc-pcf2123", },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(spi, pcf2123_spi_ids);
static struct spi_driver pcf2123_driver = { static struct spi_driver pcf2123_driver = {
.driver = { .driver = {
.name = "rtc-pcf2123", .name = "rtc-pcf2123",
.of_match_table = of_match_ptr(pcf2123_dt_ids), .of_match_table = of_match_ptr(pcf2123_dt_ids),
}, },
.probe = pcf2123_probe, .probe = pcf2123_probe,
.id_table = pcf2123_spi_ids,
}; };
module_spi_driver(pcf2123_driver); module_spi_driver(pcf2123_driver);

View File

@ -34,6 +34,7 @@
#define PCF85063_REG_CTRL1 0x00 /* status */ #define PCF85063_REG_CTRL1 0x00 /* status */
#define PCF85063_REG_CTRL1_CAP_SEL BIT(0) #define PCF85063_REG_CTRL1_CAP_SEL BIT(0)
#define PCF85063_REG_CTRL1_STOP BIT(5) #define PCF85063_REG_CTRL1_STOP BIT(5)
#define PCF85063_REG_CTRL1_EXT_TEST BIT(7)
#define PCF85063_REG_CTRL2 0x01 #define PCF85063_REG_CTRL2 0x01
#define PCF85063_CTRL2_AF BIT(6) #define PCF85063_CTRL2_AF BIT(6)
@ -117,6 +118,7 @@ static int pcf85063_rtc_set_time(struct device *dev, struct rtc_time *tm)
* reset state until all time/date registers are written * reset state until all time/date registers are written
*/ */
rc = regmap_update_bits(pcf85063->regmap, PCF85063_REG_CTRL1, rc = regmap_update_bits(pcf85063->regmap, PCF85063_REG_CTRL1,
PCF85063_REG_CTRL1_EXT_TEST |
PCF85063_REG_CTRL1_STOP, PCF85063_REG_CTRL1_STOP,
PCF85063_REG_CTRL1_STOP); PCF85063_REG_CTRL1_STOP);
if (rc) if (rc)
@ -297,7 +299,7 @@ static int pcf85063_ioctl(struct device *dev, unsigned int cmd,
if (ret < 0) if (ret < 0)
return ret; return ret;
status = status & PCF85063_REG_SC_OS ? RTC_VL_DATA_INVALID : 0; status = (status & PCF85063_REG_SC_OS) ? RTC_VL_DATA_INVALID : 0;
return put_user(status, (unsigned int __user *)arg); return put_user(status, (unsigned int __user *)arg);
@ -479,6 +481,18 @@ static struct clk *pcf85063_clkout_register_clk(struct pcf85063 *pcf85063)
struct clk *clk; struct clk *clk;
struct clk_init_data init; struct clk_init_data init;
struct device_node *node = pcf85063->rtc->dev.parent->of_node; struct device_node *node = pcf85063->rtc->dev.parent->of_node;
struct device_node *fixed_clock;
fixed_clock = of_get_child_by_name(node, "clock");
if (fixed_clock) {
/*
* skip registering square wave clock when a fixed
* clock has been registered. The fixed clock is
* registered automatically when being referenced.
*/
of_node_put(fixed_clock);
return NULL;
}
init.name = "pcf85063-clkout"; init.name = "pcf85063-clkout";
init.ops = &pcf85063_clkout_ops; init.ops = &pcf85063_clkout_ops;

View File

@ -4,8 +4,10 @@
*/ */
#include <linux/bcd.h> #include <linux/bcd.h>
#include <linux/bitfield.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/regmap.h>
#include <linux/rtc.h> #include <linux/rtc.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/pm_wakeirq.h> #include <linux/pm_wakeirq.h>
@ -19,11 +21,10 @@
#define PCF8523_CONTROL2_AF BIT(3) #define PCF8523_CONTROL2_AF BIT(3)
#define PCF8523_REG_CONTROL3 0x02 #define PCF8523_REG_CONTROL3 0x02
#define PCF8523_CONTROL3_PM_BLD BIT(7) /* battery low detection disabled */ #define PCF8523_CONTROL3_PM GENMASK(7,5)
#define PCF8523_CONTROL3_PM_VDD BIT(6) /* switch-over disabled */ #define PCF8523_PM_STANDBY 0x7
#define PCF8523_CONTROL3_PM_DSM BIT(5) /* direct switching mode */
#define PCF8523_CONTROL3_PM_MASK 0xe0
#define PCF8523_CONTROL3_BLF BIT(2) /* battery low bit, read-only */ #define PCF8523_CONTROL3_BLF BIT(2) /* battery low bit, read-only */
#define PCF8523_CONTROL3_BSF BIT(3)
#define PCF8523_REG_SECONDS 0x03 #define PCF8523_REG_SECONDS 0x03
#define PCF8523_SECONDS_OS BIT(7) #define PCF8523_SECONDS_OS BIT(7)
@ -48,127 +49,45 @@
struct pcf8523 { struct pcf8523 {
struct rtc_device *rtc; struct rtc_device *rtc;
struct i2c_client *client; struct regmap *regmap;
}; };
static int pcf8523_read(struct i2c_client *client, u8 reg, u8 *valuep) static int pcf8523_load_capacitance(struct pcf8523 *pcf8523, struct device_node *node)
{ {
struct i2c_msg msgs[2]; u32 load, value = 0;
u8 value = 0;
int err;
msgs[0].addr = client->addr;
msgs[0].flags = 0;
msgs[0].len = sizeof(reg);
msgs[0].buf = &reg;
msgs[1].addr = client->addr;
msgs[1].flags = I2C_M_RD;
msgs[1].len = sizeof(value);
msgs[1].buf = &value;
err = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
if (err < 0)
return err;
*valuep = value;
return 0;
}
static int pcf8523_write(struct i2c_client *client, u8 reg, u8 value)
{
u8 buffer[2] = { reg, value };
struct i2c_msg msg;
int err;
msg.addr = client->addr;
msg.flags = 0;
msg.len = sizeof(buffer);
msg.buf = buffer;
err = i2c_transfer(client->adapter, &msg, 1);
if (err < 0)
return err;
return 0;
}
static int pcf8523_voltage_low(struct i2c_client *client)
{
u8 value;
int err;
err = pcf8523_read(client, PCF8523_REG_CONTROL3, &value);
if (err < 0)
return err;
return !!(value & PCF8523_CONTROL3_BLF);
}
static int pcf8523_load_capacitance(struct i2c_client *client)
{
u32 load;
u8 value;
int err;
err = pcf8523_read(client, PCF8523_REG_CONTROL1, &value);
if (err < 0)
return err;
load = 12500; load = 12500;
of_property_read_u32(client->dev.of_node, "quartz-load-femtofarads", of_property_read_u32(node, "quartz-load-femtofarads", &load);
&load);
switch (load) { switch (load) {
default: default:
dev_warn(&client->dev, "Unknown quartz-load-femtofarads value: %d. Assuming 12500", dev_warn(&pcf8523->rtc->dev, "Unknown quartz-load-femtofarads value: %d. Assuming 12500",
load); load);
fallthrough; fallthrough;
case 12500: case 12500:
value |= PCF8523_CONTROL1_CAP_SEL; value |= PCF8523_CONTROL1_CAP_SEL;
break; break;
case 7000: case 7000:
value &= ~PCF8523_CONTROL1_CAP_SEL;
break; break;
} }
err = pcf8523_write(client, PCF8523_REG_CONTROL1, value); return regmap_update_bits(pcf8523->regmap, PCF8523_REG_CONTROL1,
PCF8523_CONTROL1_CAP_SEL, value);
return err;
}
static int pcf8523_set_pm(struct i2c_client *client, u8 pm)
{
u8 value;
int err;
err = pcf8523_read(client, PCF8523_REG_CONTROL3, &value);
if (err < 0)
return err;
value = (value & ~PCF8523_CONTROL3_PM_MASK) | pm;
err = pcf8523_write(client, PCF8523_REG_CONTROL3, value);
if (err < 0)
return err;
return 0;
} }
static irqreturn_t pcf8523_irq(int irq, void *dev_id) static irqreturn_t pcf8523_irq(int irq, void *dev_id)
{ {
struct pcf8523 *pcf8523 = i2c_get_clientdata(dev_id); struct pcf8523 *pcf8523 = dev_id;
u8 value; u32 value;
int err; int err;
err = pcf8523_read(pcf8523->client, PCF8523_REG_CONTROL2, &value); err = regmap_read(pcf8523->regmap, PCF8523_REG_CONTROL2, &value);
if (err < 0) if (err < 0)
return IRQ_HANDLED; return IRQ_HANDLED;
if (value & PCF8523_CONTROL2_AF) { if (value & PCF8523_CONTROL2_AF) {
value &= ~PCF8523_CONTROL2_AF; value &= ~PCF8523_CONTROL2_AF;
pcf8523_write(pcf8523->client, PCF8523_REG_CONTROL2, value); regmap_write(pcf8523->regmap, PCF8523_REG_CONTROL2, value);
rtc_update_irq(pcf8523->rtc, 1, RTC_IRQF | RTC_AF); rtc_update_irq(pcf8523->rtc, 1, RTC_IRQF | RTC_AF);
return IRQ_HANDLED; return IRQ_HANDLED;
@ -177,68 +96,14 @@ static irqreturn_t pcf8523_irq(int irq, void *dev_id)
return IRQ_NONE; return IRQ_NONE;
} }
static int pcf8523_stop_rtc(struct i2c_client *client)
{
u8 value;
int err;
err = pcf8523_read(client, PCF8523_REG_CONTROL1, &value);
if (err < 0)
return err;
value |= PCF8523_CONTROL1_STOP;
err = pcf8523_write(client, PCF8523_REG_CONTROL1, value);
if (err < 0)
return err;
return 0;
}
static int pcf8523_start_rtc(struct i2c_client *client)
{
u8 value;
int err;
err = pcf8523_read(client, PCF8523_REG_CONTROL1, &value);
if (err < 0)
return err;
value &= ~PCF8523_CONTROL1_STOP;
err = pcf8523_write(client, PCF8523_REG_CONTROL1, value);
if (err < 0)
return err;
return 0;
}
static int pcf8523_rtc_read_time(struct device *dev, struct rtc_time *tm) static int pcf8523_rtc_read_time(struct device *dev, struct rtc_time *tm)
{ {
struct i2c_client *client = to_i2c_client(dev); struct pcf8523 *pcf8523 = dev_get_drvdata(dev);
u8 start = PCF8523_REG_SECONDS, regs[7]; u8 regs[7];
struct i2c_msg msgs[2];
int err; int err;
err = pcf8523_voltage_low(client); err = regmap_bulk_read(pcf8523->regmap, PCF8523_REG_SECONDS, regs,
if (err < 0) { sizeof(regs));
return err;
} else if (err > 0) {
dev_err(dev, "low voltage detected, time is unreliable\n");
return -EINVAL;
}
msgs[0].addr = client->addr;
msgs[0].flags = 0;
msgs[0].len = 1;
msgs[0].buf = &start;
msgs[1].addr = client->addr;
msgs[1].flags = I2C_M_RD;
msgs[1].len = sizeof(regs);
msgs[1].buf = regs;
err = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
if (err < 0) if (err < 0)
return err; return err;
@ -258,63 +123,50 @@ static int pcf8523_rtc_read_time(struct device *dev, struct rtc_time *tm)
static int pcf8523_rtc_set_time(struct device *dev, struct rtc_time *tm) static int pcf8523_rtc_set_time(struct device *dev, struct rtc_time *tm)
{ {
struct i2c_client *client = to_i2c_client(dev); struct pcf8523 *pcf8523 = dev_get_drvdata(dev);
struct i2c_msg msg; u8 regs[7];
u8 regs[8];
int err; int err;
err = pcf8523_stop_rtc(client); err = regmap_update_bits(pcf8523->regmap, PCF8523_REG_CONTROL1,
PCF8523_CONTROL1_STOP, PCF8523_CONTROL1_STOP);
if (err < 0) if (err < 0)
return err; return err;
regs[0] = PCF8523_REG_SECONDS;
/* This will purposely overwrite PCF8523_SECONDS_OS */ /* This will purposely overwrite PCF8523_SECONDS_OS */
regs[1] = bin2bcd(tm->tm_sec); regs[0] = bin2bcd(tm->tm_sec);
regs[2] = bin2bcd(tm->tm_min); regs[1] = bin2bcd(tm->tm_min);
regs[3] = bin2bcd(tm->tm_hour); regs[2] = bin2bcd(tm->tm_hour);
regs[4] = bin2bcd(tm->tm_mday); regs[3] = bin2bcd(tm->tm_mday);
regs[5] = tm->tm_wday; regs[4] = tm->tm_wday;
regs[6] = bin2bcd(tm->tm_mon + 1); regs[5] = bin2bcd(tm->tm_mon + 1);
regs[7] = bin2bcd(tm->tm_year - 100); regs[6] = bin2bcd(tm->tm_year - 100);
msg.addr = client->addr; err = regmap_bulk_write(pcf8523->regmap, PCF8523_REG_SECONDS, regs,
msg.flags = 0; sizeof(regs));
msg.len = sizeof(regs);
msg.buf = regs;
err = i2c_transfer(client->adapter, &msg, 1);
if (err < 0) { if (err < 0) {
/* /*
* If the time cannot be set, restart the RTC anyway. Note * If the time cannot be set, restart the RTC anyway. Note
* that errors are ignored if the RTC cannot be started so * that errors are ignored if the RTC cannot be started so
* that we have a chance to propagate the original error. * that we have a chance to propagate the original error.
*/ */
pcf8523_start_rtc(client); regmap_update_bits(pcf8523->regmap, PCF8523_REG_CONTROL1,
PCF8523_CONTROL1_STOP, 0);
return err; return err;
} }
return pcf8523_start_rtc(client); return regmap_update_bits(pcf8523->regmap, PCF8523_REG_CONTROL1,
PCF8523_CONTROL1_STOP, 0);
} }
static int pcf8523_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *tm) static int pcf8523_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *tm)
{ {
struct i2c_client *client = to_i2c_client(dev); struct pcf8523 *pcf8523 = dev_get_drvdata(dev);
u8 start = PCF8523_REG_MINUTE_ALARM, regs[4]; u8 regs[4];
struct i2c_msg msgs[2]; u32 value;
u8 value;
int err; int err;
msgs[0].addr = client->addr; err = regmap_bulk_read(pcf8523->regmap, PCF8523_REG_MINUTE_ALARM, regs,
msgs[0].flags = 0; sizeof(regs));
msgs[0].len = 1;
msgs[0].buf = &start;
msgs[1].addr = client->addr;
msgs[1].flags = I2C_M_RD;
msgs[1].len = sizeof(regs);
msgs[1].buf = regs;
err = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
if (err < 0) if (err < 0)
return err; return err;
@ -324,12 +176,12 @@ static int pcf8523_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *tm)
tm->time.tm_mday = bcd2bin(regs[2] & 0x3F); tm->time.tm_mday = bcd2bin(regs[2] & 0x3F);
tm->time.tm_wday = bcd2bin(regs[3] & 0x7); tm->time.tm_wday = bcd2bin(regs[3] & 0x7);
err = pcf8523_read(client, PCF8523_REG_CONTROL1, &value); err = regmap_read(pcf8523->regmap, PCF8523_REG_CONTROL1, &value);
if (err < 0) if (err < 0)
return err; return err;
tm->enabled = !!(value & PCF8523_CONTROL1_AIE); tm->enabled = !!(value & PCF8523_CONTROL1_AIE);
err = pcf8523_read(client, PCF8523_REG_CONTROL2, &value); err = regmap_read(pcf8523->regmap, PCF8523_REG_CONTROL2, &value);
if (err < 0) if (err < 0)
return err; return err;
tm->pending = !!(value & PCF8523_CONTROL2_AF); tm->pending = !!(value & PCF8523_CONTROL2_AF);
@ -339,30 +191,16 @@ static int pcf8523_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *tm)
static int pcf8523_irq_enable(struct device *dev, unsigned int enabled) static int pcf8523_irq_enable(struct device *dev, unsigned int enabled)
{ {
struct i2c_client *client = to_i2c_client(dev); struct pcf8523 *pcf8523 = dev_get_drvdata(dev);
u8 value;
int err;
err = pcf8523_read(client, PCF8523_REG_CONTROL1, &value); return regmap_update_bits(pcf8523->regmap, PCF8523_REG_CONTROL1,
if (err < 0) PCF8523_CONTROL1_AIE, enabled ?
return err; PCF8523_CONTROL1_AIE : 0);
value &= PCF8523_CONTROL1_AIE;
if (enabled)
value |= PCF8523_CONTROL1_AIE;
err = pcf8523_write(client, PCF8523_REG_CONTROL1, value);
if (err < 0)
return err;
return 0;
} }
static int pcf8523_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *tm) static int pcf8523_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *tm)
{ {
struct i2c_client *client = to_i2c_client(dev); struct pcf8523 *pcf8523 = dev_get_drvdata(dev);
struct i2c_msg msg;
u8 regs[5]; u8 regs[5];
int err; int err;
@ -370,7 +208,7 @@ static int pcf8523_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *tm)
if (err) if (err)
return err; return err;
err = pcf8523_write(client, PCF8523_REG_CONTROL2, 0); err = regmap_write(pcf8523->regmap, PCF8523_REG_CONTROL2, 0);
if (err < 0) if (err < 0)
return err; return err;
@ -382,16 +220,13 @@ static int pcf8523_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *tm)
rtc_time64_to_tm(alarm_time, &tm->time); rtc_time64_to_tm(alarm_time, &tm->time);
} }
regs[0] = PCF8523_REG_MINUTE_ALARM; regs[0] = bin2bcd(tm->time.tm_min);
regs[1] = bin2bcd(tm->time.tm_min); regs[1] = bin2bcd(tm->time.tm_hour);
regs[2] = bin2bcd(tm->time.tm_hour); regs[2] = bin2bcd(tm->time.tm_mday);
regs[3] = bin2bcd(tm->time.tm_mday); regs[3] = ALARM_DIS;
regs[4] = ALARM_DIS;
msg.addr = client->addr; err = regmap_bulk_write(pcf8523->regmap, PCF8523_REG_MINUTE_ALARM, regs,
msg.flags = 0; sizeof(regs));
msg.len = sizeof(regs);
msg.buf = regs;
err = i2c_transfer(client->adapter, &msg, 1);
if (err < 0) if (err < 0)
return err; return err;
@ -401,24 +236,101 @@ static int pcf8523_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *tm)
return 0; return 0;
} }
#ifdef CONFIG_RTC_INTF_DEV static int pcf8523_param_get(struct device *dev, struct rtc_param *param)
{
struct pcf8523 *pcf8523 = dev_get_drvdata(dev);
int ret;
switch(param->param) {
u32 value;
case RTC_PARAM_BACKUP_SWITCH_MODE:
ret = regmap_read(pcf8523->regmap, PCF8523_REG_CONTROL3, &value);
if (ret < 0)
return ret;
value = FIELD_GET(PCF8523_CONTROL3_PM, value);
switch(value) {
case 0x0:
case 0x4:
param->uvalue = RTC_BSM_LEVEL;
break;
case 0x1:
case 0x5:
param->uvalue = RTC_BSM_DIRECT;
break;
case PCF8523_PM_STANDBY:
param->uvalue = RTC_BSM_STANDBY;
break;
default:
param->uvalue = RTC_BSM_DISABLED;
}
break;
default:
return -EINVAL;
}
return 0;
}
static int pcf8523_param_set(struct device *dev, struct rtc_param *param)
{
struct pcf8523 *pcf8523 = dev_get_drvdata(dev);
switch(param->param) {
u8 mode;
case RTC_PARAM_BACKUP_SWITCH_MODE:
switch (param->uvalue) {
case RTC_BSM_DISABLED:
mode = 0x2;
break;
case RTC_BSM_DIRECT:
mode = 0x1;
break;
case RTC_BSM_LEVEL:
mode = 0x0;
break;
case RTC_BSM_STANDBY:
mode = PCF8523_PM_STANDBY;
break;
default:
return -EINVAL;
}
return regmap_update_bits(pcf8523->regmap, PCF8523_REG_CONTROL3,
PCF8523_CONTROL3_PM,
FIELD_PREP(PCF8523_CONTROL3_PM, mode));
break;
default:
return -EINVAL;
}
return 0;
}
static int pcf8523_rtc_ioctl(struct device *dev, unsigned int cmd, static int pcf8523_rtc_ioctl(struct device *dev, unsigned int cmd,
unsigned long arg) unsigned long arg)
{ {
struct i2c_client *client = to_i2c_client(dev); struct pcf8523 *pcf8523 = dev_get_drvdata(dev);
unsigned int flags = 0; unsigned int flags = 0;
u8 value; u32 value;
int ret; int ret;
switch (cmd) { switch (cmd) {
case RTC_VL_READ: case RTC_VL_READ:
ret = pcf8523_voltage_low(client); ret = regmap_read(pcf8523->regmap, PCF8523_REG_CONTROL3, &value);
if (ret < 0) if (ret < 0)
return ret; return ret;
if (ret)
if (value & PCF8523_CONTROL3_BLF)
flags |= RTC_VL_BACKUP_LOW; flags |= RTC_VL_BACKUP_LOW;
ret = pcf8523_read(client, PCF8523_REG_SECONDS, &value); ret = regmap_read(pcf8523->regmap, PCF8523_REG_SECONDS, &value);
if (ret < 0) if (ret < 0)
return ret; return ret;
@ -431,18 +343,15 @@ static int pcf8523_rtc_ioctl(struct device *dev, unsigned int cmd,
return -ENOIOCTLCMD; return -ENOIOCTLCMD;
} }
} }
#else
#define pcf8523_rtc_ioctl NULL
#endif
static int pcf8523_rtc_read_offset(struct device *dev, long *offset) static int pcf8523_rtc_read_offset(struct device *dev, long *offset)
{ {
struct i2c_client *client = to_i2c_client(dev); struct pcf8523 *pcf8523 = dev_get_drvdata(dev);
int err; int err;
u8 value; u32 value;
s8 val; s8 val;
err = pcf8523_read(client, PCF8523_REG_OFFSET, &value); err = regmap_read(pcf8523->regmap, PCF8523_REG_OFFSET, &value);
if (err < 0) if (err < 0)
return err; return err;
@ -455,9 +364,9 @@ static int pcf8523_rtc_read_offset(struct device *dev, long *offset)
static int pcf8523_rtc_set_offset(struct device *dev, long offset) static int pcf8523_rtc_set_offset(struct device *dev, long offset)
{ {
struct i2c_client *client = to_i2c_client(dev); struct pcf8523 *pcf8523 = dev_get_drvdata(dev);
long reg_m0, reg_m1; long reg_m0, reg_m1;
u8 value; u32 value;
reg_m0 = clamp(DIV_ROUND_CLOSEST(offset, 4340), -64L, 63L); reg_m0 = clamp(DIV_ROUND_CLOSEST(offset, 4340), -64L, 63L);
reg_m1 = clamp(DIV_ROUND_CLOSEST(offset, 4069), -64L, 63L); reg_m1 = clamp(DIV_ROUND_CLOSEST(offset, 4069), -64L, 63L);
@ -467,7 +376,7 @@ static int pcf8523_rtc_set_offset(struct device *dev, long offset)
else else
value = (reg_m1 & 0x7f) | PCF8523_OFFSET_MODE; value = (reg_m1 & 0x7f) | PCF8523_OFFSET_MODE;
return pcf8523_write(client, PCF8523_REG_OFFSET, value); return regmap_write(pcf8523->regmap, PCF8523_REG_OFFSET, value);
} }
static const struct rtc_class_ops pcf8523_rtc_ops = { static const struct rtc_class_ops pcf8523_rtc_ops = {
@ -479,6 +388,14 @@ static const struct rtc_class_ops pcf8523_rtc_ops = {
.ioctl = pcf8523_rtc_ioctl, .ioctl = pcf8523_rtc_ioctl,
.read_offset = pcf8523_rtc_read_offset, .read_offset = pcf8523_rtc_read_offset,
.set_offset = pcf8523_rtc_set_offset, .set_offset = pcf8523_rtc_set_offset,
.param_get = pcf8523_param_get,
.param_set = pcf8523_param_set,
};
static const struct regmap_config regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = 0x13,
}; };
static int pcf8523_probe(struct i2c_client *client, static int pcf8523_probe(struct i2c_client *client,
@ -487,6 +404,7 @@ static int pcf8523_probe(struct i2c_client *client,
struct pcf8523 *pcf8523; struct pcf8523 *pcf8523;
struct rtc_device *rtc; struct rtc_device *rtc;
bool wakeup_source = false; bool wakeup_source = false;
u32 value;
int err; int err;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
@ -496,46 +414,60 @@ static int pcf8523_probe(struct i2c_client *client,
if (!pcf8523) if (!pcf8523)
return -ENOMEM; return -ENOMEM;
pcf8523->regmap = devm_regmap_init_i2c(client, &regmap_config);
if (IS_ERR(pcf8523->regmap))
return PTR_ERR(pcf8523->regmap);
i2c_set_clientdata(client, pcf8523); i2c_set_clientdata(client, pcf8523);
pcf8523->client = client;
err = pcf8523_load_capacitance(client);
if (err < 0)
dev_warn(&client->dev, "failed to set xtal load capacitance: %d",
err);
err = pcf8523_set_pm(client, 0);
if (err < 0)
return err;
rtc = devm_rtc_allocate_device(&client->dev); rtc = devm_rtc_allocate_device(&client->dev);
if (IS_ERR(rtc)) if (IS_ERR(rtc))
return PTR_ERR(rtc); return PTR_ERR(rtc);
pcf8523->rtc = rtc; pcf8523->rtc = rtc;
err = pcf8523_load_capacitance(pcf8523, client->dev.of_node);
if (err < 0)
dev_warn(&client->dev, "failed to set xtal load capacitance: %d",
err);
err = regmap_read(pcf8523->regmap, PCF8523_REG_SECONDS, &value);
if (err < 0)
return err;
if (value & PCF8523_SECONDS_OS) {
err = regmap_read(pcf8523->regmap, PCF8523_REG_CONTROL3, &value);
if (err < 0)
return err;
if (FIELD_GET(PCF8523_CONTROL3_PM, value) == PCF8523_PM_STANDBY) {
err = regmap_write(pcf8523->regmap, PCF8523_REG_CONTROL3,
value & ~PCF8523_CONTROL3_PM);
if (err < 0)
return err;
}
}
rtc->ops = &pcf8523_rtc_ops; rtc->ops = &pcf8523_rtc_ops;
rtc->range_min = RTC_TIMESTAMP_BEGIN_2000; rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
rtc->range_max = RTC_TIMESTAMP_END_2099; rtc->range_max = RTC_TIMESTAMP_END_2099;
rtc->uie_unsupported = 1; rtc->uie_unsupported = 1;
if (client->irq > 0) { if (client->irq > 0) {
err = pcf8523_write(client, PCF8523_TMR_CLKOUT_CTRL, 0x38); err = regmap_write(pcf8523->regmap, PCF8523_TMR_CLKOUT_CTRL, 0x38);
if (err < 0) if (err < 0)
return err; return err;
err = devm_request_threaded_irq(&client->dev, client->irq, err = devm_request_threaded_irq(&client->dev, client->irq,
NULL, pcf8523_irq, NULL, pcf8523_irq,
IRQF_SHARED | IRQF_ONESHOT | IRQF_TRIGGER_LOW, IRQF_SHARED | IRQF_ONESHOT | IRQF_TRIGGER_LOW,
dev_name(&rtc->dev), client); dev_name(&rtc->dev), pcf8523);
if (err) if (err)
return err; return err;
dev_pm_set_wake_irq(&client->dev, client->irq); dev_pm_set_wake_irq(&client->dev, client->irq);
} }
#ifdef CONFIG_OF
wakeup_source = of_property_read_bool(client->dev.of_node, "wakeup-source"); wakeup_source = of_property_read_bool(client->dev.of_node, "wakeup-source");
#endif
if (client->irq > 0 || wakeup_source) if (client->irq > 0 || wakeup_source)
device_init_wakeup(&client->dev, true); device_init_wakeup(&client->dev, true);
@ -548,19 +480,17 @@ static const struct i2c_device_id pcf8523_id[] = {
}; };
MODULE_DEVICE_TABLE(i2c, pcf8523_id); MODULE_DEVICE_TABLE(i2c, pcf8523_id);
#ifdef CONFIG_OF
static const struct of_device_id pcf8523_of_match[] = { static const struct of_device_id pcf8523_of_match[] = {
{ .compatible = "nxp,pcf8523" }, { .compatible = "nxp,pcf8523" },
{ .compatible = "microcrystal,rv8523" }, { .compatible = "microcrystal,rv8523" },
{ } { }
}; };
MODULE_DEVICE_TABLE(of, pcf8523_of_match); MODULE_DEVICE_TABLE(of, pcf8523_of_match);
#endif
static struct i2c_driver pcf8523_driver = { static struct i2c_driver pcf8523_driver = {
.driver = { .driver = {
.name = "rtc-pcf8523", .name = "rtc-pcf8523",
.of_match_table = of_match_ptr(pcf8523_of_match), .of_match_table = pcf8523_of_match,
}, },
.probe = pcf8523_probe, .probe = pcf8523_probe,
.id_table = pcf8523_id, .id_table = pcf8523_id,

View File

@ -10,6 +10,7 @@
#include <linux/clk-provider.h> #include <linux/clk-provider.h>
#include <linux/bcd.h> #include <linux/bcd.h>
#include <linux/bitfield.h>
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
@ -80,6 +81,10 @@
#define RV3028_BACKUP_TCE BIT(5) #define RV3028_BACKUP_TCE BIT(5)
#define RV3028_BACKUP_TCR_MASK GENMASK(1,0) #define RV3028_BACKUP_TCR_MASK GENMASK(1,0)
#define RV3028_BACKUP_BSM GENMASK(3,2)
#define RV3028_BACKUP_BSM_DSM 0x1
#define RV3028_BACKUP_BSM_LSM 0x3
#define OFFSET_STEP_PPT 953674 #define OFFSET_STEP_PPT 953674
@ -512,6 +517,71 @@ exit_eerd:
} }
static int rv3028_param_get(struct device *dev, struct rtc_param *param)
{
struct rv3028_data *rv3028 = dev_get_drvdata(dev);
int ret;
switch(param->param) {
u32 value;
case RTC_PARAM_BACKUP_SWITCH_MODE:
ret = regmap_read(rv3028->regmap, RV3028_BACKUP, &value);
if (ret < 0)
return ret;
value = FIELD_GET(RV3028_BACKUP_BSM, value);
switch(value) {
case RV3028_BACKUP_BSM_DSM:
param->uvalue = RTC_BSM_DIRECT;
break;
case RV3028_BACKUP_BSM_LSM:
param->uvalue = RTC_BSM_LEVEL;
break;
default:
param->uvalue = RTC_BSM_DISABLED;
}
break;
default:
return -EINVAL;
}
return 0;
}
static int rv3028_param_set(struct device *dev, struct rtc_param *param)
{
struct rv3028_data *rv3028 = dev_get_drvdata(dev);
switch(param->param) {
u8 mode;
case RTC_PARAM_BACKUP_SWITCH_MODE:
switch (param->uvalue) {
case RTC_BSM_DISABLED:
mode = 0;
break;
case RTC_BSM_DIRECT:
mode = RV3028_BACKUP_BSM_DSM;
break;
case RTC_BSM_LEVEL:
mode = RV3028_BACKUP_BSM_LSM;
break;
default:
return -EINVAL;
}
return rv3028_update_cfg(rv3028, RV3028_BACKUP, RV3028_BACKUP_BSM,
FIELD_PREP(RV3028_BACKUP_BSM, mode));
default:
return -EINVAL;
}
return 0;
}
static int rv3028_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) static int rv3028_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
{ {
struct rv3028_data *rv3028 = dev_get_drvdata(dev); struct rv3028_data *rv3028 = dev_get_drvdata(dev);
@ -776,6 +846,8 @@ static const struct rtc_class_ops rv3028_rtc_ops = {
.read_offset = rv3028_read_offset, .read_offset = rv3028_read_offset,
.set_offset = rv3028_set_offset, .set_offset = rv3028_set_offset,
.ioctl = rv3028_ioctl, .ioctl = rv3028_ioctl,
.param_get = rv3028_param_get,
.param_set = rv3028_param_set,
}; };
static const struct regmap_config regmap_config = { static const struct regmap_config regmap_config = {
@ -878,6 +950,8 @@ static int rv3028_probe(struct i2c_client *client)
if (ret) if (ret)
return ret; return ret;
set_bit(RTC_FEATURE_BACKUP_SWITCH_MODE, rv3028->rtc->features);
rv3028->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000; rv3028->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
rv3028->rtc->range_max = RTC_TIMESTAMP_END_2099; rv3028->rtc->range_max = RTC_TIMESTAMP_END_2099;
rv3028->rtc->ops = &rv3028_rtc_ops; rv3028->rtc->ops = &rv3028_rtc_ops;

View File

@ -106,6 +106,7 @@
struct rv3032_data { struct rv3032_data {
struct regmap *regmap; struct regmap *regmap;
struct rtc_device *rtc; struct rtc_device *rtc;
bool trickle_charger_set;
#ifdef CONFIG_COMMON_CLK #ifdef CONFIG_COMMON_CLK
struct clk_hw clkout_hw; struct clk_hw clkout_hw;
#endif #endif
@ -310,14 +311,6 @@ static int rv3032_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
u8 ctrl = 0; u8 ctrl = 0;
int ret; int ret;
/* The alarm has no seconds, round up to nearest minute */
if (alrm->time.tm_sec) {
time64_t alarm_time = rtc_tm_to_time64(&alrm->time);
alarm_time += 60 - alrm->time.tm_sec;
rtc_time64_to_tm(alarm_time, &alrm->time);
}
ret = regmap_update_bits(rv3032->regmap, RV3032_CTRL2, ret = regmap_update_bits(rv3032->regmap, RV3032_CTRL2,
RV3032_CTRL2_AIE | RV3032_CTRL2_UIE, 0); RV3032_CTRL2_AIE | RV3032_CTRL2_UIE, 0);
if (ret) if (ret)
@ -402,6 +395,75 @@ static int rv3032_set_offset(struct device *dev, long offset)
FIELD_PREP(RV3032_OFFSET_MSK, offset)); FIELD_PREP(RV3032_OFFSET_MSK, offset));
} }
static int rv3032_param_get(struct device *dev, struct rtc_param *param)
{
struct rv3032_data *rv3032 = dev_get_drvdata(dev);
int ret;
switch(param->param) {
u32 value;
case RTC_PARAM_BACKUP_SWITCH_MODE:
ret = regmap_read(rv3032->regmap, RV3032_PMU, &value);
if (ret < 0)
return ret;
value = FIELD_GET(RV3032_PMU_BSM, value);
switch(value) {
case RV3032_PMU_BSM_DSM:
param->uvalue = RTC_BSM_DIRECT;
break;
case RV3032_PMU_BSM_LSM:
param->uvalue = RTC_BSM_LEVEL;
break;
default:
param->uvalue = RTC_BSM_DISABLED;
}
break;
default:
return -EINVAL;
}
return 0;
}
static int rv3032_param_set(struct device *dev, struct rtc_param *param)
{
struct rv3032_data *rv3032 = dev_get_drvdata(dev);
switch(param->param) {
u8 mode;
case RTC_PARAM_BACKUP_SWITCH_MODE:
if (rv3032->trickle_charger_set)
return -EINVAL;
switch (param->uvalue) {
case RTC_BSM_DISABLED:
mode = 0;
break;
case RTC_BSM_DIRECT:
mode = RV3032_PMU_BSM_DSM;
break;
case RTC_BSM_LEVEL:
mode = RV3032_PMU_BSM_LSM;
break;
default:
return -EINVAL;
}
return rv3032_update_cfg(rv3032, RV3032_PMU, RV3032_PMU_BSM,
FIELD_PREP(RV3032_PMU_BSM, mode));
default:
return -EINVAL;
}
return 0;
}
static int rv3032_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) static int rv3032_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
{ {
struct rv3032_data *rv3032 = dev_get_drvdata(dev); struct rv3032_data *rv3032 = dev_get_drvdata(dev);
@ -541,6 +603,8 @@ static int rv3032_trickle_charger_setup(struct device *dev, struct rv3032_data *
return 0; return 0;
} }
rv3032->trickle_charger_set = true;
return rv3032_update_cfg(rv3032, RV3032_PMU, return rv3032_update_cfg(rv3032, RV3032_PMU,
RV3032_PMU_TCR | RV3032_PMU_TCM | RV3032_PMU_BSM, RV3032_PMU_TCR | RV3032_PMU_TCM | RV3032_PMU_BSM,
val | FIELD_PREP(RV3032_PMU_TCR, i)); val | FIELD_PREP(RV3032_PMU_TCR, i));
@ -617,11 +681,11 @@ static int rv3032_clkout_set_rate(struct clk_hw *hw, unsigned long rate,
ret = rv3032_enter_eerd(rv3032, &eerd); ret = rv3032_enter_eerd(rv3032, &eerd);
if (ret) if (ret)
goto exit_eerd; return ret;
ret = regmap_write(rv3032->regmap, RV3032_CLKOUT1, hfd & 0xff); ret = regmap_write(rv3032->regmap, RV3032_CLKOUT1, hfd & 0xff);
if (ret) if (ret)
return ret; goto exit_eerd;
ret = regmap_write(rv3032->regmap, RV3032_CLKOUT2, RV3032_CLKOUT2_OS | ret = regmap_write(rv3032->regmap, RV3032_CLKOUT2, RV3032_CLKOUT2_OS |
FIELD_PREP(RV3032_CLKOUT2_HFD_MSK, hfd >> 8)); FIELD_PREP(RV3032_CLKOUT2_HFD_MSK, hfd >> 8));
@ -813,6 +877,8 @@ static const struct rtc_class_ops rv3032_rtc_ops = {
.read_alarm = rv3032_get_alarm, .read_alarm = rv3032_get_alarm,
.set_alarm = rv3032_set_alarm, .set_alarm = rv3032_set_alarm,
.alarm_irq_enable = rv3032_alarm_irq_enable, .alarm_irq_enable = rv3032_alarm_irq_enable,
.param_get = rv3032_param_get,
.param_set = rv3032_param_set,
}; };
static const struct regmap_config regmap_config = { static const struct regmap_config regmap_config = {
@ -883,6 +949,9 @@ static int rv3032_probe(struct i2c_client *client)
rv3032_trickle_charger_setup(&client->dev, rv3032); rv3032_trickle_charger_setup(&client->dev, rv3032);
set_bit(RTC_FEATURE_BACKUP_SWITCH_MODE, rv3032->rtc->features);
set_bit(RTC_FEATURE_ALARM_RES_MINUTE, rv3032->rtc->features);
rv3032->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000; rv3032->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
rv3032->rtc->range_max = RTC_TIMESTAMP_END_2099; rv3032->rtc->range_max = RTC_TIMESTAMP_END_2099;
rv3032->rtc->ops = &rv3032_rtc_ops; rv3032->rtc->ops = &rv3032_rtc_ops;

View File

@ -340,8 +340,8 @@ static int rv8803_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
} }
} }
ctrl[1] &= ~RV8803_FLAG_AF; ctrl[0] &= ~RV8803_FLAG_AF;
err = rv8803_write_reg(rv8803->client, RV8803_FLAG, ctrl[1]); err = rv8803_write_reg(rv8803->client, RV8803_FLAG, ctrl[0]);
mutex_unlock(&rv8803->flags_lock); mutex_unlock(&rv8803->flags_lock);
if (err) if (err)
return err; return err;

View File

@ -422,7 +422,7 @@ static struct regmap_config regmap_i2c_config = {
static int rx6110_i2c_probe(struct i2c_client *client, static int rx6110_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); struct i2c_adapter *adapter = client->adapter;
struct rx6110_data *rx6110; struct rx6110_data *rx6110;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA

View File

@ -248,9 +248,6 @@ static int rx8025_set_time(struct device *dev, struct rtc_time *dt)
u8 date[7]; u8 date[7];
int ret; int ret;
if ((dt->tm_year < 100) || (dt->tm_year > 199))
return -EINVAL;
/* /*
* Here the read-only bits are written as "0". I'm not sure if that * Here the read-only bits are written as "0". I'm not sure if that
* is sound. * is sound.
@ -318,9 +315,6 @@ static int rx8025_read_alarm(struct device *dev, struct rtc_wkalrm *t)
u8 ald[2]; u8 ald[2];
int ctrl2, err; int ctrl2, err;
if (client->irq <= 0)
return -EINVAL;
err = rx8025_read_regs(client, RX8025_REG_ALDMIN, 2, ald); err = rx8025_read_regs(client, RX8025_REG_ALDMIN, 2, ald);
if (err) if (err)
return err; return err;
@ -355,20 +349,6 @@ static int rx8025_set_alarm(struct device *dev, struct rtc_wkalrm *t)
u8 ald[2]; u8 ald[2];
int err; int err;
if (client->irq <= 0)
return -EINVAL;
/*
* Hardware alarm precision is 1 minute!
* round up to nearest minute
*/
if (t->time.tm_sec) {
time64_t alarm_time = rtc_tm_to_time64(&t->time);
alarm_time += 60 - t->time.tm_sec;
rtc_time64_to_tm(alarm_time, &t->time);
}
ald[0] = bin2bcd(t->time.tm_min); ald[0] = bin2bcd(t->time.tm_min);
if (rx8025->ctrl1 & RX8025_BIT_CTRL1_1224) if (rx8025->ctrl1 & RX8025_BIT_CTRL1_1224)
ald[1] = bin2bcd(t->time.tm_hour); ald[1] = bin2bcd(t->time.tm_hour);
@ -423,17 +403,7 @@ static int rx8025_alarm_irq_enable(struct device *dev, unsigned int enabled)
return 0; return 0;
} }
static const struct rtc_class_ops rx8025_rtc_ops = {
.read_time = rx8025_get_time,
.set_time = rx8025_set_time,
.read_alarm = rx8025_read_alarm,
.set_alarm = rx8025_set_alarm,
.alarm_irq_enable = rx8025_alarm_irq_enable,
};
/* /*
* Clock precision adjustment support
*
* According to the RX8025 SA/NB application manual the frequency and * According to the RX8025 SA/NB application manual the frequency and
* temperature characteristics can be approximated using the following * temperature characteristics can be approximated using the following
* equation: * equation:
@ -444,11 +414,8 @@ static const struct rtc_class_ops rx8025_rtc_ops = {
* a : Coefficient = (-35 +-5) * 10**-9 * a : Coefficient = (-35 +-5) * 10**-9
* ut: Ultimate temperature in degree = +25 +-5 degree * ut: Ultimate temperature in degree = +25 +-5 degree
* t : Any temperature in degree * t : Any temperature in degree
*
* Note that the clock adjustment in ppb must be entered (which is
* the negative value of the deviation).
*/ */
static int rx8025_get_clock_adjust(struct device *dev, int *adj) static int rx8025_read_offset(struct device *dev, long *offset)
{ {
struct i2c_client *client = to_i2c_client(dev); struct i2c_client *client = to_i2c_client(dev);
int digoff; int digoff;
@ -457,63 +424,75 @@ static int rx8025_get_clock_adjust(struct device *dev, int *adj)
if (digoff < 0) if (digoff < 0)
return digoff; return digoff;
*adj = digoff >= 64 ? digoff - 128 : digoff; *offset = digoff >= 64 ? digoff - 128 : digoff;
if (*adj > 0) if (*offset > 0)
(*adj)--; (*offset)--;
*adj *= -RX8025_ADJ_RESOLUTION; *offset *= RX8025_ADJ_RESOLUTION;
return 0; return 0;
} }
static int rx8025_set_clock_adjust(struct device *dev, int adj) static int rx8025_set_offset(struct device *dev, long offset)
{ {
struct i2c_client *client = to_i2c_client(dev); struct i2c_client *client = to_i2c_client(dev);
u8 digoff; u8 digoff;
int err; int err;
adj /= -RX8025_ADJ_RESOLUTION; offset /= RX8025_ADJ_RESOLUTION;
if (adj > RX8025_ADJ_DATA_MAX) if (offset > RX8025_ADJ_DATA_MAX)
adj = RX8025_ADJ_DATA_MAX; offset = RX8025_ADJ_DATA_MAX;
else if (adj < RX8025_ADJ_DATA_MIN) else if (offset < RX8025_ADJ_DATA_MIN)
adj = RX8025_ADJ_DATA_MIN; offset = RX8025_ADJ_DATA_MIN;
else if (adj > 0) else if (offset > 0)
adj++; offset++;
else if (adj < 0) else if (offset < 0)
adj += 128; offset += 128;
digoff = adj; digoff = offset;
err = rx8025_write_reg(client, RX8025_REG_DIGOFF, digoff); err = rx8025_write_reg(client, RX8025_REG_DIGOFF, digoff);
if (err) if (err)
return err; return err;
dev_dbg(dev, "%s: write 0x%02x\n", __func__, digoff);
return 0; return 0;
} }
static const struct rtc_class_ops rx8025_rtc_ops = {
.read_time = rx8025_get_time,
.set_time = rx8025_set_time,
.read_alarm = rx8025_read_alarm,
.set_alarm = rx8025_set_alarm,
.alarm_irq_enable = rx8025_alarm_irq_enable,
.read_offset = rx8025_read_offset,
.set_offset = rx8025_set_offset,
};
static ssize_t rx8025_sysfs_show_clock_adjust(struct device *dev, static ssize_t rx8025_sysfs_show_clock_adjust(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr,
char *buf) char *buf)
{ {
int err, adj; long adj;
int err;
err = rx8025_get_clock_adjust(dev, &adj); dev_warn_once(dev, "clock_adjust_ppb is deprecated, use offset\n");
err = rx8025_read_offset(dev, &adj);
if (err) if (err)
return err; return err;
return sprintf(buf, "%d\n", adj); return sprintf(buf, "%ld\n", -adj);
} }
static ssize_t rx8025_sysfs_store_clock_adjust(struct device *dev, static ssize_t rx8025_sysfs_store_clock_adjust(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr,
const char *buf, size_t count) const char *buf, size_t count)
{ {
int adj, err; long adj;
int err;
if (sscanf(buf, "%i", &adj) != 1) dev_warn_once(dev, "clock_adjust_ppb is deprecated, use offset\n");
if (kstrtol(buf, 10, &adj) != 0)
return -EINVAL; return -EINVAL;
err = rx8025_set_clock_adjust(dev, adj); err = rx8025_set_offset(dev, -adj);
return err ? err : count; return err ? err : count;
} }
@ -522,15 +501,14 @@ static DEVICE_ATTR(clock_adjust_ppb, S_IRUGO | S_IWUSR,
rx8025_sysfs_show_clock_adjust, rx8025_sysfs_show_clock_adjust,
rx8025_sysfs_store_clock_adjust); rx8025_sysfs_store_clock_adjust);
static int rx8025_sysfs_register(struct device *dev) static struct attribute *rx8025_attrs[] = {
{ &dev_attr_clock_adjust_ppb.attr,
return device_create_file(dev, &dev_attr_clock_adjust_ppb); NULL
} };
static void rx8025_sysfs_unregister(struct device *dev) static const struct attribute_group rx8025_attr_group = {
{ .attrs = rx8025_attrs,
device_remove_file(dev, &dev_attr_clock_adjust_ppb); };
}
static int rx8025_probe(struct i2c_client *client, static int rx8025_probe(struct i2c_client *client,
const struct i2c_device_id *id) const struct i2c_device_id *id)
@ -559,12 +537,13 @@ static int rx8025_probe(struct i2c_client *client,
if (err) if (err)
return err; return err;
rx8025->rtc = devm_rtc_device_register(&client->dev, client->name, rx8025->rtc = devm_rtc_allocate_device(&client->dev);
&rx8025_rtc_ops, THIS_MODULE); if (IS_ERR(rx8025->rtc))
if (IS_ERR(rx8025->rtc)) {
dev_err(&client->dev, "unable to register the class device\n");
return PTR_ERR(rx8025->rtc); return PTR_ERR(rx8025->rtc);
}
rx8025->rtc->ops = &rx8025_rtc_ops;
rx8025->rtc->range_min = RTC_TIMESTAMP_BEGIN_1900;
rx8025->rtc->range_max = RTC_TIMESTAMP_END_2099;
if (client->irq > 0) { if (client->irq > 0) {
dev_info(&client->dev, "IRQ %d supplied\n", client->irq); dev_info(&client->dev, "IRQ %d supplied\n", client->irq);
@ -572,25 +551,20 @@ static int rx8025_probe(struct i2c_client *client,
rx8025_handle_irq, rx8025_handle_irq,
IRQF_ONESHOT, IRQF_ONESHOT,
"rx8025", client); "rx8025", client);
if (err) { if (err)
dev_err(&client->dev, "unable to request IRQ, alarms disabled\n"); clear_bit(RTC_FEATURE_ALARM, rx8025->rtc->features);
client->irq = 0;
}
} }
rx8025->rtc->max_user_freq = 1; rx8025->rtc->max_user_freq = 1;
/* the rx8025 alarm only supports a minute accuracy */ set_bit(RTC_FEATURE_ALARM_RES_MINUTE, rx8025->rtc->features);
rx8025->rtc->uie_unsupported = 1; clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, rx8025->rtc->features);
err = rx8025_sysfs_register(&client->dev); err = rtc_add_group(rx8025->rtc, &rx8025_attr_group);
return err; if (err)
} return err;
static int rx8025_remove(struct i2c_client *client) return devm_rtc_register_device(rx8025->rtc);
{
rx8025_sysfs_unregister(&client->dev);
return 0;
} }
static struct i2c_driver rx8025_driver = { static struct i2c_driver rx8025_driver = {
@ -598,7 +572,6 @@ static struct i2c_driver rx8025_driver = {
.name = "rtc-rx8025", .name = "rtc-rx8025",
}, },
.probe = rx8025_probe, .probe = rx8025_probe,
.remove = rx8025_remove,
.id_table = rx8025_id, .id_table = rx8025_id,
}; };

View File

@ -285,9 +285,6 @@ static int s35390a_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
alm->time.tm_min, alm->time.tm_hour, alm->time.tm_mday, alm->time.tm_min, alm->time.tm_hour, alm->time.tm_mday,
alm->time.tm_mon, alm->time.tm_year, alm->time.tm_wday); alm->time.tm_mon, alm->time.tm_year, alm->time.tm_wday);
if (alm->time.tm_sec != 0)
dev_warn(&client->dev, "Alarms are only supported on a per minute basis!\n");
/* disable interrupt (which deasserts the irq line) */ /* disable interrupt (which deasserts the irq line) */
err = s35390a_set_reg(s35390a, S35390A_CMD_STATUS2, &sts, sizeof(sts)); err = s35390a_set_reg(s35390a, S35390A_CMD_STATUS2, &sts, sizeof(sts));
if (err < 0) if (err < 0)
@ -491,8 +488,8 @@ static int s35390a_probe(struct i2c_client *client,
s35390a->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000; s35390a->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
s35390a->rtc->range_max = RTC_TIMESTAMP_END_2099; s35390a->rtc->range_max = RTC_TIMESTAMP_END_2099;
/* supports per-minute alarms only, therefore set uie_unsupported */ set_bit(RTC_FEATURE_ALARM_RES_MINUTE, s35390a->rtc->features);
s35390a->rtc->uie_unsupported = 1; clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, s35390a->rtc->features );
if (status1 & S35390A_FLAG_INT2) if (status1 & S35390A_FLAG_INT2)
rtc_update_irq(s35390a->rtc, 1, RTC_AF); rtc_update_irq(s35390a->rtc, 1, RTC_AF);

View File

@ -127,10 +127,9 @@ static int s3c_rtc_setaie(struct device *dev, unsigned int enabled)
return ret; return ret;
} }
/* Time read/write */ /* Read time from RTC and convert it from BCD */
static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm) static int s3c_rtc_read_time(struct s3c_rtc *info, struct rtc_time *tm)
{ {
struct s3c_rtc *info = dev_get_drvdata(dev);
unsigned int have_retried = 0; unsigned int have_retried = 0;
int ret; int ret;
@ -139,54 +138,40 @@ static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
return ret; return ret;
retry_get_time: retry_get_time:
rtc_tm->tm_min = readb(info->base + S3C2410_RTCMIN); tm->tm_min = readb(info->base + S3C2410_RTCMIN);
rtc_tm->tm_hour = readb(info->base + S3C2410_RTCHOUR); tm->tm_hour = readb(info->base + S3C2410_RTCHOUR);
rtc_tm->tm_mday = readb(info->base + S3C2410_RTCDATE); tm->tm_mday = readb(info->base + S3C2410_RTCDATE);
rtc_tm->tm_mon = readb(info->base + S3C2410_RTCMON); tm->tm_mon = readb(info->base + S3C2410_RTCMON);
rtc_tm->tm_year = readb(info->base + S3C2410_RTCYEAR); tm->tm_year = readb(info->base + S3C2410_RTCYEAR);
rtc_tm->tm_sec = readb(info->base + S3C2410_RTCSEC); tm->tm_sec = readb(info->base + S3C2410_RTCSEC);
/* the only way to work out whether the system was mid-update /*
* The only way to work out whether the system was mid-update
* when we read it is to check the second counter, and if it * when we read it is to check the second counter, and if it
* is zero, then we re-try the entire read * is zero, then we re-try the entire read
*/ */
if (tm->tm_sec == 0 && !have_retried) {
if (rtc_tm->tm_sec == 0 && !have_retried) {
have_retried = 1; have_retried = 1;
goto retry_get_time; goto retry_get_time;
} }
rtc_tm->tm_sec = bcd2bin(rtc_tm->tm_sec);
rtc_tm->tm_min = bcd2bin(rtc_tm->tm_min);
rtc_tm->tm_hour = bcd2bin(rtc_tm->tm_hour);
rtc_tm->tm_mday = bcd2bin(rtc_tm->tm_mday);
rtc_tm->tm_mon = bcd2bin(rtc_tm->tm_mon);
rtc_tm->tm_year = bcd2bin(rtc_tm->tm_year);
s3c_rtc_disable_clk(info); s3c_rtc_disable_clk(info);
rtc_tm->tm_year += 100; tm->tm_sec = bcd2bin(tm->tm_sec);
rtc_tm->tm_mon -= 1; tm->tm_min = bcd2bin(tm->tm_min);
tm->tm_hour = bcd2bin(tm->tm_hour);
tm->tm_mday = bcd2bin(tm->tm_mday);
tm->tm_mon = bcd2bin(tm->tm_mon);
tm->tm_year = bcd2bin(tm->tm_year);
dev_dbg(dev, "read time %ptR\n", rtc_tm);
return 0; return 0;
} }
static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm) /* Convert time to BCD and write it to RTC */
static int s3c_rtc_write_time(struct s3c_rtc *info, const struct rtc_time *tm)
{ {
struct s3c_rtc *info = dev_get_drvdata(dev);
int year = tm->tm_year - 100;
int ret; int ret;
dev_dbg(dev, "set time %ptR\n", tm);
/* we get around y2k by simply not supporting it */
if (year < 0 || year >= 100) {
dev_err(dev, "rtc only supports 100 years\n");
return -EINVAL;
}
ret = s3c_rtc_enable_clk(info); ret = s3c_rtc_enable_clk(info);
if (ret) if (ret)
return ret; return ret;
@ -195,14 +180,48 @@ static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm)
writeb(bin2bcd(tm->tm_min), info->base + S3C2410_RTCMIN); writeb(bin2bcd(tm->tm_min), info->base + S3C2410_RTCMIN);
writeb(bin2bcd(tm->tm_hour), info->base + S3C2410_RTCHOUR); writeb(bin2bcd(tm->tm_hour), info->base + S3C2410_RTCHOUR);
writeb(bin2bcd(tm->tm_mday), info->base + S3C2410_RTCDATE); writeb(bin2bcd(tm->tm_mday), info->base + S3C2410_RTCDATE);
writeb(bin2bcd(tm->tm_mon + 1), info->base + S3C2410_RTCMON); writeb(bin2bcd(tm->tm_mon), info->base + S3C2410_RTCMON);
writeb(bin2bcd(year), info->base + S3C2410_RTCYEAR); writeb(bin2bcd(tm->tm_year), info->base + S3C2410_RTCYEAR);
s3c_rtc_disable_clk(info); s3c_rtc_disable_clk(info);
return 0; return 0;
} }
static int s3c_rtc_gettime(struct device *dev, struct rtc_time *tm)
{
struct s3c_rtc *info = dev_get_drvdata(dev);
int ret;
ret = s3c_rtc_read_time(info, tm);
if (ret)
return ret;
/* Convert internal representation to actual date/time */
tm->tm_year += 100;
tm->tm_mon -= 1;
dev_dbg(dev, "read time %ptR\n", tm);
return 0;
}
static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm)
{
struct s3c_rtc *info = dev_get_drvdata(dev);
struct rtc_time rtc_tm = *tm;
dev_dbg(dev, "set time %ptR\n", tm);
/*
* Convert actual date/time to internal representation.
* We get around Y2K by simply not supporting it.
*/
rtc_tm.tm_year -= 100;
rtc_tm.tm_mon += 1;
return s3c_rtc_write_time(info, &rtc_tm);
}
static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm) static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm)
{ {
struct s3c_rtc *info = dev_get_drvdata(dev); struct s3c_rtc *info = dev_get_drvdata(dev);
@ -447,15 +466,20 @@ static int s3c_rtc_probe(struct platform_device *pdev)
device_init_wakeup(&pdev->dev, 1); device_init_wakeup(&pdev->dev, 1);
/* register RTC and exit */ info->rtc = devm_rtc_allocate_device(&pdev->dev);
info->rtc = devm_rtc_device_register(&pdev->dev, "s3c", &s3c_rtcops,
THIS_MODULE);
if (IS_ERR(info->rtc)) { if (IS_ERR(info->rtc)) {
dev_err(&pdev->dev, "cannot attach rtc\n");
ret = PTR_ERR(info->rtc); ret = PTR_ERR(info->rtc);
goto err_nortc; goto err_nortc;
} }
info->rtc->ops = &s3c_rtcops;
info->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
info->rtc->range_max = RTC_TIMESTAMP_END_2099;
ret = devm_rtc_register_device(info->rtc);
if (ret)
goto err_nortc;
ret = devm_request_irq(&pdev->dev, info->irq_alarm, s3c_rtc_alarmirq, ret = devm_request_irq(&pdev->dev, info->irq_alarm, s3c_rtc_alarmirq,
0, "s3c2410-rtc alarm", info); 0, "s3c2410-rtc alarm", info);
if (ret) { if (ret) {

View File

@ -861,4 +861,3 @@ module_platform_driver(s5m_rtc_driver);
MODULE_AUTHOR("Sangbeom Kim <sbkim73@samsung.com>"); MODULE_AUTHOR("Sangbeom Kim <sbkim73@samsung.com>");
MODULE_DESCRIPTION("Samsung S5M/S2MPS14 RTC driver"); MODULE_DESCRIPTION("Samsung S5M/S2MPS14 RTC driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:s5m-rtc");

View File

@ -673,8 +673,17 @@ static int sun6i_rtc_probe(struct platform_device *pdev)
struct sun6i_rtc_dev *chip = sun6i_rtc; struct sun6i_rtc_dev *chip = sun6i_rtc;
int ret; int ret;
if (!chip) if (!chip) {
return -ENODEV; chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
if (!chip)
return -ENOMEM;
spin_lock_init(&chip->lock);
chip->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(chip->base))
return PTR_ERR(chip->base);
}
platform_set_drvdata(pdev, chip); platform_set_drvdata(pdev, chip);

View File

@ -1,324 +0,0 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* rtc-tps80031.c -- TI TPS80031/TPS80032 RTC driver
*
* RTC driver for TI TPS80031/TPS80032 Fully Integrated
* Power Management with Power Path and Battery Charger
*
* Copyright (c) 2012, NVIDIA Corporation.
*
* Author: Laxman Dewangan <ldewangan@nvidia.com>
*/
#include <linux/bcd.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mfd/tps80031.h>
#include <linux/platform_device.h>
#include <linux/pm.h>
#include <linux/rtc.h>
#include <linux/slab.h>
#define ENABLE_ALARM_INT 0x08
#define ALARM_INT_STATUS 0x40
/**
* Setting bit to 1 in STOP_RTC will run the RTC and
* setting this bit to 0 will freeze RTC.
*/
#define STOP_RTC 0x1
/* Power on reset Values of RTC registers */
#define TPS80031_RTC_POR_YEAR 0
#define TPS80031_RTC_POR_MONTH 1
#define TPS80031_RTC_POR_DAY 1
/* Numbers of registers for time and alarms */
#define TPS80031_RTC_TIME_NUM_REGS 7
#define TPS80031_RTC_ALARM_NUM_REGS 6
/**
* PMU RTC have only 2 nibbles to store year information, so using an
* offset of 100 to set the base year as 2000 for our driver.
*/
#define RTC_YEAR_OFFSET 100
struct tps80031_rtc {
struct rtc_device *rtc;
int irq;
};
static int tps80031_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
u8 buff[TPS80031_RTC_TIME_NUM_REGS];
int ret;
ret = tps80031_reads(dev->parent, TPS80031_SLAVE_ID1,
TPS80031_SECONDS_REG, TPS80031_RTC_TIME_NUM_REGS, buff);
if (ret < 0) {
dev_err(dev, "reading RTC_SECONDS_REG failed, err = %d\n", ret);
return ret;
}
tm->tm_sec = bcd2bin(buff[0]);
tm->tm_min = bcd2bin(buff[1]);
tm->tm_hour = bcd2bin(buff[2]);
tm->tm_mday = bcd2bin(buff[3]);
tm->tm_mon = bcd2bin(buff[4]) - 1;
tm->tm_year = bcd2bin(buff[5]) + RTC_YEAR_OFFSET;
tm->tm_wday = bcd2bin(buff[6]);
return 0;
}
static int tps80031_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
u8 buff[7];
int ret;
buff[0] = bin2bcd(tm->tm_sec);
buff[1] = bin2bcd(tm->tm_min);
buff[2] = bin2bcd(tm->tm_hour);
buff[3] = bin2bcd(tm->tm_mday);
buff[4] = bin2bcd(tm->tm_mon + 1);
buff[5] = bin2bcd(tm->tm_year % RTC_YEAR_OFFSET);
buff[6] = bin2bcd(tm->tm_wday);
/* Stop RTC while updating the RTC time registers */
ret = tps80031_clr_bits(dev->parent, TPS80031_SLAVE_ID1,
TPS80031_RTC_CTRL_REG, STOP_RTC);
if (ret < 0) {
dev_err(dev->parent, "Stop RTC failed, err = %d\n", ret);
return ret;
}
ret = tps80031_writes(dev->parent, TPS80031_SLAVE_ID1,
TPS80031_SECONDS_REG,
TPS80031_RTC_TIME_NUM_REGS, buff);
if (ret < 0) {
dev_err(dev, "writing RTC_SECONDS_REG failed, err %d\n", ret);
return ret;
}
ret = tps80031_set_bits(dev->parent, TPS80031_SLAVE_ID1,
TPS80031_RTC_CTRL_REG, STOP_RTC);
if (ret < 0)
dev_err(dev->parent, "Start RTC failed, err = %d\n", ret);
return ret;
}
static int tps80031_rtc_alarm_irq_enable(struct device *dev,
unsigned int enable)
{
int ret;
if (enable)
ret = tps80031_set_bits(dev->parent, TPS80031_SLAVE_ID1,
TPS80031_RTC_INTERRUPTS_REG, ENABLE_ALARM_INT);
else
ret = tps80031_clr_bits(dev->parent, TPS80031_SLAVE_ID1,
TPS80031_RTC_INTERRUPTS_REG, ENABLE_ALARM_INT);
if (ret < 0) {
dev_err(dev, "Update on RTC_INT failed, err = %d\n", ret);
return ret;
}
return 0;
}
static int tps80031_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
u8 buff[TPS80031_RTC_ALARM_NUM_REGS];
int ret;
buff[0] = bin2bcd(alrm->time.tm_sec);
buff[1] = bin2bcd(alrm->time.tm_min);
buff[2] = bin2bcd(alrm->time.tm_hour);
buff[3] = bin2bcd(alrm->time.tm_mday);
buff[4] = bin2bcd(alrm->time.tm_mon + 1);
buff[5] = bin2bcd(alrm->time.tm_year % RTC_YEAR_OFFSET);
ret = tps80031_writes(dev->parent, TPS80031_SLAVE_ID1,
TPS80031_ALARM_SECONDS_REG,
TPS80031_RTC_ALARM_NUM_REGS, buff);
if (ret < 0) {
dev_err(dev, "Writing RTC_ALARM failed, err %d\n", ret);
return ret;
}
return tps80031_rtc_alarm_irq_enable(dev, alrm->enabled);
}
static int tps80031_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
u8 buff[6];
int ret;
ret = tps80031_reads(dev->parent, TPS80031_SLAVE_ID1,
TPS80031_ALARM_SECONDS_REG,
TPS80031_RTC_ALARM_NUM_REGS, buff);
if (ret < 0) {
dev_err(dev->parent,
"reading RTC_ALARM failed, err = %d\n", ret);
return ret;
}
alrm->time.tm_sec = bcd2bin(buff[0]);
alrm->time.tm_min = bcd2bin(buff[1]);
alrm->time.tm_hour = bcd2bin(buff[2]);
alrm->time.tm_mday = bcd2bin(buff[3]);
alrm->time.tm_mon = bcd2bin(buff[4]) - 1;
alrm->time.tm_year = bcd2bin(buff[5]) + RTC_YEAR_OFFSET;
return 0;
}
static int clear_alarm_int_status(struct device *dev, struct tps80031_rtc *rtc)
{
int ret;
u8 buf;
/**
* As per datasheet, A dummy read of this RTC_STATUS_REG register
* is necessary before each I2C read in order to update the status
* register value.
*/
ret = tps80031_read(dev->parent, TPS80031_SLAVE_ID1,
TPS80031_RTC_STATUS_REG, &buf);
if (ret < 0) {
dev_err(dev, "reading RTC_STATUS failed. err = %d\n", ret);
return ret;
}
/* clear Alarm status bits.*/
ret = tps80031_set_bits(dev->parent, TPS80031_SLAVE_ID1,
TPS80031_RTC_STATUS_REG, ALARM_INT_STATUS);
if (ret < 0) {
dev_err(dev, "clear Alarm INT failed, err = %d\n", ret);
return ret;
}
return 0;
}
static irqreturn_t tps80031_rtc_irq(int irq, void *data)
{
struct device *dev = data;
struct tps80031_rtc *rtc = dev_get_drvdata(dev);
int ret;
ret = clear_alarm_int_status(dev, rtc);
if (ret < 0)
return ret;
rtc_update_irq(rtc->rtc, 1, RTC_IRQF | RTC_AF);
return IRQ_HANDLED;
}
static const struct rtc_class_ops tps80031_rtc_ops = {
.read_time = tps80031_rtc_read_time,
.set_time = tps80031_rtc_set_time,
.set_alarm = tps80031_rtc_set_alarm,
.read_alarm = tps80031_rtc_read_alarm,
.alarm_irq_enable = tps80031_rtc_alarm_irq_enable,
};
static int tps80031_rtc_probe(struct platform_device *pdev)
{
struct tps80031_rtc *rtc;
struct rtc_time tm;
int ret;
rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL);
if (!rtc)
return -ENOMEM;
rtc->irq = platform_get_irq(pdev, 0);
platform_set_drvdata(pdev, rtc);
/* Start RTC */
ret = tps80031_set_bits(pdev->dev.parent, TPS80031_SLAVE_ID1,
TPS80031_RTC_CTRL_REG, STOP_RTC);
if (ret < 0) {
dev_err(&pdev->dev, "failed to start RTC. err = %d\n", ret);
return ret;
}
/* If RTC have POR values, set time 01:01:2000 */
tps80031_rtc_read_time(&pdev->dev, &tm);
if ((tm.tm_year == RTC_YEAR_OFFSET + TPS80031_RTC_POR_YEAR) &&
(tm.tm_mon == (TPS80031_RTC_POR_MONTH - 1)) &&
(tm.tm_mday == TPS80031_RTC_POR_DAY)) {
tm.tm_year = 2000;
tm.tm_mday = 1;
tm.tm_mon = 1;
ret = tps80031_rtc_set_time(&pdev->dev, &tm);
if (ret < 0) {
dev_err(&pdev->dev,
"RTC set time failed, err = %d\n", ret);
return ret;
}
}
/* Clear alarm intretupt status if it is there */
ret = clear_alarm_int_status(&pdev->dev, rtc);
if (ret < 0) {
dev_err(&pdev->dev, "Clear alarm int failed, err = %d\n", ret);
return ret;
}
rtc->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
&tps80031_rtc_ops, THIS_MODULE);
if (IS_ERR(rtc->rtc)) {
ret = PTR_ERR(rtc->rtc);
dev_err(&pdev->dev, "RTC registration failed, err %d\n", ret);
return ret;
}
ret = devm_request_threaded_irq(&pdev->dev, rtc->irq, NULL,
tps80031_rtc_irq,
IRQF_ONESHOT,
dev_name(&pdev->dev), rtc);
if (ret < 0) {
dev_err(&pdev->dev, "request IRQ:%d failed, err = %d\n",
rtc->irq, ret);
return ret;
}
device_set_wakeup_capable(&pdev->dev, 1);
return 0;
}
#ifdef CONFIG_PM_SLEEP
static int tps80031_rtc_suspend(struct device *dev)
{
struct tps80031_rtc *rtc = dev_get_drvdata(dev);
if (device_may_wakeup(dev))
enable_irq_wake(rtc->irq);
return 0;
}
static int tps80031_rtc_resume(struct device *dev)
{
struct tps80031_rtc *rtc = dev_get_drvdata(dev);
if (device_may_wakeup(dev))
disable_irq_wake(rtc->irq);
return 0;
};
#endif
static SIMPLE_DEV_PM_OPS(tps80031_pm_ops, tps80031_rtc_suspend,
tps80031_rtc_resume);
static struct platform_driver tps80031_rtc_driver = {
.driver = {
.name = "tps80031-rtc",
.pm = &tps80031_pm_ops,
},
.probe = tps80031_rtc_probe,
};
module_platform_driver(tps80031_rtc_driver);
MODULE_ALIAS("platform:tps80031-rtc");
MODULE_DESCRIPTION("TI TPS80031/TPS80032 RTC driver");
MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
MODULE_LICENSE("GPL v2");

View File

@ -66,6 +66,8 @@ struct rtc_class_ops {
int (*alarm_irq_enable)(struct device *, unsigned int enabled); int (*alarm_irq_enable)(struct device *, unsigned int enabled);
int (*read_offset)(struct device *, long *offset); int (*read_offset)(struct device *, long *offset);
int (*set_offset)(struct device *, long offset); int (*set_offset)(struct device *, long offset);
int (*param_get)(struct device *, struct rtc_param *param);
int (*param_set)(struct device *, struct rtc_param *param);
}; };
struct rtc_device; struct rtc_device;
@ -80,6 +82,7 @@ struct rtc_timer {
/* flags */ /* flags */
#define RTC_DEV_BUSY 0 #define RTC_DEV_BUSY 0
#define RTC_NO_CDEV 1
struct rtc_device { struct rtc_device {
struct device dev; struct device dev;

View File

@ -14,6 +14,7 @@
#include <linux/const.h> #include <linux/const.h>
#include <linux/ioctl.h> #include <linux/ioctl.h>
#include <linux/types.h>
/* /*
* The struct used to pass data via the following ioctl. Similar to the * The struct used to pass data via the following ioctl. Similar to the
@ -66,6 +67,17 @@ struct rtc_pll_info {
long pll_clock; /* base PLL frequency */ long pll_clock; /* base PLL frequency */
}; };
struct rtc_param {
__u64 param;
union {
__u64 uvalue;
__s64 svalue;
__u64 ptr;
};
__u32 index;
__u32 __pad;
};
/* /*
* ioctl calls that are permitted to the /dev/rtc interface, if * ioctl calls that are permitted to the /dev/rtc interface, if
* any of the RTC drivers are enabled. * any of the RTC drivers are enabled.
@ -95,6 +107,9 @@ struct rtc_pll_info {
#define RTC_PLL_GET _IOR('p', 0x11, struct rtc_pll_info) /* Get PLL correction */ #define RTC_PLL_GET _IOR('p', 0x11, struct rtc_pll_info) /* Get PLL correction */
#define RTC_PLL_SET _IOW('p', 0x12, struct rtc_pll_info) /* Set PLL correction */ #define RTC_PLL_SET _IOW('p', 0x12, struct rtc_pll_info) /* Set PLL correction */
#define RTC_PARAM_GET _IOW('p', 0x13, struct rtc_param) /* Get parameter */
#define RTC_PARAM_SET _IOW('p', 0x14, struct rtc_param) /* Set parameter */
#define RTC_VL_DATA_INVALID _BITUL(0) /* Voltage too low, RTC data is invalid */ #define RTC_VL_DATA_INVALID _BITUL(0) /* Voltage too low, RTC data is invalid */
#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 */
@ -114,7 +129,21 @@ struct rtc_pll_info {
#define RTC_FEATURE_ALARM 0 #define RTC_FEATURE_ALARM 0
#define RTC_FEATURE_ALARM_RES_MINUTE 1 #define RTC_FEATURE_ALARM_RES_MINUTE 1
#define RTC_FEATURE_NEED_WEEK_DAY 2 #define RTC_FEATURE_NEED_WEEK_DAY 2
#define RTC_FEATURE_CNT 3 #define RTC_FEATURE_ALARM_RES_2S 3
#define RTC_FEATURE_UPDATE_INTERRUPT 4
#define RTC_FEATURE_CORRECTION 5
#define RTC_FEATURE_BACKUP_SWITCH_MODE 6
#define RTC_FEATURE_CNT 7
/* parameter list */
#define RTC_PARAM_FEATURES 0
#define RTC_PARAM_CORRECTION 1
#define RTC_PARAM_BACKUP_SWITCH_MODE 2
#define RTC_BSM_DISABLED 0
#define RTC_BSM_DIRECT 1
#define RTC_BSM_LEVEL 2
#define RTC_BSM_STANDBY 3
#define RTC_MAX_FREQ 8192 #define RTC_MAX_FREQ 8192