* [PATCH 1/3] rtc: pcf8523: remove useless define
@ 2021-04-18 0:20 Alexandre Belloni
2021-04-18 0:20 ` [PATCH 2/3] rtc: pcf8523: add alarm support Alexandre Belloni
2021-04-18 0:20 ` [PATCH 3/3] rtc: pcf8523: report oscillator failures Alexandre Belloni
0 siblings, 2 replies; 4+ messages in thread
From: Alexandre Belloni @ 2021-04-18 0:20 UTC (permalink / raw)
To: Alessandro Zummo, Alexandre Belloni; +Cc: linux-rtc, linux-kernel
Drop DRIVER_NAME as it is only used once
Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
---
drivers/rtc/rtc-pcf8523.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/drivers/rtc/rtc-pcf8523.c b/drivers/rtc/rtc-pcf8523.c
index 5e1e7b2a8c9a..fe3ab41d8326 100644
--- a/drivers/rtc/rtc-pcf8523.c
+++ b/drivers/rtc/rtc-pcf8523.c
@@ -9,8 +9,6 @@
#include <linux/rtc.h>
#include <linux/of.h>
-#define DRIVER_NAME "rtc-pcf8523"
-
#define REG_CONTROL1 0x00
#define REG_CONTROL1_CAP_SEL BIT(7)
#define REG_CONTROL1_STOP BIT(5)
@@ -373,7 +371,7 @@ MODULE_DEVICE_TABLE(of, pcf8523_of_match);
static struct i2c_driver pcf8523_driver = {
.driver = {
- .name = DRIVER_NAME,
+ .name = "rtc-pcf8523",
.of_match_table = of_match_ptr(pcf8523_of_match),
},
.probe = pcf8523_probe,
--
2.30.2
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 2/3] rtc: pcf8523: add alarm support
2021-04-18 0:20 [PATCH 1/3] rtc: pcf8523: remove useless define Alexandre Belloni
@ 2021-04-18 0:20 ` Alexandre Belloni
2021-04-18 3:06 ` kernel test robot
2021-04-18 0:20 ` [PATCH 3/3] rtc: pcf8523: report oscillator failures Alexandre Belloni
1 sibling, 1 reply; 4+ messages in thread
From: Alexandre Belloni @ 2021-04-18 0:20 UTC (permalink / raw)
To: Alessandro Zummo, Alexandre Belloni; +Cc: linux-rtc, linux-kernel
Alarm support requires unconditionally disabling clock out because it is
using the int1 pin.
Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
---
drivers/rtc/rtc-pcf8523.c | 181 +++++++++++++++++++++++++++++++++++++-
1 file changed, 180 insertions(+), 1 deletion(-)
diff --git a/drivers/rtc/rtc-pcf8523.c b/drivers/rtc/rtc-pcf8523.c
index fe3ab41d8326..feadab8e3bd3 100644
--- a/drivers/rtc/rtc-pcf8523.c
+++ b/drivers/rtc/rtc-pcf8523.c
@@ -8,10 +8,15 @@
#include <linux/module.h>
#include <linux/rtc.h>
#include <linux/of.h>
+#include <linux/pm_wakeirq.h>
#define REG_CONTROL1 0x00
#define REG_CONTROL1_CAP_SEL BIT(7)
#define REG_CONTROL1_STOP BIT(5)
+#define REG_CONTROL1_AIE BIT(1)
+
+#define REG_CONTROL2 0x01
+#define REG_CONTROL2_AF BIT(3)
#define REG_CONTROL3 0x02
#define REG_CONTROL3_PM_BLD BIT(7) /* battery low detection disabled */
@@ -30,9 +35,22 @@
#define REG_MONTHS 0x08
#define REG_YEARS 0x09
+#define REG_MINUTE_ALARM 0x0a
+#define REG_HOUR_ALARM 0x0b
+#define REG_DAY_ALARM 0x0c
+#define REG_WEEKDAY_ALARM 0x0d
+#define ALARM_DIS BIT(7)
+
#define REG_OFFSET 0x0e
#define REG_OFFSET_MODE BIT(7)
+#define REG_TMR_CLKOUT_CTRL 0x0f
+
+struct pcf8523 {
+ struct rtc_device *rtc;
+ struct i2c_client *client;
+};
+
static int pcf8523_read(struct i2c_client *client, u8 reg, u8 *valuep)
{
struct i2c_msg msgs[2];
@@ -138,6 +156,27 @@ static int pcf8523_set_pm(struct i2c_client *client, u8 pm)
return 0;
}
+static irqreturn_t pcf8523_irq(int irq, void *dev_id)
+{
+ struct pcf8523 *pcf8523 = i2c_get_clientdata(dev_id);
+ u8 value;
+ int err;
+
+ err = pcf8523_read(pcf8523->client, REG_CONTROL2, &value);
+ if (err < 0)
+ return IRQ_HANDLED;
+
+ if (value & REG_CONTROL2_AF) {
+ value &= ~REG_CONTROL2_AF;
+ pcf8523_write(pcf8523->client, REG_CONTROL2, value);
+ rtc_update_irq(pcf8523->rtc, 1, RTC_IRQF | RTC_AF);
+
+ return IRQ_HANDLED;
+ }
+
+ return IRQ_NONE;
+}
+
static int pcf8523_stop_rtc(struct i2c_client *client)
{
u8 value;
@@ -257,6 +296,111 @@ static int pcf8523_rtc_set_time(struct device *dev, struct rtc_time *tm)
return pcf8523_start_rtc(client);
}
+static int pcf8523_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *tm)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ u8 start = REG_MINUTE_ALARM, regs[4];
+ struct i2c_msg msgs[2];
+ u8 value;
+ int err;
+
+ msgs[0].addr = client->addr;
+ msgs[0].flags = 0;
+ msgs[0].len = 1;
+ msgs[0].buf = &start;
+
+ msgs[1].addr = client->addr;
+ msgs[1].flags = I2C_M_RD;
+ msgs[1].len = sizeof(regs);
+ msgs[1].buf = regs;
+
+ err = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
+ if (err < 0)
+ return err;
+
+ tm->time.tm_sec = 0;
+ tm->time.tm_min = bcd2bin(regs[0] & 0x7F);
+ tm->time.tm_hour = bcd2bin(regs[1] & 0x3F);
+ tm->time.tm_mday = bcd2bin(regs[2] & 0x3F);
+ tm->time.tm_wday = bcd2bin(regs[3] & 0x7);
+
+ err = pcf8523_read(client, REG_CONTROL1, &value);
+ if (err < 0)
+ return err;
+ tm->enabled = !!(value & REG_CONTROL1_AIE);
+
+ err = pcf8523_read(client, REG_CONTROL2, &value);
+ if (err < 0)
+ return err;
+ tm->pending = !!(value & REG_CONTROL2_AF);
+
+ return 0;
+}
+
+static int pcf8523_irq_enable(struct device *dev, unsigned int enabled)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ u8 value;
+ int err;
+
+ err = pcf8523_read(client, REG_CONTROL1, &value);
+ if (err < 0)
+ return err;
+
+ value &= REG_CONTROL1_AIE;
+
+ if (enabled)
+ value |= REG_CONTROL1_AIE;
+
+ err = pcf8523_write(client, REG_CONTROL1, value);
+ if (err < 0)
+ return err;
+
+ return 0;
+}
+
+static int pcf8523_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *tm)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct i2c_msg msg;
+ u8 regs[5];
+ int err;
+
+ err = pcf8523_irq_enable(dev, 0);
+ if (err)
+ return err;
+
+ err = pcf8523_write(client, REG_CONTROL2, 0);
+ if (err < 0)
+ return err;
+
+ /* The alarm has no seconds, round up to nearest minute */
+ if (tm->time.tm_sec) {
+ time64_t alarm_time = rtc_tm_to_time64(&tm->time);
+
+ alarm_time += 60 - tm->time.tm_sec;
+ rtc_time64_to_tm(alarm_time, &tm->time);
+ }
+
+ regs[0] = REG_MINUTE_ALARM;
+ regs[1] = bin2bcd(tm->time.tm_min);
+ regs[2] = bin2bcd(tm->time.tm_hour);
+ regs[3] = bin2bcd(tm->time.tm_mday);
+ regs[4] = ALARM_DIS;
+ msg.addr = client->addr;
+ msg.flags = 0;
+ msg.len = sizeof(regs);
+ msg.buf = regs;
+ err = i2c_transfer(client->adapter, &msg, 1);
+ if (err < 0)
+ return err;
+
+ if (tm->enabled)
+ return pcf8523_irq_enable(dev, tm->enabled);
+
+ return 0;
+}
+
#ifdef CONFIG_RTC_INTF_DEV
static int pcf8523_rtc_ioctl(struct device *dev, unsigned int cmd,
unsigned long arg)
@@ -320,6 +464,9 @@ static int pcf8523_rtc_set_offset(struct device *dev, long offset)
static const struct rtc_class_ops pcf8523_rtc_ops = {
.read_time = pcf8523_rtc_read_time,
.set_time = pcf8523_rtc_set_time,
+ .read_alarm = pcf8523_rtc_read_alarm,
+ .set_alarm = pcf8523_rtc_set_alarm,
+ .alarm_irq_enable = pcf8523_irq_enable,
.ioctl = pcf8523_rtc_ioctl,
.read_offset = pcf8523_rtc_read_offset,
.set_offset = pcf8523_rtc_set_offset,
@@ -328,12 +475,21 @@ static const struct rtc_class_ops pcf8523_rtc_ops = {
static int pcf8523_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
+ struct pcf8523 *pcf8523;
struct rtc_device *rtc;
+ bool wakeup_source = false;
int err;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
return -ENODEV;
+ pcf8523 = devm_kzalloc(&client->dev, sizeof(struct pcf8523), GFP_KERNEL);
+ if (!pcf8523)
+ return -ENOMEM;
+
+ i2c_set_clientdata(client, pcf8523);
+ pcf8523->client = client;
+
err = pcf8523_load_capacitance(client);
if (err < 0)
dev_warn(&client->dev, "failed to set xtal load capacitance: %d",
@@ -347,11 +503,34 @@ static int pcf8523_probe(struct i2c_client *client,
if (IS_ERR(rtc))
return PTR_ERR(rtc);
+ pcf8523->rtc = rtc;
rtc->ops = &pcf8523_rtc_ops;
rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
rtc->range_max = RTC_TIMESTAMP_END_2099;
+ rtc->uie_unsupported = 1;
+
+ if (client->irq > 0) {
+ err = pcf8523_write(client, REG_TMR_CLKOUT_CTRL, 0x38);
+ if (err < 0)
+ return err;
+
+ err = devm_request_threaded_irq(&client->dev, client->irq,
+ NULL, pcf8523_irq,
+ IRQF_SHARED | IRQF_ONESHOT | IRQF_TRIGGER_LOW,
+ dev_name(&rtc->dev), client);
+ if (err)
+ return err;
+
+ dev_pm_set_wake_irq(&client->dev, client->irq);
+ }
+
+#ifdef CONFIG_OF
+ wakeup_source = of_property_read_bool(client->dev.of_node, "wakeup-source");
+#endif
+ if (client->irq > 0 || wakeup_source)
+ device_init_wakeup(&client->dev, true);
- return devm_rtc_register_device(rtc);
+ return rtc_register_device(rtc);
}
static const struct i2c_device_id pcf8523_id[] = {
--
2.30.2
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 3/3] rtc: pcf8523: report oscillator failures
2021-04-18 0:20 [PATCH 1/3] rtc: pcf8523: remove useless define Alexandre Belloni
2021-04-18 0:20 ` [PATCH 2/3] rtc: pcf8523: add alarm support Alexandre Belloni
@ 2021-04-18 0:20 ` Alexandre Belloni
1 sibling, 0 replies; 4+ messages in thread
From: Alexandre Belloni @ 2021-04-18 0:20 UTC (permalink / raw)
To: Alessandro Zummo, Alexandre Belloni; +Cc: linux-rtc, linux-kernel
Report oscillator failures and invalid date/time on RTC_VL_READ.
Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
---
drivers/rtc/rtc-pcf8523.c | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/drivers/rtc/rtc-pcf8523.c b/drivers/rtc/rtc-pcf8523.c
index feadab8e3bd3..bb23379bbfc7 100644
--- a/drivers/rtc/rtc-pcf8523.c
+++ b/drivers/rtc/rtc-pcf8523.c
@@ -406,6 +406,8 @@ static int pcf8523_rtc_ioctl(struct device *dev, unsigned int cmd,
unsigned long arg)
{
struct i2c_client *client = to_i2c_client(dev);
+ unsigned int flags = 0;
+ u8 value;
int ret;
switch (cmd) {
@@ -414,9 +416,16 @@ static int pcf8523_rtc_ioctl(struct device *dev, unsigned int cmd,
if (ret < 0)
return ret;
if (ret)
- ret = RTC_VL_BACKUP_LOW;
+ flags |= RTC_VL_BACKUP_LOW;
+
+ ret = pcf8523_read(client, REG_SECONDS, &value);
+ if (ret < 0)
+ return ret;
+
+ if (value & REG_SECONDS_OS)
+ flags |= RTC_VL_DATA_INVALID;
- return put_user(ret, (unsigned int __user *)arg);
+ return put_user(flags, (unsigned int __user *)arg);
default:
return -ENOIOCTLCMD;
--
2.30.2
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH 2/3] rtc: pcf8523: add alarm support
2021-04-18 0:20 ` [PATCH 2/3] rtc: pcf8523: add alarm support Alexandre Belloni
@ 2021-04-18 3:06 ` kernel test robot
0 siblings, 0 replies; 4+ messages in thread
From: kernel test robot @ 2021-04-18 3:06 UTC (permalink / raw)
To: kbuild-all
[-- Attachment #1: Type: text/plain, Size: 3823 bytes --]
Hi Alexandre,
I love your patch! Yet something to improve:
[auto build test ERROR on abelloni/rtc-next]
[also build test ERROR on v5.12-rc7 next-20210416]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]
url: https://github.com/0day-ci/linux/commits/Alexandre-Belloni/rtc-pcf8523-remove-useless-define/20210418-082211
base: https://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux.git rtc-next
config: x86_64-rhel-8.3-kselftests (attached as .config)
compiler: gcc-9 (Debian 9.3.0-22) 9.3.0
reproduce (this is a W=1 build):
# https://github.com/0day-ci/linux/commit/ac4cc9aaf864c91e0bc0ec85c0a37c5983d350ba
git remote add linux-review https://github.com/0day-ci/linux
git fetch --no-tags linux-review Alexandre-Belloni/rtc-pcf8523-remove-useless-define/20210418-082211
git checkout ac4cc9aaf864c91e0bc0ec85c0a37c5983d350ba
# save the attached .config to linux build tree
make W=1 W=1 ARCH=x86_64
If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>
All errors (new ones prefixed by >>):
drivers/rtc/rtc-pcf8523.c: In function 'pcf8523_probe':
>> drivers/rtc/rtc-pcf8523.c:533:9: error: implicit declaration of function 'rtc_register_device'; did you mean 'i2c_unregister_device'? [-Werror=implicit-function-declaration]
533 | return rtc_register_device(rtc);
| ^~~~~~~~~~~~~~~~~~~
| i2c_unregister_device
cc1: some warnings being treated as errors
vim +533 drivers/rtc/rtc-pcf8523.c
474
475 static int pcf8523_probe(struct i2c_client *client,
476 const struct i2c_device_id *id)
477 {
478 struct pcf8523 *pcf8523;
479 struct rtc_device *rtc;
480 bool wakeup_source = false;
481 int err;
482
483 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
484 return -ENODEV;
485
486 pcf8523 = devm_kzalloc(&client->dev, sizeof(struct pcf8523), GFP_KERNEL);
487 if (!pcf8523)
488 return -ENOMEM;
489
490 i2c_set_clientdata(client, pcf8523);
491 pcf8523->client = client;
492
493 err = pcf8523_load_capacitance(client);
494 if (err < 0)
495 dev_warn(&client->dev, "failed to set xtal load capacitance: %d",
496 err);
497
498 err = pcf8523_set_pm(client, 0);
499 if (err < 0)
500 return err;
501
502 rtc = devm_rtc_allocate_device(&client->dev);
503 if (IS_ERR(rtc))
504 return PTR_ERR(rtc);
505
506 pcf8523->rtc = rtc;
507 rtc->ops = &pcf8523_rtc_ops;
508 rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
509 rtc->range_max = RTC_TIMESTAMP_END_2099;
510 rtc->uie_unsupported = 1;
511
512 if (client->irq > 0) {
513 err = pcf8523_write(client, REG_TMR_CLKOUT_CTRL, 0x38);
514 if (err < 0)
515 return err;
516
517 err = devm_request_threaded_irq(&client->dev, client->irq,
518 NULL, pcf8523_irq,
519 IRQF_SHARED | IRQF_ONESHOT | IRQF_TRIGGER_LOW,
520 dev_name(&rtc->dev), client);
521 if (err)
522 return err;
523
524 dev_pm_set_wake_irq(&client->dev, client->irq);
525 }
526
527 #ifdef CONFIG_OF
528 wakeup_source = of_property_read_bool(client->dev.of_node, "wakeup-source");
529 #endif
530 if (client->irq > 0 || wakeup_source)
531 device_init_wakeup(&client->dev, true);
532
> 533 return rtc_register_device(rtc);
534 }
535
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org
[-- Attachment #2: config.gz --]
[-- Type: application/gzip, Size: 41509 bytes --]
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2021-04-18 3:06 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-04-18 0:20 [PATCH 1/3] rtc: pcf8523: remove useless define Alexandre Belloni
2021-04-18 0:20 ` [PATCH 2/3] rtc: pcf8523: add alarm support Alexandre Belloni
2021-04-18 3:06 ` kernel test robot
2021-04-18 0:20 ` [PATCH 3/3] rtc: pcf8523: report oscillator failures Alexandre Belloni
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.