mirror of
https://github.com/Dasharo/linux.git
synced 2026-03-06 15:25:10 -08:00
Merge tag 'rtc-5.11' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux
Pull RTC updates from Alexandre Belloni:
"Subsystem:
- Remove nvram ABI. There was no complaints about the deprecation for
the last 3 years.
- Improve RTC device allocation and registration
- Now available for ARCH=um
Drivers:
- at91rm9200: correction and sam9x60 support
- ds1307: improve ACPI support
- mxc: now DT only
- pcf2127: watchdog support now needs the reset-source property
- pcf8523: set range
- rx6110: i2c support"
* tag 'rtc-5.11' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux: (43 commits)
rtc: pcf2127: only use watchdog when explicitly available
dt-bindings: rtc: add reset-source property
rtc: fix RTC removal
rtc: s3c: Remove dead code related to periodic tick handling
rtc: s3c: Disable all enable (RTC, tick) bits in the probe
rtc: ep93xx: Fix NULL pointer dereference in ep93xx_rtc_read_time
rtc: test: remove debug message
rtc: mxc{,_v2}: enable COMPILE_TEST
rtc: enable RTC framework on ARCH=um
rtc: pcf8523: use BIT
rtc: pcf8523: set range
rtc: pcf8523: switch to devm_rtc_allocate_device
rtc: destroy mutex when releasing the device
rtc: shrink devm_rtc_allocate_device()
rtc: rework rtc_register_device() resource management
rtc: nvmem: emit an error message when nvmem registration fails
rtc: add devm_ prefix to rtc_nvmem_register()
rtc: nvmem: remove nvram ABI
Documentation: list RTC devres helpers in devres.rst
rtc: omap: use devm_pinctrl_register()
...
This commit is contained in:
@@ -63,6 +63,11 @@ properties:
|
||||
description:
|
||||
Enables wake up of host system on alarm.
|
||||
|
||||
reset-source:
|
||||
$ref: /schemas/types.yaml#/definitions/flag
|
||||
description:
|
||||
The RTC is able to reset the machine.
|
||||
|
||||
additionalProperties: true
|
||||
|
||||
...
|
||||
|
||||
@@ -411,6 +411,12 @@ RESET
|
||||
devm_reset_control_get()
|
||||
devm_reset_controller_register()
|
||||
|
||||
RTC
|
||||
devm_rtc_device_register()
|
||||
devm_rtc_allocate_device()
|
||||
devm_rtc_register_device()
|
||||
devm_rtc_nvmem_register()
|
||||
|
||||
SERDEV
|
||||
devm_serdev_device_open()
|
||||
|
||||
|
||||
@@ -1183,7 +1183,7 @@ F: Documentation/devicetree/bindings/interrupt-controller/google,goldfish-pic.tx
|
||||
F: drivers/irqchip/irq-goldfish-pic.c
|
||||
|
||||
ANDROID GOLDFISH RTC DRIVER
|
||||
M: Miodrag Dinic <miodrag.dinic@mips.com>
|
||||
M: Jiaxun Yang <jiaxun.yang@flygoat.com>
|
||||
S: Supported
|
||||
F: Documentation/devicetree/bindings/rtc/google,goldfish-rtc.txt
|
||||
F: drivers/rtc/rtc-goldfish.c
|
||||
|
||||
@@ -216,6 +216,6 @@ alpha_rtc_init(void)
|
||||
rtc->ops = &remote_rtc_ops;
|
||||
#endif
|
||||
|
||||
return rtc_register_device(rtc);
|
||||
return devm_rtc_register_device(rtc);
|
||||
}
|
||||
device_initcall(alpha_rtc_init);
|
||||
|
||||
@@ -1119,7 +1119,7 @@ static inline void menelaus_rtc_init(struct menelaus_chip *m)
|
||||
menelaus_write_reg(MENELAUS_RTC_CTRL, m->rtc_control);
|
||||
}
|
||||
|
||||
err = rtc_register_device(m->rtc);
|
||||
err = devm_rtc_register_device(m->rtc);
|
||||
if (err) {
|
||||
if (alarm) {
|
||||
menelaus_remove_irq_work(MENELAUS_RTCALM_IRQ);
|
||||
|
||||
@@ -13,7 +13,7 @@ config RTC_MC146818_LIB
|
||||
menuconfig RTC_CLASS
|
||||
bool "Real Time Clock"
|
||||
default n
|
||||
depends on !S390 && !UML
|
||||
depends on !S390
|
||||
select RTC_LIB
|
||||
help
|
||||
Generic RTC class support. If you say yes here, you will
|
||||
@@ -817,15 +817,6 @@ config RTC_DRV_RX4581
|
||||
This driver can also be built as a module. If so the module
|
||||
will be called rtc-rx4581.
|
||||
|
||||
config RTC_DRV_RX6110
|
||||
tristate "Epson RX-6110"
|
||||
select REGMAP_SPI
|
||||
help
|
||||
If you say yes here you will get support for the Epson RX-6610.
|
||||
|
||||
This driver can also be built as a module. If so the module
|
||||
will be called rtc-rx6110.
|
||||
|
||||
config RTC_DRV_RS5C348
|
||||
tristate "Ricoh RS5C348A/B"
|
||||
help
|
||||
@@ -936,6 +927,17 @@ config RTC_DRV_RV3029_HWMON
|
||||
Say Y here if you want to expose temperature sensor data on
|
||||
rtc-rv3029.
|
||||
|
||||
config RTC_DRV_RX6110
|
||||
tristate "Epson RX-6110"
|
||||
depends on RTC_I2C_AND_SPI
|
||||
select REGMAP_SPI if SPI_MASTER
|
||||
select REGMAP_I2C if I2C
|
||||
help
|
||||
If you say yes here you will get support for the Epson RX-6110.
|
||||
|
||||
This driver can also be built as a module. If so the module
|
||||
will be called rtc-rx6110.
|
||||
|
||||
comment "Platform RTC drivers"
|
||||
|
||||
# this 'CMOS' RTC driver is arch dependent because it requires
|
||||
@@ -1017,6 +1019,7 @@ config RTC_DRV_DS1553
|
||||
|
||||
config RTC_DRV_DS1685_FAMILY
|
||||
tristate "Dallas/Maxim DS1685 Family"
|
||||
depends on HAS_IOMEM
|
||||
help
|
||||
If you say yes here you get support for the Dallas/Maxim DS1685
|
||||
family of real time chips. This family includes the DS1685/DS1687,
|
||||
@@ -1150,6 +1153,7 @@ config RTC_DRV_STK17TA8
|
||||
|
||||
config RTC_DRV_M48T86
|
||||
tristate "ST M48T86/Dallas DS12887"
|
||||
depends on HAS_IOMEM
|
||||
help
|
||||
If you say Y here you will get support for the
|
||||
ST M48T86 and Dallas DS12887 RTC chips.
|
||||
@@ -1752,7 +1756,9 @@ config RTC_DRV_LOONGSON1
|
||||
|
||||
config RTC_DRV_MXC
|
||||
tristate "Freescale MXC Real Time Clock"
|
||||
depends on ARCH_MXC
|
||||
depends on ARCH_MXC || COMPILE_TEST
|
||||
depends on HAS_IOMEM
|
||||
depends on OF
|
||||
help
|
||||
If you say yes here you get support for the Freescale MXC
|
||||
RTC module.
|
||||
@@ -1762,7 +1768,9 @@ config RTC_DRV_MXC
|
||||
|
||||
config RTC_DRV_MXC_V2
|
||||
tristate "Freescale MXC Real Time Clock for i.MX53"
|
||||
depends on ARCH_MXC
|
||||
depends on ARCH_MXC || COMPILE_TEST
|
||||
depends on HAS_IOMEM
|
||||
depends on OF
|
||||
help
|
||||
If you say yes here you get support for the Freescale MXC
|
||||
SRTC module in i.MX53 processor.
|
||||
@@ -1935,7 +1943,6 @@ config RTC_DRV_HID_SENSOR_TIME
|
||||
config RTC_DRV_GOLDFISH
|
||||
tristate "Goldfish Real Time Clock"
|
||||
depends on OF && HAS_IOMEM
|
||||
depends on GOLDFISH || COMPILE_TEST
|
||||
help
|
||||
Say yes to enable RTC driver for the Goldfish based virtual platform.
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ static void rtc_device_release(struct device *dev)
|
||||
struct rtc_device *rtc = to_rtc_device(dev);
|
||||
|
||||
ida_simple_remove(&rtc_ida, rtc->id);
|
||||
mutex_destroy(&rtc->ops_lock);
|
||||
kfree(rtc);
|
||||
}
|
||||
|
||||
@@ -326,8 +327,10 @@ static void rtc_device_get_offset(struct rtc_device *rtc)
|
||||
*
|
||||
* @rtc: the RTC class device to destroy
|
||||
*/
|
||||
static void rtc_device_unregister(struct rtc_device *rtc)
|
||||
static void devm_rtc_unregister_device(void *data)
|
||||
{
|
||||
struct rtc_device *rtc = data;
|
||||
|
||||
mutex_lock(&rtc->ops_lock);
|
||||
/*
|
||||
* Remove innards of this RTC, then disable it, before
|
||||
@@ -337,60 +340,43 @@ static void rtc_device_unregister(struct rtc_device *rtc)
|
||||
cdev_device_del(&rtc->char_dev, &rtc->dev);
|
||||
rtc->ops = NULL;
|
||||
mutex_unlock(&rtc->ops_lock);
|
||||
put_device(&rtc->dev);
|
||||
}
|
||||
|
||||
static void devm_rtc_release_device(struct device *dev, void *res)
|
||||
static void devm_rtc_release_device(void *res)
|
||||
{
|
||||
struct rtc_device *rtc = *(struct rtc_device **)res;
|
||||
struct rtc_device *rtc = res;
|
||||
|
||||
rtc_nvmem_unregister(rtc);
|
||||
|
||||
if (rtc->registered)
|
||||
rtc_device_unregister(rtc);
|
||||
else
|
||||
put_device(&rtc->dev);
|
||||
put_device(&rtc->dev);
|
||||
}
|
||||
|
||||
struct rtc_device *devm_rtc_allocate_device(struct device *dev)
|
||||
{
|
||||
struct rtc_device **ptr, *rtc;
|
||||
struct rtc_device *rtc;
|
||||
int id, err;
|
||||
|
||||
id = rtc_device_get_id(dev);
|
||||
if (id < 0)
|
||||
return ERR_PTR(id);
|
||||
|
||||
ptr = devres_alloc(devm_rtc_release_device, sizeof(*ptr), GFP_KERNEL);
|
||||
if (!ptr) {
|
||||
err = -ENOMEM;
|
||||
goto exit_ida;
|
||||
}
|
||||
|
||||
rtc = rtc_allocate_device();
|
||||
if (!rtc) {
|
||||
err = -ENOMEM;
|
||||
goto exit_devres;
|
||||
ida_simple_remove(&rtc_ida, id);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
*ptr = rtc;
|
||||
devres_add(dev, ptr);
|
||||
|
||||
rtc->id = id;
|
||||
rtc->dev.parent = dev;
|
||||
dev_set_name(&rtc->dev, "rtc%d", id);
|
||||
|
||||
return rtc;
|
||||
err = devm_add_action_or_reset(dev, devm_rtc_release_device, rtc);
|
||||
if (err)
|
||||
return ERR_PTR(err);
|
||||
|
||||
exit_devres:
|
||||
devres_free(ptr);
|
||||
exit_ida:
|
||||
ida_simple_remove(&rtc_ida, id);
|
||||
return ERR_PTR(err);
|
||||
return rtc;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_rtc_allocate_device);
|
||||
|
||||
int __rtc_register_device(struct module *owner, struct rtc_device *rtc)
|
||||
int __devm_rtc_register_device(struct module *owner, struct rtc_device *rtc)
|
||||
{
|
||||
struct rtc_wkalrm alrm;
|
||||
int err;
|
||||
@@ -420,7 +406,6 @@ int __rtc_register_device(struct module *owner, struct rtc_device *rtc)
|
||||
|
||||
rtc_proc_add_device(rtc);
|
||||
|
||||
rtc->registered = true;
|
||||
dev_info(rtc->dev.parent, "registered as %s\n",
|
||||
dev_name(&rtc->dev));
|
||||
|
||||
@@ -429,9 +414,10 @@ int __rtc_register_device(struct module *owner, struct rtc_device *rtc)
|
||||
rtc_hctosys(rtc);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
return devm_add_action_or_reset(rtc->dev.parent,
|
||||
devm_rtc_unregister_device, rtc);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__rtc_register_device);
|
||||
EXPORT_SYMBOL_GPL(__devm_rtc_register_device);
|
||||
|
||||
/**
|
||||
* devm_rtc_device_register - resource managed rtc_device_register()
|
||||
@@ -461,7 +447,7 @@ struct rtc_device *devm_rtc_device_register(struct device *dev,
|
||||
|
||||
rtc->ops = ops;
|
||||
|
||||
err = __rtc_register_device(owner, rtc);
|
||||
err = __devm_rtc_register_device(owner, rtc);
|
||||
if (err)
|
||||
return ERR_PTR(err);
|
||||
|
||||
|
||||
@@ -9,99 +9,22 @@
|
||||
#include <linux/types.h>
|
||||
#include <linux/nvmem-consumer.h>
|
||||
#include <linux/rtc.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/sysfs.h>
|
||||
|
||||
/*
|
||||
* Deprecated ABI compatibility, this should be removed at some point
|
||||
*/
|
||||
|
||||
static const char nvram_warning[] = "Deprecated ABI, please use nvmem";
|
||||
|
||||
static ssize_t
|
||||
rtc_nvram_read(struct file *filp, struct kobject *kobj,
|
||||
struct bin_attribute *attr,
|
||||
char *buf, loff_t off, size_t count)
|
||||
{
|
||||
dev_warn_once(kobj_to_dev(kobj), nvram_warning);
|
||||
|
||||
return nvmem_device_read(attr->private, off, count, buf);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
rtc_nvram_write(struct file *filp, struct kobject *kobj,
|
||||
struct bin_attribute *attr,
|
||||
char *buf, loff_t off, size_t count)
|
||||
{
|
||||
dev_warn_once(kobj_to_dev(kobj), nvram_warning);
|
||||
|
||||
return nvmem_device_write(attr->private, off, count, buf);
|
||||
}
|
||||
|
||||
static int rtc_nvram_register(struct rtc_device *rtc,
|
||||
struct nvmem_device *nvmem, size_t size)
|
||||
{
|
||||
int err;
|
||||
|
||||
rtc->nvram = kzalloc(sizeof(*rtc->nvram), GFP_KERNEL);
|
||||
if (!rtc->nvram)
|
||||
return -ENOMEM;
|
||||
|
||||
rtc->nvram->attr.name = "nvram";
|
||||
rtc->nvram->attr.mode = 0644;
|
||||
rtc->nvram->private = nvmem;
|
||||
|
||||
sysfs_bin_attr_init(rtc->nvram);
|
||||
|
||||
rtc->nvram->read = rtc_nvram_read;
|
||||
rtc->nvram->write = rtc_nvram_write;
|
||||
rtc->nvram->size = size;
|
||||
|
||||
err = sysfs_create_bin_file(&rtc->dev.parent->kobj,
|
||||
rtc->nvram);
|
||||
if (err) {
|
||||
kfree(rtc->nvram);
|
||||
rtc->nvram = NULL;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void rtc_nvram_unregister(struct rtc_device *rtc)
|
||||
{
|
||||
sysfs_remove_bin_file(&rtc->dev.parent->kobj, rtc->nvram);
|
||||
kfree(rtc->nvram);
|
||||
rtc->nvram = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* New ABI, uses nvmem
|
||||
*/
|
||||
int rtc_nvmem_register(struct rtc_device *rtc,
|
||||
int devm_rtc_nvmem_register(struct rtc_device *rtc,
|
||||
struct nvmem_config *nvmem_config)
|
||||
{
|
||||
struct device *dev = rtc->dev.parent;
|
||||
struct nvmem_device *nvmem;
|
||||
|
||||
if (!nvmem_config)
|
||||
return -ENODEV;
|
||||
|
||||
nvmem_config->dev = rtc->dev.parent;
|
||||
nvmem_config->dev = dev;
|
||||
nvmem_config->owner = rtc->owner;
|
||||
nvmem = devm_nvmem_register(rtc->dev.parent, nvmem_config);
|
||||
nvmem = devm_nvmem_register(dev, nvmem_config);
|
||||
if (IS_ERR(nvmem))
|
||||
return PTR_ERR(nvmem);
|
||||
dev_err(dev, "failed to register nvmem device for RTC\n");
|
||||
|
||||
/* Register the old ABI */
|
||||
if (rtc->nvram_old_abi)
|
||||
rtc_nvram_register(rtc, nvmem, nvmem_config->size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rtc_nvmem_register);
|
||||
|
||||
void rtc_nvmem_unregister(struct rtc_device *rtc)
|
||||
{
|
||||
/* unregister the old ABI */
|
||||
if (rtc->nvram)
|
||||
rtc_nvram_unregister(rtc);
|
||||
return PTR_ERR_OR_ZERO(nvmem);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_rtc_nvmem_register);
|
||||
|
||||
@@ -294,7 +294,7 @@ static int pm80x_rtc_probe(struct platform_device *pdev)
|
||||
info->rtc_dev->ops = &pm80x_rtc_ops;
|
||||
info->rtc_dev->range_max = U32_MAX;
|
||||
|
||||
ret = rtc_register_device(info->rtc_dev);
|
||||
ret = devm_rtc_register_device(info->rtc_dev);
|
||||
if (ret)
|
||||
goto out_rtc;
|
||||
|
||||
|
||||
@@ -307,7 +307,7 @@ static int pm860x_rtc_probe(struct platform_device *pdev)
|
||||
info->rtc_dev->ops = &pm860x_rtc_ops;
|
||||
info->rtc_dev->range_max = U32_MAX;
|
||||
|
||||
ret = rtc_register_device(info->rtc_dev);
|
||||
ret = devm_rtc_register_device(info->rtc_dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
||||
@@ -892,7 +892,7 @@ static int abb5zes3_probe(struct i2c_client *client,
|
||||
}
|
||||
}
|
||||
|
||||
ret = rtc_register_device(data->rtc);
|
||||
ret = devm_rtc_register_device(data->rtc);
|
||||
|
||||
err:
|
||||
if (ret && data->irq)
|
||||
|
||||
@@ -420,7 +420,7 @@ static int abeoz9_probe(struct i2c_client *client,
|
||||
data->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
|
||||
data->rtc->range_max = RTC_TIMESTAMP_END_2099;
|
||||
|
||||
ret = rtc_register_device(data->rtc);
|
||||
ret = devm_rtc_register_device(data->rtc);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
||||
@@ -238,7 +238,7 @@ static int __init ab3100_rtc_probe(struct platform_device *pdev)
|
||||
|
||||
platform_set_drvdata(pdev, rtc);
|
||||
|
||||
return rtc_register_device(rtc);
|
||||
return devm_rtc_register_device(rtc);
|
||||
}
|
||||
|
||||
static struct platform_driver ab3100_rtc_driver = {
|
||||
|
||||
@@ -404,7 +404,7 @@ static int ab8500_rtc_probe(struct platform_device *pdev)
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return rtc_register_device(rtc);
|
||||
return devm_rtc_register_device(rtc);
|
||||
}
|
||||
|
||||
static int ab8500_rtc_remove(struct platform_device *pdev)
|
||||
|
||||
@@ -851,7 +851,7 @@ static int abx80x_probe(struct i2c_client *client,
|
||||
return err;
|
||||
}
|
||||
|
||||
return rtc_register_device(priv->rtc);
|
||||
return devm_rtc_register_device(priv->rtc);
|
||||
}
|
||||
|
||||
static const struct i2c_device_id abx80x_id[] = {
|
||||
|
||||
@@ -610,7 +610,7 @@ static int ac100_rtc_probe(struct platform_device *pdev)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return rtc_register_device(chip->rtc);
|
||||
return devm_rtc_register_device(chip->rtc);
|
||||
}
|
||||
|
||||
static int ac100_rtc_remove(struct platform_device *pdev)
|
||||
|
||||
@@ -556,7 +556,7 @@ static __init int armada38x_rtc_probe(struct platform_device *pdev)
|
||||
|
||||
rtc->rtc_dev->range_max = U32_MAX;
|
||||
|
||||
return rtc_register_device(rtc->rtc_dev);
|
||||
return devm_rtc_register_device(rtc->rtc_dev);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
|
||||
@@ -104,7 +104,7 @@ static int aspeed_rtc_probe(struct platform_device *pdev)
|
||||
rtc->rtc_dev->range_min = RTC_TIMESTAMP_BEGIN_1900;
|
||||
rtc->rtc_dev->range_max = 38814989399LL; /* 3199-12-31 23:59:59 */
|
||||
|
||||
return rtc_register_device(rtc->rtc_dev);
|
||||
return devm_rtc_register_device(rtc->rtc_dev);
|
||||
}
|
||||
|
||||
static const struct of_device_id aspeed_rtc_match[] = {
|
||||
|
||||
@@ -36,6 +36,10 @@
|
||||
#define AT91_RTC_UPDCAL BIT(1) /* Update Request Calendar Register */
|
||||
|
||||
#define AT91_RTC_MR 0x04 /* Mode Register */
|
||||
#define AT91_RTC_HRMOD BIT(0) /* 12/24 hour mode */
|
||||
#define AT91_RTC_NEGPPM BIT(4) /* Negative PPM correction */
|
||||
#define AT91_RTC_CORRECTION GENMASK(14, 8) /* Slow clock correction */
|
||||
#define AT91_RTC_HIGHPPM BIT(15) /* High PPM correction */
|
||||
|
||||
#define AT91_RTC_TIMR 0x08 /* Time Register */
|
||||
#define AT91_RTC_SEC GENMASK(6, 0) /* Current Second */
|
||||
@@ -77,6 +81,9 @@
|
||||
#define AT91_RTC_NVTIMALR BIT(2) /* Non valid Time Alarm */
|
||||
#define AT91_RTC_NVCALALR BIT(3) /* Non valid Calendar Alarm */
|
||||
|
||||
#define AT91_RTC_CORR_DIVIDEND 3906000
|
||||
#define AT91_RTC_CORR_LOW_RATIO 20
|
||||
|
||||
#define at91_rtc_read(field) \
|
||||
readl_relaxed(at91_rtc_regs + field)
|
||||
#define at91_rtc_write(field, val) \
|
||||
@@ -84,6 +91,7 @@
|
||||
|
||||
struct at91_rtc_config {
|
||||
bool use_shadow_imr;
|
||||
bool has_correction;
|
||||
};
|
||||
|
||||
static const struct at91_rtc_config *at91_rtc_config;
|
||||
@@ -293,6 +301,75 @@ static int at91_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int at91_rtc_readoffset(struct device *dev, long *offset)
|
||||
{
|
||||
u32 mr = at91_rtc_read(AT91_RTC_MR);
|
||||
long val = FIELD_GET(AT91_RTC_CORRECTION, mr);
|
||||
|
||||
if (!val) {
|
||||
*offset = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
val++;
|
||||
|
||||
if (!(mr & AT91_RTC_NEGPPM))
|
||||
val = -val;
|
||||
|
||||
if (!(mr & AT91_RTC_HIGHPPM))
|
||||
val *= AT91_RTC_CORR_LOW_RATIO;
|
||||
|
||||
*offset = DIV_ROUND_CLOSEST(AT91_RTC_CORR_DIVIDEND, val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int at91_rtc_setoffset(struct device *dev, long offset)
|
||||
{
|
||||
long corr;
|
||||
u32 mr;
|
||||
|
||||
if (offset > AT91_RTC_CORR_DIVIDEND / 2)
|
||||
return -ERANGE;
|
||||
if (offset < -AT91_RTC_CORR_DIVIDEND / 2)
|
||||
return -ERANGE;
|
||||
|
||||
mr = at91_rtc_read(AT91_RTC_MR);
|
||||
mr &= ~(AT91_RTC_NEGPPM | AT91_RTC_CORRECTION | AT91_RTC_HIGHPPM);
|
||||
|
||||
if (offset > 0)
|
||||
mr |= AT91_RTC_NEGPPM;
|
||||
else
|
||||
offset = -offset;
|
||||
|
||||
/* offset less than 764 ppb, disable correction*/
|
||||
if (offset < 764) {
|
||||
at91_rtc_write(AT91_RTC_MR, mr & ~AT91_RTC_NEGPPM);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* 29208 ppb is the perfect cutoff between low range and high range
|
||||
* low range values are never better than high range value after that.
|
||||
*/
|
||||
if (offset < 29208) {
|
||||
corr = DIV_ROUND_CLOSEST(AT91_RTC_CORR_DIVIDEND, offset * AT91_RTC_CORR_LOW_RATIO);
|
||||
} else {
|
||||
corr = DIV_ROUND_CLOSEST(AT91_RTC_CORR_DIVIDEND, offset);
|
||||
mr |= AT91_RTC_HIGHPPM;
|
||||
}
|
||||
|
||||
if (corr > 128)
|
||||
corr = 128;
|
||||
|
||||
mr |= FIELD_PREP(AT91_RTC_CORRECTION, corr - 1);
|
||||
|
||||
at91_rtc_write(AT91_RTC_MR, mr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* IRQ handler for the RTC
|
||||
*/
|
||||
@@ -343,6 +420,10 @@ static const struct at91_rtc_config at91sam9x5_config = {
|
||||
.use_shadow_imr = true,
|
||||
};
|
||||
|
||||
static const struct at91_rtc_config sama5d4_config = {
|
||||
.has_correction = true,
|
||||
};
|
||||
|
||||
static const struct of_device_id at91_rtc_dt_ids[] = {
|
||||
{
|
||||
.compatible = "atmel,at91rm9200-rtc",
|
||||
@@ -352,10 +433,13 @@ static const struct of_device_id at91_rtc_dt_ids[] = {
|
||||
.data = &at91sam9x5_config,
|
||||
}, {
|
||||
.compatible = "atmel,sama5d4-rtc",
|
||||
.data = &at91rm9200_config,
|
||||
.data = &sama5d4_config,
|
||||
}, {
|
||||
.compatible = "atmel,sama5d2-rtc",
|
||||
.data = &at91rm9200_config,
|
||||
.data = &sama5d4_config,
|
||||
}, {
|
||||
.compatible = "microchip,sam9x60-rtc",
|
||||
.data = &sama5d4_config,
|
||||
}, {
|
||||
/* sentinel */
|
||||
}
|
||||
@@ -370,6 +454,16 @@ static const struct rtc_class_ops at91_rtc_ops = {
|
||||
.alarm_irq_enable = at91_rtc_alarm_irq_enable,
|
||||
};
|
||||
|
||||
static const struct rtc_class_ops sama5d4_rtc_ops = {
|
||||
.read_time = at91_rtc_readtime,
|
||||
.set_time = at91_rtc_settime,
|
||||
.read_alarm = at91_rtc_readalarm,
|
||||
.set_alarm = at91_rtc_setalarm,
|
||||
.alarm_irq_enable = at91_rtc_alarm_irq_enable,
|
||||
.set_offset = at91_rtc_setoffset,
|
||||
.read_offset = at91_rtc_readoffset,
|
||||
};
|
||||
|
||||
/*
|
||||
* Initialize and install RTC driver
|
||||
*/
|
||||
@@ -416,7 +510,7 @@ static int __init at91_rtc_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
at91_rtc_write(AT91_RTC_CR, 0);
|
||||
at91_rtc_write(AT91_RTC_MR, 0); /* 24 hour mode */
|
||||
at91_rtc_write(AT91_RTC_MR, at91_rtc_read(AT91_RTC_MR) & ~AT91_RTC_HRMOD);
|
||||
|
||||
/* Disable all interrupts */
|
||||
at91_rtc_write_idr(AT91_RTC_ACKUPD | AT91_RTC_ALARM |
|
||||
@@ -437,10 +531,14 @@ static int __init at91_rtc_probe(struct platform_device *pdev)
|
||||
if (!device_can_wakeup(&pdev->dev))
|
||||
device_init_wakeup(&pdev->dev, 1);
|
||||
|
||||
rtc->ops = &at91_rtc_ops;
|
||||
if (at91_rtc_config->has_correction)
|
||||
rtc->ops = &sama5d4_rtc_ops;
|
||||
else
|
||||
rtc->ops = &at91_rtc_ops;
|
||||
|
||||
rtc->range_min = RTC_TIMESTAMP_BEGIN_1900;
|
||||
rtc->range_max = RTC_TIMESTAMP_END_2099;
|
||||
ret = rtc_register_device(rtc);
|
||||
ret = devm_rtc_register_device(rtc);
|
||||
if (ret)
|
||||
goto err_clk;
|
||||
|
||||
|
||||
@@ -431,7 +431,7 @@ static int at91_rtc_probe(struct platform_device *pdev)
|
||||
dev_warn(&pdev->dev, "%s: SET TIME!\n",
|
||||
dev_name(&rtc->rtcdev->dev));
|
||||
|
||||
return rtc_register_device(rtc->rtcdev);
|
||||
return devm_rtc_register_device(rtc->rtcdev);
|
||||
|
||||
err_clk:
|
||||
clk_disable_unprepare(rtc->sclk);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user