rtc: opal: Implement rtc_class_ops.alarm_irq_enable callback
authorVaibhav Jain <vaibhav@linux.vnet.ibm.com>
Wed, 31 May 2017 13:09:01 +0000 (18:39 +0530)
committerAlexandre Belloni <alexandre.belloni@free-electrons.com>
Sat, 24 Jun 2017 05:48:30 +0000 (07:48 +0200)
Provide an implementation of the callback
rtc_class_ops.alarm_irq_enable for rtc-opal driver. This callback is
called when the wake alarm is disabled via the command:

'echo 0 > /sys/class/rtc/rtc0/wakealarm'

Without this the Timed-Power-On(TPO) config remains set even when its
disabled by the above command and FSP will still force machine
boot at previously configured alarm time.

The callback is implemented as function opal_tpo_alarm_irq_enable()
which calls opal_set_tpo_time() with alarm.enabled == 0. A branch is
added to opal_set_tpo_time() to handle this case by passing y_m_d ==
h_m_s_ms == 0 to opal as arguments for opal_tpo_write() call.

Signed-off-by: Vaibhav Jain <vaibhav@linux.vnet.ibm.com>
Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
drivers/rtc/rtc-opal.c

index 2d84e2a28772c115a1f018b22d29bd7422d4dfa8..e2a946c0e667e150e1029728134c6d20baf4d076 100644 (file)
@@ -167,7 +167,14 @@ static int opal_set_tpo_time(struct device *dev, struct rtc_wkalrm *alarm)
        u32 y_m_d = 0;
        int token, rc;
 
-       tm_to_opal(&alarm->time, &y_m_d, &h_m_s_ms);
+       /* if alarm is enabled */
+       if (alarm->enabled) {
+               tm_to_opal(&alarm->time, &y_m_d, &h_m_s_ms);
+               pr_debug("Alarm set to %x %llx\n", y_m_d, h_m_s_ms);
+
+       } else {
+               pr_debug("Alarm getting disabled\n");
+       }
 
        token = opal_async_get_token_interruptible();
        if (token < 0) {
@@ -200,6 +207,18 @@ exit:
        return rc;
 }
 
+int opal_tpo_alarm_irq_enable(struct device *dev, unsigned int enabled)
+{
+       struct rtc_wkalrm alarm = { .enabled = 0 };
+
+       /*
+        * TPO is automatically enabled when opal_set_tpo_time() is called with
+        * non-zero rtc-time. We only handle disable case which needs to be
+        * explicitly told to opal.
+        */
+       return enabled ? 0 : opal_set_tpo_time(dev, &alarm);
+}
+
 static struct rtc_class_ops opal_rtc_ops = {
        .read_time      = opal_get_rtc_time,
        .set_time       = opal_set_rtc_time,
@@ -215,6 +234,7 @@ static int opal_rtc_probe(struct platform_device *pdev)
                device_set_wakeup_capable(&pdev->dev, true);
                opal_rtc_ops.read_alarm = opal_get_tpo_time;
                opal_rtc_ops.set_alarm = opal_set_tpo_time;
+               opal_rtc_ops.alarm_irq_enable = opal_tpo_alarm_irq_enable;
        }
 
        rtc = devm_rtc_device_register(&pdev->dev, DRVNAME, &opal_rtc_ops,