All of lore.kernel.org
 help / color / mirror / Atom feed
From: Geert Uytterhoeven <geert@linux-m68k.org>
To: Alessandro Zummo <a.zummo@towertech.it>
Cc: "Linux/m68k" <linux-m68k@vger.kernel.org>,
	rtc-linux@googlegroups.com,
	Linux Kernel Development <linux-kernel@vger.kernel.org>
Subject: Re: [PATCH] rtc: rp5c01 - Add NVRAM support
Date: Sun, 18 Jul 2010 20:32:06 +0200	[thread overview]
Message-ID: <AANLkTilzH61NsPF5maM77chbuQA8ptUiV5iaXtOShYOB@mail.gmail.com> (raw)
In-Reply-To: <alpine.DEB.2.00.1006131208470.18415@ayla.of.borg>

On Sun, Jun 13, 2010 at 12:12, Geert Uytterhoeven <geert@linux-m68k.org> wrote:
> The Ricoh RP5C01 RTC contains 26 x 4 bits of NVRAM.
> Provide access to it via a sysfs "nvram" attribute file.
>
> Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>

Alessandro: Ping?

> --
> Question: Is a spinlock in priv the right kind of locking?
>          Should I use e.g. rtc-device.ops_lock instead?
>
> diff --git a/drivers/rtc/rtc-rp5c01.c b/drivers/rtc/rtc-rp5c01.c
> index a95f733..36eb661 100644
> --- a/drivers/rtc/rtc-rp5c01.c
> +++ b/drivers/rtc/rtc-rp5c01.c
> @@ -63,6 +63,8 @@ enum {
>  struct rp5c01_priv {
>        u32 __iomem *regs;
>        struct rtc_device *rtc;
> +       spinlock_t lock;        /* against concurrent RTC/NVRAM access */
> +       struct bin_attribute nvram_attr;
>  };
>
>  static inline unsigned int rp5c01_read(struct rp5c01_priv *priv,
> @@ -92,6 +94,7 @@ static int rp5c01_read_time(struct device *dev, struct rtc_time *tm)
>  {
>        struct rp5c01_priv *priv = dev_get_drvdata(dev);
>
> +       spin_lock_irq(&priv->lock);
>        rp5c01_lock(priv);
>
>        tm->tm_sec  = rp5c01_read(priv, RP5C01_10_SECOND) * 10 +
> @@ -111,6 +114,7 @@ static int rp5c01_read_time(struct device *dev, struct rtc_time *tm)
>                tm->tm_year += 100;
>
>        rp5c01_unlock(priv);
> +       spin_unlock_irq(&priv->lock);
>
>        return rtc_valid_tm(tm);
>  }
> @@ -119,6 +123,7 @@ static int rp5c01_set_time(struct device *dev, struct rtc_time *tm)
>  {
>        struct rp5c01_priv *priv = dev_get_drvdata(dev);
>
> +       spin_lock_irq(&priv->lock);
>        rp5c01_lock(priv);
>
>        rp5c01_write(priv, tm->tm_sec / 10, RP5C01_10_SECOND);
> @@ -139,6 +144,7 @@ static int rp5c01_set_time(struct device *dev, struct rtc_time *tm)
>        rp5c01_write(priv, tm->tm_year % 10, RP5C01_1_YEAR);
>
>        rp5c01_unlock(priv);
> +       spin_unlock_irq(&priv->lock);
>        return 0;
>  }
>
> @@ -147,6 +153,72 @@ static const struct rtc_class_ops rp5c01_rtc_ops = {
>        .set_time       = rp5c01_set_time,
>  };
>
> +
> +/*
> + * The NVRAM is organized as 2 blocks of 13 nibbles of 4 bits.
> + * We provide access to them like AmigaOS does: the high nibble of each 8-bit
> + * byte is stored in BLOCK10, the low nibble in BLOCK11.
> + */
> +
> +static ssize_t rp5c01_nvram_read(struct file *filp, struct kobject *kobj,
> +                                struct bin_attribute *bin_attr,
> +                                char *buf, loff_t pos, size_t size)
> +{
> +       struct device *dev = container_of(kobj, struct device, kobj);
> +       struct rp5c01_priv *priv = dev_get_drvdata(dev);
> +       ssize_t count;
> +
> +       spin_lock_irq(&priv->lock);
> +
> +       for (count = 0; size > 0 && pos < RP5C01_MODE; count++, size--) {
> +               u8 data;
> +
> +               rp5c01_write(priv,
> +                            RP5C01_MODE_TIMER_EN | RP5C01_MODE_RAM_BLOCK10,
> +                            RP5C01_MODE);
> +               data = rp5c01_read(priv, pos) << 4;
> +               rp5c01_write(priv,
> +                            RP5C01_MODE_TIMER_EN | RP5C01_MODE_RAM_BLOCK11,
> +                            RP5C01_MODE);
> +               data |= rp5c01_read(priv, pos++);
> +               rp5c01_write(priv, RP5C01_MODE_TIMER_EN | RP5C01_MODE_MODE01,
> +                            RP5C01_MODE);
> +               *buf++ = data;
> +       }
> +
> +       spin_unlock_irq(&priv->lock);
> +       return count;
> +}
> +
> +static ssize_t rp5c01_nvram_write(struct file *filp, struct kobject *kobj,
> +                                 struct bin_attribute *bin_attr,
> +                                 char *buf, loff_t pos, size_t size)
> +{
> +       struct device *dev = container_of(kobj, struct device, kobj);
> +       struct rp5c01_priv *priv = dev_get_drvdata(dev);
> +       ssize_t count;
> +
> +       spin_lock_irq(&priv->lock);
> +
> +       for (count = 0; size > 0 && pos < RP5C01_MODE; count++, size--) {
> +               u8 data = *buf++;
> +
> +               rp5c01_write(priv,
> +                            RP5C01_MODE_TIMER_EN | RP5C01_MODE_RAM_BLOCK10,
> +                            RP5C01_MODE);
> +               rp5c01_write(priv, data >> 4, pos);
> +               rp5c01_write(priv,
> +                            RP5C01_MODE_TIMER_EN | RP5C01_MODE_RAM_BLOCK11,
> +                            RP5C01_MODE);
> +               rp5c01_write(priv, data & 0xf, pos++);
> +               rp5c01_write(priv, RP5C01_MODE_TIMER_EN | RP5C01_MODE_MODE01,
> +                            RP5C01_MODE);
> +       }
> +
> +       spin_unlock_irq(&priv->lock);
> +       return count;
> +}
> +
>  static int __init rp5c01_rtc_probe(struct platform_device *dev)
>  {
>        struct resource *res;
> @@ -168,6 +240,15 @@ static int __init rp5c01_rtc_probe(struct platform_device *dev)
>                goto out_free_priv;
>        }
>
> +       sysfs_bin_attr_init(&priv->nvram_attr);
> +       priv->nvram_attr.attr.name = "nvram";
> +       priv->nvram_attr.attr.mode = S_IRUGO | S_IWUSR;
> +       priv->nvram_attr.read = rp5c01_nvram_read;
> +       priv->nvram_attr.write = rp5c01_nvram_write;
> +       priv->nvram_attr.size = RP5C01_MODE;
> +
> +       spin_lock_init(&priv->lock);
> +
>        rtc = rtc_device_register("rtc-rp5c01", &dev->dev, &rp5c01_rtc_ops,
>                                  THIS_MODULE);
>        if (IS_ERR(rtc)) {
> @@ -177,8 +258,15 @@ static int __init rp5c01_rtc_probe(struct platform_device *dev)
>
>        priv->rtc = rtc;
>        platform_set_drvdata(dev, priv);
> +
> +       error = sysfs_create_bin_file(&dev->dev.kobj, &priv->nvram_attr);
> +       if (error)
> +               goto out_unregister;
> +
>        return 0;
>
> +out_unregister:
> +       rtc_device_unregister(rtc);
>  out_unmap:
>        iounmap(priv->regs);
>  out_free_priv:
> @@ -190,6 +278,7 @@ static int __exit rp5c01_rtc_remove(struct platform_device *dev)
>  {
>        struct rp5c01_priv *priv = platform_get_drvdata(dev);
>
> +       sysfs_remove_bin_file(&dev->dev.kobj, &priv->nvram_attr);
>        rtc_device_unregister(priv->rtc);
>        iounmap(priv->regs);
>        kfree(priv);
> --
> 1.7.0.4

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

      parent reply	other threads:[~2010-07-18 18:32 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-06-13 10:12 [PATCH] rtc: rp5c01 - Add NVRAM support Geert Uytterhoeven
2010-06-13 10:12 ` Geert Uytterhoeven
2010-06-13 13:41 ` [rtc-linux] " Wan ZongShun
2010-06-13 17:44   ` Geert Uytterhoeven
2010-06-13 13:41 ` Wan ZongShun
2010-06-23 19:55 ` Geert Uytterhoeven
2010-07-18 18:32 ` Geert Uytterhoeven [this message]

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=AANLkTilzH61NsPF5maM77chbuQA8ptUiV5iaXtOShYOB@mail.gmail.com \
    --to=geert@linux-m68k.org \
    --cc=a.zummo@towertech.it \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-m68k@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.