Commit 28e8c4bc authored by Linus Torvalds's avatar Linus Torvalds

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

Pull RTC updates from Alexandre Belloni:
 "Subsystem:
   - new %ptR printk format
   - rename core files
   - allow registration of multiple nvmem devices

  New driver:
   - i.MX system controller RTC

  Driver updates:
   - abx80x: handle voltage ioctls, correct binding doc
   - m41t80: correct month in alarm reads
   - pcf85363: add pcf85263 support
   - pcf8523: properly handle battery low flag
   - s3c: limit alarm to one year in the future as ALMYEAR is broken
   - sun6i: rework clock output binding"

* tag 'rtc-4.21' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux: (54 commits)
  rtc: rename core files
  rtc: nvmem: fix possible use after free
  rtc: add i.MX system controller RTC support
  dt-bindings: fsl: scu: add rtc binding
  rtc: pcf2123: Add Microcrystal rv2123
  rtc: class: reimplement devm_rtc_device_register
  rtc: enforce rtc_timer_init private_data type
  rtc: abx80x: Implement RTC_VL_READ,CLR ioctls
  rtc: pcf85363: Add support for NXP pcf85263 rtc
  dt-bindings: rtc: pcf85363: Document pcf85263 real-time clock
  rtc: pcf8523: don't return invalid date when battery is low
  dt-bindings: rtc: use a generic node name for ds1307
  PM: Switch to use %ptR
  m68k/mac: Switch to use %ptR
  Input: hp_sdc_rtc - Switch to use %ptR
  rtc: tegra: Switch to use %ptR
  rtc: s5m: Switch to use %ptR
  rtc: s3c: Switch to use %ptR
  rtc: rx8025: Switch to use %ptR
  rtc: rx6110: Switch to use %ptR
  ...
parents c9bef4a6 36e14f5f
......@@ -412,6 +412,24 @@ Examples::
Passed by reference.
Time and date (struct rtc_time)
-------------------------------
::
%ptR YYYY-mm-ddTHH:MM:SS
%ptRd YYYY-mm-dd
%ptRt HH:MM:SS
%ptR[dt][r]
For printing date and time as represented by struct rtc_time structure in
human readable format.
By default year will be incremented by 1900 and month by 1. Use %ptRr (raw)
to suppress this behaviour.
Passed by reference.
struct clk
----------
......
......@@ -109,6 +109,12 @@ Required properties for Pinctrl sub nodes:
[2] Documentation/devicetree/bindings/power/power_domain.txt
[3] Documentation/devicetree/bindings/pinctrl/fsl,imx-pinctrl.txt
RTC bindings based on SCU Message Protocol
------------------------------------------------------------
Required properties:
- compatible: should be "fsl,imx8qxp-sc-rtc";
Example (imx8qxp):
-------------
lsio_mu1: mailbox@5d1c0000 {
......@@ -151,6 +157,10 @@ firmware {
compatible = "fsl,imx8qxp-scu-pd";
#power-domain-cells = <1>;
};
rtc: rtc {
compatible = "fsl,imx8qxp-sc-rtc";
};
};
};
......
......@@ -27,4 +27,4 @@ and valid to enable charging:
- "abracon,tc-diode": should be "standard" (0.6V) or "schottky" (0.3V)
- "abracon,tc-resistor": should be <0>, <3>, <6> or <11>. 0 disables the output
resistor, the other values are in ohm.
resistor, the other values are in kOhm.
......@@ -2,6 +2,7 @@ NXP PCF2123 SPI Real Time Clock
Required properties:
- compatible: should be: "nxp,rtc-pcf2123"
or "microcrystal,rv2123"
- reg: should be the SPI slave chipselect address
Optional properties:
......
NXP PCF85363 Real Time Clock
NXP PCF85263/PCF85363 Real Time Clock
============================
Required properties:
- compatible: Should contain "nxp,pcf85363".
- compatible: Should contain "nxp,pcf85263" or "nxp,pcf85363".
- reg: I2C address for chip.
Optional properties:
......
......@@ -35,7 +35,7 @@ Optional properties:
Should be given if internal trickle charger diode should be disabled
Example:
rtc1: ds1339@68 {
ds1339: rtc@68 {
compatible = "dallas,ds1339";
reg = <0x68>;
interrupt-parent = <&gpio4>;
......
......@@ -3,25 +3,44 @@
RTC controller for the Allwinner A31
Required properties:
- compatible : Should be "allwinner,sun6i-a31-rtc"
- compatible : Should be one of the following combinations:
- "allwinner,sun6i-a31-rtc"
- "allwinner,sun8i-a23-rtc"
- "allwinner,sun8i-h3-rtc"
- "allwinner,sun8i-r40-rtc", "allwinner,sun8i-h3-rtc"
- "allwinner,sun8i-v3-rtc"
- "allwinner,sun50i-a64-rtc", "allwinner,sun8i-h3-rtc"
- "allwinner,sun50i-h5-rtc"
Where there are two or more compatible strings, this
denotes the hardware covered by the most specific one
is backward-compatible with the latter ones, and the
implementation for the latter ones can be used, albeit
with reduced functionality.
- reg : physical base address of the controller and length of
memory mapped region.
- interrupts : IRQ lines for the RTC alarm 0 and alarm 1, in that order.
Required properties for new device trees
- clocks : phandle to the 32kHz external oscillator
- clock-output-names : names of the LOSC and its external output clocks created
- #clock-cells : must be equals to 1. The RTC provides two clocks: the
LOSC and its external output, with index 0 and 1
respectively.
- clock-output-names : names of up to three clock outputs. See below.
- #clock-cells : must be equal to 1.
The RTC provides the following clocks at the given indices:
- 0: LOSC
- 1: LOSC external output, known as X32KFOUT in the datasheet.
This clock is not available on the A31 and is deprecated for old
device trees still using the "allwinner,sun6i-a31-rtc" compatible.
- 2: InternalOSC, or internal RC oscillator (A64/H3/H5 only)
Example:
rtc: rtc@1f00000 {
compatible = "allwinner,sun6i-a31-rtc";
reg = <0x01f00000 0x54>;
reg = <0x01f00000 0x400>;
interrupts = <0 40 4>, <0 41 4>;
clock-output-names = "osc32k", "osc32k-out";
clock-output-names = "osc32k";
clocks = <&ext_osc32k>;
#clock-cells = <1>;
};
......@@ -605,13 +605,9 @@ int mac_hwclk(int op, struct rtc_time *t)
unmktime(now, 0,
&t->tm_year, &t->tm_mon, &t->tm_mday,
&t->tm_hour, &t->tm_min, &t->tm_sec);
pr_debug("%s: read %04d-%02d-%-2d %02d:%02d:%02d\n",
__func__, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
t->tm_hour, t->tm_min, t->tm_sec);
pr_debug("%s: read %ptR\n", __func__, t);
} else { /* write */
pr_debug("%s: tried to write %04d-%02d-%-2d %02d:%02d:%02d\n",
__func__, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
t->tm_hour, t->tm_min, t->tm_sec);
pr_debug("%s: tried to write %ptR\n", __func__, t);
switch (macintosh_config->adb_type) {
case MAC_ADB_IOP:
......
......@@ -118,9 +118,7 @@ static unsigned int read_magic_time(void)
unsigned int val;
mc146818_get_time(&time);
pr_info("RTC time: %2d:%02d:%02d, date: %02d/%02d/%02d\n",
time.tm_hour, time.tm_min, time.tm_sec,
time.tm_mon + 1, time.tm_mday, time.tm_year % 100);
pr_info("RTC time: %ptRt, date: %ptRd\n", &time, &time);
val = time.tm_year; /* 100 years */
if (val > 100)
val -= 100;
......
......@@ -1125,11 +1125,10 @@ static int rtc_proc_show(struct seq_file *seq, void *v)
* time or for Universal Standard Time (GMT). Probably local though.
*/
seq_printf(seq,
"rtc_time\t: %02d:%02d:%02d\n"
"rtc_date\t: %04d-%02d-%02d\n"
"rtc_time\t: %ptRt\n"
"rtc_date\t: %ptRd\n"
"rtc_epoch\t: %04lu\n",
tm.tm_hour, tm.tm_min, tm.tm_sec,
tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, epoch);
&tm, &tm, epoch);
get_rtc_alm_time(&tm);
......
......@@ -441,12 +441,10 @@ static int hp_sdc_rtc_proc_show(struct seq_file *m, void *v)
seq_puts(m, "BBRTC\t\t: READ FAILED!\n");
} else {
seq_printf(m,
"rtc_time\t: %02d:%02d:%02d\n"
"rtc_date\t: %04d-%02d-%02d\n"
"rtc_time\t: %ptRt\n"
"rtc_date\t: %ptRd\n"
"rtc_epoch\t: %04lu\n",
tm.tm_hour, tm.tm_min, tm.tm_sec,
tm.tm_year + 1900, tm.tm_mon + 1,
tm.tm_mday, epoch);
&tm, &tm, epoch);
}
if (hp_sdc_rtc_read_rt(&tv)) {
......
......@@ -1677,6 +1677,13 @@ config RTC_DRV_SNVS
This driver can also be built as a module, if so, the module
will be called "rtc-snvs".
config RTC_DRV_IMX_SC
depends on IMX_SCU
tristate "NXP i.MX System Controller RTC support"
help
If you say yes here you get support for the NXP i.MX System
Controller RTC module.
config RTC_DRV_SIRFSOC
tristate "SiRFSOC RTC"
depends on ARCH_SIRF
......
......@@ -5,7 +5,7 @@
ccflags-$(CONFIG_RTC_DEBUG) := -DDEBUG
obj-$(CONFIG_RTC_LIB) += rtc-lib.o
obj-$(CONFIG_RTC_LIB) += lib.o
obj-$(CONFIG_RTC_HCTOSYS) += hctosys.o
obj-$(CONFIG_RTC_SYSTOHC) += systohc.o
obj-$(CONFIG_RTC_CLASS) += rtc-core.o
......@@ -17,9 +17,9 @@ rtc-core-y += rtc-efi-platform.o
endif
rtc-core-$(CONFIG_RTC_NVMEM) += nvmem.o
rtc-core-$(CONFIG_RTC_INTF_DEV) += rtc-dev.o
rtc-core-$(CONFIG_RTC_INTF_PROC) += rtc-proc.o
rtc-core-$(CONFIG_RTC_INTF_SYSFS) += rtc-sysfs.o
rtc-core-$(CONFIG_RTC_INTF_DEV) += dev.o
rtc-core-$(CONFIG_RTC_INTF_PROC) += proc.o
rtc-core-$(CONFIG_RTC_INTF_SYSFS) += sysfs.o
# Keep the list ordered.
......@@ -75,6 +75,7 @@ obj-$(CONFIG_RTC_DRV_GOLDFISH) += rtc-goldfish.o
obj-$(CONFIG_RTC_DRV_HID_SENSOR_TIME) += rtc-hid-sensor-time.o
obj-$(CONFIG_RTC_DRV_HYM8563) += rtc-hym8563.o
obj-$(CONFIG_RTC_DRV_IMXDI) += rtc-imxdi.o
obj-$(CONFIG_RTC_DRV_IMX_SC) += rtc-imx-sc.o
obj-$(CONFIG_RTC_DRV_ISL12022) += rtc-isl12022.o
obj-$(CONFIG_RTC_DRV_ISL12026) += rtc-isl12026.o
obj-$(CONFIG_RTC_DRV_ISL1208) += rtc-isl1208.o
......
......@@ -178,9 +178,9 @@ static struct rtc_device *rtc_allocate_device(void)
timerqueue_init_head(&rtc->timerqueue);
INIT_WORK(&rtc->irqwork, rtc_timer_do_work);
/* Init aie timer */
rtc_timer_init(&rtc->aie_timer, rtc_aie_update_irq, (void *)rtc);
rtc_timer_init(&rtc->aie_timer, rtc_aie_update_irq, rtc);
/* Init uie timer */
rtc_timer_init(&rtc->uie_rtctimer, rtc_uie_update_irq, (void *)rtc);
rtc_timer_init(&rtc->uie_rtctimer, rtc_uie_update_irq, rtc);
/* Init pie timer */
hrtimer_init(&rtc->pie_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
rtc->pie_timer.function = rtc_pie_update_irq;
......@@ -277,82 +277,6 @@ static void rtc_device_get_offset(struct rtc_device *rtc)
rtc->offset_secs = 0;
}
/**
* rtc_device_register - register w/ RTC class
* @dev: the device to register
*
* rtc_device_unregister() must be called when the class device is no
* longer needed.
*
* Returns the pointer to the new struct class device.
*/
static struct rtc_device *rtc_device_register(const char *name,
struct device *dev,
const struct rtc_class_ops *ops,
struct module *owner)
{
struct rtc_device *rtc;
struct rtc_wkalrm alrm;
int id, err;
id = rtc_device_get_id(dev);
if (id < 0) {
err = id;
goto exit;
}
rtc = rtc_allocate_device();
if (!rtc) {
err = -ENOMEM;
goto exit_ida;
}
rtc->id = id;
rtc->ops = ops;
rtc->owner = owner;
rtc->dev.parent = dev;
dev_set_name(&rtc->dev, "rtc%d", id);
rtc_device_get_offset(rtc);
/* Check to see if there is an ALARM already set in hw */
err = __rtc_read_alarm(rtc, &alrm);
if (!err && !rtc_valid_tm(&alrm.time))
rtc_initialize_alarm(rtc, &alrm);
rtc_dev_prepare(rtc);
err = cdev_device_add(&rtc->char_dev, &rtc->dev);
if (err) {
dev_warn(&rtc->dev, "%s: failed to add char device %d:%d\n",
name, MAJOR(rtc->dev.devt), rtc->id);
/* This will free both memory and the ID */
put_device(&rtc->dev);
goto exit;
} else {
dev_dbg(&rtc->dev, "%s: dev (%d:%d)\n", name,
MAJOR(rtc->dev.devt), rtc->id);
}
rtc_proc_add_device(rtc);
dev_info(dev, "rtc core: registered %s as %s\n",
name, dev_name(&rtc->dev));
return rtc;
exit_ida:
ida_simple_remove(&rtc_ida, id);
exit:
dev_err(dev, "rtc core: unable to register %s, err = %d\n",
name, err);
return ERR_PTR(err);
}
/**
* rtc_device_unregister - removes the previously registered RTC class device
*
......@@ -372,77 +296,6 @@ static void rtc_device_unregister(struct rtc_device *rtc)
put_device(&rtc->dev);
}
static void devm_rtc_device_release(struct device *dev, void *res)
{
struct rtc_device *rtc = *(struct rtc_device **)res;
rtc_nvmem_unregister(rtc);
rtc_device_unregister(rtc);
}
static int devm_rtc_device_match(struct device *dev, void *res, void *data)
{
struct rtc **r = res;
return *r == data;
}
/**
* devm_rtc_device_register - resource managed rtc_device_register()
* @dev: the device to register
* @name: the name of the device
* @ops: the rtc operations structure
* @owner: the module owner
*
* @return a struct rtc on success, or an ERR_PTR on error
*
* Managed rtc_device_register(). The rtc_device returned from this function
* are automatically freed on driver detach. See rtc_device_register()
* for more information.
*/
struct rtc_device *devm_rtc_device_register(struct device *dev,
const char *name,
const struct rtc_class_ops *ops,
struct module *owner)
{
struct rtc_device **ptr, *rtc;
ptr = devres_alloc(devm_rtc_device_release, sizeof(*ptr), GFP_KERNEL);
if (!ptr)
return ERR_PTR(-ENOMEM);
rtc = rtc_device_register(name, dev, ops, owner);
if (!IS_ERR(rtc)) {
*ptr = rtc;
devres_add(dev, ptr);
} else {
devres_free(ptr);
}
return rtc;
}
EXPORT_SYMBOL_GPL(devm_rtc_device_register);
/**
* devm_rtc_device_unregister - resource managed devm_rtc_device_unregister()
* @dev: the device to unregister
* @rtc: the RTC class device to unregister
*
* Deallocated a rtc allocated with devm_rtc_device_register(). Normally this
* function will not need to be called and the resource management code will
* ensure that the resource is freed.
*/
void devm_rtc_device_unregister(struct device *dev, struct rtc_device *rtc)
{
int rc;
rc = devres_release(dev, devm_rtc_device_release,
devm_rtc_device_match, rtc);
WARN_ON(rc);
}
EXPORT_SYMBOL_GPL(devm_rtc_device_unregister);
static void devm_rtc_release_device(struct device *dev, void *res)
{
struct rtc_device *rtc = *(struct rtc_device **)res;
......@@ -529,6 +382,42 @@ int __rtc_register_device(struct module *owner, struct rtc_device *rtc)
}
EXPORT_SYMBOL_GPL(__rtc_register_device);
/**
* devm_rtc_device_register - resource managed rtc_device_register()
* @dev: the device to register
* @name: the name of the device (unused)
* @ops: the rtc operations structure
* @owner: the module owner
*
* @return a struct rtc on success, or an ERR_PTR on error
*
* Managed rtc_device_register(). The rtc_device returned from this function
* are automatically freed on driver detach.
* This function is deprecated, use devm_rtc_allocate_device and
* rtc_register_device instead
*/
struct rtc_device *devm_rtc_device_register(struct device *dev,
const char *name,
const struct rtc_class_ops *ops,
struct module *owner)
{
struct rtc_device *rtc;
int err;
rtc = devm_rtc_allocate_device(dev);
if (IS_ERR(rtc))
return rtc;
rtc->ops = ops;
err = __rtc_register_device(owner, rtc);
if (err)
return ERR_PTR(err);
return rtc;
}
EXPORT_SYMBOL_GPL(devm_rtc_device_register);
static int __init rtc_init(void)
{
rtc_class = class_create(THIS_MODULE, "rtc");
......
......@@ -58,12 +58,8 @@ static int __init rtc_hctosys(void)
err = do_settimeofday64(&tv64);
dev_info(rtc->dev.parent,
"setting system clock to "
"%d-%02d-%02d %02d:%02d:%02d UTC (%lld)\n",
tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
tm.tm_hour, tm.tm_min, tm.tm_sec,
(long long) tv64.tv_sec);
dev_info(rtc->dev.parent, "setting system clock to %ptR UTC (%lld)\n",
&tm, (long long)tv64.tv_sec);
err_read:
rtc_class_close(rtc);
......
......@@ -368,12 +368,8 @@ int __rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
err = rtc_valid_tm(&alarm->time);
done:
if (err) {
dev_warn(&rtc->dev, "invalid alarm value: %d-%d-%d %d:%d:%d\n",
alarm->time.tm_year + 1900, alarm->time.tm_mon + 1,
alarm->time.tm_mday, alarm->time.tm_hour, alarm->time.tm_min,
alarm->time.tm_sec);
}
if (err)
dev_warn(&rtc->dev, "invalid alarm value: %ptR\n", &alarm->time);
return err;
}
......@@ -613,26 +609,24 @@ void rtc_handle_legacy_irq(struct rtc_device *rtc, int num, int mode)
/**
* rtc_aie_update_irq - AIE mode rtctimer hook
* @private: pointer to the rtc_device
* @rtc: pointer to the rtc_device
*
* This functions is called when the aie_timer expires.
*/
void rtc_aie_update_irq(void *private)
void rtc_aie_update_irq(struct rtc_device *rtc)
{
struct rtc_device *rtc = (struct rtc_device *)private;
rtc_handle_legacy_irq(rtc, 1, RTC_AF);
}
/**
* rtc_uie_update_irq - UIE mode rtctimer hook
* @private: pointer to the rtc_device
* @rtc: pointer to the rtc_device
*
* This functions is called when the uie_timer expires.
*/
void rtc_uie_update_irq(void *private)
void rtc_uie_update_irq(struct rtc_device *rtc)
{
struct rtc_device *rtc = (struct rtc_device *)private;
rtc_handle_legacy_irq(rtc, 1, RTC_UF);
}
......@@ -912,7 +906,7 @@ void rtc_timer_do_work(struct work_struct *work)
trace_rtc_timer_dequeue(timer);
timer->enabled = 0;
if (timer->func)
timer->func(timer->private_data);
timer->func(timer->rtc);
trace_rtc_timer_fired(timer);
/* Re-add/fwd periodic timers */
......@@ -959,16 +953,17 @@ void rtc_timer_do_work(struct work_struct *work)
/* rtc_timer_init - Initializes an rtc_timer
* @timer: timer to be intiialized
* @f: function pointer to be called when timer fires
* @data: private data passed to function pointer
* @rtc: pointer to the rtc_device
*
* Kernel interface to initializing an rtc_timer.
*/
void rtc_timer_init(struct rtc_timer *timer, void (*f)(void *p), void *data)
void rtc_timer_init(struct rtc_timer *timer, void (*f)(struct rtc_device *r),
struct rtc_device *rtc)
{
timerqueue_init(&timer->node);
timer->enabled = 0;
timer->func = f;
timer->private_data = data;
timer->rtc = rtc;
}
/* rtc_timer_start - Sets an rtc_timer to fire in the future
......
......@@ -12,6 +12,7 @@
#include <linux/types.h>
#include <linux/nvmem-consumer.h>
#include <linux/rtc.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
/*
......@@ -25,11 +26,9 @@ rtc_nvram_read(struct file *filp, struct kobject *kobj,
struct bin_attribute *attr,
char *buf, loff_t off, size_t count)
{
struct rtc_device *rtc = attr->private;
dev_warn_once(kobj_to_dev(kobj), nvram_warning);
return nvmem_device_read(rtc->nvmem, off, count, buf);
return nvmem_device_read(attr->private, off, count, buf);
}
static ssize_t
......@@ -37,26 +36,23 @@ rtc_nvram_write(struct file *filp, struct kobject *kobj,
struct bin_attribute *attr,
char *buf, loff_t off, size_t count)
{
struct rtc_device *rtc = attr->private;
dev_warn_once(kobj_to_dev(kobj), nvram_warning);
return nvmem_device_write(rtc->nvmem, off, count, buf);
return nvmem_device_write(attr->private, off, count, buf);
}
static int rtc_nvram_register(struct rtc_device *rtc, size_t size)
static int rtc_nvram_register(struct rtc_device *rtc,
struct nvmem_device *nvmem, size_t size)
{
int err;
rtc->nvram = devm_kzalloc(rtc->dev.parent,
sizeof(struct bin_attribute),
GFP_KERNEL);
rtc->nvram = kzalloc(sizeof(struct bin_attribute), GFP_KERNEL);
if (!rtc->nvram)
return -ENOMEM;
rtc->nvram->attr.name = "nvram";
rtc->nvram->attr.mode = 0644;
rtc->nvram->private = rtc;
rtc->nvram->private = nvmem;
sysfs_bin_attr_init(rtc->nvram);
......@@ -67,7 +63,7 @@ static int rtc_nvram_register(struct rtc_device *rtc, size_t size)
err = sysfs_create_bin_file(&rtc->dev.parent->kobj,
rtc->nvram);
if (err) {
devm_kfree(rtc->dev.parent, rtc->nvram);
kfree(rtc->nvram);
rtc->nvram = NULL;
}
......@@ -77,6 +73,8 @@ static int rtc_nvram_register(struct rtc_device *rtc, size_t size)
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;
}
/*
......@@ -85,21 +83,20 @@ static void rtc_nvram_unregister(struct rtc_device *rtc)
int rtc_nvmem_register(struct rtc_device *rtc,
struct nvmem_config *nvmem_config)
{
if (!IS_ERR_OR_NULL(rtc->nvmem))
return -EBUSY;
struct nvmem_device *nvmem;
if (!nvmem_config)
return -ENODEV;
nvmem_config->dev = rtc->dev.parent;
nvmem_config->owner = rtc->owner;
rtc->nvmem = nvmem_register(nvmem_config);
if (IS_ERR(rtc->nvmem))
return PTR_ERR(rtc->nvmem);
nvmem = devm_nvmem_register(rtc->dev.parent, nvmem_config);
if (IS_ERR(nvmem))
return PTR_ERR(nvmem);
/* Register the old ABI */
if (rtc->nvram_old_abi)
rtc_nvram_register(rtc, nvmem_config->size);
rtc_nvram_register(rtc, nvmem, nvmem_config->size);
return 0;
}
......@@ -107,12 +104,7 @@ EXPORT_SYMBOL_GPL(rtc_nvmem_register);
void rtc_nvmem_unregister(struct rtc_device *rtc)
{
if (IS_ERR_OR_NULL(rtc->nvmem))
return;
/* unregister the old ABI */
if (rtc->nvram)
rtc_nvram_unregister(rtc);
nvmem_unregister(rtc->nvmem);
}
......@@ -50,41 +50,15 @@ static int rtc_proc_show(struct seq_file *seq, void *offset)
err = rtc_read_time(rtc, &tm);
if (err == 0) {
seq_printf(seq,
"rtc_time\t: %02d:%02d:%02d\n"
"rtc_date\t: %04d-%02d-%02d\n",
tm.tm_hour, tm.tm_min, tm.tm_sec,
tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday);
"rtc_time\t: %ptRt\n"
"rtc_date\t: %ptRd\n",
&tm, &tm);
}
err = rtc_read_alarm(rtc, &alrm);
if (err == 0) {
seq_printf(seq, "alrm_time\t: ");
if ((unsigned int)alrm.time.tm_hour <= 24)
seq_printf(seq, "%02d:", alrm.time.tm_hour);
else
seq_printf(seq, "**:");
if ((unsigned int)alrm.time.tm_min <= 59)
seq_printf(seq, "%02d:", alrm.time.tm_min);
else
seq_printf(seq, "**:");
if ((unsigned int)alrm.time.tm_sec <= 59)
seq_printf(seq, "%02d\n", alrm.time.tm_sec);
else
seq_printf(seq, "**\n");
seq_printf(seq, "alrm_date\t: ");
if ((unsigned int)alrm.time.tm_year <= 200)
seq_printf(seq, "%04d-", alrm.time.tm_year + 1900);
else
seq_printf(seq, "****-");
if ((unsigned int)alrm.time.tm_mon <= 11)
seq_printf(seq, "%02d-", alrm.time.tm_mon + 1);
else
seq_printf(seq, "**-");
if (alrm.time.tm_mday && (unsigned int)alrm.time.tm_mday <= 31)
seq_printf(seq, "%02d\n", alrm.time.tm_mday);
else
seq_printf(seq, "**\n");
seq_printf(seq, "alrm_time\t: %ptRt\n", &alrm.time);
seq_printf(seq, "alrm_date\t: %ptRd\n", &alrm.time);
seq_printf(seq, "alarm_IRQ\t: %s\n",
alrm.enabled ? "yes" : "no");
seq_printf(seq, "alrm_pending\t: %s\n",
......
......@@ -38,6 +38,7 @@
#define ABX8XX_REG_STATUS 0x0f
#define ABX8XX_STATUS_AF BIT(2)
#define ABX8XX_STATUS_BLF BIT(4)
#define ABX8XX_STATUS_WDT BIT(6)
#define ABX8XX_REG_CTRL1 0x10
......@@ -507,12 +508,49 @@ static int abx80x_alarm_irq_enable(struct device *dev, unsigned int enabled)
return err;
}
static int abx80x_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
{
struct i2c_client *client = to_i2c_client(dev);
int status, tmp;
switch (cmd) {
case RTC_VL_READ:
status = i2c_smbus_read_byte_data(client, ABX8XX_REG_STATUS);
if (status < 0)
return status;
tmp = !!(status & ABX8XX_STATUS_BLF);
if (copy_to_user((void __user *)arg, &tmp, sizeof(int)))
return -EFAULT;
return 0;
case RTC_VL_CLR:
status = i2c_smbus_read_byte_data(client, ABX8XX_REG_STATUS);
if (status < 0)
return status;
status &= ~ABX8XX_STATUS_BLF;
tmp = i2c_smbus_write_byte_data(client, ABX8XX_REG_STATUS, 0);
if (tmp < 0)
return tmp;
return 0;
default:
return -ENOIOCTLCMD;
}
}
static const struct rtc_class_ops abx80x_rtc_ops = {
.read_time = abx80x_rtc_read_time,
.set_time = abx80x_rtc_set_time,
.read_alarm = abx80x_read_alarm,
.set_alarm = abx80x_set_alarm,
.alarm_irq_enable = abx80x_alarm_irq_enable,
.ioctl = abx80x_ioctl,
};
static int abx80x_dt_trickle_cfg(struct device_node *np)
......
......@@ -147,9 +147,7 @@ static int at91_rtc_readtime(struct device *dev, struct rtc_time *tm)
tm->tm_yday = rtc_year_days(tm->tm_mday, tm->tm_mon, tm->tm_year);
tm->tm_year = tm->tm_year - 1900;
dev_dbg(dev, "%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __func__,
1900 + tm->tm_year, tm->tm_mon, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec);
dev_dbg(dev, "%s(): %ptR\n", __func__, tm);
return 0;
}
......@@ -161,9 +159,7 @@ static int at91_rtc_settime(struct device *dev, struct rtc_time *tm)
{
unsigned long cr;
dev_dbg(dev, "%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __func__,
1900 + tm->tm_year, tm->tm_mon, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec);
dev_dbg(dev, "%s(): %ptR\n", __func__, tm);
wait_for_completion(&at91_rtc_upd_rdy);
......@@ -209,8 +205,7 @@ static int at91_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm)
alrm->enabled = (at91_rtc_read_imr() & AT91_RTC_ALARM)
? 1 : 0;
dev_dbg(dev, "%s(): %02d-%02d %02d:%02d:%02d %sabled\n", __func__,
tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec,
dev_dbg(dev, "%s(): %ptR %sabled\n", __func__, tm,
alrm->enabled ? "en" : "dis");
return 0;
......@@ -247,9 +242,7 @@ static int at91_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
at91_rtc_write_ier(AT91_RTC_ALARM);
}
dev_dbg(dev, "%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __func__,
tm.tm_year, tm.tm_mon, tm.tm_mday, tm.tm_hour,
tm.tm_min, tm.tm_sec);
dev_dbg(dev, "%s(): %ptR\n", __func__, &tm);
return 0;
}
......
......@@ -124,9 +124,7 @@ static int at91_rtc_readtime(struct device *dev, struct rtc_time *tm)
rtc_time_to_tm(offset + secs, tm);
dev_dbg(dev, "%s: %4d-%02d-%02d %02d:%02d:%02d\n", "readtime",
1900 + tm->tm_year, tm->tm_mon, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec);
dev_dbg(dev, "%s: %ptR\n", __func__, tm);
return 0;
}
......@@ -141,9 +139,7 @@ static int at91_rtc_settime(struct device *dev, struct rtc_time *tm)
u32 offset, alarm, mr;
unsigned long secs;
dev_dbg(dev, "%s: %4d-%02d-%02d %02d:%02d:%02d\n", "settime",
1900 + tm->tm_year, tm->tm_mon, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec);
dev_dbg(dev, "%s: %ptR\n", __func__, tm);
err = rtc_tm_to_time(tm, &secs);
if (err != 0)
......@@ -199,9 +195,7 @@ static int at91_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm)
if (alarm != ALARM_DISABLED && offset != 0) {
rtc_time_to_tm(offset + alarm, tm);
dev_dbg(dev, "%s: %4d-%02d-%02d %02d:%02d:%02d\n", "readalarm",
1900 + tm->tm_year, tm->tm_mon, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec);
dev_dbg(dev, "%s: %ptR\n", __func__, tm);
if (rtt_readl(rtc, MR) & AT91_RTT_ALMIEN)
alrm->enabled = 1;
......@@ -242,9 +236,7 @@ static int at91_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
if (alrm->enabled)
rtt_writel(rtc, MR, mr | AT91_RTT_ALMIEN);
dev_dbg(dev, "%s: %4d-%02d-%02d %02d:%02d:%02d\n", "setalarm",
tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour,
tm->tm_min, tm->tm_sec);
dev_dbg(dev, "%s: %ptR\n", __func__, tm);
return 0;
}
......
......@@ -61,7 +61,7 @@ static int ep93xx_rtc_read_time(struct device *dev, struct rtc_time *tm)
struct ep93xx_rtc *ep93xx_rtc = dev_get_platdata(dev);
unsigned long time;
time = readl(ep93xx_rtc->mmio_base + EP93XX_RTC_DATA);
time = readl(ep93xx_rtc->mmio_base + EP93XX_RTC_DATA);
rtc_time_to_tm(time, tm);
return 0;
......
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2018 NXP.
*/
#include <linux/firmware/imx/sci.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/rtc.h>
#define IMX_SC_TIMER_FUNC_GET_RTC_SEC1970 9
#define IMX_SC_TIMER_FUNC_SET_RTC_TIME 6
static struct imx_sc_ipc *rtc_ipc_handle;
static struct rtc_device *imx_sc_rtc;
struct imx_sc_msg_timer_get_rtc_time {
struct imx_sc_rpc_msg hdr;
u32 time;
} __packed;
static int imx_sc_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
struct imx_sc_msg_timer_get_rtc_time msg;
struct imx_sc_rpc_msg *hdr = &msg.hdr;
int ret;
hdr->ver = IMX_SC_RPC_VERSION;
hdr->svc = IMX_SC_RPC_SVC_TIMER;
hdr->func = IMX_SC_TIMER_FUNC_GET_RTC_SEC1970;
hdr->size = 1;
ret = imx_scu_call_rpc(rtc_ipc_handle, &msg, true);
if (ret) {
dev_err(dev, "read rtc time failed, ret %d\n", ret);
return ret;
}
rtc_time_to_tm(msg.time, tm);
return 0;
}
static const struct rtc_class_ops imx_sc_rtc_ops = {
.read_time = imx_sc_rtc_read_time,
};
static int imx_sc_rtc_probe(struct platform_device *pdev)
{
int ret;
ret = imx_scu_get_handle(&rtc_ipc_handle);
if (ret)
return ret;
imx_sc_rtc = devm_rtc_allocate_device(&pdev->dev);
if (IS_ERR(imx_sc_rtc))
return PTR_ERR(imx_sc_rtc);
imx_sc_rtc->ops = &imx_sc_rtc_ops;
imx_sc_rtc->range_min = 0;
imx_sc_rtc->range_max = U32_MAX;
ret = rtc_register_device(imx_sc_rtc);
if (ret) {
dev_err(&pdev->dev, "failed to register rtc: %d\n", ret);
return ret;
}
return 0;
}
static const struct of_device_id imx_sc_dt_ids[] = {
{ .compatible = "fsl,imx8qxp-sc-rtc", },
{}
};
MODULE_DEVICE_TABLE(of, imx_sc_dt_ids);
static struct platform_driver imx_sc_rtc_driver = {
.driver = {
.name = "imx-sc-rtc",
.of_match_table = imx_sc_dt_ids,
},
.probe = imx_sc_rtc_probe,
};
module_platform_driver(imx_sc_rtc_driver);
MODULE_AUTHOR("Anson Huang <Anson.Huang@nxp.com>");
MODULE_DESCRIPTION("NXP i.MX System Controller RTC Driver");
MODULE_LICENSE("GPL");
......@@ -84,29 +84,13 @@ static int
isl1208_i2c_read_regs(struct i2c_client *client, u8 reg, u8 buf[],
unsigned len)
{
u8 reg_addr[1] = { reg };
struct i2c_msg msgs[2] = {
{
.addr = client->addr,
.len = sizeof(reg_addr),
.buf = reg_addr
},
{
.addr = client->addr,
.flags = I2C_M_RD,
.len = len,
.buf = buf
}
};
int ret;
WARN_ON(reg > ISL1219_REG_YRT);
WARN_ON(reg + len > ISL1219_REG_YRT + 1);
ret = i2c_transfer(client->adapter, msgs, 2);
if (ret > 0)
ret = 0;
return ret;
ret = i2c_smbus_read_i2c_block_data(client, reg, len, buf);
return (ret < 0) ? ret : 0;
}
/* block write */
......@@ -114,26 +98,13 @@ static int
isl1208_i2c_set_regs(struct i2c_client *client, u8 reg, u8 const buf[],
unsigned len)
{
u8 i2c_buf[ISL1208_REG_USR2 + 2];
struct i2c_msg msgs[1] = {
{
.addr = client->addr,
.len = len + 1,
.buf = i2c_buf
}
};
int ret;
WARN_ON(reg > ISL1219_REG_YRT);
WARN_ON(reg + len > ISL1219_REG_YRT + 1);
i2c_buf[0] = reg;
memcpy(&i2c_buf[1], &buf[0], len);
ret = i2c_transfer(client->adapter, msgs, 1);
if (ret > 0)
ret = 0;
return ret;
ret = i2c_smbus_write_i2c_block_data(client, reg, len, buf);
return (ret < 0) ? ret : 0;
}
/* simple check to see whether we have a isl1208 */
......
......@@ -217,7 +217,7 @@ static int m41t80_rtc_read_time(struct device *dev, struct rtc_time *tm)
sizeof(buf), buf);
if (err < 0) {
dev_err(&client->dev, "Unable to read date\n");
return -EIO;
return err;
}
tm->tm_sec = bcd2bin(buf[M41T80_REG_SEC] & 0x7f);
......@@ -274,10 +274,11 @@ static int m41t80_rtc_set_time(struct device *dev, struct rtc_time *tm)
if (flags < 0)
return flags;
if (i2c_smbus_write_byte_data(client, M41T80_REG_FLAGS,
flags & ~M41T80_FLAGS_OF)) {
err = i2c_smbus_write_byte_data(client, M41T80_REG_FLAGS,
flags & ~M41T80_FLAGS_OF);
if (err < 0) {
dev_err(&client->dev, "Unable to write flags register\n");
return -EIO;
return err;
}
return err;
......@@ -287,10 +288,12 @@ static int m41t80_rtc_proc(struct device *dev, struct seq_file *seq)
{
struct i2c_client *client = to_i2c_client(dev);
struct m41t80_data *clientdata = i2c_get_clientdata(client);
u8 reg;
int reg;
if (clientdata->features & M41T80_FEATURE_BL) {
reg = i2c_smbus_read_byte_data(client, M41T80_REG_FLAGS);
if (reg < 0)
return reg;
seq_printf(seq, "battery\t\t: %s\n",
(reg & M41T80_FLAGS_BATT_LOW) ? "exhausted" : "ok");
}
......@@ -393,7 +396,7 @@ static int m41t80_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
alrm->time.tm_min = bcd2bin(alarmvals[3] & 0x7f);
alrm->time.tm_hour = bcd2bin(alarmvals[2] & 0x3f);
alrm->time.tm_mday = bcd2bin(alarmvals[1] & 0x3f);
alrm->time.tm_mon = bcd2bin(alarmvals[0] & 0x3f);
alrm->time.tm_mon = bcd2bin(alarmvals[0] & 0x3f) - 1;
alrm->enabled = !!(alarmvals[0] & M41T80_ALMON_AFE);
alrm->pending = (flags & M41T80_FLAGS_AF) && alrm->enabled;
......@@ -939,11 +942,7 @@ static int m41t80_probe(struct i2c_client *client,
if (m41t80_data->features & M41T80_FEATURE_HT) {
m41t80_rtc_read_time(&client->dev, &tm);
dev_info(&client->dev, "HT bit was set!\n");
dev_info(&client->dev,
"Power Down at %04i-%02i-%02i %02i:%02i:%02i\n",
tm.tm_year + 1900,
tm.tm_mon + 1, tm.tm_mday, tm.tm_hour,
tm.tm_min, tm.tm_sec);
dev_info(&client->dev, "Power Down at %ptR\n", &tm);
}
rc = i2c_smbus_write_byte_data(client, M41T80_REG_ALARM_HOUR,
rc & ~M41T80_ALHOUR_HT);
......
......@@ -99,9 +99,7 @@ static int m48t59_rtc_read_time(struct device *dev, struct rtc_time *tm)
M48T59_CLEAR_BITS(M48T59_CNTL_READ, M48T59_CNTL);
spin_unlock_irqrestore(&m48t59->lock, flags);
dev_dbg(dev, "RTC read time %04d-%02d-%02d %02d/%02d/%02d\n",
tm->tm_year + 1900, tm->tm_mon, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec);
dev_dbg(dev, "RTC read time %ptR\n", tm);
return 0;
}
......@@ -188,9 +186,7 @@ static int m48t59_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm)
M48T59_CLEAR_BITS(M48T59_CNTL_READ, M48T59_CNTL);
spin_unlock_irqrestore(&m48t59->lock, flags);
dev_dbg(dev, "RTC read alarm time %04d-%02d-%02d %02d/%02d/%02d\n",
tm->tm_year + 1900, tm->tm_mon, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec);
dev_dbg(dev, "RTC read alarm time %ptR\n", tm);
return rtc_valid_tm(tm);
}
......
......@@ -86,7 +86,7 @@ static int max6916_set_time(struct device *dev, struct rtc_time *dt)
if (dt->tm_year < 100 || dt->tm_year > 199) {
dev_err(&spi->dev, "Year must be between 2000 and 2099. It's %d.\n",
dt->tm_year + 1900);
return -EINVAL;
return -EINVAL;
}
buf[0] = MAX6916_CLOCK_BURST & 0x7F;
......
......@@ -360,7 +360,7 @@ static int max77686_rtc_read_time(struct device *dev, struct rtc_time *tm)
out:
mutex_unlock(&info->lock);
return 0;
return ret;
}
static int max77686_rtc_set_time(struct device *dev, struct rtc_time *tm)
......
......@@ -215,7 +215,7 @@ static int max8997_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
out:
mutex_unlock(&info->lock);
return 0;
return ret;
}
static int max8997_rtc_stop_alarm(struct max8997_rtc_info *info)
......
......@@ -233,9 +233,7 @@ static int mcp795_set_time(struct device *dev, struct rtc_time *tim)
if (ret)
return ret;
dev_dbg(dev, "Set mcp795: %04d-%02d-%02d(%d) %02d:%02d:%02d\n",
tim->tm_year + 1900, tim->tm_mon, tim->tm_mday,
tim->tm_wday, tim->tm_hour, tim->tm_min, tim->tm_sec);
dev_dbg(dev, "Set mcp795: %ptR\n", tim);
return 0;
}
......@@ -258,9 +256,7 @@ static int mcp795_read_time(struct device *dev, struct rtc_time *tim)
tim->tm_mon = bcd2bin(data[5] & 0x1F) - 1;
tim->tm_year = bcd2bin(data[6]) + 100; /* Assume we are in 20xx */
dev_dbg(dev, "Read from mcp795: %04d-%02d-%02d(%d) %02d:%02d:%02d\n",
tim->tm_year + 1900, tim->tm_mon, tim->tm_mday,
tim->tm_wday, tim->tm_hour, tim->tm_min, tim->tm_sec);
dev_dbg(dev, "Read from mcp795: %ptR\n", tim);
return 0;
}
......@@ -319,9 +315,8 @@ static int mcp795_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
return ret;
dev_dbg(dev, "Alarm IRQ armed\n");
}
dev_dbg(dev, "Set alarm: %02d-%02d(%d) %02d:%02d:%02d\n",
alm->time.tm_mon, alm->time.tm_mday, alm->time.tm_wday,
alm->time.tm_hour, alm->time.tm_min, alm->time.tm_sec);
dev_dbg(dev, "Set alarm: %ptRdr(%d) %ptRt\n",
&alm->time, alm->time.tm_wday, &alm->time);
return 0;
}
......@@ -345,9 +340,8 @@ static int mcp795_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
alm->time.tm_isdst = -1;
alm->time.tm_yday = -1;
dev_dbg(dev, "Read alarm: %02d-%02d(%d) %02d:%02d:%02d\n",
alm->time.tm_mon, alm->time.tm_mday, alm->time.tm_wday,
alm->time.tm_hour, alm->time.tm_min, alm->time.tm_sec);
dev_dbg(dev, "Read alarm: %ptRdr(%d) %ptRt\n",
&alm->time, alm->time.tm_wday, &alm->time);
return 0;
}
......
......@@ -566,9 +566,7 @@ static const struct pinctrl_ops rtc_pinctrl_ops = {
.dt_free_map = pinconf_generic_dt_free_map,
};
enum rtc_pin_config_param {
PIN_CONFIG_ACTIVE_HIGH = PIN_CONFIG_END + 1,
};
#define PIN_CONFIG_ACTIVE_HIGH (PIN_CONFIG_END + 1)
static const struct pinconf_generic_params rtc_params[] = {
{"ti,active-high", PIN_CONFIG_ACTIVE_HIGH, 0},
......
......@@ -453,6 +453,7 @@ static int pcf2123_remove(struct spi_device *spi)
#ifdef CONFIG_OF
static const struct of_device_id pcf2123_dt_ids[] = {
{ .compatible = "nxp,rtc-pcf2123", },
{ .compatible = "microcrystal,rv2123", },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, pcf2123_dt_ids);
......
......@@ -131,9 +131,7 @@ static int pcf50633_rtc_read_time(struct device *dev, struct rtc_time *tm)
pcf2rtc_time(tm, &pcf_tm);
dev_dbg(dev, "RTC_TIME: %u.%u.%u %u:%u:%u\n",
tm->tm_mday, tm->tm_mon, tm->tm_year,
tm->tm_hour, tm->tm_min, tm->tm_sec);
dev_dbg(dev, "RTC_TIME: %ptRr\n", tm);
return 0;
}
......@@ -146,9 +144,7 @@ static int pcf50633_rtc_set_time(struct device *dev, struct rtc_time *tm)
rtc = dev_get_drvdata(dev);
dev_dbg(dev, "RTC_TIME: %u.%u.%u %u:%u:%u\n",
tm->tm_mday, tm->tm_mon, tm->tm_year,
tm->tm_hour, tm->tm_min, tm->tm_sec);
dev_dbg(dev, "RTC_TIME: %ptRr\n", tm);
rtc2pcf_time(&pcf_tm, tm);
......
......@@ -85,6 +85,18 @@ static int pcf8523_write(struct i2c_client *client, u8 reg, u8 value)
return 0;
}
static int pcf8523_voltage_low(struct i2c_client *client)
{
u8 value;
int err;
err = pcf8523_read(client, REG_CONTROL3, &value);
if (err < 0)
return err;
return !!(value & REG_CONTROL3_BLF);
}
static int pcf8523_select_capacitance(struct i2c_client *client, bool high)
{
u8 value;
......@@ -167,6 +179,14 @@ static int pcf8523_rtc_read_time(struct device *dev, struct rtc_time *tm)
struct i2c_msg msgs[2];
int err;
err = pcf8523_voltage_low(client);
if (err < 0) {
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;
......@@ -251,17 +271,13 @@ static int pcf8523_rtc_ioctl(struct device *dev, unsigned int cmd,
unsigned long arg)
{
struct i2c_client *client = to_i2c_client(dev);
u8 value;
int ret = 0, err;
int ret;
switch (cmd) {
case RTC_VL_READ:
err = pcf8523_read(client, REG_CONTROL3, &value);
if (err < 0)
return err;
if (value & REG_CONTROL3_BLF)
ret = 1;
ret = pcf8523_voltage_low(client);
if (ret < 0)
return ret;
if (copy_to_user((void __user *)arg, &ret, sizeof(int)))
return -EFAULT;
......
......@@ -120,6 +120,11 @@ struct pcf85363 {
struct regmap *regmap;
};
struct pcf85x63_config {
struct regmap_config regmap;
unsigned int num_nvram;
};
static int pcf85363_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
struct pcf85363 *pcf85363 = dev_get_drvdata(dev);
......@@ -311,25 +316,75 @@ static int pcf85363_nvram_write(void *priv, unsigned int offset, void *val,
val, bytes);
}
static const struct regmap_config regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = 0x7f,
static int pcf85x63_nvram_read(void *priv, unsigned int offset, void *val,
size_t bytes)
{
struct pcf85363 *pcf85363 = priv;
unsigned int tmp_val;
int ret;
ret = regmap_read(pcf85363->regmap, CTRL_RAMBYTE, &tmp_val);
(*(unsigned char *) val) = (unsigned char) tmp_val;
return ret;
}
static int pcf85x63_nvram_write(void *priv, unsigned int offset, void *val,
size_t bytes)
{
struct pcf85363 *pcf85363 = priv;
unsigned char tmp_val;
tmp_val = *((unsigned char *)val);
return regmap_write(pcf85363->regmap, CTRL_RAMBYTE,
(unsigned int)tmp_val);
}
static const struct pcf85x63_config pcf_85263_config = {
.regmap = {
.reg_bits = 8,
.val_bits = 8,
.max_register = 0x2f,
},
.num_nvram = 1
};
static const struct pcf85x63_config pcf_85363_config = {
.regmap = {
.reg_bits = 8,
.val_bits = 8,
.max_register = 0x7f,
},
.num_nvram = 2
};
static int pcf85363_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct pcf85363 *pcf85363;
struct nvmem_config nvmem_cfg = {
.name = "pcf85363-",
.word_size = 1,
.stride = 1,
.size = NVRAM_SIZE,
.reg_read = pcf85363_nvram_read,
.reg_write = pcf85363_nvram_write,
const struct pcf85x63_config *config = &pcf_85363_config;
const void *data = of_device_get_match_data(&client->dev);
static struct nvmem_config nvmem_cfg[] = {
{
.name = "pcf85x63-",
.word_size = 1,
.stride = 1,
.size = 1,
.reg_read = pcf85x63_nvram_read,
.reg_write = pcf85x63_nvram_write,
}, {
.name = "pcf85363-",
.word_size = 1,
.stride = 1,
.size = NVRAM_SIZE,
.reg_read = pcf85363_nvram_read,
.reg_write = pcf85363_nvram_write,
},
};
int ret;
int ret, i;
if (data)
config = data;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
return -ENODEV;
......@@ -339,7 +394,7 @@ static int pcf85363_probe(struct i2c_client *client,
if (!pcf85363)
return -ENOMEM;
pcf85363->regmap = devm_regmap_init_i2c(client, &regmap_config);
pcf85363->regmap = devm_regmap_init_i2c(client, &config->regmap);
if (IS_ERR(pcf85363->regmap)) {
dev_err(&client->dev, "regmap allocation failed\n");
return PTR_ERR(pcf85363->regmap);
......@@ -370,15 +425,18 @@ static int pcf85363_probe(struct i2c_client *client,
ret = rtc_register_device(pcf85363->rtc);
nvmem_cfg.priv = pcf85363;
rtc_nvmem_register(pcf85363->rtc, &nvmem_cfg);
for (i = 0; i < config->num_nvram; i++) {
nvmem_cfg[i].priv = pcf85363;
rtc_nvmem_register(pcf85363->rtc, &nvmem_cfg[i]);
}
return ret;
}
static const struct of_device_id dev_ids[] = {
{ .compatible = "nxp,pcf85363" },
{}
{ .compatible = "nxp,pcf85263", .data = &pcf_85263_config },
{ .compatible = "nxp,pcf85363", .data = &pcf_85363_config },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, dev_ids);
......@@ -393,5 +451,5 @@ static struct i2c_driver pcf85363_driver = {
module_i2c_driver(pcf85363_driver);
MODULE_AUTHOR("Eric Nelson");
MODULE_DESCRIPTION("pcf85363 I2C RTC driver");
MODULE_DESCRIPTION("pcf85263/pcf85363 I2C RTC driver");
MODULE_LICENSE("GPL");
......@@ -170,9 +170,7 @@ static int pic32_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
rtc_tm->tm_year += 100;
dev_dbg(dev, "read time %04d.%02d.%02d %02d:%02d:%02d\n",
1900 + rtc_tm->tm_year, rtc_tm->tm_mon, rtc_tm->tm_mday,
rtc_tm->tm_hour, rtc_tm->tm_min, rtc_tm->tm_sec);
dev_dbg(dev, "read time %ptR\n", rtc_tm);
clk_disable(pdata->clk);
return 0;
......@@ -184,9 +182,7 @@ static int pic32_rtc_settime(struct device *dev, struct rtc_time *tm)
void __iomem *base = pdata->reg_base;
int year = tm->tm_year - 100;
dev_dbg(dev, "set time %04d.%02d.%02d %02d:%02d:%02d\n",
1900 + tm->tm_year, tm->tm_mon, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec);
dev_dbg(dev, "set time %ptR\n", tm);
if (year < 0 || year >= 100) {
dev_err(dev, "rtc only supports 100 years\n");
......@@ -224,10 +220,7 @@ static int pic32_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm)
alrm->enabled = (alm_en & PIC32_RTCALRM_ALRMEN) ? 1 : 0;
dev_dbg(dev, "getalarm: %d, %04d.%02d.%02d %02d:%02d:%02d\n",
alm_en,
1900 + alm_tm->tm_year, alm_tm->tm_mon, alm_tm->tm_mday,
alm_tm->tm_hour, alm_tm->tm_min, alm_tm->tm_sec);
dev_dbg(dev, "getalarm: %d, %ptR\n", alm_en, alm_tm);
alm_tm->tm_sec = bcd2bin(alm_tm->tm_sec);
alm_tm->tm_min = bcd2bin(alm_tm->tm_min);
......@@ -247,10 +240,7 @@ static int pic32_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
void __iomem *base = pdata->reg_base;
clk_enable(pdata->clk);
dev_dbg(dev, "setalarm: %d, %04d.%02d.%02d %02d:%02d:%02d\n",
alrm->enabled,
1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec);
dev_dbg(dev, "setalarm: %d, %ptR\n", alrm->enabled, tm);
writel(0x00, base + PIC32_ALRMTIME);
writel(0x00, base + PIC32_ALRMDATE);
......
......@@ -217,9 +217,7 @@ static int pm8xxx_rtc_read_time(struct device *dev, struct rtc_time *tm)
rtc_time_to_tm(secs, tm);
dev_dbg(dev, "secs = %lu, h:m:s == %d:%d:%d, d/m/y = %d/%d/%d\n",
secs, tm->tm_hour, tm->tm_min, tm->tm_sec,
tm->tm_mday, tm->tm_mon, tm->tm_year);
dev_dbg(dev, "secs = %lu, h:m:s == %ptRt, y-m-d = %ptRdr\n", secs, tm, tm);
return 0;
}
......@@ -264,10 +262,8 @@ static int pm8xxx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
goto rtc_rw_fail;
}
dev_dbg(dev, "Alarm Set for h:r:s=%d:%d:%d, d/m/y=%d/%d/%d\n",
alarm->time.tm_hour, alarm->time.tm_min,
alarm->time.tm_sec, alarm->time.tm_mday,
alarm->time.tm_mon, alarm->time.tm_year);
dev_dbg(dev, "Alarm Set for h:m:s=%ptRt, y-m-d=%ptRdr\n",
&alarm->time, &alarm->time);
rtc_rw_fail:
spin_unlock_irqrestore(&rtc_dd->ctrl_reg_lock, irq_flags);
return rc;
......@@ -298,10 +294,8 @@ static int pm8xxx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
return rc;
}
dev_dbg(dev, "Alarm set for - h:r:s=%d:%d:%d, d/m/y=%d/%d/%d\n",
alarm->time.tm_hour, alarm->time.tm_min,
alarm->time.tm_sec, alarm->time.tm_mday,
alarm->time.tm_mon, alarm->time.tm_year);
dev_dbg(dev, "Alarm set for - h:m:s=%ptRt, y-m-d=%ptRdr\n",
&alarm->time, &alarm->time);
return 0;
}
......
......@@ -90,9 +90,7 @@ static int puv3_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
{
rtc_time_to_tm(readl(RTC_RCNR), rtc_tm);
dev_dbg(dev, "read time %02x.%02x.%02x %02x/%02x/%02x\n",
rtc_tm->tm_year, rtc_tm->tm_mon, rtc_tm->tm_mday,
rtc_tm->tm_hour, rtc_tm->tm_min, rtc_tm->tm_sec);
dev_dbg(dev, "read time %ptRr\n", rtc_tm);
return 0;
}
......@@ -101,9 +99,7 @@ static int puv3_rtc_settime(struct device *dev, struct rtc_time *tm)
{
unsigned long rtc_count = 0;
dev_dbg(dev, "set time %02d.%02d.%02d %02d/%02d/%02d\n",
tm->tm_year, tm->tm_mon, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec);
dev_dbg(dev, "set time %ptRr\n", tm);
rtc_tm_to_time(tm, &rtc_count);
writel(rtc_count, RTC_RCNR);
......@@ -119,10 +115,7 @@ static int puv3_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm)
alrm->enabled = readl(RTC_RTSR) & RTC_RTSR_ALE;
dev_dbg(dev, "read alarm %02x %02x.%02x.%02x %02x/%02x/%02x\n",
alrm->enabled,
alm_tm->tm_year, alm_tm->tm_mon, alm_tm->tm_mday,
alm_tm->tm_hour, alm_tm->tm_min, alm_tm->tm_sec);
dev_dbg(dev, "read alarm: %d, %ptRr\n", alrm->enabled, alm_tm);
return 0;
}
......@@ -132,10 +125,7 @@ static int puv3_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
struct rtc_time *tm = &alrm->time;
unsigned long rtcalarm_count = 0;
dev_dbg(dev, "puv3_rtc_setalarm: %d, %02x/%02x/%02x %02x.%02x.%02x\n",
alrm->enabled,
tm->tm_mday & 0xff, tm->tm_mon & 0xff, tm->tm_year & 0xff,
tm->tm_hour & 0xff, tm->tm_min & 0xff, tm->tm_sec);
dev_dbg(dev, "set alarm: %d, %ptRr\n", alrm->enabled, tm);
rtc_tm_to_time(tm, &rtcalarm_count);
writel(rtcalarm_count, RTC_RTAR);
......
......@@ -138,9 +138,7 @@ static int rk808_rtc_readtime(struct device *dev, struct rtc_time *tm)
tm->tm_year = (bcd2bin(rtc_data[5] & YEARS_REG_MSK)) + 100;
tm->tm_wday = bcd2bin(rtc_data[6] & WEEKS_REG_MSK);
rockchip_to_gregorian(tm);
dev_dbg(dev, "RTC date/time %4d-%02d-%02d(%d) %02d:%02d:%02d\n",
1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday,
tm->tm_wday, tm->tm_hour, tm->tm_min, tm->tm_sec);
dev_dbg(dev, "RTC date/time %ptRd(%d) %ptRt\n", tm, tm->tm_wday, tm);
return ret;
}
......@@ -153,9 +151,7 @@ static int rk808_rtc_set_time(struct device *dev, struct rtc_time *tm)
u8 rtc_data[NUM_TIME_REGS];
int ret;
dev_dbg(dev, "set RTC date/time %4d-%02d-%02d(%d) %02d:%02d:%02d\n",
1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday,
tm->tm_wday, tm->tm_hour, tm->tm_min, tm->tm_sec);
dev_dbg(dev, "set RTC date/time %ptRd(%d) %ptRt\n", tm, tm->tm_wday, tm);
gregorian_to_rockchip(tm);
rtc_data[0] = bin2bcd(tm->tm_sec);
rtc_data[1] = bin2bcd(tm->tm_min);
......@@ -216,10 +212,8 @@ static int rk808_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm)
return ret;
}
dev_dbg(dev, "alrm read RTC date/time %4d-%02d-%02d(%d) %02d:%02d:%02d\n",
1900 + alrm->time.tm_year, alrm->time.tm_mon + 1,
alrm->time.tm_mday, alrm->time.tm_wday, alrm->time.tm_hour,
alrm->time.tm_min, alrm->time.tm_sec);
dev_dbg(dev, "alrm read RTC date/time %ptRd(%d) %ptRt\n",
&alrm->time, alrm->time.tm_wday, &alrm->time);
alrm->enabled = (int_reg & BIT_RTC_INTERRUPTS_REG_IT_ALARM_M) ? 1 : 0;
......@@ -261,10 +255,8 @@ static int rk808_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
dev_err(dev, "Failed to stop alarm: %d\n", ret);
return ret;
}
dev_dbg(dev, "alrm set RTC date/time %4d-%02d-%02d(%d) %02d:%02d:%02d\n",
1900 + alrm->time.tm_year, alrm->time.tm_mon + 1,
alrm->time.tm_mday, alrm->time.tm_wday, alrm->time.tm_hour,
alrm->time.tm_min, alrm->time.tm_sec);
dev_dbg(dev, "alrm set RTC date/time %ptRd(%d) %ptRt\n",
&alrm->time, alrm->time.tm_wday, &alrm->time);
gregorian_to_rockchip(&alrm->time);
alrm_data[0] = bin2bcd(alrm->time.tm_sec);
......@@ -400,7 +392,7 @@ static int rk808_rtc_probe(struct platform_device *pdev)
if (ret) {
dev_err(&pdev->dev,
"Failed to write RTC status: %d\n", ret);
return ret;
return ret;
}
device_init_wakeup(&pdev->dev, 1);
......
......@@ -114,9 +114,7 @@ struct rx6110_data {
*/
static int rx6110_rtc_tm_to_data(struct rtc_time *tm, u8 *data)
{
pr_debug("%s: date %ds %dm %dh %dmd %dm %dy\n", __func__,
tm->tm_sec, tm->tm_min, tm->tm_hour,
tm->tm_mday, tm->tm_mon, tm->tm_year);
pr_debug("%s: date %ptRr\n", __func__, tm);
/*
* The year in the RTC is a value between 0 and 99.
......@@ -154,9 +152,7 @@ static int rx6110_data_to_rtc_tm(u8 *data, struct rtc_time *tm)
tm->tm_mon = bcd2bin(data[RTC_MONTH] & 0x1f) - 1;
tm->tm_year = bcd2bin(data[RTC_YEAR]) + 100;
pr_debug("%s: date %ds %dm %dh %dmd %dm %dy\n", __func__,
tm->tm_sec, tm->tm_min, tm->tm_hour,
tm->tm_mday, tm->tm_mon, tm->tm_year);
pr_debug("%s: date %ptRr\n", __func__, tm);
/*
* The year in the RTC is a value between 0 and 99.
......@@ -248,9 +244,7 @@ static int rx6110_get_time(struct device *dev, struct rtc_time *tm)
if (ret)
return ret;
dev_dbg(dev, "%s: date %ds %dm %dh %dmd %dm %dy\n", __func__,
tm->tm_sec, tm->tm_min, tm->tm_hour,
tm->tm_mday, tm->tm_mon, tm->tm_year);
dev_dbg(dev, "%s: date %ptRr\n", __func__, tm);
return 0;
}
......
......@@ -193,10 +193,7 @@ static int rx8025_get_time(struct device *dev, struct rtc_time *dt)
if (err)
return err;
dev_dbg(dev, "%s: read 0x%02x 0x%02x "
"0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n", __func__,
date[0], date[1], date[2], date[3], date[4],
date[5], date[6]);
dev_dbg(dev, "%s: read %7ph\n", __func__, date);
dt->tm_sec = bcd2bin(date[RX8025_REG_SEC] & 0x7f);
dt->tm_min = bcd2bin(date[RX8025_REG_MIN] & 0x7f);
......@@ -210,9 +207,7 @@ static int rx8025_get_time(struct device *dev, struct rtc_time *dt)
dt->tm_mon = bcd2bin(date[RX8025_REG_MONTH] & 0x1f) - 1;
dt->tm_year = bcd2bin(date[RX8025_REG_YEAR]) + 100;
dev_dbg(dev, "%s: date %ds %dm %dh %dmd %dm %dy\n", __func__,
dt->tm_sec, dt->tm_min, dt->tm_hour,
dt->tm_mday, dt->tm_mon, dt->tm_year);
dev_dbg(dev, "%s: date %ptRr\n", __func__, dt);
return 0;
}
......@@ -243,10 +238,7 @@ static int rx8025_set_time(struct device *dev, struct rtc_time *dt)
date[RX8025_REG_MONTH] = bin2bcd(dt->tm_mon + 1);
date[RX8025_REG_YEAR] = bin2bcd(dt->tm_year - 100);
dev_dbg(dev,
"%s: write 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
__func__,
date[0], date[1], date[2], date[3], date[4], date[5], date[6]);
dev_dbg(dev, "%s: write %7ph\n", __func__, date);
ret = rx8025_write_regs(rx8025->client, RX8025_REG_SEC, 7, date);
if (ret < 0)
......@@ -319,10 +311,7 @@ static int rx8025_read_alarm(struct device *dev, struct rtc_wkalrm *t)
t->time.tm_hour = bcd2bin(ald[1] & 0x1f) % 12
+ (ald[1] & 0x20 ? 12 : 0);
dev_dbg(dev, "%s: date: %ds %dm %dh %dmd %dm %dy\n",
__func__,
t->time.tm_sec, t->time.tm_min, t->time.tm_hour,
t->time.tm_mday, t->time.tm_mon, t->time.tm_year);
dev_dbg(dev, "%s: date: %ptRr\n", __func__, t);
t->enabled = !!(rx8025->ctrl1 & RX8025_BIT_CTRL1_DALE);
t->pending = (ctrl2 & RX8025_BIT_CTRL2_DAFG) && t->enabled;
......
......@@ -225,13 +225,9 @@ static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
s3c_rtc_disable_clk(info);
rtc_tm->tm_year += 100;
dev_dbg(dev, "read time %04d.%02d.%02d %02d:%02d:%02d\n",
1900 + rtc_tm->tm_year, rtc_tm->tm_mon, rtc_tm->tm_mday,
rtc_tm->tm_hour, rtc_tm->tm_min, rtc_tm->tm_sec);
rtc_tm->tm_mon -= 1;
dev_dbg(dev, "read time %ptR\n", rtc_tm);
return 0;
}
......@@ -241,9 +237,7 @@ static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm)
int year = tm->tm_year - 100;
int ret;
dev_dbg(dev, "set time %04d.%02d.%02d %02d:%02d:%02d\n",
1900 + tm->tm_year, tm->tm_mon, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec);
dev_dbg(dev, "set time %ptR\n", tm);
/* we get around y2k by simply not supporting it */
......@@ -292,10 +286,7 @@ static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm)
alrm->enabled = (alm_en & S3C2410_RTCALM_ALMEN) ? 1 : 0;
dev_dbg(dev, "read alarm %d, %04d.%02d.%02d %02d:%02d:%02d\n",
alm_en,
1900 + alm_tm->tm_year, alm_tm->tm_mon, alm_tm->tm_mday,
alm_tm->tm_hour, alm_tm->tm_min, alm_tm->tm_sec);
dev_dbg(dev, "read alarm %d, %ptR\n", alm_en, alm_tm);
/* decode the alarm enable field */
if (alm_en & S3C2410_RTCALM_SECEN)
......@@ -327,12 +318,8 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
struct rtc_time *tm = &alrm->time;
unsigned int alrm_en;
int ret;
int year = tm->tm_year - 100;
dev_dbg(dev, "s3c_rtc_setalarm: %d, %04d.%02d.%02d %02d:%02d:%02d\n",
alrm->enabled,
1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec);
dev_dbg(dev, "s3c_rtc_setalarm: %d, %ptR\n", alrm->enabled, tm);
ret = s3c_rtc_enable_clk(info);
if (ret)
......@@ -356,11 +343,6 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
writeb(bin2bcd(tm->tm_hour), info->base + S3C2410_ALMHOUR);
}
if (year < 100 && year >= 0) {
alrm_en |= S3C2410_RTCALM_YEAREN;
writeb(bin2bcd(year), info->base + S3C2410_ALMYEAR);
}
if (tm->tm_mon < 12 && tm->tm_mon >= 0) {
alrm_en |= S3C2410_RTCALM_MONEN;
writeb(bin2bcd(tm->tm_mon + 1), info->base + S3C2410_ALMMON);
......
......@@ -406,9 +406,7 @@ static int s5m_rtc_read_time(struct device *dev, struct rtc_time *tm)
return -EINVAL;
}
dev_dbg(dev, "%s: %d/%d/%d %d:%d:%d(%d)\n", __func__,
1900 + tm->tm_year, 1 + tm->tm_mon, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec, tm->tm_wday);
dev_dbg(dev, "%s: %ptR(%d)\n", __func__, tm, tm->tm_wday);
return 0;
}
......@@ -436,9 +434,7 @@ static int s5m_rtc_set_time(struct device *dev, struct rtc_time *tm)
if (ret < 0)
return ret;
dev_dbg(dev, "%s: %d/%d/%d %d:%d:%d(%d)\n", __func__,
1900 + tm->tm_year, 1 + tm->tm_mon, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec, tm->tm_wday);
dev_dbg(dev, "%s: %ptR(%d)\n", __func__, tm, tm->tm_wday);
ret = regmap_raw_write(info->regmap, info->regs->time, data,
info->regs->regs_count);
......@@ -490,11 +486,7 @@ static int s5m_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
return -EINVAL;
}
dev_dbg(dev, "%s: %d/%d/%d %d:%d:%d(%d)\n", __func__,
1900 + alrm->time.tm_year, 1 + alrm->time.tm_mon,
alrm->time.tm_mday, alrm->time.tm_hour,
alrm->time.tm_min, alrm->time.tm_sec,
alrm->time.tm_wday);
dev_dbg(dev, "%s: %ptR(%d)\n", __func__, &alrm->time, alrm->time.tm_wday);
ret = s5m_check_peding_alarm_interrupt(info, alrm);
......@@ -513,9 +505,7 @@ static int s5m_rtc_stop_alarm(struct s5m_rtc_info *info)
return ret;
s5m8767_data_to_tm(data, &tm, info->rtc_24hr_mode);
dev_dbg(info->dev, "%s: %d/%d/%d %d:%d:%d(%d)\n", __func__,
1900 + tm.tm_year, 1 + tm.tm_mon, tm.tm_mday,
tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_wday);
dev_dbg(info->dev, "%s: %ptR(%d)\n", __func__, &tm, tm.tm_wday);
switch (info->device_type) {
case S5M8763X:
......@@ -558,9 +548,7 @@ static int s5m_rtc_start_alarm(struct s5m_rtc_info *info)
return ret;
s5m8767_data_to_tm(data, &tm, info->rtc_24hr_mode);
dev_dbg(info->dev, "%s: %d/%d/%d %d:%d:%d(%d)\n", __func__,
1900 + tm.tm_year, 1 + tm.tm_mon, tm.tm_mday,
tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_wday);
dev_dbg(info->dev, "%s: %ptR(%d)\n", __func__, &tm, tm.tm_wday);
switch (info->device_type) {
case S5M8763X:
......@@ -620,10 +608,7 @@ static int s5m_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
return -EINVAL;
}
dev_dbg(dev, "%s: %d/%d/%d %d:%d:%d(%d)\n", __func__,
1900 + alrm->time.tm_year, 1 + alrm->time.tm_mon,
alrm->time.tm_mday, alrm->time.tm_hour, alrm->time.tm_min,
alrm->time.tm_sec, alrm->time.tm_wday);
dev_dbg(dev, "%s: %ptR(%d)\n", __func__, &alrm->time, alrm->time.tm_wday);
ret = s5m_rtc_stop_alarm(info);
if (ret < 0)
......
// SPDX-License-Identifier: GPL-2.0
/*
* SuperH On-Chip RTC Support
*
......@@ -9,10 +10,6 @@
*
* Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
* Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*/
#include <linux/module.h>
#include <linux/mod_devicetable.h>
......@@ -681,5 +678,5 @@ MODULE_DESCRIPTION("SuperH on-chip RTC driver");
MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>, "
"Jamie Lenehan <lenehan@twibble.org>, "
"Angelo Castello <angelo.castello@st.com>");
MODULE_LICENSE("GPL");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:" DRV_NAME);
......@@ -118,9 +118,31 @@
#define SUN6I_YEAR_MAX 2033
#define SUN6I_YEAR_OFF (SUN6I_YEAR_MIN - 1900)
/*
* There are other differences between models, including:
*
* - number of GPIO pins that can be configured to hold a certain level
* - crypto-key related registers (H5, H6)
* - boot process related (super standby, secondary processor entry address)
* registers (R40, H6)
* - SYS power domain controls (R40)
* - DCXO controls (H6)
* - RC oscillator calibration (H6)
*
* These functions are not covered by this driver.
*/
struct sun6i_rtc_clk_data {
unsigned long rc_osc_rate;
unsigned int fixed_prescaler : 16;
unsigned int has_prescaler : 1;
unsigned int has_out_clk : 1;
unsigned int export_iosc : 1;
};
struct sun6i_rtc_dev {
struct rtc_device *rtc;
struct device *dev;
const struct sun6i_rtc_clk_data *data;
void __iomem *base;
int irq;
unsigned long alarm;
......@@ -139,14 +161,19 @@ static unsigned long sun6i_rtc_osc_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct sun6i_rtc_dev *rtc = container_of(hw, struct sun6i_rtc_dev, hw);
u32 val;
u32 val = 0;
val = readl(rtc->base + SUN6I_LOSC_CTRL);
if (val & SUN6I_LOSC_CTRL_EXT_OSC)
return parent_rate;
val = readl(rtc->base + SUN6I_LOSC_CLK_PRESCAL);
val &= GENMASK(4, 0);
if (rtc->data->fixed_prescaler)
parent_rate /= rtc->data->fixed_prescaler;
if (rtc->data->has_prescaler) {
val = readl(rtc->base + SUN6I_LOSC_CLK_PRESCAL);
val &= GENMASK(4, 0);
}
return parent_rate / (val + 1);
}
......@@ -185,13 +212,16 @@ static const struct clk_ops sun6i_rtc_osc_ops = {
.set_parent = sun6i_rtc_osc_set_parent,
};
static void __init sun6i_rtc_clk_init(struct device_node *node)
static void __init sun6i_rtc_clk_init(struct device_node *node,
const struct sun6i_rtc_clk_data *data)
{
struct clk_hw_onecell_data *clk_data;
struct sun6i_rtc_dev *rtc;
struct clk_init_data init = {
.ops = &sun6i_rtc_osc_ops,
.name = "losc",
};
const char *iosc_name = "rtc-int-osc";
const char *clkout_name = "osc32k-out";
const char *parents[2];
......@@ -199,7 +229,8 @@ static void __init sun6i_rtc_clk_init(struct device_node *node)
if (!rtc)
return;
clk_data = kzalloc(struct_size(clk_data, hws, 2), GFP_KERNEL);
rtc->data = data;
clk_data = kzalloc(struct_size(clk_data, hws, 3), GFP_KERNEL);
if (!clk_data) {
kfree(rtc);
return;
......@@ -224,10 +255,15 @@ static void __init sun6i_rtc_clk_init(struct device_node *node)
if (!of_get_property(node, "clocks", NULL))
goto err;
/* Only read IOSC name from device tree if it is exported */
if (rtc->data->export_iosc)
of_property_read_string_index(node, "clock-output-names", 2,
&iosc_name);
rtc->int_osc = clk_hw_register_fixed_rate_with_accuracy(NULL,
"rtc-int-osc",
iosc_name,
NULL, 0,
667000,
rtc->data->rc_osc_rate,
300000000);
if (IS_ERR(rtc->int_osc)) {
pr_crit("Couldn't register the internal oscillator\n");
......@@ -264,14 +300,71 @@ static void __init sun6i_rtc_clk_init(struct device_node *node)
clk_data->num = 2;
clk_data->hws[0] = &rtc->hw;
clk_data->hws[1] = __clk_get_hw(rtc->ext_losc);
if (rtc->data->export_iosc) {
clk_data->hws[2] = rtc->int_osc;
clk_data->num = 3;
}
of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data);
return;
err:
kfree(clk_data);
}
CLK_OF_DECLARE_DRIVER(sun6i_rtc_clk, "allwinner,sun6i-a31-rtc",
sun6i_rtc_clk_init);
static const struct sun6i_rtc_clk_data sun6i_a31_rtc_data = {
.rc_osc_rate = 667000, /* datasheet says 600 ~ 700 KHz */
.has_prescaler = 1,
};
static void __init sun6i_a31_rtc_clk_init(struct device_node *node)
{
sun6i_rtc_clk_init(node, &sun6i_a31_rtc_data);
}
CLK_OF_DECLARE_DRIVER(sun6i_a31_rtc_clk, "allwinner,sun6i-a31-rtc",
sun6i_a31_rtc_clk_init);
static const struct sun6i_rtc_clk_data sun8i_a23_rtc_data = {
.rc_osc_rate = 667000, /* datasheet says 600 ~ 700 KHz */
.has_prescaler = 1,
.has_out_clk = 1,
};
static void __init sun8i_a23_rtc_clk_init(struct device_node *node)
{
sun6i_rtc_clk_init(node, &sun8i_a23_rtc_data);
}
CLK_OF_DECLARE_DRIVER(sun8i_a23_rtc_clk, "allwinner,sun8i-a23-rtc",
sun8i_a23_rtc_clk_init);
static const struct sun6i_rtc_clk_data sun8i_h3_rtc_data = {
.rc_osc_rate = 16000000,
.fixed_prescaler = 32,
.has_prescaler = 1,
.has_out_clk = 1,
.export_iosc = 1,
};
static void __init sun8i_h3_rtc_clk_init(struct device_node *node)
{
sun6i_rtc_clk_init(node, &sun8i_h3_rtc_data);
}
CLK_OF_DECLARE_DRIVER(sun8i_h3_rtc_clk, "allwinner,sun8i-h3-rtc",
sun8i_h3_rtc_clk_init);
/* As far as we are concerned, clocks for H5 are the same as H3 */
CLK_OF_DECLARE_DRIVER(sun50i_h5_rtc_clk, "allwinner,sun50i-h5-rtc",
sun8i_h3_rtc_clk_init);
static const struct sun6i_rtc_clk_data sun8i_v3_rtc_data = {
.rc_osc_rate = 32000,
.has_out_clk = 1,
};
static void __init sun8i_v3_rtc_clk_init(struct device_node *node)
{
sun6i_rtc_clk_init(node, &sun8i_v3_rtc_data);
}
CLK_OF_DECLARE_DRIVER(sun8i_v3_rtc_clk, "allwinner,sun8i-v3-rtc",
sun8i_v3_rtc_clk_init);
static irqreturn_t sun6i_rtc_alarmirq(int irq, void *id)
{
......@@ -578,8 +671,18 @@ static int sun6i_rtc_probe(struct platform_device *pdev)
return 0;
}
/*
* As far as RTC functionality goes, all models are the same. The
* datasheets claim that different models have different number of
* registers available for non-volatile storage, but experiments show
* that all SoCs have 16 registers available for this purpose.
*/
static const struct of_device_id sun6i_rtc_dt_ids[] = {
{ .compatible = "allwinner,sun6i-a31-rtc" },
{ .compatible = "allwinner,sun8i-a23-rtc" },
{ .compatible = "allwinner,sun8i-h3-rtc" },
{ .compatible = "allwinner,sun8i-v3-rtc" },
{ .compatible = "allwinner,sun50i-h5-rtc" },
{ /* sentinel */ },
};
MODULE_DEVICE_TABLE(of, sun6i_rtc_dt_ids);
......
......@@ -125,15 +125,7 @@ static int tegra_rtc_read_time(struct device *dev, struct rtc_time *tm)
rtc_time_to_tm(sec, tm);
dev_vdbg(dev, "time read as %lu. %d/%d/%d %d:%02u:%02u\n",
sec,
tm->tm_mon + 1,
tm->tm_mday,
tm->tm_year + 1900,
tm->tm_hour,
tm->tm_min,
tm->tm_sec
);
dev_vdbg(dev, "time read as %lu. %ptR\n", sec, tm);
return 0;
}
......@@ -147,15 +139,7 @@ static int tegra_rtc_set_time(struct device *dev, struct rtc_time *tm)
/* convert tm to seconds. */
rtc_tm_to_time(tm, &sec);
dev_vdbg(dev, "time set to %lu. %d/%d/%d %d:%02u:%02u\n",
sec,
tm->tm_mon+1,
tm->tm_mday,
tm->tm_year+1900,
tm->tm_hour,
tm->tm_min,
tm->tm_sec
);
dev_vdbg(dev, "time set to %lu. %ptR\n", sec, tm);
/* seconds only written if wait succeeded. */
ret = tegra_rtc_wait_while_busy(dev);
......@@ -232,15 +216,7 @@ static int tegra_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
/* if successfully written and alarm is enabled ... */
if (sec) {
tegra_rtc_alarm_irq_enable(dev, 1);
dev_vdbg(dev, "alarm set as %lu. %d/%d/%d %d:%02u:%02u\n",
sec,
alarm->time.tm_mon+1,
alarm->time.tm_mday,
alarm->time.tm_year+1900,
alarm->time.tm_hour,
alarm->time.tm_min,
alarm->time.tm_sec);
dev_vdbg(dev, "alarm set as %lu. %ptR\n", sec, &alarm->time);
} else {
/* disable alarm if 0 or write error. */
dev_vdbg(dev, "alarm disabled\n");
......
......@@ -39,12 +39,10 @@ date_show(struct device *dev, struct device_attribute *attr, char *buf)
struct rtc_time tm;
retval = rtc_read_time(to_rtc_device(dev), &tm);
if (retval == 0) {
retval = sprintf(buf, "%04d-%02d-%02d\n",
tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday);
}
if (retval)
return retval;
return retval;
return sprintf(buf, "%ptRd\n", &tm);
}
static DEVICE_ATTR_RO(date);
......@@ -55,12 +53,10 @@ time_show(struct device *dev, struct device_attribute *attr, char *buf)
struct rtc_time tm;
retval = rtc_read_time(to_rtc_device(dev), &tm);
if (retval == 0) {
retval = sprintf(buf, "%02d:%02d:%02d\n",
tm.tm_hour, tm.tm_min, tm.tm_sec);
}
if (retval)
return retval;
return retval;
return sprintf(buf, "%ptRt\n", &tm);
}
static DEVICE_ATTR_RO(time);
......
......@@ -87,15 +87,16 @@ struct rtc_class_ops {
int (*set_offset)(struct device *, long offset);
};
struct rtc_device;
struct rtc_timer {
struct timerqueue_node node;
ktime_t period;
void (*func)(void *private_data);
void *private_data;
void (*func)(struct rtc_device *rtc);
struct rtc_device *rtc;
int enabled;
};
/* flags */
#define RTC_DEV_BUSY 0
......@@ -138,7 +139,6 @@ struct rtc_device {
bool registered;
struct nvmem_device *nvmem;
/* Old ABI support */
bool nvram_old_abi;
struct bin_attribute *nvram;
......@@ -173,8 +173,6 @@ extern struct rtc_device *devm_rtc_device_register(struct device *dev,
struct module *owner);
struct rtc_device *devm_rtc_allocate_device(struct device *dev);
int __rtc_register_device(struct module *owner, struct rtc_device *rtc);
extern void devm_rtc_device_unregister(struct device *dev,
struct rtc_device *rtc);
extern int rtc_read_time(struct rtc_device *rtc, struct rtc_time *tm);
extern int rtc_set_time(struct rtc_device *rtc, struct rtc_time *tm);
......@@ -200,11 +198,12 @@ extern int rtc_dev_update_irq_enable_emul(struct rtc_device *rtc,
unsigned int enabled);
void rtc_handle_legacy_irq(struct rtc_device *rtc, int num, int mode);
void rtc_aie_update_irq(void *private);
void rtc_uie_update_irq(void *private);
void rtc_aie_update_irq(struct rtc_device *rtc);
void rtc_uie_update_irq(struct rtc_device *rtc);
enum hrtimer_restart rtc_pie_update_irq(struct hrtimer *timer);
void rtc_timer_init(struct rtc_timer *timer, void (*f)(void *p), void *data);
void rtc_timer_init(struct rtc_timer *timer, void (*f)(struct rtc_device *r),
struct rtc_device *rtc);
int rtc_timer_start(struct rtc_device *rtc, struct rtc_timer *timer,
ktime_t expires, ktime_t period);
void rtc_timer_cancel(struct rtc_device *rtc, struct rtc_timer *timer);
......
......@@ -9,6 +9,7 @@
#include <linux/module.h>
#include <linux/printk.h>
#include <linux/random.h>
#include <linux/rtc.h>
#include <linux/slab.h>
#include <linux/string.h>
......@@ -249,12 +250,11 @@ plain_format(void)
#endif /* BITS_PER_LONG == 64 */
static int __init
plain_hash(void)
plain_hash_to_buffer(const void *p, char *buf, size_t len)
{
char buf[PLAIN_BUF_SIZE];
int nchars;
nchars = snprintf(buf, PLAIN_BUF_SIZE, "%p", PTR);
nchars = snprintf(buf, len, "%p", p);
if (nchars != PTR_WIDTH)
return -1;
......@@ -265,6 +265,20 @@ plain_hash(void)
return 0;
}
return 0;
}
static int __init
plain_hash(void)
{
char buf[PLAIN_BUF_SIZE];
int ret;
ret = plain_hash_to_buffer(PTR, buf, PLAIN_BUF_SIZE);
if (ret)
return ret;
if (strncmp(buf, PTR_STR, PTR_WIDTH) == 0)
return -1;
......@@ -294,6 +308,23 @@ plain(void)
}
}
static void __init
test_hashed(const char *fmt, const void *p)
{
char buf[PLAIN_BUF_SIZE];
int ret;
/*
* No need to increase failed test counter since this is assumed
* to be called after plain().
*/
ret = plain_hash_to_buffer(p, buf, PLAIN_BUF_SIZE);
if (ret)
return;
test(buf, fmt, p);
}
static void __init
symbol_ptr(void)
{
......@@ -418,6 +449,29 @@ struct_va_format(void)
{
}
static void __init
struct_rtc_time(void)
{
/* 1543210543 */
const struct rtc_time tm = {
.tm_sec = 43,
.tm_min = 35,
.tm_hour = 5,
.tm_mday = 26,
.tm_mon = 10,
.tm_year = 118,
};
test_hashed("%pt", &tm);
test("2018-11-26T05:35:43", "%ptR", &tm);
test("0118-10-26T05:35:43", "%ptRr", &tm);
test("05:35:43|2018-11-26", "%ptRt|%ptRd", &tm, &tm);
test("05:35:43|0118-10-26", "%ptRtr|%ptRdr", &tm, &tm);
test("05:35:43|2018-11-26", "%ptRttr|%ptRdtr", &tm, &tm);
test("05:35:43 tr|2018-11-26 tr", "%ptRt tr|%ptRd tr", &tm, &tm);
}
static void __init
struct_clk(void)
{
......@@ -529,6 +583,7 @@ test_pointer(void)
uuid();
dentry();
struct_va_format();
struct_rtc_time();
struct_clk();
bitmap();
netdev_features();
......
......@@ -30,6 +30,7 @@
#include <linux/ioport.h>
#include <linux/dcache.h>
#include <linux/cred.h>
#include <linux/rtc.h>
#include <linux/uuid.h>
#include <linux/of.h>
#include <net/addrconf.h>
......@@ -822,6 +823,20 @@ static const struct printf_spec default_dec_spec = {
.precision = -1,
};
static const struct printf_spec default_dec02_spec = {
.base = 10,
.field_width = 2,
.precision = -1,
.flags = ZEROPAD,
};
static const struct printf_spec default_dec04_spec = {
.base = 10,
.field_width = 4,
.precision = -1,
.flags = ZEROPAD,
};
static noinline_for_stack
char *resource_string(char *buf, char *end, struct resource *res,
struct printf_spec spec, const char *fmt)
......@@ -1549,6 +1564,87 @@ char *address_val(char *buf, char *end, const void *addr, const char *fmt)
return special_hex_number(buf, end, num, size);
}
static noinline_for_stack
char *date_str(char *buf, char *end, const struct rtc_time *tm, bool r)
{
int year = tm->tm_year + (r ? 0 : 1900);
int mon = tm->tm_mon + (r ? 0 : 1);
buf = number(buf, end, year, default_dec04_spec);
if (buf < end)
*buf = '-';
buf++;
buf = number(buf, end, mon, default_dec02_spec);
if (buf < end)
*buf = '-';
buf++;
return number(buf, end, tm->tm_mday, default_dec02_spec);
}
static noinline_for_stack
char *time_str(char *buf, char *end, const struct rtc_time *tm, bool r)
{
buf = number(buf, end, tm->tm_hour, default_dec02_spec);
if (buf < end)
*buf = ':';
buf++;
buf = number(buf, end, tm->tm_min, default_dec02_spec);
if (buf < end)
*buf = ':';
buf++;
return number(buf, end, tm->tm_sec, default_dec02_spec);
}
static noinline_for_stack
char *rtc_str(char *buf, char *end, const struct rtc_time *tm, const char *fmt)
{
bool have_t = true, have_d = true;
bool raw = false;
int count = 2;
switch (fmt[count]) {
case 'd':
have_t = false;
count++;
break;
case 't':
have_d = false;
count++;
break;
}
raw = fmt[count] == 'r';
if (have_d)
buf = date_str(buf, end, tm, raw);
if (have_d && have_t) {
/* Respect ISO 8601 */
if (buf < end)
*buf = 'T';
buf++;
}
if (have_t)
buf = time_str(buf, end, tm, raw);
return buf;
}
static noinline_for_stack
char *time_and_date(char *buf, char *end, void *ptr, struct printf_spec spec,
const char *fmt)
{
switch (fmt[1]) {
case 'R':
return rtc_str(buf, end, (const struct rtc_time *)ptr, fmt);
default:
return ptr_to_id(buf, end, ptr, spec);
}
}
static noinline_for_stack
char *clock(char *buf, char *end, struct clk *clk, struct printf_spec spec,
const char *fmt)
......@@ -1828,6 +1924,8 @@ char *device_node_string(char *buf, char *end, struct device_node *dn,
* - 'd[234]' For a dentry name (optionally 2-4 last components)
* - 'D[234]' Same as 'd' but for a struct file
* - 'g' For block_device name (gendisk + partition number)
* - 't[R][dt][r]' For time and date as represented:
* R struct rtc_time
* - 'C' For a clock, it prints the name (Common Clock Framework) or address
* (legacy clock framework) of the clock
* - 'Cn' For a clock, it prints the name (Common Clock Framework) or address
......@@ -1952,6 +2050,8 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr,
return address_val(buf, end, ptr, fmt);
case 'd':
return dentry_name(buf, end, ptr, spec, fmt);
case 't':
return time_and_date(buf, end, ptr, spec, fmt);
case 'C':
return clock(buf, end, ptr, spec, fmt);
case 'D':
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment