From dd279f6127c0f64dfb0055bc0adb97a284a08df3 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Tue, 5 Aug 2008 13:01:15 -0700 Subject: blackfin RTC driver: if we dont define irq_set_freq, the common rtc-dev layer will give us the same behavior of returning ENOTTY Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu Signed-off-by: Bryan Wu Cc: David Brownell Cc: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-bfin.c | 15 --------------- 1 file changed, 15 deletions(-) (limited to 'drivers/rtc/rtc-bfin.c') diff --git a/drivers/rtc/rtc-bfin.c b/drivers/rtc/rtc-bfin.c index 8624f55d0560..48ada599477b 100644 --- a/drivers/rtc/rtc-bfin.c +++ b/drivers/rtc/rtc-bfin.c @@ -381,20 +381,6 @@ static int bfin_rtc_proc(struct device *dev, struct seq_file *seq) #undef yesno } -/** - * bfin_irq_set_freq - make sure hardware supports requested freq - * @dev: pointer to RTC device structure - * @freq: requested frequency rate - * - * The Blackfin RTC can only generate periodic events at 1 per - * second (1 Hz), so reject any attempt at changing it. - */ -static int bfin_irq_set_freq(struct device *dev, int freq) -{ - dev_dbg_stamp(dev); - return -ENOTTY; -} - static struct rtc_class_ops bfin_rtc_ops = { .open = bfin_rtc_open, .release = bfin_rtc_release, @@ -404,7 +390,6 @@ static struct rtc_class_ops bfin_rtc_ops = { .read_alarm = bfin_rtc_read_alarm, .set_alarm = bfin_rtc_set_alarm, .proc = bfin_rtc_proc, - .irq_set_freq = bfin_irq_set_freq, }; static int __devinit bfin_rtc_probe(struct platform_device *pdev) -- cgit v1.2.3 From 5aeb776d0c2bb1dd3ef01f4805929e2bc2923e7b Mon Sep 17 00:00:00 2001 From: Sonic Zhang Date: Tue, 5 Aug 2008 13:01:17 -0700 Subject: blackfin RTC driver: Fix bug Only RTC interrupt can wake up deeper sleep core Signed-off-by: Sonic Zhang Signed-off-by: Bryan Wu Signed-off-by: Bryan Wu Cc: David Brownell Cc: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-bfin.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) (limited to 'drivers/rtc/rtc-bfin.c') diff --git a/drivers/rtc/rtc-bfin.c b/drivers/rtc/rtc-bfin.c index 48ada599477b..a568d29b0742 100644 --- a/drivers/rtc/rtc-bfin.c +++ b/drivers/rtc/rtc-bfin.c @@ -430,6 +430,30 @@ static int __devexit bfin_rtc_remove(struct platform_device *pdev) return 0; } +#ifdef CONFIG_PM +static int bfin_rtc_suspend(struct platform_device *pdev, pm_message_t state) +{ +#ifdef PM_WAKEUP_SIC_IWR + struct bfin_rtc *rtc = dev_get_drvdata(&pdev->dev); +#endif + bfin_rtc_reset(&pdev->dev); +#ifdef PM_WAKEUP_SIC_IWR + bfin_write_RTC_SWCNT(10); + bfin_rtc_int_set(rtc, RTC_ISTAT_STOPWATCH); +#endif + return 0; +} + +static int bfin_rtc_resume(struct platform_device *pdev) +{ +#ifdef PM_WAKEUP_SIC_IWR + struct bfin_rtc *rtc = dev_get_drvdata(&pdev->dev); + bfin_rtc_int_clear(rtc, RTC_ISTAT_STOPWATCH); +#endif + return 0; +} +#endif + static struct platform_driver bfin_rtc_driver = { .driver = { .name = "rtc-bfin", @@ -437,6 +461,10 @@ static struct platform_driver bfin_rtc_driver = { }, .probe = bfin_rtc_probe, .remove = __devexit_p(bfin_rtc_remove), +#ifdef CONFIG_PM + .suspend = bfin_rtc_suspend, + .resume = bfin_rtc_resume, +#endif }; static int __init bfin_rtc_init(void) -- cgit v1.2.3 From 813006f4bb4a39afdde8ab2e3559971c029d1dc0 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Tue, 5 Aug 2008 13:01:18 -0700 Subject: blackfin RTC driver: add support for power management framework Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu Signed-off-by: Bryan Wu Cc: David Brownell Cc: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-bfin.c | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) (limited to 'drivers/rtc/rtc-bfin.c') diff --git a/drivers/rtc/rtc-bfin.c b/drivers/rtc/rtc-bfin.c index a568d29b0742..23b991d41ef1 100644 --- a/drivers/rtc/rtc-bfin.c +++ b/drivers/rtc/rtc-bfin.c @@ -2,7 +2,7 @@ * Blackfin On-Chip Real Time Clock Driver * Supports BF52[257]/BF53[123]/BF53[467]/BF54[24789] * - * Copyright 2004-2007 Analog Devices Inc. + * Copyright 2004-2008 Analog Devices Inc. * * Enter bugs at http://blackfin.uclinux.org/ * @@ -412,6 +412,8 @@ static int __devinit bfin_rtc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, rtc); + device_init_wakeup(&pdev->dev, 1); + return 0; err: @@ -433,25 +435,28 @@ static int __devexit bfin_rtc_remove(struct platform_device *pdev) #ifdef CONFIG_PM static int bfin_rtc_suspend(struct platform_device *pdev, pm_message_t state) { -#ifdef PM_WAKEUP_SIC_IWR struct bfin_rtc *rtc = dev_get_drvdata(&pdev->dev); -#endif - bfin_rtc_reset(&pdev->dev); -#ifdef PM_WAKEUP_SIC_IWR - bfin_write_RTC_SWCNT(10); - bfin_rtc_int_set(rtc, RTC_ISTAT_STOPWATCH); -#endif + + if (device_may_wakeup(&pdev->dev)) + enable_irq_wake(IRQ_RTC); + else + bfin_rtc_int_clear(rtc, -1); + return 0; } static int bfin_rtc_resume(struct platform_device *pdev) { -#ifdef PM_WAKEUP_SIC_IWR - struct bfin_rtc *rtc = dev_get_drvdata(&pdev->dev); - bfin_rtc_int_clear(rtc, RTC_ISTAT_STOPWATCH); -#endif + if (device_may_wakeup(&pdev->dev)) + disable_irq_wake(IRQ_RTC); + else + bfin_write_RTC_ISTAT(-1); + return 0; } +#else +# define bfin_rtc_suspend NULL +# define bfin_rtc_resume NULL #endif static struct platform_driver bfin_rtc_driver = { @@ -461,10 +466,8 @@ static struct platform_driver bfin_rtc_driver = { }, .probe = bfin_rtc_probe, .remove = __devexit_p(bfin_rtc_remove), -#ifdef CONFIG_PM .suspend = bfin_rtc_suspend, .resume = bfin_rtc_resume, -#endif }; static int __init bfin_rtc_init(void) -- cgit v1.2.3 From 605eb8b3c05e970caf71c48f693efe33c212fb7b Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Tue, 5 Aug 2008 13:01:18 -0700 Subject: blackfin RTC driver: don't bother passing the rtc struct down to bfin_rtc_int_{set,clear} since it isnt needed (shaves off ~100bytes) Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu Signed-off-by: Bryan Wu Cc: David Brownell Cc: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-bfin.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) (limited to 'drivers/rtc/rtc-bfin.c') diff --git a/drivers/rtc/rtc-bfin.c b/drivers/rtc/rtc-bfin.c index 23b991d41ef1..56656dd6b2c1 100644 --- a/drivers/rtc/rtc-bfin.c +++ b/drivers/rtc/rtc-bfin.c @@ -238,12 +238,12 @@ static void bfin_rtc_release(struct device *dev) free_irq(IRQ_RTC, dev); } -static void bfin_rtc_int_set(struct bfin_rtc *rtc, u16 rtc_int) +static void bfin_rtc_int_set(u16 rtc_int) { bfin_write_RTC_ISTAT(rtc_int); bfin_write_RTC_ICTL(bfin_read_RTC_ICTL() | rtc_int); } -static void bfin_rtc_int_clear(struct bfin_rtc *rtc, u16 rtc_int) +static void bfin_rtc_int_clear(u16 rtc_int) { bfin_write_RTC_ICTL(bfin_read_RTC_ICTL() & rtc_int); } @@ -252,7 +252,7 @@ static void bfin_rtc_int_set_alarm(struct bfin_rtc *rtc) /* Blackfin has different bits for whether the alarm is * more than 24 hours away. */ - bfin_rtc_int_set(rtc, (rtc->rtc_alarm.tm_yday == -1 ? RTC_ISTAT_ALARM : RTC_ISTAT_ALARM_DAY)); + bfin_rtc_int_set(rtc->rtc_alarm.tm_yday == -1 ? RTC_ISTAT_ALARM : RTC_ISTAT_ALARM_DAY); } static int bfin_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) { @@ -266,21 +266,21 @@ static int bfin_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long ar switch (cmd) { case RTC_PIE_ON: dev_dbg_stamp(dev); - bfin_rtc_int_set(rtc, RTC_ISTAT_STOPWATCH); + bfin_rtc_int_set(RTC_ISTAT_STOPWATCH); bfin_write_RTC_SWCNT(rtc->rtc_dev->irq_freq); break; case RTC_PIE_OFF: dev_dbg_stamp(dev); - bfin_rtc_int_clear(rtc, ~RTC_ISTAT_STOPWATCH); + bfin_rtc_int_clear(~RTC_ISTAT_STOPWATCH); break; case RTC_UIE_ON: dev_dbg_stamp(dev); - bfin_rtc_int_set(rtc, RTC_ISTAT_SEC); + bfin_rtc_int_set(RTC_ISTAT_SEC); break; case RTC_UIE_OFF: dev_dbg_stamp(dev); - bfin_rtc_int_clear(rtc, ~RTC_ISTAT_SEC); + bfin_rtc_int_clear(~RTC_ISTAT_SEC); break; case RTC_AIE_ON: @@ -289,7 +289,7 @@ static int bfin_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long ar break; case RTC_AIE_OFF: dev_dbg_stamp(dev); - bfin_rtc_int_clear(rtc, ~(RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY)); + bfin_rtc_int_clear(~(RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY)); break; default: @@ -435,12 +435,10 @@ static int __devexit bfin_rtc_remove(struct platform_device *pdev) #ifdef CONFIG_PM static int bfin_rtc_suspend(struct platform_device *pdev, pm_message_t state) { - struct bfin_rtc *rtc = dev_get_drvdata(&pdev->dev); - if (device_may_wakeup(&pdev->dev)) enable_irq_wake(IRQ_RTC); else - bfin_rtc_int_clear(rtc, -1); + bfin_rtc_int_clear(-1); return 0; } -- cgit v1.2.3 From 3b128fe04a3087d6e974b87402dc6e75d3142186 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Tue, 5 Aug 2008 13:01:19 -0700 Subject: blackfin RTC driver: disable the write complete irq upon close Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu Cc: David Brownell Cc: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-bfin.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/rtc/rtc-bfin.c') diff --git a/drivers/rtc/rtc-bfin.c b/drivers/rtc/rtc-bfin.c index 56656dd6b2c1..d53772f59ce5 100644 --- a/drivers/rtc/rtc-bfin.c +++ b/drivers/rtc/rtc-bfin.c @@ -144,13 +144,13 @@ static void bfin_rtc_sync_pending(struct device *dev) * Initialize the RTC. Enable pre-scaler to scale RTC clock * to 1Hz and clear interrupt/status registers. */ -static void bfin_rtc_reset(struct device *dev) +static void bfin_rtc_reset(struct device *dev, u16 rtc_ictl) { struct bfin_rtc *rtc = dev_get_drvdata(dev); dev_dbg_stamp(dev); bfin_rtc_sync_pending(dev); bfin_write_RTC_PREN(0x1); - bfin_write_RTC_ICTL(RTC_ISTAT_WRITE_COMPLETE); + bfin_write_RTC_ICTL(rtc_ictl); bfin_write_RTC_SWCNT(0); bfin_write_RTC_ALARM(0); bfin_write_RTC_ISTAT(0xFFFF); @@ -226,7 +226,7 @@ static int bfin_rtc_open(struct device *dev) ret = request_irq(IRQ_RTC, bfin_rtc_interrupt, IRQF_SHARED, to_platform_device(dev)->name, dev); if (!ret) - bfin_rtc_reset(dev); + bfin_rtc_reset(dev, RTC_ISTAT_WRITE_COMPLETE); return ret; } @@ -234,7 +234,7 @@ static int bfin_rtc_open(struct device *dev) static void bfin_rtc_release(struct device *dev) { dev_dbg_stamp(dev); - bfin_rtc_reset(dev); + bfin_rtc_reset(dev, 0); free_irq(IRQ_RTC, dev); } -- cgit v1.2.3 From 140fab14aef093cedf87f69234474c04fdcec99c Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Tue, 5 Aug 2008 13:01:20 -0700 Subject: blackfin RTC driver: wait for the write complete interrupt complete before sleeping Since we use the write complete interrupt, wait for it to complete before sleeping so we don't wake right back up due to it Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu Cc: David Brownell Cc: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-bfin.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/rtc/rtc-bfin.c') diff --git a/drivers/rtc/rtc-bfin.c b/drivers/rtc/rtc-bfin.c index d53772f59ce5..e6b0470063e8 100644 --- a/drivers/rtc/rtc-bfin.c +++ b/drivers/rtc/rtc-bfin.c @@ -435,9 +435,10 @@ static int __devexit bfin_rtc_remove(struct platform_device *pdev) #ifdef CONFIG_PM static int bfin_rtc_suspend(struct platform_device *pdev, pm_message_t state) { - if (device_may_wakeup(&pdev->dev)) + if (device_may_wakeup(&pdev->dev)) { enable_irq_wake(IRQ_RTC); - else + bfin_rtc_sync_pending(&pdev->dev); + } else bfin_rtc_int_clear(-1); return 0; -- cgit v1.2.3 From e12af37d9ee09c2ac6da26a51c77754dec09fed4 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Tue, 5 Aug 2008 13:01:21 -0700 Subject: blackfin RTC driver: convert PIE handling to irq_set_state() as pointed out by David Brownell Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu Cc: David Brownell Cc: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-bfin.c | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) (limited to 'drivers/rtc/rtc-bfin.c') diff --git a/drivers/rtc/rtc-bfin.c b/drivers/rtc/rtc-bfin.c index e6b0470063e8..ceebce7e0a0f 100644 --- a/drivers/rtc/rtc-bfin.c +++ b/drivers/rtc/rtc-bfin.c @@ -264,16 +264,6 @@ static int bfin_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long ar bfin_rtc_sync_pending(dev); switch (cmd) { - case RTC_PIE_ON: - dev_dbg_stamp(dev); - bfin_rtc_int_set(RTC_ISTAT_STOPWATCH); - bfin_write_RTC_SWCNT(rtc->rtc_dev->irq_freq); - break; - case RTC_PIE_OFF: - dev_dbg_stamp(dev); - bfin_rtc_int_clear(~RTC_ISTAT_STOPWATCH); - break; - case RTC_UIE_ON: dev_dbg_stamp(dev); bfin_rtc_int_set(RTC_ISTAT_SEC); @@ -381,6 +371,23 @@ static int bfin_rtc_proc(struct device *dev, struct seq_file *seq) #undef yesno } +static int bfin_irq_set_state(struct device *dev, int enabled) +{ + struct bfin_rtc *rtc = dev_get_drvdata(dev); + + dev_dbg_stamp(dev); + + bfin_rtc_sync_pending(dev); + + if (enabled) { + bfin_rtc_int_set(RTC_ISTAT_STOPWATCH); + bfin_write_RTC_SWCNT(rtc->rtc_dev->irq_freq); + } else + bfin_rtc_int_clear(~RTC_ISTAT_STOPWATCH); + + return 0; +} + static struct rtc_class_ops bfin_rtc_ops = { .open = bfin_rtc_open, .release = bfin_rtc_release, @@ -390,6 +397,7 @@ static struct rtc_class_ops bfin_rtc_ops = { .read_alarm = bfin_rtc_read_alarm, .set_alarm = bfin_rtc_set_alarm, .proc = bfin_rtc_proc, + .irq_set_state = bfin_irq_set_state, }; static int __devinit bfin_rtc_probe(struct platform_device *pdev) -- cgit v1.2.3 From 26cb8bb21b11245a53f79d9fa766537752f77d88 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Tue, 5 Aug 2008 13:01:21 -0700 Subject: blackfin RTC driver: drop PIE/stopwatch code since the hardware can only do a max of 1HZ and this same functionality is provided by UIE Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu Cc: David Brownell Cc: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-bfin.c | 46 ++++++++++++++-------------------------------- 1 file changed, 14 insertions(+), 32 deletions(-) (limited to 'drivers/rtc/rtc-bfin.c') diff --git a/drivers/rtc/rtc-bfin.c b/drivers/rtc/rtc-bfin.c index ceebce7e0a0f..a1af4c27939b 100644 --- a/drivers/rtc/rtc-bfin.c +++ b/drivers/rtc/rtc-bfin.c @@ -32,6 +32,15 @@ * writes to clear status registers complete immediately. */ +/* It may seem odd that there is no SWCNT code in here (which would be exposed + * via the periodic interrupt event, or PIE). Since the Blackfin RTC peripheral + * runs in units of seconds (N/HZ) but the Linux framework runs in units of HZ + * (2^N HZ), there is no point in keeping code that only provides 1 HZ PIEs. + * The same exact behavior can be accomplished by using the update interrupt + * event (UIE). Maybe down the line the RTC peripheral will suck less in which + * case we can re-introduce PIE support. + */ + #include #include #include @@ -151,7 +160,6 @@ static void bfin_rtc_reset(struct device *dev, u16 rtc_ictl) bfin_rtc_sync_pending(dev); bfin_write_RTC_PREN(0x1); bfin_write_RTC_ICTL(rtc_ictl); - bfin_write_RTC_SWCNT(0); bfin_write_RTC_ALARM(0); bfin_write_RTC_ISTAT(0xFFFF); rtc->rtc_wrote_regs = 0; @@ -194,14 +202,6 @@ static irqreturn_t bfin_rtc_interrupt(int irq, void *dev_id) } } - if (rtc_ictl & RTC_ISTAT_STOPWATCH) { - if (rtc_istat & RTC_ISTAT_STOPWATCH) { - bfin_write_RTC_ISTAT(RTC_ISTAT_STOPWATCH); - events |= RTC_PF | RTC_IRQF; - bfin_write_RTC_SWCNT(rtc->rtc_dev->irq_freq); - } - } - if (rtc_ictl & RTC_ISTAT_SEC) { if (rtc_istat & RTC_ISTAT_SEC) { bfin_write_RTC_ISTAT(RTC_ISTAT_SEC); @@ -361,33 +361,14 @@ static int bfin_rtc_proc(struct device *dev, struct seq_file *seq) seq_printf(seq, "alarm_IRQ\t: %s\n" "wkalarm_IRQ\t: %s\n" - "seconds_IRQ\t: %s\n" - "periodic_IRQ\t: %s\n", + "seconds_IRQ\t: %s\n", yesno(ictl & RTC_ISTAT_ALARM), yesno(ictl & RTC_ISTAT_ALARM_DAY), - yesno(ictl & RTC_ISTAT_SEC), - yesno(ictl & RTC_ISTAT_STOPWATCH)); + yesno(ictl & RTC_ISTAT_SEC)); return 0; #undef yesno } -static int bfin_irq_set_state(struct device *dev, int enabled) -{ - struct bfin_rtc *rtc = dev_get_drvdata(dev); - - dev_dbg_stamp(dev); - - bfin_rtc_sync_pending(dev); - - if (enabled) { - bfin_rtc_int_set(RTC_ISTAT_STOPWATCH); - bfin_write_RTC_SWCNT(rtc->rtc_dev->irq_freq); - } else - bfin_rtc_int_clear(~RTC_ISTAT_STOPWATCH); - - return 0; -} - static struct rtc_class_ops bfin_rtc_ops = { .open = bfin_rtc_open, .release = bfin_rtc_release, @@ -397,7 +378,6 @@ static struct rtc_class_ops bfin_rtc_ops = { .read_alarm = bfin_rtc_read_alarm, .set_alarm = bfin_rtc_set_alarm, .proc = bfin_rtc_proc, - .irq_set_state = bfin_irq_set_state, }; static int __devinit bfin_rtc_probe(struct platform_device *pdev) @@ -416,7 +396,9 @@ static int __devinit bfin_rtc_probe(struct platform_device *pdev) ret = PTR_ERR(rtc->rtc_dev); goto err; } - rtc->rtc_dev->irq_freq = 1; + + /* see comment at top of file about stopwatch/PIE */ + bfin_write_RTC_SWCNT(0); platform_set_drvdata(pdev, rtc); -- cgit v1.2.3