From: Alexandre Belloni <alexandre.belloni@bootlin.com>
To: Srinivas Neeli <srinivas.neeli@xilinx.com>
Cc: linux-rtc@vger.kernel.org, a.zummo@towertech.it,
Srinivas Goud <srinivas.goud@xilinx.com>,
sgoud@xilinx.com, michal.simek@xilinx.com,
linux-kernel@vger.kernel.org, git@xilinx.com,
shubhraj@xilinx.com, linux-arm-kernel@lists.infradead.org
Subject: Re: [PATCH] rtc: zynqmp: Add calibration set and get support
Date: Thu, 27 Feb 2020 12:45:54 +0100 [thread overview]
Message-ID: <20200227114554.GA3436@piout.net> (raw)
In-Reply-To: <1582191106-30431-1-git-send-email-srinivas.neeli@xilinx.com>
Hi,
On 20/02/2020 15:01:46+0530, Srinivas Neeli wrote:
> diff --git a/drivers/rtc/rtc-zynqmp.c b/drivers/rtc/rtc-zynqmp.c
> index 4b1077e2f826..b4118e9e4fcc 100644
> --- a/drivers/rtc/rtc-zynqmp.c
> +++ b/drivers/rtc/rtc-zynqmp.c
> @@ -40,6 +40,12 @@
> #define RTC_CALIB_MASK 0x1FFFFF
> #define RTC_ALRM_MASK BIT(1)
> #define RTC_MSEC 1000
> +#define RTC_FR_MASK 0xF0000
> +#define RTC_SEC_MAX_VAL 0xFFFFFFFF
This value is not used
> +#define RTC_FR_MAX_TICKS 16
> +#define RTC_OFFSET_MAX 150000
> +#define RTC_OFFSET_MIN -150000
> +#define RTC_PPB 1000000000LL
>
> struct xlnx_rtc_dev {
> struct rtc_device *rtc;
> @@ -184,12 +190,84 @@ static void xlnx_init_rtc(struct xlnx_rtc_dev *xrtcdev)
> writel(xrtcdev->calibval, (xrtcdev->reg_base + RTC_CALIB_WR));
> }
>
> +static int xlnx_rtc_read_offset(struct device *dev, long *offset)
> +{
> + struct xlnx_rtc_dev *xrtcdev = dev_get_drvdata(dev);
> + long offset_val;
> + unsigned int reg;
> + unsigned int tick_mult = RTC_PPB / xrtcdev->calibval;
> +
I don't get why you are not simply reusing xrtcdev->calibval. Using
.set_offset has to take precedence on any value that would have been set
using DT. Ideally, the DT binding should be removed too.
Currently, the calibration value is overwritten using the DT value
every time .set_time is called because xrtcdev->calibval is never
updated.
> + reg = readl(xrtcdev->reg_base + RTC_CALIB_RD);
> +
> + /* Offset with seconds ticks */
> + offset_val = reg & RTC_TICK_MASK;
> + offset_val = offset_val - xrtcdev->calibval;
> + offset_val = offset_val * tick_mult;
> +
> + /* Offset with fractional ticks */
> + if (reg & RTC_FR_EN)
> + offset_val += ((reg & RTC_FR_MASK) >> RTC_FR_DATSHIFT)
> + * (tick_mult / RTC_FR_MAX_TICKS);
> + *offset = offset_val;
> +
> + return 0;
> +}
> +
> +static int xlnx_rtc_set_offset(struct device *dev, long offset)
> +{
> + struct xlnx_rtc_dev *xrtcdev = dev_get_drvdata(dev);
> + short int max_tick;
> + unsigned char fract_tick = 0;
> + unsigned int calibval;
> + int fract_offset;
> + unsigned int tick_mult = RTC_PPB / xrtcdev->calibval;
> +
> + /* Make sure offset value is within supported range */
> + if (offset < RTC_OFFSET_MIN || offset > RTC_OFFSET_MAX)
> + return -ERANGE;
> +
> + /* Number ticks for given offset */
> + max_tick = div_s64_rem(offset, tick_mult, &fract_offset);
> +
> + /* Number fractional ticks for given offset */
> + if (fract_offset) {
> + if (fract_offset < 0) {
> + fract_offset = fract_offset + tick_mult;
> + max_tick--;
> + }
> + if (fract_offset > (tick_mult / RTC_FR_MAX_TICKS)) {
> + for (fract_tick = 1; fract_tick < 16; fract_tick++) {
> + if (fract_offset <=
> + (fract_tick *
> + (tick_mult / RTC_FR_MAX_TICKS)))
> + break;
> + }
> + }
> + }
> +
> + /* Zynqmp RTC uses second and fractional tick
> + * counters for compensation
> + */
> + calibval = max_tick + xrtcdev->calibval;
> +
> + if (fract_tick)
> + calibval |= RTC_FR_EN;
> +
> + calibval |= (fract_tick << RTC_FR_DATSHIFT);
> +
> + writel(calibval, (xrtcdev->reg_base + RTC_CALIB_WR));
> +
> + return 0;
> +}
> +
> static const struct rtc_class_ops xlnx_rtc_ops = {
> .set_time = xlnx_rtc_set_time,
> .read_time = xlnx_rtc_read_time,
> .read_alarm = xlnx_rtc_read_alarm,
> .set_alarm = xlnx_rtc_set_alarm,
> .alarm_irq_enable = xlnx_rtc_alarm_irq_enable,
> + .read_offset = xlnx_rtc_read_offset,
> + .set_offset = xlnx_rtc_set_offset,
> };
>
> static irqreturn_t xlnx_rtc_interrupt(int irq, void *id)
> --
> 2.7.4
>
--
Alexandre Belloni, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
next prev parent reply other threads:[~2020-02-27 11:46 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-02-20 9:31 [PATCH] rtc: zynqmp: Add calibration set and get support Srinivas Neeli
2020-02-24 11:16 ` Michal Simek
2020-02-25 1:19 ` kbuild test robot
2020-02-27 11:45 ` Alexandre Belloni [this message]
-- strict thread matches above, loose matches on Subject: below --
2021-07-14 8:08 Srinivas Neeli
2021-08-09 10:05 ` Srinivas Neeli
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=20200227114554.GA3436@piout.net \
--to=alexandre.belloni@bootlin.com \
--cc=a.zummo@towertech.it \
--cc=git@xilinx.com \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-rtc@vger.kernel.org \
--cc=michal.simek@xilinx.com \
--cc=sgoud@xilinx.com \
--cc=shubhraj@xilinx.com \
--cc=srinivas.goud@xilinx.com \
--cc=srinivas.neeli@xilinx.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).