Merge branch 'sh/for-2.6.30' of git://git.kernel.org/pub/scm/linux/kernel/git/lethal/sh-2.6

* 'sh/for-2.6.30' of git://git.kernel.org/pub/scm/linux/kernel/git/lethal/sh-2.6:
  sh: Fix mmap2 for handling differing PAGE_SIZEs.
  sh: sh7723: Don't default enable the RTC clock.
  sh: sh7722: Don't default enable the RTC clock.
  rtc: rtc-sh: clock framework support.
This commit is contained in:
Linus Torvalds 2009-04-21 08:16:14 -07:00
commit 81ca980369
5 changed files with 59 additions and 21 deletions

View File

@ -256,7 +256,6 @@ static int __init sh7722_devices_setup(void)
{ {
clk_always_enable("uram0"); /* URAM */ clk_always_enable("uram0"); /* URAM */
clk_always_enable("xymem0"); /* XYMEM */ clk_always_enable("xymem0"); /* XYMEM */
clk_always_enable("rtc0"); /* RTC */
clk_always_enable("veu0"); /* VEU */ clk_always_enable("veu0"); /* VEU */
clk_always_enable("vpu0"); /* VPU */ clk_always_enable("vpu0"); /* VPU */
clk_always_enable("jpu0"); /* JPU */ clk_always_enable("jpu0"); /* JPU */

View File

@ -267,7 +267,6 @@ static struct platform_device *sh7723_devices[] __initdata = {
static int __init sh7723_devices_setup(void) static int __init sh7723_devices_setup(void)
{ {
clk_always_enable("meram0"); /* MERAM */ clk_always_enable("meram0"); /* MERAM */
clk_always_enable("rtc0"); /* RTC */
clk_always_enable("veu1"); /* VEU2H1 */ clk_always_enable("veu1"); /* VEU2H1 */
clk_always_enable("veu0"); /* VEU2H0 */ clk_always_enable("veu0"); /* VEU2H0 */
clk_always_enable("vpu0"); /* VPU */ clk_always_enable("vpu0"); /* VPU */

View File

@ -63,6 +63,15 @@ asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
unsigned long prot, unsigned long flags, unsigned long prot, unsigned long flags,
unsigned long fd, unsigned long pgoff) unsigned long fd, unsigned long pgoff)
{ {
/*
* The shift for mmap2 is constant, regardless of PAGE_SIZE
* setting.
*/
if (pgoff & ((1 << (PAGE_SHIFT - 12)) - 1))
return -EINVAL;
pgoff >>= PAGE_SHIFT - 12;
return do_mmap2(addr, len, prot, flags, fd, pgoff); return do_mmap2(addr, len, prot, flags, fd, pgoff);
} }

View File

@ -573,7 +573,7 @@ config RTC_DRV_SA1100
config RTC_DRV_SH config RTC_DRV_SH
tristate "SuperH On-Chip RTC" tristate "SuperH On-Chip RTC"
depends on RTC_CLASS && SUPERH depends on RTC_CLASS && SUPERH && HAVE_CLK
help help
Say Y here to enable support for the on-chip RTC found in Say Y here to enable support for the on-chip RTC found in
most SuperH processors. most SuperH processors.

View File

@ -1,7 +1,7 @@
/* /*
* SuperH On-Chip RTC Support * SuperH On-Chip RTC Support
* *
* Copyright (C) 2006, 2007, 2008 Paul Mundt * Copyright (C) 2006 - 2009 Paul Mundt
* Copyright (C) 2006 Jamie Lenehan * Copyright (C) 2006 Jamie Lenehan
* Copyright (C) 2008 Angelo Castello * Copyright (C) 2008 Angelo Castello
* *
@ -25,10 +25,11 @@
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/log2.h> #include <linux/log2.h>
#include <linux/clk.h>
#include <asm/rtc.h> #include <asm/rtc.h>
#define DRV_NAME "sh-rtc" #define DRV_NAME "sh-rtc"
#define DRV_VERSION "0.2.1" #define DRV_VERSION "0.2.2"
#define RTC_REG(r) ((r) * rtc_reg_size) #define RTC_REG(r) ((r) * rtc_reg_size)
@ -87,16 +88,17 @@
#define RCR2_START 0x01 /* Start bit */ #define RCR2_START 0x01 /* Start bit */
struct sh_rtc { struct sh_rtc {
void __iomem *regbase; void __iomem *regbase;
unsigned long regsize; unsigned long regsize;
struct resource *res; struct resource *res;
int alarm_irq; int alarm_irq;
int periodic_irq; int periodic_irq;
int carry_irq; int carry_irq;
struct rtc_device *rtc_dev; struct clk *clk;
spinlock_t lock; struct rtc_device *rtc_dev;
unsigned long capabilities; /* See asm-sh/rtc.h for cap bits */ spinlock_t lock;
unsigned short periodic_freq; unsigned long capabilities; /* See asm/rtc.h for cap bits */
unsigned short periodic_freq;
}; };
static int __sh_rtc_interrupt(struct sh_rtc *rtc) static int __sh_rtc_interrupt(struct sh_rtc *rtc)
@ -294,10 +296,10 @@ static inline void sh_rtc_setaie(struct device *dev, unsigned int enable)
tmp = readb(rtc->regbase + RCR1); tmp = readb(rtc->regbase + RCR1);
if (!enable) if (enable)
tmp &= ~RCR1_AIE;
else
tmp |= RCR1_AIE; tmp |= RCR1_AIE;
else
tmp &= ~RCR1_AIE;
writeb(tmp, rtc->regbase + RCR1); writeb(tmp, rtc->regbase + RCR1);
@ -618,6 +620,7 @@ static int sh_rtc_irq_set_freq(struct device *dev, int freq)
{ {
if (!is_power_of_2(freq)) if (!is_power_of_2(freq))
return -EINVAL; return -EINVAL;
return sh_rtc_ioctl(dev, RTC_IRQP_SET, freq); return sh_rtc_ioctl(dev, RTC_IRQP_SET, freq);
} }
@ -637,7 +640,8 @@ static int __devinit sh_rtc_probe(struct platform_device *pdev)
struct sh_rtc *rtc; struct sh_rtc *rtc;
struct resource *res; struct resource *res;
struct rtc_time r; struct rtc_time r;
int ret; char clk_name[6];
int clk_id, ret;
rtc = kzalloc(sizeof(struct sh_rtc), GFP_KERNEL); rtc = kzalloc(sizeof(struct sh_rtc), GFP_KERNEL);
if (unlikely(!rtc)) if (unlikely(!rtc))
@ -652,6 +656,7 @@ static int __devinit sh_rtc_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "No IRQ resource\n"); dev_err(&pdev->dev, "No IRQ resource\n");
goto err_badres; goto err_badres;
} }
rtc->periodic_irq = ret; rtc->periodic_irq = ret;
rtc->carry_irq = platform_get_irq(pdev, 1); rtc->carry_irq = platform_get_irq(pdev, 1);
rtc->alarm_irq = platform_get_irq(pdev, 2); rtc->alarm_irq = platform_get_irq(pdev, 2);
@ -663,7 +668,7 @@ static int __devinit sh_rtc_probe(struct platform_device *pdev)
goto err_badres; goto err_badres;
} }
rtc->regsize = res->end - res->start + 1; rtc->regsize = resource_size(res);
rtc->res = request_mem_region(res->start, rtc->regsize, pdev->name); rtc->res = request_mem_region(res->start, rtc->regsize, pdev->name);
if (unlikely(!rtc->res)) { if (unlikely(!rtc->res)) {
@ -677,6 +682,26 @@ static int __devinit sh_rtc_probe(struct platform_device *pdev)
goto err_badmap; goto err_badmap;
} }
clk_id = pdev->id;
/* With a single device, the clock id is still "rtc0" */
if (clk_id < 0)
clk_id = 0;
snprintf(clk_name, sizeof(clk_name), "rtc%d", clk_id);
rtc->clk = clk_get(&pdev->dev, clk_name);
if (IS_ERR(rtc->clk)) {
/*
* No error handling for rtc->clk intentionally, not all
* platforms will have a unique clock for the RTC, and
* the clk API can handle the struct clk pointer being
* NULL.
*/
rtc->clk = NULL;
}
clk_enable(rtc->clk);
rtc->rtc_dev = rtc_device_register("sh", &pdev->dev, rtc->rtc_dev = rtc_device_register("sh", &pdev->dev,
&sh_rtc_ops, THIS_MODULE); &sh_rtc_ops, THIS_MODULE);
if (IS_ERR(rtc->rtc_dev)) { if (IS_ERR(rtc->rtc_dev)) {
@ -759,6 +784,8 @@ static int __devinit sh_rtc_probe(struct platform_device *pdev)
return 0; return 0;
err_unmap: err_unmap:
clk_disable(rtc->clk);
clk_put(rtc->clk);
iounmap(rtc->regbase); iounmap(rtc->regbase);
err_badmap: err_badmap:
release_resource(rtc->res); release_resource(rtc->res);
@ -780,6 +807,7 @@ static int __devexit sh_rtc_remove(struct platform_device *pdev)
sh_rtc_setcie(&pdev->dev, 0); sh_rtc_setcie(&pdev->dev, 0);
free_irq(rtc->periodic_irq, rtc); free_irq(rtc->periodic_irq, rtc);
if (rtc->carry_irq > 0) { if (rtc->carry_irq > 0) {
free_irq(rtc->carry_irq, rtc); free_irq(rtc->carry_irq, rtc);
free_irq(rtc->alarm_irq, rtc); free_irq(rtc->alarm_irq, rtc);
@ -789,6 +817,9 @@ static int __devexit sh_rtc_remove(struct platform_device *pdev)
iounmap(rtc->regbase); iounmap(rtc->regbase);
clk_disable(rtc->clk);
clk_put(rtc->clk);
platform_set_drvdata(pdev, NULL); platform_set_drvdata(pdev, NULL);
kfree(rtc); kfree(rtc);
@ -802,11 +833,11 @@ static void sh_rtc_set_irq_wake(struct device *dev, int enabled)
struct sh_rtc *rtc = platform_get_drvdata(pdev); struct sh_rtc *rtc = platform_get_drvdata(pdev);
set_irq_wake(rtc->periodic_irq, enabled); set_irq_wake(rtc->periodic_irq, enabled);
if (rtc->carry_irq > 0) { if (rtc->carry_irq > 0) {
set_irq_wake(rtc->carry_irq, enabled); set_irq_wake(rtc->carry_irq, enabled);
set_irq_wake(rtc->alarm_irq, enabled); set_irq_wake(rtc->alarm_irq, enabled);
} }
} }
static int sh_rtc_suspend(struct device *dev) static int sh_rtc_suspend(struct device *dev)