Linux Clock source from FPGA

I’m trying to get the Linux kernel (and system as a whole) to sync to a monotonically incrementing clock from a FPGA register in memory. The clock is 64-bits wide and divided into two 32-bit sections: a 32-bit seconds register and a 32-bit nanoseconds register which increments in 10s of nanoseconds.

I created an initial implementation based off of the ARM global timer thinking this would be a good starting approach. The driver successful registers (in kernel, not a kernel module), and I can switch the clocksource to the driver, but the timing is off and I get quite a few panics about the scheduler not executing.

My goal is that I can use the typical POSIX APIs to set and get the time from a userspace application without having the userspace involved in reading a register in memory for the time.

Is using the clocksource the right tool for this job? Or do I need something else?

#include <linux/module.h>
#include <linux/init.h>
#include <linux/mod_devicetable.h>
#include <linux/property.h>
#include <linux/platform_device.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/clocksource.h>
#include <linux/slab.h>
#include <linux/sched_clock.h>

/* Meta Information */
MODULE_LICENSE("GPL");

#define FPGA_TIME_DRIVER_NAME "fpga_time"


/* 32-bit seconds register */
#define FPGA_TIME_ADDR_CTRL_TIME_SECONDS         0x00
/* 32-bit subseconds register incrementing in 10s of nanoseconds
 */
#define FPGA_TIME_ADDR_INFO_TIME_SUBSECONDS      0x04

/* Rate at which the time is updated (10ns) */
#define FPGA_TIME_TIMER_TICK_100MHZ              (100 * 1000 * 1000)
/* Rating/priority of the clock source compared to other clocks.
 * Higher rating means it will be preferred over other clock sources.
 */
#define FPGA_TIME_TIMER_RATING                   (100)

static u64 FPGA_TIME_clocksource_read(struct clocksource *cs);

/**
 * @brief The global timer structure that holds the clocksource info and the
 * base register address for reading from memory.
 */
struct clocksource_fpga {
    void __iomem *reg;
    struct clocksource clksrc;
} g_timerInfo = {
    .clksrc = {
        .name = FPGA_TIME_DRIVER_NAME,
        .rating = FPGA_TIME_TIMER_RATING,
        .read = FPGA_TIME_clocksource_read,
        .mask = CLOCKSOURCE_MASK(64),
        .flags = CLOCK_SOURCE_IS_CONTINUOUS
    }
};

static u64 _FPGA_TIME_clocksource_read(void)
{
    u64 counter;
    u32 seconds, subseconds;

    seconds = readl_relaxed(g_timerInfo.reg + FPGA_TIME_ADDR_CTRL_TIME_SECONDS);
    subseconds = readl_relaxed(g_timerInfo.reg + FPGA_TIME_ADDR_INFO_TIME_SUBSECONDS);

    counter = seconds;
    counter <<= 32;
    counter |= (subseconds << 1);

    return counter;
}

static u64 FPGA_TIME_clocksource_read(struct clocksource *cs)
{
    return _FPGA_TIME_clocksource_read();
}

/**
 * @brief Linux scheduler clock read.
 * @return The current time as a 64-bit integer.
 */
#ifdef CONFIG_CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK
static u64 notrace FPGA_TIME_sched_clock_read(void)
{
    return _FPGA_TIME_clocksource_read();
}
#endif

/**
 * @brief Registers the timewarp clocksource and if applicable, registers with
 * the scheduler.
 * @return Returns 0 on success, errno otherwise.
 */
static int timer_clocksource_init(void)
{
    int ret;
#ifdef CONFIG_CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK
    printk(FPGA_TIME_DRIVER_NAME " - Registering the scheduler...n");
    sched_clock_register(FPGA_TIME_sched_clock_read, 64, FPGA_TIME_TIMER_TICK_100MHZ);
#endif
    ret = clocksource_register_hz(&g_timerInfo.clksrc, FPGA_TIME_TIMER_TICK_100MHZ);
    printk(FPGA_TIME_DRIVER_NAME " - Registering the clocksource returned = %dn", ret);
    return ret;
}

/**
 * @brief Device driver probed when detected in the device tree.
 * This reads in all the property values and initializes the driver.
 * 
 * @param pdev The plaform device which contains the information about the driver.
 * @return Returns 0 on success, errno otherwise.
 */
static int __init FPGA_TIME_register(struct device_node *np)
{
    printk(FPGA_TIME_DRIVER_NAME " - Loading the driver...n");

    /* Get the base address and size. */
    g_timerInfo.reg = of_iomap(np, 0);

    return timer_clocksource_init();
}

I’m trying to get the Linux kernel and system to use time from an FPGA register in memory using a kernel module. I was expecting that the system time would align properly to the clock, but it is not.

New contributor

Ryan Sherlock is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật