{"id":22334607,"url":"https://github.com/rubberazer/jetclocks","last_synced_at":"2026-01-25T11:32:23.381Z","repository":{"id":228583880,"uuid":"727351934","full_name":"Rubberazer/Jetclocks","owner":"Rubberazer","description":"Simple kernel module to control the Jetson Orin clocks","archived":false,"fork":false,"pushed_at":"2025-04-28T19:38:35.000Z","size":80,"stargazers_count":3,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-07-29T22:25:41.655Z","etag":null,"topics":["clocks","jetson-orin","kernel-module","orin"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Rubberazer.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2023-12-04T17:34:53.000Z","updated_at":"2025-04-28T19:38:38.000Z","dependencies_parsed_at":"2025-04-28T20:28:53.841Z","dependency_job_id":"8ee79cd3-2f70-4ddf-b84e-f497221fee74","html_url":"https://github.com/Rubberazer/Jetclocks","commit_stats":null,"previous_names":["rubberazer/jetclocks"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/Rubberazer/Jetclocks","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Rubberazer%2FJetclocks","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Rubberazer%2FJetclocks/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Rubberazer%2FJetclocks/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Rubberazer%2FJetclocks/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Rubberazer","download_url":"https://codeload.github.com/Rubberazer/Jetclocks/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Rubberazer%2FJetclocks/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28752668,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-25T10:25:12.305Z","status":"ssl_error","status_checked_at":"2026-01-25T10:25:11.933Z","response_time":113,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["clocks","jetson-orin","kernel-module","orin"],"created_at":"2024-12-04T05:08:44.898Z","updated_at":"2026-01-25T11:32:23.354Z","avatar_url":"https://github.com/Rubberazer.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Jetclocks\nSimple kernel module to control the Jetson Orin clocks.\nThe aim of this kernel module is to provide applications in user space access to the clocks in Jetson Orin machines through system calls - ioctls().\n\nBasically is a wrapper of the standard Linux Kernel Common Clock Framework, actually it could be used in any other platform just by changing the device tree overlay, everything else is completely generic.\n\nThis module is based on the NVIDIA MODS kernel driver by NVIDIA CORPORATION. For more information on the MODS kernel driver check the Linux for Tegra kernel sources.\n\n\u003ch2 align=\"left\"\u003eSUPPORTED MODELS:\u003c/h2\u003e\n\n- Jetson Orin family: Orin Nano, NX and AGX\n\n\u003ch2 align=\"left\"\u003eFUNCTIONALITY:\u003c/h2\u003e\n\n- Enable/disable any clock\n- Check whether a clock is enabled or disabled\n- Set clock rate in Hz\n- Get current clock rate in Hz\n\n\u003ch2 align=\"left\"\u003eGETTING STARTED:\u003c/h2\u003e\n\nThis module is basically a platform driver and makes use of the device tree, so the first step is to compile the device tree overlay and use it to patch the main device tree blob, there are several ways of going about this, the following one has been tested and it doesn't imply reflashing or recompiling the whole kernel.\n\n**DISCLAIMER** - Manipulating the device tree blob might cause your system to behave in unexpected, undesirable ways, handle with care.\n\n- First of all, clone/download this module sources anywhere in your Orin, say to your home directory:\n\n    ```\n    cd ~ \u0026\u0026 \\\n    git clone https://github.com/Rubberazer/Jetclocks.git\n    ```\n\n\u003ch3 align=\"left\"\u003eAUTOMATIC INSTALL:\u003c/h3\u003e\n\nThere is an option to install the module automatically with make, this would include applying the overlay to the main dtb blob and also modifying the /boot/extlinux/extlinux.conf file so it gets loaded at next reboot, if you want to do it manually, you can skip the next step and just go through the process along the DEVICE TREE and COMPILE sections.\n\n\n    cd ~/Jetclocks \u0026\u0026 \\\n    make \u0026\u0026 sudo make install\n\n\n\u003ch2 align=\"left\"\u003eDEVICE TREE:\u003c/h2\u003e\n\n- Download the Linux for Tegra kernel sources according the version of the kernel running on your Orin, all versions can be downloaded directly from: https://developer.nvidia.com/embedded/jetson-linux-archive\n\n- Unzip de sources, for instance on your /home directory, you should get a folder looking like ~/Linux_for_Tegra/ with all the kernel sources inside\n\nNOTE: A PRECOMPILED VERSION OF THE OVERLAY IS PROVIDED FOR CONVENIENCE (jetclocks.dtbo), YOU SHOULD BE ABLE TO SKIP OVER THE NEXT TWO STEPS. \n\n- Preprocess the overlay file with some kernel headers:\n\n    ```\n    cd ~/Jetclocks \u0026\u0026 \\\n    cpp -nostdinc -I ~/Linux_for_Tegra/source/public/hardware/nvidia/soc/t23x/kernel-include/ -undef -x assembler-with-cpp jetclocks.dts  jetclocks.dts.new\n    ```\n\n- Compile overlay:\n\n    ```\n    dtc -I dts -O dtb ./jetclocks.dts.new -o ./jetclocks.dtbo\n    ```\n\n- Check current device tree in use:\n\n    ```\n    sudo nano /boot/extlinux/extlinux.conf\n    ```\n\n- You should have something like below, on the FDT line you will also see where your device tree blob (.dtb file) is located and its name, this will be used later:\n\n  TIMEOUT 30\n  DEFAULT primary\n\n  MENU TITLE L4T boot options\n\n  LABEL primary\n\n  LINUX /boot/Image\n  FDT /boot/dtb/kernel_tegra234-p3767-0004-p3768-0000-a0.dtb\n\n  ...\n\n- Make sure there is a backup entry, copy and paste the primary label inmediately below, call it backup, afterwards rename the FDT with the name of the future device tree blob on the primary one, let's call it new in our example. It should look something like this:\n\n  TIMEOUT 30\n  DEFAULT primary\n\n  MENU TITLE L4T boot options\n\n  LABEL primary\n\n  LINUX /boot/Image\n  FDT /boot/dtb/new.dtb\n\n  ...\n\n  LABEL backup\n\n  LINUX /boot/Image\n  FDT /boot/dtb/kernel_tegra234-p3767-0004-p3768-0000-a0.dtb\n\n  ...\n\t\n- Apply overlay blob (dtbo) to main dt blob, here on the 4th line the name of the original .dtb file is the one you saw before in your extlinux.conf:\n\n    ```\n    cd ~/Jetclocks \u0026\u0026 \\\n    sudo cp jetclocks.dtbo /boot/dtb \u0026\u0026 \\\n    cd /boot/dtb \u0026\u0026 \\\n    sudo fdtoverlay -i kernel_tegra234-p3767-0004-p3768-0000-a0.dtb -o new.dtb jetclocks.dtbo\n    ```\n\n- Make sure that everything is OK, if you corrupt your device tree and your backup label in extlinux.conf is not correct you will be in trouble.\n\n- Reboot, after reboot you can check wheter the overlay has been applied:\n\n    ```\n    ls /proc/device-tree/jetclocks/\n    ```\n    If everything went OK, you should see:\n    ```\n    clock-names  clocks  compatible  name  status\n    ```\n\n\u003ch2 align=\"left\"\u003eCOMPILE THE MODULE:\u003c/h2\u003e\n\nTo compile the module just:\n\n    cd ~/Jetclocks \u0026\u0026 \\\n    make\n\n\n\u003ch2 align=\"left\"\u003eDEPLOYMENT:\u003c/h2\u003e\n\nAs mentioned before, you can try the automatic proccess as shown here: [Automatic install](#automatic-install) but you can also do it manually just to try the module before installing it. \n\nTo insert the module:\n\n    sudo insmod jetclocks.ko\n\nIf you type a:\n\n    sudo dmesg\n\nYou should see something like below, you can ignore the \"tainting kernel\" message, this just means that is not signed (out of tree module), it doesn't have any practical implications:\n\n    Probing jetclocks\n    jetclocks module loaded\n\nTo remove the module:\n\n    sudo rmmod jetclocks\n\n\u003ch2 align=\"left\"\u003eUNINSTALL THE MODULE:\u003c/h2\u003e\nYou can always revert the process manually but there is also a make option to do it automatically:\n\n\n    sudo make uninstall\n\n\u003ch2 align=\"left\"\u003eUSE THE MODULE:\u003c/h2\u003e\n\nThis module is all about using it from user space, there are 3 basic operations that you can perform from your user space applications that interact with this module. You are going to need a list with valid clock names, you can find this at [clock_names.md](https://github.com/Rubberazer/Jetclocks/blob/main/clock_names.md). There is also a sample application here [jetclocks_user](https://github.com/Rubberazer/Jetclocks/blob/main/jetclocks_user.c), to verify whether a clock is enabled/disabled, clock rate and other parameters, you can type the following from the shell, for instance to check the status of clock spi1:\n\n     sudo cat /sys/kernel/debug/bpmp/debug/clk/clk_tree | grep spi1\n\n**LIMITATIONS**: you might not be able to enable or disable clocks already enabled (in use by some other peripheral), this is due to the fact that the module is not going to be able to get the clock handler. So basically, if some clock is already disabled you should be able to enable and disable it from that point, but not if it is already in use by something else.\n\n**Check whether a clock is enabled:**\n\n```\n#include \u003cstdio.h\u003e\n#include \u003cstdlib.h\u003e\n#include \u003cunistd.h\u003e\n#include \u003cfcntl.h\u003e\n#include \u003cstring.h\u003e\n#include \u003csys/ioctl.h\u003e\n\n#include \"jetclocks.h\"\n\nint main() {\n\n    struct jetclk clock = {0};\t\n\n    int dev = open(\"/dev/jetclocks\", O_WRONLY);\n    if(dev \u003c 0) {\n\tprintf(\"Opening /dev/jetclocks not possible\\n\");\n\treturn -1;\n    }\n\n    /* Checking whether the \"spi1\" clok is enabled*/\n\n    strncpy(clock.clk, \"spi1\", sizeof(clock.clk));\n    ioctl(dev, CLK_IS_ENABLED, \u0026clock);\n    printf(\"clock: %s status(0 disabled, 1 enabled): %d\\n\",clock.clk, clock.clk_enabled);\n \n    close(dev);\n    return 0;\n}\n```\n**Enable clock:**\n\n```\n#include \u003cstdio.h\u003e\n#include \u003cstdlib.h\u003e\n#include \u003cunistd.h\u003e\n#include \u003cfcntl.h\u003e\n#include \u003cstring.h\u003e\n#include \u003csys/ioctl.h\u003e\n\n#include \"jetclocks.h\"\n\nint main() {\n\n    struct jetclk clock = {0};\n\n    int dev = open(\"/dev/jetclocks\", O_WRONLY);\n    if(dev \u003c 0) {\n\tprintf(\"Opening /dev/jetclocks not possible\\n\");\n\treturn -1;\n    }\n\n    /* Enabling clock \"spi1\" */\n    \n    strncpy(clock.clk, \"spi1\", sizeof(clock.clk));\n    ioctl(dev, CLK_ENABLE, \u0026clock);\n    printf(\"Enabling clock: %s \\n\",clock.clk);\n\n    close(dev);\n    return 0;\n}\n```\n\n**Disable clock:**\n\n```\n#include \u003cstdio.h\u003e\n#include \u003cstdlib.h\u003e\n#include \u003cunistd.h\u003e\n#include \u003cfcntl.h\u003e\n#include \u003cstring.h\u003e\n#include \u003csys/ioctl.h\u003e\n\n#include \"jetclocks.h\"\n\nint main() {\n\n    struct jetclk clock = {0};\n\n    int dev = open(\"/dev/jetclocks\", O_WRONLY);\n    if(dev \u003c 0) {\n\tprintf(\"Opening /dev/jetclocks not possible\\n\");\n\treturn -1;\n    }\n\n    /* Disabling clock \"spi1\" */\n    \n    strncpy(clock.clk, \"spi1\", sizeof(clock.clk));\n    ioctl(dev, CLK_DISABLE, \u0026clock);\n    printf(\"Disabling clock: %s \\n\",clock.clk);\n\n    close(dev);\n    return 0;\n}\n```\n**Set/Get clock rate:**\n\n```\n#include \u003cstdio.h\u003e\n#include \u003cstdlib.h\u003e\n#include \u003cunistd.h\u003e\n#include \u003cfcntl.h\u003e\n#include \u003cstring.h\u003e\n#include \u003csys/ioctl.h\u003e\n\n#include \"jetclocks.h\"\n\nint main() {\n\n    struct jetclk clock = {0};\n\n    int dev = open(\"/dev/jetclocks\", O_WRONLY);\n    if(dev \u003c 0) {\n\tprintf(\"Opening /dev/jetclocks not possible\\n\");\n\treturn -1;\n    }\n\n    /* Setting up rate to clock \"spi1\" */\n    \n    strncpy(clock.clk, \"spi1\", sizeof(clock.clk));\n    clock.clk_set_rate = 40800000; //Default is 81600000\n\n    ioctl(dev, CLK_SET_RATE, \u0026clock);\n    printf(\"Setting rate: %lu on clock: %s \\n\",clock.clk_set_rate, clock.clk);\n\n    /* Checking current rate on clock \"spi1\" */\n\n    ioctl(dev, CLK_GET_RATE, \u0026clock);\n    printf(\"Rate on clock: %s is %lu\\n\",clock.clk, clock.clk_rate);\n \n    close(dev);\n    return 0;\n}\n\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frubberazer%2Fjetclocks","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frubberazer%2Fjetclocks","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frubberazer%2Fjetclocks/lists"}