From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752659AbbCYJxi (ORCPT ); Wed, 25 Mar 2015 05:53:38 -0400 Received: from www.linutronix.de ([62.245.132.108]:50589 "EHLO Galois.linutronix.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752535AbbCYJwv (ORCPT ); Wed, 25 Mar 2015 05:52:51 -0400 From: Holger Dengler To: linux-kernel@vger.kernel.org Cc: Peter Mahler , Juergen Bubeck , Benedikt Spranger , Holger Dengler , Daniel Lezcano , Thomas Gleixner Subject: [PATCH 11/11] clocksource: flexcard: Support timestamp trigger selection Date: Wed, 25 Mar 2015 10:52:00 +0100 Message-Id: <1427277120-16924-12-git-send-email-dengler@linutronix.de> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1427277120-16924-1-git-send-email-dengler@linutronix.de> References: <1427277120-16924-1-git-send-email-dengler@linutronix.de> X-Linutronix-Spam-Score: -1.0 X-Linutronix-Spam-Level: - X-Linutronix-Spam-Status: No , -1.0 points, 5.0 required, ALL_TRUSTED=-1,SHORTCIRCUIT=-0.0001,URIBL_BLOCKED=0.001 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Benedikt Spranger The Flexcard timestamp counter can be triggered from two external trigger inputs or an internal clock at 1 MHz, 10 Mhz or 100 MHz. Add support for timestamp trigger selection. Signed-off-by: Holger Dengler Signed-off-by: Benedikt Spranger cc: Daniel Lezcano cc: Thomas Gleixner --- drivers/clocksource/flexcard-time.c | 50 ++++++++++++++++++++++++++++++++++--- include/uapi/linux/flexcard.h | 16 ++++++++++++ 2 files changed, 63 insertions(+), 3 deletions(-) diff --git a/drivers/clocksource/flexcard-time.c b/drivers/clocksource/flexcard-time.c index f2efb53..101a989 100644 --- a/drivers/clocksource/flexcard-time.c +++ b/drivers/clocksource/flexcard-time.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -26,8 +27,10 @@ static dev_t flexcard_clk_devt; static struct class *flexcard_clk_class; struct flexcard_clk { + struct flexcard_clk_desc desc; struct posix_clock clock; dev_t devid; + u32 mul; struct device *dev; void __iomem *ts64; void __iomem *reset; @@ -35,8 +38,9 @@ struct flexcard_clk { static int flexcard_clk_getres(struct posix_clock *pc, struct timespec *tp) { + struct flexcard_clk *clk = container_of(pc, struct flexcard_clk, clock); tp->tv_sec = 0; - tp->tv_nsec = 1000; + tp->tv_nsec = clk->mul; return 0; } @@ -54,7 +58,7 @@ retry: goto retry; tp->tv_sec = div_u64_rem(now, clk->desc.freq, &rem); - tp->tv_nsec = rem * 1000; + tp->tv_nsec = rem * clk->mul; return 0; } @@ -73,11 +77,48 @@ static int flexcard_clk_settime(struct posix_clock *pc, return 0; } +static long flexcard_clk_ioctl(struct posix_clock *pc, unsigned int cmd, + unsigned long arg) +{ + struct flexcard_clk *clk = container_of(pc, struct flexcard_clk, clock); + struct flexcard_clk_desc desc; + + if (copy_from_user(&desc, (void __user *)arg, sizeof(desc))) + return -EFAULT; + + switch (cmd) { + case FLEXCARD_CLK_1MHZ: + clk->desc.freq = 1000000; + break; + case FLEXCARD_CLK_10MHZ: + clk->desc.freq = 10000000; + break; + case FLEXCARD_CLK_100MHZ: + clk->desc.freq = 100000000; + break; + case FLEXCARD_CLK_EXT1: + case FLEXCARD_CLK_EXT2: + if (desc.freq < 1 || desc.freq > NSEC_PER_SEC) + return -EINVAL; + break; + default: + return -ENOTTY; + } + + clk->desc = desc; + clk->mul = NSEC_PER_SEC/desc.freq; + writel(clk->desc.type, clk->ts64 + CLKSEL_OFF); + writel(FLEXCARD_RST_TS, clk->reset); + + return 0; +} + static struct posix_clock_operations flexcard_clk_ops = { .owner = THIS_MODULE, .clock_getres = flexcard_clk_getres, .clock_gettime = flexcard_clk_gettime, .clock_settime = flexcard_clk_settime, + .ioctl = flexcard_clk_ioctl, }; static int flexcard_clksrc_iomap(struct platform_device *pdev) @@ -134,8 +175,11 @@ static int flexcard_clksrc_probe(struct platform_device *pdev) clk->devid = MKDEV(major, cell->id); clk->clock.ops = flexcard_clk_ops; + clk->desc.type = FLEXCARD_CLK_1MHZ; + clk->desc.freq = 1000000; + clk->mul = 1000; - writel(FLEXCARD_CLK_1MHZ, clk->ts64 + CLKSEL_OFF); + writel(clk->desc.type, clk->ts64 + CLKSEL_OFF); writel(FLEXCARD_RST_TS, clk->reset); clk->dev = device_create(flexcard_clk_class, &pdev->dev, clk->devid, diff --git a/include/uapi/linux/flexcard.h b/include/uapi/linux/flexcard.h index 9b73d8d..7939d94 100644 --- a/include/uapi/linux/flexcard.h +++ b/include/uapi/linux/flexcard.h @@ -15,6 +15,22 @@ #include +enum flexcard_clk_type { + FLEXCARD_CLK_1MHZ = 0x0, + FLEXCARD_CLK_10MHZ = 0x1, + FLEXCARD_CLK_100MHZ = 0x2, + FLEXCARD_CLK_EXT1 = 0x11, + FLEXCARD_CLK_EXT2 = 0x12, +}; + +struct flexcard_clk_desc { + enum flexcard_clk_type type; + __u32 freq; +}; + +#define FCGCLKSRC _IOR(0xeb, 0, struct flexcard_clk_desc) +#define FCSCLKSRC _IOW(0xeb, 1, struct flexcard_clk_desc) + struct fc_version { __u8 dev; __u8 min; -- 2.1.4