0

I am working on an embedded Linux system (kernel-5.10.24).

And there is a PCF8563 RTC in system, its CLKOUT is connected to other hardware logic.

Now in Linux system, I want to configure the CLKOUT rate (it is configurable in PCF8563), but I did NOT find the user space API to do that.

By googling, I found it might be done in kernel module, with clk_get() and clk_set_rate().

So I wrote a simple kernel module to do that, as follows,

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/clk.h>

static struct clk *rtc_clk;

static int __init rtc_module_init(void)
{
    int ret;

    rtc_clk = clk_get(NULL, "pcf8563");   // Get the RTC of the name
    if (IS_ERR(rtc_clk)) {
        ret = PTR_ERR(rtc_clk);
        printk(KERN_ERR "Failed to get RTC clock: %d\n", ret);
        return ret;
    }

    unsigned long rate = clk_get_rate(rtc_clk);
    printk(KERN_INFO "Current RTC clock rate: %lu Hz\n", rate);

    unsigned long new_rate = 32768;
    ret = clk_set_rate(rtc_clk, new_rate);
    if (ret < 0) {
        printk(KERN_ERR "Failed to set RTC clock rate: %d\n", ret);
        return ret;
    }

    rate = clk_get_rate(rtc_clk);
    printk(KERN_INFO "Updated RTC clock rate: %lu Hz\n", rate);

    return 0;
}

static void __exit rtc_module_exit(void)
{
    if (rtc_clk)
        clk_put(rtc_clk);
}

module_init(rtc_module_init);
module_exit(rtc_module_exit);

MODULE_LICENSE("GPL");

When loading the module in Linux, I got error like this, Failed to get RTC clock: -2

The device tree of RTC is as follows,

    rtc_pcf8563:rtc_pcf8563@51{
                compatible = "nxp,pcf8563";
                reg = <0x51>;
                status = "okay";
    }

I am wondering what name should be passed to clk_get(NULL, ???) ?

I also checked the PCF8563 driver, found following definition.

static const struct clk_ops pcf8563_clkout_ops = {
    .prepare = pcf8563_clkout_prepare,
    .unprepare = pcf8563_clkout_unprepare,
    .is_prepared = pcf8563_clkout_is_prepared,
    .recalc_rate = pcf8563_clkout_recalc_rate,
    .round_rate = pcf8563_clkout_round_rate,
    .set_rate = pcf8563_clkout_set_rate,
};

static struct clk *pcf8563_clkout_register_clk(struct pcf8563 *pcf8563)
{
    struct i2c_client *client = pcf8563->client;
    struct device_node *node = client->dev.of_node;
    struct clk *clk;
    struct clk_init_data init;
    int ret;
    unsigned char buf;

    /* disable the clkout output */
    buf = 0;
    ret = pcf8563_write_block_data(client, PCF8563_REG_CLKO, 1, &buf);
    if (ret < 0)
        return ERR_PTR(ret);

    init.name = "pcf8563-clkout";
    init.ops = &pcf8563_clkout_ops;
    init.flags = 0;
    init.parent_names = NULL;
    init.num_parents = 0;
    pcf8563->clkout_hw.init = &init;

    /* optional override of the clockname */
    of_property_read_string(node, "clock-output-names", &init.name);

    /* register the clock */
    clk = devm_clk_register(&client->dev, &pcf8563->clkout_hw);

    if (!IS_ERR(clk))
        of_clk_add_provider(node, of_clk_src_simple_get, clk);

    return clk;
}

So, how do these functions being called in Linux? Or if a system wants to enable the CLKOUT of PCF8563, how to do that? Is there any user space interface to call these functions in Linux?

wangt13
  • 959
  • 7
  • 17
  • Would writing your own device driver to interface with user-mode and call kernel functions, be out of the question? – Irelia Jul 06 '23 at 13:44
  • The default name of the clock source is "pcf8563-clkout", not "pcf8563", although the name of the clock source can be changed from the default by the "clock-output-names" string property in the RTC's device tree node. – Ian Abbott Jul 06 '23 at 14:53
  • I changed to use `rtc_clk = clk_get(NULL, "pcf8563-clkout");`, but still got error number of -2. – wangt13 Jul 07 '23 at 00:02
  • @Irelia, as I posted here, I am writing a kernel module to do the clock rate get and set, and I hit an error when called `clk_get()`. If that can work, I can extend the kernel module as a device driver to interface with user-mode. – wangt13 Jul 07 '23 at 00:05

0 Answers0