Merge branch 'devel' of master.kernel.org:/home/rmk/linux-2.6-arm
* 'devel' of master.kernel.org:/home/rmk/linux-2.6-arm: (416 commits) ARM: DMA: add support for DMA debugging ARM: PL011: add DMA burst threshold support for ST variants ARM: PL011: Add support for transmit DMA ARM: PL011: Ensure IRQs are disabled in UART interrupt handler ARM: PL011: Separate hardware FIFO size from TTY FIFO size ARM: PL011: Allow better handling of vendor data ARM: PL011: Ensure error flags are clear at startup ARM: PL011: include revision number in boot-time port printk ARM: vexpress: add sched_clock() for Versatile Express ARM i.MX53: Make MX53 EVK bootable ARM i.MX53: Some bug fix about MX53 MSL code ARM: 6607/1: sa1100: Update platform device registration ARM: 6606/1: sa1100: Fix platform device registration ARM i.MX51: rename IPU irqs ARM i.MX51: Add ipu clock support ARM: imx/mx27_3ds: Add PMIC support ARM: DMA: Replace page_to_dma()/dma_to_page() with pfn_to_dma()/dma_to_pfn() mx51: fix usb clock support MX51: Add support for usb host 2 arch/arm/plat-mxc/ehci.c: fix errors/typos ...
This commit is contained in:
@@ -39,10 +39,10 @@
|
||||
#include <mach/regs-ost.h>
|
||||
#endif
|
||||
|
||||
#define RTC_DEF_DIVIDER 32768 - 1
|
||||
#define RTC_DEF_DIVIDER (32768 - 1)
|
||||
#define RTC_DEF_TRIM 0
|
||||
|
||||
static unsigned long rtc_freq = 1024;
|
||||
static const unsigned long RTC_FREQ = 1024;
|
||||
static unsigned long timer_freq;
|
||||
static struct rtc_time rtc_alarm;
|
||||
static DEFINE_SPINLOCK(sa1100_rtc_lock);
|
||||
@@ -61,7 +61,8 @@ static inline int rtc_periodic_alarm(struct rtc_time *tm)
|
||||
* Calculate the next alarm time given the requested alarm time mask
|
||||
* and the current time.
|
||||
*/
|
||||
static void rtc_next_alarm_time(struct rtc_time *next, struct rtc_time *now, struct rtc_time *alrm)
|
||||
static void rtc_next_alarm_time(struct rtc_time *next, struct rtc_time *now,
|
||||
struct rtc_time *alrm)
|
||||
{
|
||||
unsigned long next_time;
|
||||
unsigned long now_time;
|
||||
@@ -116,7 +117,23 @@ static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id)
|
||||
rtsr = RTSR;
|
||||
/* clear interrupt sources */
|
||||
RTSR = 0;
|
||||
RTSR = (RTSR_AL | RTSR_HZ) & (rtsr >> 2);
|
||||
/* Fix for a nasty initialization problem the in SA11xx RTSR register.
|
||||
* See also the comments in sa1100_rtc_probe(). */
|
||||
if (rtsr & (RTSR_ALE | RTSR_HZE)) {
|
||||
/* This is the original code, before there was the if test
|
||||
* above. This code does not clear interrupts that were not
|
||||
* enabled. */
|
||||
RTSR = (RTSR_AL | RTSR_HZ) & (rtsr >> 2);
|
||||
} else {
|
||||
/* For some reason, it is possible to enter this routine
|
||||
* without interruptions enabled, it has been tested with
|
||||
* several units (Bug in SA11xx chip?).
|
||||
*
|
||||
* This situation leads to an infinite "loop" of interrupt
|
||||
* routine calling and as a result the processor seems to
|
||||
* lock on its first call to open(). */
|
||||
RTSR = RTSR_AL | RTSR_HZ;
|
||||
}
|
||||
|
||||
/* clear alarm interrupt if it has occurred */
|
||||
if (rtsr & RTSR_AL)
|
||||
@@ -139,8 +156,58 @@ static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int sa1100_irq_set_freq(struct device *dev, int freq)
|
||||
{
|
||||
if (freq < 1 || freq > timer_freq) {
|
||||
return -EINVAL;
|
||||
} else {
|
||||
struct rtc_device *rtc = (struct rtc_device *)dev;
|
||||
|
||||
rtc->irq_freq = freq;
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int rtc_timer1_count;
|
||||
|
||||
static int sa1100_irq_set_state(struct device *dev, int enabled)
|
||||
{
|
||||
spin_lock_irq(&sa1100_rtc_lock);
|
||||
if (enabled) {
|
||||
struct rtc_device *rtc = (struct rtc_device *)dev;
|
||||
|
||||
OSMR1 = timer_freq / rtc->irq_freq + OSCR;
|
||||
OIER |= OIER_E1;
|
||||
rtc_timer1_count = 1;
|
||||
} else {
|
||||
OIER &= ~OIER_E1;
|
||||
}
|
||||
spin_unlock_irq(&sa1100_rtc_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int sa1100_timer1_retrigger(struct rtc_device *rtc)
|
||||
{
|
||||
unsigned long diff;
|
||||
unsigned long period = timer_freq / rtc->irq_freq;
|
||||
|
||||
spin_lock_irq(&sa1100_rtc_lock);
|
||||
|
||||
do {
|
||||
OSMR1 += period;
|
||||
diff = OSMR1 - OSCR;
|
||||
/* If OSCR > OSMR1, diff is a very large number (unsigned
|
||||
* math). This means we have a lost interrupt. */
|
||||
} while (diff > period);
|
||||
OIER |= OIER_E1;
|
||||
|
||||
spin_unlock_irq(&sa1100_rtc_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static irqreturn_t timer1_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev_id);
|
||||
@@ -158,7 +225,11 @@ static irqreturn_t timer1_interrupt(int irq, void *dev_id)
|
||||
rtc_update_irq(rtc, rtc_timer1_count, RTC_PF | RTC_IRQF);
|
||||
|
||||
if (rtc_timer1_count == 1)
|
||||
rtc_timer1_count = (rtc_freq * ((1 << 30) / (timer_freq >> 2)));
|
||||
rtc_timer1_count =
|
||||
(rtc->irq_freq * ((1 << 30) / (timer_freq >> 2)));
|
||||
|
||||
/* retrigger. */
|
||||
sa1100_timer1_retrigger(rtc);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
@@ -166,8 +237,10 @@ static irqreturn_t timer1_interrupt(int irq, void *dev_id)
|
||||
static int sa1100_rtc_read_callback(struct device *dev, int data)
|
||||
{
|
||||
if (data & RTC_PF) {
|
||||
struct rtc_device *rtc = (struct rtc_device *)dev;
|
||||
|
||||
/* interpolate missed periods and set match for the next */
|
||||
unsigned long period = timer_freq / rtc_freq;
|
||||
unsigned long period = timer_freq / rtc->irq_freq;
|
||||
unsigned long oscr = OSCR;
|
||||
unsigned long osmr1 = OSMR1;
|
||||
unsigned long missed = (oscr - osmr1)/period;
|
||||
@@ -178,7 +251,7 @@ static int sa1100_rtc_read_callback(struct device *dev, int data)
|
||||
* Here we compare (match - OSCR) 8 instead of 0 --
|
||||
* see comment in pxa_timer_interrupt() for explanation.
|
||||
*/
|
||||
while( (signed long)((osmr1 = OSMR1) - OSCR) <= 8 ) {
|
||||
while ((signed long)((osmr1 = OSMR1) - OSCR) <= 8) {
|
||||
data += 0x100;
|
||||
OSSR = OSSR_M1; /* clear match on timer 1 */
|
||||
OSMR1 = osmr1 + period;
|
||||
@@ -190,25 +263,29 @@ static int sa1100_rtc_read_callback(struct device *dev, int data)
|
||||
static int sa1100_rtc_open(struct device *dev)
|
||||
{
|
||||
int ret;
|
||||
struct rtc_device *rtc = (struct rtc_device *)dev;
|
||||
|
||||
ret = request_irq(IRQ_RTC1Hz, sa1100_rtc_interrupt, IRQF_DISABLED,
|
||||
"rtc 1Hz", dev);
|
||||
"rtc 1Hz", dev);
|
||||
if (ret) {
|
||||
dev_err(dev, "IRQ %d already in use.\n", IRQ_RTC1Hz);
|
||||
goto fail_ui;
|
||||
}
|
||||
ret = request_irq(IRQ_RTCAlrm, sa1100_rtc_interrupt, IRQF_DISABLED,
|
||||
"rtc Alrm", dev);
|
||||
"rtc Alrm", dev);
|
||||
if (ret) {
|
||||
dev_err(dev, "IRQ %d already in use.\n", IRQ_RTCAlrm);
|
||||
goto fail_ai;
|
||||
}
|
||||
ret = request_irq(IRQ_OST1, timer1_interrupt, IRQF_DISABLED,
|
||||
"rtc timer", dev);
|
||||
"rtc timer", dev);
|
||||
if (ret) {
|
||||
dev_err(dev, "IRQ %d already in use.\n", IRQ_OST1);
|
||||
goto fail_pi;
|
||||
}
|
||||
rtc->max_user_freq = RTC_FREQ;
|
||||
sa1100_irq_set_freq(dev, RTC_FREQ);
|
||||
|
||||
return 0;
|
||||
|
||||
fail_pi:
|
||||
@@ -236,7 +313,7 @@ static void sa1100_rtc_release(struct device *dev)
|
||||
static int sa1100_rtc_ioctl(struct device *dev, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
{
|
||||
switch(cmd) {
|
||||
switch (cmd) {
|
||||
case RTC_AIE_OFF:
|
||||
spin_lock_irq(&sa1100_rtc_lock);
|
||||
RTSR &= ~RTSR_ALE;
|
||||
@@ -257,25 +334,6 @@ static int sa1100_rtc_ioctl(struct device *dev, unsigned int cmd,
|
||||
RTSR |= RTSR_HZE;
|
||||
spin_unlock_irq(&sa1100_rtc_lock);
|
||||
return 0;
|
||||
case RTC_PIE_OFF:
|
||||
spin_lock_irq(&sa1100_rtc_lock);
|
||||
OIER &= ~OIER_E1;
|
||||
spin_unlock_irq(&sa1100_rtc_lock);
|
||||
return 0;
|
||||
case RTC_PIE_ON:
|
||||
spin_lock_irq(&sa1100_rtc_lock);
|
||||
OSMR1 = timer_freq / rtc_freq + OSCR;
|
||||
OIER |= OIER_E1;
|
||||
rtc_timer1_count = 1;
|
||||
spin_unlock_irq(&sa1100_rtc_lock);
|
||||
return 0;
|
||||
case RTC_IRQP_READ:
|
||||
return put_user(rtc_freq, (unsigned long *)arg);
|
||||
case RTC_IRQP_SET:
|
||||
if (arg < 1 || arg > timer_freq)
|
||||
return -EINVAL;
|
||||
rtc_freq = arg;
|
||||
return 0;
|
||||
}
|
||||
return -ENOIOCTLCMD;
|
||||
}
|
||||
@@ -327,12 +385,15 @@ static int sa1100_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
|
||||
|
||||
static int sa1100_rtc_proc(struct device *dev, struct seq_file *seq)
|
||||
{
|
||||
struct rtc_device *rtc = (struct rtc_device *)dev;
|
||||
|
||||
seq_printf(seq, "trim/divider\t: 0x%08x\n", (u32) RTTR);
|
||||
seq_printf(seq, "update_IRQ\t: %s\n",
|
||||
(RTSR & RTSR_HZE) ? "yes" : "no");
|
||||
seq_printf(seq, "periodic_IRQ\t: %s\n",
|
||||
(OIER & OIER_E1) ? "yes" : "no");
|
||||
seq_printf(seq, "periodic_freq\t: %ld\n", rtc_freq);
|
||||
seq_printf(seq, "periodic_freq\t: %d\n", rtc->irq_freq);
|
||||
seq_printf(seq, "RTSR\t\t: 0x%08x\n", (u32)RTSR);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -347,6 +408,8 @@ static const struct rtc_class_ops sa1100_rtc_ops = {
|
||||
.read_alarm = sa1100_rtc_read_alarm,
|
||||
.set_alarm = sa1100_rtc_set_alarm,
|
||||
.proc = sa1100_rtc_proc,
|
||||
.irq_set_freq = sa1100_irq_set_freq,
|
||||
.irq_set_state = sa1100_irq_set_state,
|
||||
};
|
||||
|
||||
static int sa1100_rtc_probe(struct platform_device *pdev)
|
||||
@@ -364,7 +427,8 @@ static int sa1100_rtc_probe(struct platform_device *pdev)
|
||||
*/
|
||||
if (RTTR == 0) {
|
||||
RTTR = RTC_DEF_DIVIDER + (RTC_DEF_TRIM << 16);
|
||||
dev_warn(&pdev->dev, "warning: initializing default clock divider/trim value\n");
|
||||
dev_warn(&pdev->dev, "warning: "
|
||||
"initializing default clock divider/trim value\n");
|
||||
/* The current RTC value probably doesn't make sense either */
|
||||
RCNR = 0;
|
||||
}
|
||||
@@ -372,13 +436,42 @@ static int sa1100_rtc_probe(struct platform_device *pdev)
|
||||
device_init_wakeup(&pdev->dev, 1);
|
||||
|
||||
rtc = rtc_device_register(pdev->name, &pdev->dev, &sa1100_rtc_ops,
|
||||
THIS_MODULE);
|
||||
THIS_MODULE);
|
||||
|
||||
if (IS_ERR(rtc))
|
||||
return PTR_ERR(rtc);
|
||||
|
||||
platform_set_drvdata(pdev, rtc);
|
||||
|
||||
/* Set the irq_freq */
|
||||
/*TODO: Find out who is messing with this value after we initialize
|
||||
* it here.*/
|
||||
rtc->irq_freq = RTC_FREQ;
|
||||
|
||||
/* Fix for a nasty initialization problem the in SA11xx RTSR register.
|
||||
* See also the comments in sa1100_rtc_interrupt().
|
||||
*
|
||||
* Sometimes bit 1 of the RTSR (RTSR_HZ) will wake up 1, which means an
|
||||
* interrupt pending, even though interrupts were never enabled.
|
||||
* In this case, this bit it must be reset before enabling
|
||||
* interruptions to avoid a nonexistent interrupt to occur.
|
||||
*
|
||||
* In principle, the same problem would apply to bit 0, although it has
|
||||
* never been observed to happen.
|
||||
*
|
||||
* This issue is addressed both here and in sa1100_rtc_interrupt().
|
||||
* If the issue is not addressed here, in the times when the processor
|
||||
* wakes up with the bit set there will be one spurious interrupt.
|
||||
*
|
||||
* The issue is also dealt with in sa1100_rtc_interrupt() to be on the
|
||||
* safe side, once the condition that lead to this strange
|
||||
* initialization is unknown and could in principle happen during
|
||||
* normal processing.
|
||||
*
|
||||
* Notice that clearing bit 1 and 0 is accomplished by writting ONES to
|
||||
* the corresponding bits in RTSR. */
|
||||
RTSR = RTSR_AL | RTSR_HZ;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -386,7 +479,7 @@ static int sa1100_rtc_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct rtc_device *rtc = platform_get_drvdata(pdev);
|
||||
|
||||
if (rtc)
|
||||
if (rtc)
|
||||
rtc_device_unregister(rtc);
|
||||
|
||||
return 0;
|
||||
|
Reference in New Issue
Block a user