From: Andrew Morton <akpm@linux-foundation.org>
To: Baruch Siach <baruch@tkos.co.il>
Cc: rtc-linux@googlegroups.com, linux-kernel@vger.kernel.org,
Alessandro Zummo <a.zummo@towertech.it>
Subject: Re: [PATCH] rtc: driver for the DryIce block found in i.MX25 chips
Date: Fri, 4 Jun 2010 14:53:04 -0700 [thread overview]
Message-ID: <20100604145304.b2cfca17.akpm@linux-foundation.org> (raw)
In-Reply-To: <0173f18c60cb4d1f8a0d123da6cd3cfca0224788.1275456869.git.baruch@tkos.co.il>
On Wed, 2 Jun 2010 08:37:21 +0300
Baruch Siach <baruch@tkos.co.il> wrote:
> This driver is based on code from Freescale which accompanies their i.MX25 PDK
> board, with some cleanup.
Do we know who at freescale worked on this? Are there any signoffs or
attributions we could be adding?
>
> ...
>
> +static inline void di_int_enable(struct imxdi_dev *imxdi, u32 intr)
> +{
> + unsigned long flags;
> +
> + spin_lock_irqsave(&imxdi->irq_lock, flags);
> + __raw_writel(__raw_readl(imxdi->ioaddr + DIER) | intr,
> + imxdi->ioaddr + DIER);
> + spin_unlock_irqrestore(&imxdi->irq_lock, flags);
> +}
> +
> +/*
> + * disable a dryice interrupt
> + */
> +static inline void di_int_disable(struct imxdi_dev *imxdi, u32 intr)
> +{
> + unsigned long flags;
> +
> + spin_lock_irqsave(&imxdi->irq_lock, flags);
> + __raw_writel(__raw_readl(imxdi->ioaddr + DIER) & ~intr,
> + imxdi->ioaddr + DIER);
> + spin_unlock_irqrestore(&imxdi->irq_lock, flags);
> +}
You may find that you'll end up with a smaller and faster driver if
these are uninlined.
You may well find that gcc went and uninlined them anwyay.
> +/*
> + * This function attempts to clear the dryice write-error flag.
> + *
> + * A dryice write error is similar to a bus fault and should not occur in
> + * normal operation. Clearing the flag requires another write, so the root
> + * cause of the problem may need to be fixed before the flag can be cleared.
> + */
> +static void clear_write_error(struct imxdi_dev *imxdi)
> +{
> + int cnt;
> +
> + dev_warn(&imxdi->pdev->dev, "WARNING: Register write error!\n");
> +
> + for (;;) {
> + /* clear the write error flag */
> + __raw_writel(DSR_WEF, imxdi->ioaddr + DSR);
> +
> + /* wait for it to take effect */
> + for (cnt = 0; cnt < 100; cnt++) {
> + if ((__raw_readl(imxdi->ioaddr + DSR) & DSR_WEF) == 0)
> + return;
> + udelay(10);
> + }
> + dev_err(&imxdi->pdev->dev,
> + "ERROR: Cannot clear write-error flag!\n");
> + }
> +}
The potential infinite loop is a worry.
> +/*
> + * Write a dryice register and wait until it completes.
> + *
> + * This function uses interrupts to determine when the
> + * write has completed.
> + */
> +static int di_write_wait(struct imxdi_dev *imxdi, u32 val, int reg)
> +{
> + int ret;
> + int rc = 0;
> +
> + /* serialize register writes */
> + mutex_lock(&imxdi->write_mutex);
> +
> + /* enable the write-complete interrupt */
> + di_int_enable(imxdi, DIER_WCIE);
> +
> + imxdi->dsr = 0;
> +
> + /* do the register write */
> + __raw_writel(val, imxdi->ioaddr + reg);
> +
> + /* wait for the write to finish */
> + ret = wait_event_interruptible_timeout(imxdi->write_wait,
> + imxdi->dsr & (DSR_WCF | DSR_WEF), msecs_to_jiffies(1));
This wait will terminate immediately if the calling task has
signal_pending().
> + if (ret == 0)
> + dev_warn(&imxdi->pdev->dev,
> + "Write-wait timeout "
> + "val = 0x%08x reg = 0x%08x\n", val, reg);
But the code incorrectly assumes that the hardware signalled readiness.
> + /* check for write error */
> + if (imxdi->dsr & DSR_WEF) {
> + clear_write_error(imxdi);
> + rc = -EIO;
> + }
> + mutex_unlock(&imxdi->write_mutex);
> + return rc;
> +}
> +
>
> ...
>
> +static int __devexit dryice_rtc_remove(struct platform_device *pdev)
> +{
> + struct imxdi_dev *imxdi = platform_get_drvdata(pdev);
> +
> + flush_scheduled_work();
We only need to wait for imxdi->work to complete, so a simple
flush_work() would suffice here.
> + /* mask all interrupts */
> + __raw_writel(0, imxdi->ioaddr + DIER);
> +
> + rtc_device_unregister(imxdi->rtc);
> +
> + clk_disable(imxdi->clk);
> + clk_put(imxdi->clk);
> +
> + return 0;
> +}
>
> ...
>
next prev parent reply other threads:[~2010-06-04 21:53 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-06-02 5:37 [PATCH] rtc: driver for the DryIce block found in i.MX25 chips Baruch Siach
2010-06-04 21:53 ` Andrew Morton [this message]
2010-06-07 4:56 ` Baruch Siach
2010-06-05 15:08 ` [rtc-linux] " Wan ZongShun
2010-06-06 15:37 ` Wan ZongShun
2010-06-07 4:53 ` Baruch Siach
2010-06-07 5:20 ` Baruch Siach
2010-06-07 6:20 ` Wan ZongShun
-- strict thread matches above, loose matches on Subject: below --
2010-01-29 10:10 [rtc-linux] [PATCH 1/3] " Alessandro Zummo
2010-02-01 7:36 ` [PATCH] " Baruch Siach
2010-02-01 8:08 ` Lothar Waßmann
2010-02-01 8:28 ` Baruch Siach
2010-02-01 9:20 ` Alessandro Zummo
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20100604145304.b2cfca17.akpm@linux-foundation.org \
--to=akpm@linux-foundation.org \
--cc=a.zummo@towertech.it \
--cc=baruch@tkos.co.il \
--cc=linux-kernel@vger.kernel.org \
--cc=rtc-linux@googlegroups.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.