Message ID | 1390281891-9632-1-git-send-email-dongsheng.wang@freescale.com (mailing list archive) |
---|---|
State | Superseded, archived |
Headers | show |
On Tue, 21 Jan 2014 13:24:51 +0800 Dongsheng Wang <dongsheng.wang@freescale.com> wrote: > From: Wang Dongsheng <dongsheng.wang@freescale.com> > > Add suspend/resume and device_init_wakeup to enable ds3232 as > wakeup source, /sys/class/rtc/rtcX/wakealarm for set wakeup alarm. > > ... > > @@ -411,23 +424,21 @@ static int ds3232_probe(struct i2c_client *client, > if (ret) > return ret; > > - ds3232->rtc = devm_rtc_device_register(&client->dev, client->name, > - &ds3232_rtc_ops, THIS_MODULE); > - if (IS_ERR(ds3232->rtc)) { > - dev_err(&client->dev, "unable to register the class device\n"); > - return PTR_ERR(ds3232->rtc); > - } > - > - if (client->irq >= 0) { > + if (client->irq != NO_IRQ) { x86_64 allmodconfig: drivers/rtc/rtc-ds3232.c: In function 'ds3232_probe': drivers/rtc/rtc-ds3232.c:427: error: 'NO_IRQ' undeclared (first use in this function) drivers/rtc/rtc-ds3232.c:427: error: (Each undeclared identifier is reported only once drivers/rtc/rtc-ds3232.c:427: error: for each function it appears in.) Not all architectures implement NO_IRQ. I think this should be if (client->irq > 0) { but I'm not sure - iirc, x86 (at least) treats zero as "not an IRQ". But I think some architectures permit IRQ 0. There was discussion many years ago but I don't think anything got resolved. Help! I think some ppc people will know what to do here?
> -----Original Message----- > From: Andrew Morton [mailto:akpm@linux-foundation.org] > Sent: Wednesday, February 26, 2014 6:07 AM > To: rtc-linux@googlegroups.com > Cc: Wang Dongsheng-B40534; a.zummo@towertech.it; Zhao Chenhui-B35336; linuxppc- > dev@lists.ozlabs.org > Subject: Re: [rtc-linux] [PATCH] rtc/ds3232: Enable ds3232 to work as wakeup > source > > On Tue, 21 Jan 2014 13:24:51 +0800 Dongsheng Wang <dongsheng.wang@freescale.com> > wrote: > > > From: Wang Dongsheng <dongsheng.wang@freescale.com> > > > > Add suspend/resume and device_init_wakeup to enable ds3232 as > > wakeup source, /sys/class/rtc/rtcX/wakealarm for set wakeup alarm. > > > > ... > > > > @@ -411,23 +424,21 @@ static int ds3232_probe(struct i2c_client *client, > > if (ret) > > return ret; > > > > - ds3232->rtc = devm_rtc_device_register(&client->dev, client->name, > > - &ds3232_rtc_ops, THIS_MODULE); > > - if (IS_ERR(ds3232->rtc)) { > > - dev_err(&client->dev, "unable to register the class device\n"); > > - return PTR_ERR(ds3232->rtc); > > - } > > - > > - if (client->irq >= 0) { > > + if (client->irq != NO_IRQ) { > > x86_64 allmodconfig: > > drivers/rtc/rtc-ds3232.c: In function 'ds3232_probe': > drivers/rtc/rtc-ds3232.c:427: error: 'NO_IRQ' undeclared (first use in this > function) > drivers/rtc/rtc-ds3232.c:427: error: (Each undeclared identifier is reported > only once > drivers/rtc/rtc-ds3232.c:427: error: for each function it appears in.) > > Not all architectures implement NO_IRQ. > > I think this should be > > if (client->irq > 0) { > > but I'm not sure - iirc, x86 (at least) treats zero as "not an IRQ". > But I think some architectures permit IRQ 0. There was discussion many > years ago but I don't think anything got resolved. > I think this is why NO_IRQ is defined in kernel, that should be resolved this issue. Sorry, I don't know why some architectures didn't define this macro? Hi Ben, Did you have some suggestion? Thanks, -Dongsheng > > Help! I think some ppc people will know what to do here? >
On Tue, 2014-02-25 at 21:09 -0600, Wang Dongsheng-B40534 wrote: > > > -----Original Message----- > > From: Andrew Morton [mailto:akpm@linux-foundation.org] > > Sent: Wednesday, February 26, 2014 6:07 AM > > To: rtc-linux@googlegroups.com > > Cc: Wang Dongsheng-B40534; a.zummo@towertech.it; Zhao Chenhui-B35336; linuxppc- > > dev@lists.ozlabs.org > > Subject: Re: [rtc-linux] [PATCH] rtc/ds3232: Enable ds3232 to work as wakeup > > source > > > > On Tue, 21 Jan 2014 13:24:51 +0800 Dongsheng Wang <dongsheng.wang@freescale.com> > > wrote: > > > > > + if (client->irq != NO_IRQ) { > > > > x86_64 allmodconfig: > > > > drivers/rtc/rtc-ds3232.c: In function 'ds3232_probe': > > drivers/rtc/rtc-ds3232.c:427: error: 'NO_IRQ' undeclared (first use in this > > function) > > drivers/rtc/rtc-ds3232.c:427: error: (Each undeclared identifier is reported > > only once > > drivers/rtc/rtc-ds3232.c:427: error: for each function it appears in.) > > > > Not all architectures implement NO_IRQ. > > > > I think this should be > > > > if (client->irq > 0) { > > > > but I'm not sure - iirc, x86 (at least) treats zero as "not an IRQ". > > But I think some architectures permit IRQ 0. There was discussion many > > years ago but I don't think anything got resolved. > > > I think this is why NO_IRQ is defined in kernel, that should be resolved this issue. > > Sorry, I don't know why some architectures didn't define this macro? NO_IRQ is deprecated (see "git log -SNO_IRQ" for the trend of removing uses of it, as well as situations where it gives the wrong results). "if (client->irq > 0)" is correct. -Scott
> -----Original Message----- > From: Wood Scott-B07421 > Sent: Wednesday, February 26, 2014 11:21 AM > To: Wang Dongsheng-B40534 > Cc: Andrew Morton; rtc-linux@googlegroups.com; benh@kernel.crashing.org; > a.zummo@towertech.it; Zhao Chenhui-B35336; linuxppc-dev@lists.ozlabs.org > Subject: Re: [rtc-linux] [PATCH] rtc/ds3232: Enable ds3232 to work as wakeup > source > > On Tue, 2014-02-25 at 21:09 -0600, Wang Dongsheng-B40534 wrote: > > > > > -----Original Message----- > > > From: Andrew Morton [mailto:akpm@linux-foundation.org] > > > Sent: Wednesday, February 26, 2014 6:07 AM > > > To: rtc-linux@googlegroups.com > > > Cc: Wang Dongsheng-B40534; a.zummo@towertech.it; Zhao Chenhui-B35336; > linuxppc- > > > dev@lists.ozlabs.org > > > Subject: Re: [rtc-linux] [PATCH] rtc/ds3232: Enable ds3232 to work as wakeup > > > source > > > > > > On Tue, 21 Jan 2014 13:24:51 +0800 Dongsheng Wang > <dongsheng.wang@freescale.com> > > > wrote: > > > > > > > + if (client->irq != NO_IRQ) { > > > > > > x86_64 allmodconfig: > > > > > > drivers/rtc/rtc-ds3232.c: In function 'ds3232_probe': > > > drivers/rtc/rtc-ds3232.c:427: error: 'NO_IRQ' undeclared (first use in this > > > function) > > > drivers/rtc/rtc-ds3232.c:427: error: (Each undeclared identifier is reported > > > only once > > > drivers/rtc/rtc-ds3232.c:427: error: for each function it appears in.) > > > > > > Not all architectures implement NO_IRQ. > > > > > > I think this should be > > > > > > if (client->irq > 0) { > > > > > > but I'm not sure - iirc, x86 (at least) treats zero as "not an IRQ". > > > But I think some architectures permit IRQ 0. There was discussion many > > > years ago but I don't think anything got resolved. > > > > > I think this is why NO_IRQ is defined in kernel, that should be resolved this > issue. > > > > Sorry, I don't know why some architectures didn't define this macro? > > NO_IRQ is deprecated (see "git log -SNO_IRQ" for the trend of removing > uses of it, as well as situations where it gives the wrong results). > "if (client->irq > 0)" is correct. > Thanks. -Dongsheng > -Scott >
diff --git a/drivers/rtc/rtc-ds3232.c b/drivers/rtc/rtc-ds3232.c index b83bb5a5..a3c40d5 100644 --- a/drivers/rtc/rtc-ds3232.c +++ b/drivers/rtc/rtc-ds3232.c @@ -57,6 +57,7 @@ struct ds3232 { * in the remove function. */ struct mutex mutex; + bool suspended; int exiting; }; @@ -345,7 +346,15 @@ static irqreturn_t ds3232_irq(int irq, void *dev_id) struct ds3232 *ds3232 = i2c_get_clientdata(client); disable_irq_nosync(irq); - schedule_work(&ds3232->work); + + /* + * If rtc as a wakeup source, can't schedule the work + * at system resume flow, because at this time the i2c bus + * has not been resumed. + */ + if (!ds3232->suspended) + schedule_work(&ds3232->work); + return IRQ_HANDLED; } @@ -363,22 +372,26 @@ static void ds3232_work(struct work_struct *work) if (stat & DS3232_REG_SR_A1F) { control = i2c_smbus_read_byte_data(client, DS3232_REG_CR); - if (control < 0) - goto out; - /* disable alarm1 interrupt */ - control &= ~(DS3232_REG_CR_A1IE); - i2c_smbus_write_byte_data(client, DS3232_REG_CR, control); - - /* clear the alarm pend flag */ - stat &= ~DS3232_REG_SR_A1F; - i2c_smbus_write_byte_data(client, DS3232_REG_SR, stat); - - rtc_update_irq(ds3232->rtc, 1, RTC_AF | RTC_IRQF); + if (control < 0) { + pr_warn("Read DS3232 Control Register error." + "Disable IRQ%d.\n", client->irq); + } else { + /* disable alarm1 interrupt */ + control &= ~(DS3232_REG_CR_A1IE); + i2c_smbus_write_byte_data(client, DS3232_REG_CR, + control); + + /* clear the alarm pend flag */ + stat &= ~DS3232_REG_SR_A1F; + i2c_smbus_write_byte_data(client, DS3232_REG_SR, stat); + + rtc_update_irq(ds3232->rtc, 1, RTC_AF | RTC_IRQF); + + if (!ds3232->exiting) + enable_irq(client->irq); + } } -out: - if (!ds3232->exiting) - enable_irq(client->irq); unlock: mutex_unlock(&ds3232->mutex); } @@ -411,23 +424,21 @@ static int ds3232_probe(struct i2c_client *client, if (ret) return ret; - ds3232->rtc = devm_rtc_device_register(&client->dev, client->name, - &ds3232_rtc_ops, THIS_MODULE); - if (IS_ERR(ds3232->rtc)) { - dev_err(&client->dev, "unable to register the class device\n"); - return PTR_ERR(ds3232->rtc); - } - - if (client->irq >= 0) { + if (client->irq != NO_IRQ) { ret = devm_request_irq(&client->dev, client->irq, ds3232_irq, 0, "ds3232", client); if (ret) { dev_err(&client->dev, "unable to request IRQ\n"); return ret; } + + device_init_wakeup(&client->dev, 1); + } - return 0; + ds3232->rtc = devm_rtc_device_register(&client->dev, client->name, + &ds3232_rtc_ops, THIS_MODULE); + return PTR_ERR_OR_ZERO(ds3232->rtc); } static int ds3232_remove(struct i2c_client *client) @@ -446,6 +457,42 @@ static int ds3232_remove(struct i2c_client *client) return 0; } +#ifdef CONFIG_PM_SLEEP +static int ds3232_suspend(struct device *dev) +{ + struct ds3232 *ds3232 = dev_get_drvdata(dev); + struct i2c_client *client = to_i2c_client(dev); + + if (device_can_wakeup(dev)) { + ds3232->suspended = true; + irq_set_irq_wake(client->irq, 1); + } + + return 0; +} + +static int ds3232_resume(struct device *dev) +{ + struct ds3232 *ds3232 = dev_get_drvdata(dev); + struct i2c_client *client = to_i2c_client(dev); + + if (ds3232->suspended) { + ds3232->suspended = false; + + /* Clear the hardware alarm pend flag */ + schedule_work(&ds3232->work); + + irq_set_irq_wake(client->irq, 0); + } + + return 0; +} +#endif + +static const struct dev_pm_ops ds3232_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(ds3232_suspend, ds3232_resume) +}; + static const struct i2c_device_id ds3232_id[] = { { "ds3232", 0 }, { } @@ -456,6 +503,7 @@ static struct i2c_driver ds3232_driver = { .driver = { .name = "rtc-ds3232", .owner = THIS_MODULE, + .pm = &ds3232_pm_ops, }, .probe = ds3232_probe, .remove = ds3232_remove,