Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 063adc75 authored by Paul Mundt's avatar Paul Mundt
Browse files

rtc: rtc-sh: clock framework support.



This adds clock framework support to the rtc-sh driver. With this in
place, platforms can default to leaving the clock disabled rather than
placing it in the always enabled state.

Signed-off-by: default avatarPaul Mundt <lethal@linux-sh.org>
parent 3ee8da87
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -573,7 +573,7 @@ config RTC_DRV_SA1100

config RTC_DRV_SH
	tristate "SuperH On-Chip RTC"
	depends on RTC_CLASS && SUPERH
	depends on RTC_CLASS && SUPERH && HAVE_CLK
	help
	  Say Y here to enable support for the on-chip RTC found in
	  most SuperH processors.
+49 −18
Original line number Diff line number Diff line
/*
 * 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) 2008  Angelo Castello
 *
@@ -25,10 +25,11 @@
#include <linux/spinlock.h>
#include <linux/io.h>
#include <linux/log2.h>
#include <linux/clk.h>
#include <asm/rtc.h>

#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)

@@ -93,9 +94,10 @@ struct sh_rtc {
	int			alarm_irq;
	int			periodic_irq;
	int			carry_irq;
	struct clk		*clk;
	struct rtc_device	*rtc_dev;
	spinlock_t		lock;
	unsigned long capabilities;	/* See asm-sh/rtc.h for cap bits */
	unsigned long		capabilities;	/* See asm/rtc.h for cap bits */
	unsigned short		periodic_freq;
};

@@ -294,10 +296,10 @@ static inline void sh_rtc_setaie(struct device *dev, unsigned int enable)

	tmp = readb(rtc->regbase + RCR1);

	if (!enable)
		tmp &= ~RCR1_AIE;
	else
	if (enable)
		tmp |= RCR1_AIE;
	else
		tmp &= ~RCR1_AIE;

	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))
		return -EINVAL;

	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 resource *res;
	struct rtc_time r;
	int ret;
	char clk_name[6];
	int clk_id, ret;

	rtc = kzalloc(sizeof(struct sh_rtc), GFP_KERNEL);
	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");
		goto err_badres;
	}

	rtc->periodic_irq = ret;
	rtc->carry_irq = platform_get_irq(pdev, 1);
	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;
	}

	rtc->regsize = res->end - res->start + 1;
	rtc->regsize = resource_size(res);

	rtc->res = request_mem_region(res->start, rtc->regsize, pdev->name);
	if (unlikely(!rtc->res)) {
@@ -677,6 +682,26 @@ static int __devinit sh_rtc_probe(struct platform_device *pdev)
		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,
					   &sh_rtc_ops, THIS_MODULE);
	if (IS_ERR(rtc->rtc_dev)) {
@@ -759,6 +784,8 @@ static int __devinit sh_rtc_probe(struct platform_device *pdev)
	return 0;

err_unmap:
	clk_disable(rtc->clk);
	clk_put(rtc->clk);
	iounmap(rtc->regbase);
err_badmap:
	release_resource(rtc->res);
@@ -780,6 +807,7 @@ static int __devexit sh_rtc_remove(struct platform_device *pdev)
	sh_rtc_setcie(&pdev->dev, 0);

	free_irq(rtc->periodic_irq, rtc);

	if (rtc->carry_irq > 0) {
		free_irq(rtc->carry_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);

	clk_disable(rtc->clk);
	clk_put(rtc->clk);

	platform_set_drvdata(pdev, NULL);

	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);

	set_irq_wake(rtc->periodic_irq, enabled);

	if (rtc->carry_irq > 0) {
		set_irq_wake(rtc->carry_irq, enabled);
		set_irq_wake(rtc->alarm_irq, enabled);
	}

}

static int sh_rtc_suspend(struct device *dev)