summaryrefslogtreecommitdiffstats
path: root/drivers/rtc/rtc-spear.c
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2012-04-14 13:18:27 +0200
committerIngo Molnar <mingo@kernel.org>2012-04-14 13:19:04 +0200
commit6ac1ef482d7ae0c690f1640bf6eb818ff9a2d91e (patch)
tree021cc9f6b477146fcebe6f3be4752abfa2ba18a9 /drivers/rtc/rtc-spear.c
parent682968e0c425c60f0dde37977e5beb2b12ddc4cc (diff)
parenta385ec4f11bdcf81af094c03e2444ee9b7fad2e5 (diff)
Merge branch 'perf/core' into perf/uprobes
Merge in latest upstream (and the latest perf development tree), to prepare for tooling changes, and also to pick up v3.4 MM changes that the uprobes code needs to take care of. Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'drivers/rtc/rtc-spear.c')
-rw-r--r--drivers/rtc/rtc-spear.c100
1 files changed, 57 insertions, 43 deletions
diff --git a/drivers/rtc/rtc-spear.c b/drivers/rtc/rtc-spear.c
index 19a28a671a8..e38da0dc418 100644
--- a/drivers/rtc/rtc-spear.c
+++ b/drivers/rtc/rtc-spear.c
@@ -77,9 +77,11 @@
#define STATUS_FAIL (LOST_WR_TIME | LOST_WR_DATE)
struct spear_rtc_config {
+ struct rtc_device *rtc;
struct clk *clk;
spinlock_t lock;
void __iomem *ioaddr;
+ unsigned int irq_wake;
};
static inline void spear_rtc_clear_interrupt(struct spear_rtc_config *config)
@@ -149,8 +151,7 @@ static void rtc_wait_not_busy(struct spear_rtc_config *config)
static irqreturn_t spear_rtc_irq(int irq, void *dev_id)
{
- struct rtc_device *rtc = (struct rtc_device *)dev_id;
- struct spear_rtc_config *config = dev_get_drvdata(&rtc->dev);
+ struct spear_rtc_config *config = dev_id;
unsigned long flags, events = 0;
unsigned int irq_data;
@@ -161,7 +162,7 @@ static irqreturn_t spear_rtc_irq(int irq, void *dev_id)
if ((irq_data & RTC_INT_MASK)) {
spear_rtc_clear_interrupt(config);
events = RTC_IRQF | RTC_AF;
- rtc_update_irq(rtc, 1, events);
+ rtc_update_irq(config->rtc, 1, events);
return IRQ_HANDLED;
} else
return IRQ_NONE;
@@ -203,9 +204,7 @@ static void bcd2tm(struct rtc_time *tm)
*/
static int spear_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct rtc_device *rtc = platform_get_drvdata(pdev);
- struct spear_rtc_config *config = dev_get_drvdata(&rtc->dev);
+ struct spear_rtc_config *config = dev_get_drvdata(dev);
unsigned int time, date;
/* we don't report wday/yday/isdst ... */
@@ -234,9 +233,7 @@ static int spear_rtc_read_time(struct device *dev, struct rtc_time *tm)
*/
static int spear_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct rtc_device *rtc = platform_get_drvdata(pdev);
- struct spear_rtc_config *config = dev_get_drvdata(&rtc->dev);
+ struct spear_rtc_config *config = dev_get_drvdata(dev);
unsigned int time, date, err = 0;
if (tm2bcd(tm) < 0)
@@ -266,9 +263,7 @@ static int spear_rtc_set_time(struct device *dev, struct rtc_time *tm)
*/
static int spear_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct rtc_device *rtc = platform_get_drvdata(pdev);
- struct spear_rtc_config *config = dev_get_drvdata(&rtc->dev);
+ struct spear_rtc_config *config = dev_get_drvdata(dev);
unsigned int time, date;
rtc_wait_not_busy(config);
@@ -298,9 +293,7 @@ static int spear_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
*/
static int spear_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct rtc_device *rtc = platform_get_drvdata(pdev);
- struct spear_rtc_config *config = dev_get_drvdata(&rtc->dev);
+ struct spear_rtc_config *config = dev_get_drvdata(dev);
unsigned int time, date, err = 0;
if (tm2bcd(&alm->time) < 0)
@@ -326,17 +319,42 @@ static int spear_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
return 0;
}
+
+static int spear_alarm_irq_enable(struct device *dev, unsigned int enabled)
+{
+ struct spear_rtc_config *config = dev_get_drvdata(dev);
+ int ret = 0;
+
+ spear_rtc_clear_interrupt(config);
+
+ switch (enabled) {
+ case 0:
+ /* alarm off */
+ spear_rtc_disable_interrupt(config);
+ break;
+ case 1:
+ /* alarm on */
+ spear_rtc_enable_interrupt(config);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
static struct rtc_class_ops spear_rtc_ops = {
.read_time = spear_rtc_read_time,
.set_time = spear_rtc_set_time,
.read_alarm = spear_rtc_read_alarm,
.set_alarm = spear_rtc_set_alarm,
+ .alarm_irq_enable = spear_alarm_irq_enable,
};
static int __devinit spear_rtc_probe(struct platform_device *pdev)
{
struct resource *res;
- struct rtc_device *rtc;
struct spear_rtc_config *config;
unsigned int status = 0;
int irq;
@@ -376,19 +394,17 @@ static int __devinit spear_rtc_probe(struct platform_device *pdev)
}
spin_lock_init(&config->lock);
+ platform_set_drvdata(pdev, config);
- rtc = rtc_device_register(pdev->name, &pdev->dev, &spear_rtc_ops,
- THIS_MODULE);
- if (IS_ERR(rtc)) {
+ config->rtc = rtc_device_register(pdev->name, &pdev->dev,
+ &spear_rtc_ops, THIS_MODULE);
+ if (IS_ERR(config->rtc)) {
dev_err(&pdev->dev, "can't register RTC device, err %ld\n",
- PTR_ERR(rtc));
- status = PTR_ERR(rtc);
+ PTR_ERR(config->rtc));
+ status = PTR_ERR(config->rtc);
goto err_iounmap;
}
- platform_set_drvdata(pdev, rtc);
- dev_set_drvdata(&rtc->dev, config);
-
/* alarm irqs */
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
@@ -397,7 +413,7 @@ static int __devinit spear_rtc_probe(struct platform_device *pdev)
goto err_clear_platdata;
}
- status = request_irq(irq, spear_rtc_irq, 0, pdev->name, rtc);
+ status = request_irq(irq, spear_rtc_irq, 0, pdev->name, config);
if (status) {
dev_err(&pdev->dev, "Alarm interrupt IRQ%d already \
claimed\n", irq);
@@ -411,8 +427,7 @@ static int __devinit spear_rtc_probe(struct platform_device *pdev)
err_clear_platdata:
platform_set_drvdata(pdev, NULL);
- dev_set_drvdata(&rtc->dev, NULL);
- rtc_device_unregister(rtc);
+ rtc_device_unregister(config->rtc);
err_iounmap:
iounmap(config->ioaddr);
err_disable_clock:
@@ -429,8 +444,7 @@ err_release_region:
static int __devexit spear_rtc_remove(struct platform_device *pdev)
{
- struct rtc_device *rtc = platform_get_drvdata(pdev);
- struct spear_rtc_config *config = dev_get_drvdata(&rtc->dev);
+ struct spear_rtc_config *config = platform_get_drvdata(pdev);
int irq;
struct resource *res;
@@ -448,8 +462,7 @@ static int __devexit spear_rtc_remove(struct platform_device *pdev)
if (res)
release_mem_region(res->start, resource_size(res));
platform_set_drvdata(pdev, NULL);
- dev_set_drvdata(&rtc->dev, NULL);
- rtc_device_unregister(rtc);
+ rtc_device_unregister(config->rtc);
return 0;
}
@@ -458,14 +471,14 @@ static int __devexit spear_rtc_remove(struct platform_device *pdev)
static int spear_rtc_suspend(struct platform_device *pdev, pm_message_t state)
{
- struct rtc_device *rtc = platform_get_drvdata(pdev);
- struct spear_rtc_config *config = dev_get_drvdata(&rtc->dev);
+ struct spear_rtc_config *config = platform_get_drvdata(pdev);
int irq;
irq = platform_get_irq(pdev, 0);
- if (device_may_wakeup(&pdev->dev))
- enable_irq_wake(irq);
- else {
+ if (device_may_wakeup(&pdev->dev)) {
+ if (!enable_irq_wake(irq))
+ config->irq_wake = 1;
+ } else {
spear_rtc_disable_interrupt(config);
clk_disable(config->clk);
}
@@ -475,15 +488,17 @@ static int spear_rtc_suspend(struct platform_device *pdev, pm_message_t state)
static int spear_rtc_resume(struct platform_device *pdev)
{
- struct rtc_device *rtc = platform_get_drvdata(pdev);
- struct spear_rtc_config *config = dev_get_drvdata(&rtc->dev);
+ struct spear_rtc_config *config = platform_get_drvdata(pdev);
int irq;
irq = platform_get_irq(pdev, 0);
- if (device_may_wakeup(&pdev->dev))
- disable_irq_wake(irq);
- else {
+ if (device_may_wakeup(&pdev->dev)) {
+ if (config->irq_wake) {
+ disable_irq_wake(irq);
+ config->irq_wake = 0;
+ }
+ } else {
clk_enable(config->clk);
spear_rtc_enable_interrupt(config);
}
@@ -498,8 +513,7 @@ static int spear_rtc_resume(struct platform_device *pdev)
static void spear_rtc_shutdown(struct platform_device *pdev)
{
- struct rtc_device *rtc = platform_get_drvdata(pdev);
- struct spear_rtc_config *config = dev_get_drvdata(&rtc->dev);
+ struct spear_rtc_config *config = platform_get_drvdata(pdev);
spear_rtc_disable_interrupt(config);
clk_disable(config->clk);