diff options
author | Nishanth Menon <nm@ti.com> | 2015-06-24 12:26:54 -0400 |
---|---|---|
committer | Alexandre Belloni <alexandre.belloni@free-electrons.com> | 2015-09-05 07:19:05 -0400 |
commit | 7abea617a4bae178da0f42983998c779ec2f732d (patch) | |
tree | a4053e8b785c6d3b63e01f78a30e751618371da1 /drivers/rtc | |
parent | eac7237fd8432e232af3c407e667dbdc17ebf1d8 (diff) |
rtc: ds1307: Support optional wakeup interrupt source
With the recent pinctrl-single changes, SoCs such as Texas
Instrument's OMAP processors can treat wake-up events from deeper idle
states as interrupts.
Let's add support for the optional second interrupt for wake-up using
the generic wakeirq support added in commit 4990d4fe327b ("PM /
Wakeirq: Add automated device wake IRQ handling")
Finally, to pass the wake-up interrupt in the dts file,
interrupts-extended property needs to be passed.
This is similar in approach to commit 2a0b965cfb6e ("serial: omap: Add
support for optional wake-up") + ee83bd3b6483 ("serial: omap: Switch
wake-up interrupt to generic wakeirq")
Signed-off-by: Nishanth Menon <nm@ti.com>
Reviewed-by: Grygorii Strashko <grygorii.strashko@ti.com>
Acked-by: Tony Lindgren <tony@atomide.com>
Acked-by: Felipe Balbi <balbi@ti.com>
Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
Diffstat (limited to 'drivers/rtc')
-rw-r--r-- | drivers/rtc/rtc-ds1307.c | 36 |
1 files changed, 33 insertions, 3 deletions
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c index b03880fc32b5..e16989c48a90 100644 --- a/drivers/rtc/rtc-ds1307.c +++ b/drivers/rtc/rtc-ds1307.c | |||
@@ -15,6 +15,9 @@ | |||
15 | #include <linux/i2c.h> | 15 | #include <linux/i2c.h> |
16 | #include <linux/init.h> | 16 | #include <linux/init.h> |
17 | #include <linux/module.h> | 17 | #include <linux/module.h> |
18 | #include <linux/of_device.h> | ||
19 | #include <linux/of_irq.h> | ||
20 | #include <linux/pm_wakeirq.h> | ||
18 | #include <linux/rtc/ds1307.h> | 21 | #include <linux/rtc/ds1307.h> |
19 | #include <linux/rtc.h> | 22 | #include <linux/rtc.h> |
20 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
@@ -114,6 +117,7 @@ struct ds1307 { | |||
114 | #define HAS_ALARM 1 /* bit 1 == irq claimed */ | 117 | #define HAS_ALARM 1 /* bit 1 == irq claimed */ |
115 | struct i2c_client *client; | 118 | struct i2c_client *client; |
116 | struct rtc_device *rtc; | 119 | struct rtc_device *rtc; |
120 | int wakeirq; | ||
117 | s32 (*read_block_data)(const struct i2c_client *client, u8 command, | 121 | s32 (*read_block_data)(const struct i2c_client *client, u8 command, |
118 | u8 length, u8 *values); | 122 | u8 length, u8 *values); |
119 | s32 (*write_block_data)(const struct i2c_client *client, u8 command, | 123 | s32 (*write_block_data)(const struct i2c_client *client, u8 command, |
@@ -1156,6 +1160,8 @@ read_rtc: | |||
1156 | } | 1160 | } |
1157 | 1161 | ||
1158 | if (want_irq) { | 1162 | if (want_irq) { |
1163 | struct device_node *node = client->dev.of_node; | ||
1164 | |||
1159 | err = devm_request_threaded_irq(&client->dev, | 1165 | err = devm_request_threaded_irq(&client->dev, |
1160 | client->irq, NULL, irq_handler, | 1166 | client->irq, NULL, irq_handler, |
1161 | IRQF_SHARED | IRQF_ONESHOT, | 1167 | IRQF_SHARED | IRQF_ONESHOT, |
@@ -1163,13 +1169,34 @@ read_rtc: | |||
1163 | if (err) { | 1169 | if (err) { |
1164 | client->irq = 0; | 1170 | client->irq = 0; |
1165 | dev_err(&client->dev, "unable to request IRQ!\n"); | 1171 | dev_err(&client->dev, "unable to request IRQ!\n"); |
1166 | } else { | 1172 | goto no_irq; |
1173 | } | ||
1167 | 1174 | ||
1168 | set_bit(HAS_ALARM, &ds1307->flags); | 1175 | set_bit(HAS_ALARM, &ds1307->flags); |
1169 | dev_dbg(&client->dev, "got IRQ %d\n", client->irq); | 1176 | dev_dbg(&client->dev, "got IRQ %d\n", client->irq); |
1177 | |||
1178 | /* Currently supported by OF code only! */ | ||
1179 | if (!node) | ||
1180 | goto no_irq; | ||
1181 | |||
1182 | err = of_irq_get(node, 1); | ||
1183 | if (err <= 0) { | ||
1184 | if (err == -EPROBE_DEFER) | ||
1185 | goto exit; | ||
1186 | goto no_irq; | ||
1187 | } | ||
1188 | ds1307->wakeirq = err; | ||
1189 | |||
1190 | err = dev_pm_set_dedicated_wake_irq(&client->dev, | ||
1191 | ds1307->wakeirq); | ||
1192 | if (err) { | ||
1193 | dev_err(&client->dev, "unable to setup wakeIRQ %d!\n", | ||
1194 | err); | ||
1195 | goto exit; | ||
1170 | } | 1196 | } |
1171 | } | 1197 | } |
1172 | 1198 | ||
1199 | no_irq: | ||
1173 | if (chip->nvram_size) { | 1200 | if (chip->nvram_size) { |
1174 | 1201 | ||
1175 | ds1307->nvram = devm_kzalloc(&client->dev, | 1202 | ds1307->nvram = devm_kzalloc(&client->dev, |
@@ -1213,6 +1240,9 @@ static int ds1307_remove(struct i2c_client *client) | |||
1213 | { | 1240 | { |
1214 | struct ds1307 *ds1307 = i2c_get_clientdata(client); | 1241 | struct ds1307 *ds1307 = i2c_get_clientdata(client); |
1215 | 1242 | ||
1243 | if (ds1307->wakeirq) | ||
1244 | dev_pm_clear_wake_irq(&client->dev); | ||
1245 | |||
1216 | if (test_and_clear_bit(HAS_NVRAM, &ds1307->flags)) | 1246 | if (test_and_clear_bit(HAS_NVRAM, &ds1307->flags)) |
1217 | sysfs_remove_bin_file(&client->dev.kobj, ds1307->nvram); | 1247 | sysfs_remove_bin_file(&client->dev.kobj, ds1307->nvram); |
1218 | 1248 | ||