From: Alexandre Belloni <alexandre.belloni@bootlin.com>
To: WANG Xuerui <git@xen0n.name>
Cc: linux-rtc@vger.kernel.org, linux-mips@vger.kernel.org,
devicetree@vger.kernel.org, Huacai Chen <chenhuacai@kernel.org>
Subject: Re: [PATCH v3 1/6] rtc: ls2x: Add support for the Loongson-2K/LS7A RTC
Date: Mon, 21 Jun 2021 00:15:51 +0200 [thread overview]
Message-ID: <YM++F4j/omXvsWGQ@piout.net> (raw)
In-Reply-To: <20210506010435.1333647-2-git@xen0n.name>
Hi,
On 06/05/2021 09:04:30+0800, WANG Xuerui wrote:
> This RTC module is integrated into the Loongson-2K SoC and the LS7A
> bridge chip. This version is almost entirely rewritten to make use of
> current kernel API.
>
> Signed-off-by: Huacai Chen <chenhuacai@kernel.org>
> Signed-off-by: WANG Xuerui <git@xen0n.name>
> ---
> drivers/rtc/Kconfig | 11 ++
> drivers/rtc/Makefile | 1 +
> drivers/rtc/rtc-ls2x.c | 225 +++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 237 insertions(+)
> create mode 100644 drivers/rtc/rtc-ls2x.c
>
> diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
> index d8c13fded164..55beede68829 100644
> --- a/drivers/rtc/Kconfig
> +++ b/drivers/rtc/Kconfig
> @@ -1304,6 +1304,17 @@ config RTC_DRV_NTXEC
> embedded controller found in certain e-book readers designed by the
> original design manufacturer Netronix.
>
> +config RTC_DRV_LS2X
> + tristate "Loongson LS2X RTC"
> + depends on MACH_LOONGSON64 || COMPILE_TEST
> + select REGMAP_MMIO
> + help
> + If you say yes here you get support for the RTC on the Loongson-2K
> + SoC and LS7A bridge, which first appeared on the Loongson-2H.
> +
> + This driver can also be built as a module. If so, the module
> + will be called rtc-ls2x.
> +
> comment "on-CPU RTC drivers"
>
> config RTC_DRV_ASM9260
> diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
> index 2dd0dd956b0e..6042ff1e73b7 100644
> --- a/drivers/rtc/Makefile
> +++ b/drivers/rtc/Makefile
> @@ -81,6 +81,7 @@ obj-$(CONFIG_RTC_DRV_LOONGSON1) += rtc-ls1x.o
> obj-$(CONFIG_RTC_DRV_LP8788) += rtc-lp8788.o
> obj-$(CONFIG_RTC_DRV_LPC24XX) += rtc-lpc24xx.o
> obj-$(CONFIG_RTC_DRV_LPC32XX) += rtc-lpc32xx.o
> +obj-$(CONFIG_RTC_DRV_LS2X) += rtc-ls2x.o
> obj-$(CONFIG_RTC_DRV_M41T80) += rtc-m41t80.o
> obj-$(CONFIG_RTC_DRV_M41T93) += rtc-m41t93.o
> obj-$(CONFIG_RTC_DRV_M41T94) += rtc-m41t94.o
> diff --git a/drivers/rtc/rtc-ls2x.c b/drivers/rtc/rtc-ls2x.c
> new file mode 100644
> index 000000000000..6508a87bdb31
> --- /dev/null
> +++ b/drivers/rtc/rtc-ls2x.c
> @@ -0,0 +1,225 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Loongson-2K/7A RTC driver
> + *
> + * Based on the out-of-tree Loongson-2H RTC driver for Linux 2.6.32, by
> + * Shaozong Liu <liushaozong@loongson.cn>.
> + *
> + * Maintained out-of-tree by Huacai Chen <chenhuacai@kernel.org>.
> + *
> + * Rewritten for mainline by WANG Xuerui <git@xen0n.name>.
> + */
> +
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/regmap.h>
> +#include <linux/rtc.h>
> +#include <linux/spinlock.h>
> +
> +#define TOY_TRIM_REG 0x20
> +#define TOY_WRITE0_REG 0x24
> +#define TOY_WRITE1_REG 0x28
> +#define TOY_READ0_REG 0x2c
> +#define TOY_READ1_REG 0x30
> +#define TOY_MATCH0_REG 0x34
> +#define TOY_MATCH1_REG 0x38
> +#define TOY_MATCH2_REG 0x3c
> +#define RTC_CTRL_REG 0x40
> +#define RTC_TRIM_REG 0x60
> +#define RTC_WRITE0_REG 0x64
> +#define RTC_READ0_REG 0x68
> +#define RTC_MATCH0_REG 0x6c
> +#define RTC_MATCH1_REG 0x70
> +#define RTC_MATCH2_REG 0x74
> +
> +#define TOY_MON GENMASK(31, 26)
> +#define TOY_MON_SHIFT 26
> +#define TOY_DAY GENMASK(25, 21)
> +#define TOY_DAY_SHIFT 21
> +#define TOY_HOUR GENMASK(20, 16)
> +#define TOY_HOUR_SHIFT 16
> +#define TOY_MIN GENMASK(15, 10)
> +#define TOY_MIN_SHIFT 10
> +#define TOY_SEC GENMASK(9, 4)
> +#define TOY_SEC_SHIFT 4
> +#define TOY_MSEC GENMASK(3, 0)
> +#define TOY_MSEC_SHIFT 0
> +
> +struct ls2x_rtc_priv {
> + struct regmap *regmap;
> + spinlock_t lock;
> +};
> +
> +static const struct regmap_config ls2x_rtc_regmap_config = {
> + .reg_bits = 32,
> + .val_bits = 32,
> + .reg_stride = 4,
> +};
> +
> +struct ls2x_rtc_regs {
> + u32 reg0;
> + u32 reg1;
> +};
> +
> +static inline void ls2x_rtc_regs_to_time(struct ls2x_rtc_regs *regs,
> + struct rtc_time *tm)
> +{
> + tm->tm_year = regs->reg1;
> + tm->tm_sec = (regs->reg0 & TOY_SEC) >> TOY_SEC_SHIFT;
> + tm->tm_min = (regs->reg0 & TOY_MIN) >> TOY_MIN_SHIFT;
> + tm->tm_hour = (regs->reg0 & TOY_HOUR) >> TOY_HOUR_SHIFT;
> + tm->tm_mday = (regs->reg0 & TOY_DAY) >> TOY_DAY_SHIFT;
> + tm->tm_mon = ((regs->reg0 & TOY_MON) >> TOY_MON_SHIFT) - 1;
Please use FIELD_GET
> +}
> +
> +static inline void ls2x_rtc_time_to_regs(struct rtc_time *tm,
> + struct ls2x_rtc_regs *regs)
> +{
> + regs->reg0 = (tm->tm_sec << TOY_SEC_SHIFT) & TOY_SEC;
> + regs->reg0 |= (tm->tm_min << TOY_MIN_SHIFT) & TOY_MIN;
> + regs->reg0 |= (tm->tm_hour << TOY_HOUR_SHIFT) & TOY_HOUR;
> + regs->reg0 |= (tm->tm_mday << TOY_DAY_SHIFT) & TOY_DAY;
> + regs->reg0 |= ((tm->tm_mon + 1) << TOY_MON_SHIFT) & TOY_MON;
and FIELD_PREP, this should remove the need for *_SHIFT
> + regs->reg1 = tm->tm_year;
> +}
> +
> +static int ls2x_rtc_read_time(struct device *dev, struct rtc_time *tm)
> +{
> + struct ls2x_rtc_priv *priv = dev_get_drvdata(dev);
> + struct ls2x_rtc_regs regs;
> + int ret;
> +
> + spin_lock_irq(&priv->lock);
What are you locking against?
> +
> + ret = regmap_read(priv->regmap, TOY_READ1_REG, ®s.reg1);
> + if (unlikely(ret)) {
> + dev_err(dev, "Failed to read time: %d\n", ret);
Please avoid those error message, they are not that useful and bloat the
kernel.
> + goto fail;
> + }
> +
> + ret = regmap_read(priv->regmap, TOY_READ0_REG, ®s.reg0);
> + if (unlikely(ret)) {
> + dev_err(dev, "Failed to read time: %d\n", ret);
> + goto fail;
> + }
> +
> + spin_unlock_irq(&priv->lock);
> +
> + ls2x_rtc_regs_to_time(®s, tm);
> +
> + return 0;
> +
> +fail:
> + spin_unlock_irq(&priv->lock);
> + return ret;
> +}
> +
> +static int ls2x_rtc_set_time(struct device *dev, struct rtc_time *tm)
> +{
> + struct ls2x_rtc_priv *priv = dev_get_drvdata(dev);
> + struct ls2x_rtc_regs regs;
> + int ret;
> +
> + ls2x_rtc_time_to_regs(tm, ®s);
> +
> + spin_lock_irq(&priv->lock);
> +
> + ret = regmap_write(priv->regmap, TOY_WRITE0_REG, regs.reg0);
> + if (unlikely(ret)) {
> + dev_err(dev, "Failed to set time: %d\n", ret);
> + goto fail;
> + }
> +
> + ret = regmap_write(priv->regmap, TOY_WRITE1_REG, regs.reg1);
> + if (unlikely(ret)) {
> + dev_err(dev, "Failed to set time: %d\n", ret);
> + goto fail;
> + }
> +
> + spin_unlock_irq(&priv->lock);
> +
> + return 0;
> +
> +fail:
> + spin_unlock_irq(&priv->lock);
> + return ret;
> +}
> +
> +static struct rtc_class_ops ls2x_rtc_ops = {
> + .read_time = ls2x_rtc_read_time,
> + .set_time = ls2x_rtc_set_time,
> +};
> +
> +static int ls2x_rtc_probe(struct platform_device *pdev)
> +{
> + struct device *dev = &pdev->dev;
> + struct rtc_device *rtc;
> + struct ls2x_rtc_priv *priv;
> + void __iomem *regs;
> + int ret;
> +
> + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
> + if (unlikely(!priv))
> + return -ENOMEM;
> +
> + spin_lock_init(&priv->lock);
> + platform_set_drvdata(pdev, priv);
> +
> + regs = devm_platform_ioremap_resource(pdev, 0);
> + if (IS_ERR(regs)) {
> + ret = PTR_ERR(regs);
> + dev_err(dev, "Failed to map rtc registers: %d\n", ret);
I'm pretty sure this error message is unnecessary
> + return ret;
> + }
> +
> + priv->regmap = devm_regmap_init_mmio(dev, regs,
> + &ls2x_rtc_regmap_config);
> + if (IS_ERR(priv->regmap)) {
> + ret = PTR_ERR(priv->regmap);
> + dev_err(dev, "Failed to init regmap: %d\n", ret);
ditto
> + return ret;
> + }
> +
> + rtc = devm_rtc_allocate_device(dev);
> + if (IS_ERR(rtc)) {
> + ret = PTR_ERR(rtc);
> + dev_err(dev, "Failed to allocate rtc device: %d\n", ret);
This on has to be removed.
> + return ret;
> + }
> +
> + rtc->ops = &ls2x_rtc_ops;
> +
> + /* Due to hardware erratum, all years multiple of 4 are considered
> + * leap year, so only years 2000 through 2099 are usable.
> + *
> + * Previous out-of-tree versions of this driver wrote tm_year directly
> + * into the year register, so epoch 2000 must be used to preserve
> + * semantics on shipped systems.
> + */
> + rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
> + rtc->range_max = RTC_TIMESTAMP_END_2099;
> +
> + return devm_rtc_register_device(rtc);
> +}
> +
> +static const struct of_device_id ls2x_rtc_of_match[] = {
> + { .compatible = "loongson,ls2x-rtc" },
> + { /* sentinel */ },
> +};
> +MODULE_DEVICE_TABLE(of, ls2x_rtc_of_match);
> +
> +static struct platform_driver ls2x_rtc_driver = {
> + .probe = ls2x_rtc_probe,
> + .driver = {
> + .name = "ls2x-rtc",
> + .of_match_table = of_match_ptr(ls2x_rtc_of_match),
> + },
> +};
> +
> +module_platform_driver(ls2x_rtc_driver);
> +
> +MODULE_DESCRIPTION("LS2X RTC driver");
> +MODULE_AUTHOR("WANG Xuerui");
> +MODULE_AUTHOR("Huacai Chen");
> +MODULE_LICENSE("GPL");
> +MODULE_ALIAS("platform:ls2x-rtc");
> --
> 2.30.1
>
--
Alexandre Belloni, co-owner and COO, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
next prev parent reply other threads:[~2021-06-20 22:15 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-05-06 1:04 [PATCH v3 0/6] rtc: ls2x: Add support for the Loongson-2K/LS7A RTC WANG Xuerui
2021-05-06 1:04 ` [PATCH v3 1/6] " WANG Xuerui
2021-06-20 22:15 ` Alexandre Belloni [this message]
2021-05-06 1:04 ` [PATCH v3 2/6] dt-bindings: rtc: Add bindings for LS2X RTC WANG Xuerui
2021-05-06 1:04 ` [PATCH v3 3/6] MIPS: Loongson64: DTS: Add RTC support to LS7A WANG Xuerui
2021-05-06 1:04 ` [PATCH v3 4/6] MIPS: Loongson: Enable LS2X RTC in loongson3_defconfig WANG Xuerui
2021-05-06 1:04 ` [PATCH v3 5/6] MIPS: Loongson64: DTS: Add RTC support to Loongson-2K WANG Xuerui
2021-05-06 1:04 ` [PATCH v3 6/6] MIPS: Loongson: Enable LS2X RTC in loongson2k_defconfig WANG Xuerui
2021-05-07 2:42 ` [PATCH v3 0/6] rtc: ls2x: Add support for the Loongson-2K/LS7A RTC Jiaxun Yang
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=YM++F4j/omXvsWGQ@piout.net \
--to=alexandre.belloni@bootlin.com \
--cc=chenhuacai@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=git@xen0n.name \
--cc=linux-mips@vger.kernel.org \
--cc=linux-rtc@vger.kernel.org \
/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.