How to apply PWM-patch?


I am trying to generate a PWM-signal via PWM1 by following this tutorial:

However it is not totally clear to me how to apply this patch. I found one single “board-ardbeg-panel.c”-file in /usr/src/kernel/arch/arm/mach-tegra/

What next? How shall I proceed? Because I see that this patch file makes a a comparison between two file while I only have one on my system.

The ‘-’ lines are lines which get removed, and a ‘+’ line is a line which gets added. Usually 1 line removed with 1 added. For reference example from that URL:

@@ -1015,10 +1015,10 @@

pu3 {
nvidia,pins = "pu3";
- nvidia,function = "gmi";
+ nvidia,function = "pwm0";
nvidia,pull = <TEGRA_PIN_PULL_NONE>;
nvidia,tristate = <TEGRA_PIN_DISABLE>;

At around line 1015 (changes depending on your file), 10 lines are affected. Within that, this line is replaced:

nvidia,function = "gmi";

…the code replacing it is:

nvidia,function = "pwm0";

The reason two files are mentioned is because it is a difference between a “before” and “after” file.

Thanks for your reply

I copied this to a separate file called myPatch (no specific extention):

diff --git a/arch/arm/mach-tegra/board-ardbeg-panel.c b/arch/arm/mach- tegra/board-ardbeg-panel.c
index c7da1e3..f954956 100644
--- a/arch/arm/mach-tegra/board-ardbeg-panel.c
+++ b/arch/arm/mach-tegra/board-ardbeg-panel.c
@@ -765,7 +765,6 @@ static struct tegra_panel      *ardbeg_panel_configure(struct board_info *board_out,
- panel = &dsi_p_wuxga_10_1;
@@ -775,7 +774,7 @@ static struct tegra_panel                      *ardbeg_panel_configure(struct board_info *board_out,
return panel;

-static void ardbeg_panel_select(void)
+static struct tegra_panel *ardbeg_panel_select(void)
struct tegra_panel *panel = NULL;
struct board_info board;
@@ -828,6 +827,8 @@ static void ardbeg_panel_select(void)

+ return panel;

@@ -837,7 +838,7 @@ int __init ardbeg_panel_init(void)
struct resource __maybe_unused *res;
struct platform_device *phost1x = NULL;
struct board_info board_info;
+ struct tegra_panel *panel = NULL;
struct device_node *dc1_node = NULL;
struct device_node *dc2_node = NULL;
@@ -848,7 +849,7 @@ int __init ardbeg_panel_init(void)
find_dc_node(&dc1_node, &dc2_node);

- ardbeg_panel_select();
+ panel = ardbeg_panel_select();

@@ -943,8 +944,8 @@ int __init ardbeg_panel_init(void)
tegra_fb2_start, tegra_fb2_size);

- if (!of_have_populated_dt() || !dc1_node ||
- !of_device_is_available(dc1_node)) {
+ if (panel && (!of_have_populated_dt() || !dc1_node ||
+ !of_device_is_available(dc1_node))) { = &phost1x->dev;
err = platform_device_register(&ardbeg_disp1_device);
if (err) {

and tried to apply it as follows:

cd  /usr/src/kernel/arch/arm/mach-tegra/

git apply /pathToMyPatch/myPatch

But that returns: fatal: corrupt patch at line 6

Am I doing this incorrectly?

The traditional file name extension for this is “.diff”, and if you use a tool to update based on local files then the tool is “patch”. You might consider just updating the lines by hand with an editor to see what it’s doing.

Sorry, more explanation is a bit long, I don’t know what you already know about diff, patch, and git tools.

git has some ability to compare one file against a git repo file assuming you have access to the repo. I don’t know about the corrupt patch note, but I see this as your first line being different than the patch (this assumes what you pasted here is the same as what you used…perhaps other lines were also changed due to copy and paste errors…note the extra space in this case):

# Your .diff:
diff --git a/arch/arm/mach-tegra/board-ardbeg-panel.c b/arch/arm/<b>mach- tegra</b>/board-ardbeg-panel.c
# Web URL's .diff:
diff --git a/arch/arm/mach-tegra/board-ardbeg-panel.c b/arch/arm/<b>mach-tegra</b>/board-ardbeg-panel.c

Typically at the top of a patch file you’d see two file paths. One is an original file, another is the destination to patch to make those blocks of code the same. The diff tool creating the diff file requires both files to be present; the patch tool requires a diff file (a specification of differences) and the destination file to edit (diff finds differences, patch reverses differences). Often the paths are shown as relative paths like this:


…in this example the “a/” and “b/” are “levels”. If you cd to a directory where you see the file path “b/some/path/file.c”, then you’d just use “patch” without a “-pNumber” (or with “-p0” which is the same as no stripping of a path element or level). If you had done a “cd b/some/” from that sample location (you performed a cd to two directories closer to the edit file), then you’d need to strip two levels for the patch tool, and the patch command would be:

patch -p2 < patchfile.diff

(see “man patch”)

git can deal with differences using git repositories. git can generate a diff file based on file revisions or different repositories. git can patch with a diff. The diff tool requires two exact hard files and does not understand repositories or revision numbers; git can refer to different file revision specifications (versus hard files) in a git repo. You are patching to a local file and have a “.diff” file for specification, so you do not need to use the git command. The reason you might be interested in git is that instead of copy and paste to create a diff file you could just use git if you know the remote git file specification.

Think of something like this:

cd /where/ever/kernel/source/is/
cd arch/arm/mach-tegra/
patch -p3 < /where/ever/it/is/the_diff_file.diff

The “-p3” is because you want to strip 3 leading directories of:


(you are in “mach-tegra”, your cd took away the meaning of “b/arch/arm/” and puts you in “mach-tegra/”)

can someone please explain the whole procedure step by step of how to apply the patch?? i am a newbie to linux and unable to understand the process. i would be grateful if u could also upload some snaps of the process

To some extent it depends which Linux version you have flashed to your Jetson. Have you flashed yet? If not, it is advised. You can see what your current version is via:

head -n 1 /etc/nv_tegra_release

JetPack is a front end to the flash software (it does a few things on top of just flash, but flash is the basic update). The Ubuntu Linux distribution is just one “flavor” of Linux (“Linux” is really the kernel, everything around it is part of the “distribution”, e.g., Ubuntu versus RedHat/Fedora versus Debian versus SuSE, so on). When NVIDIA hardware drivers are added to Ubuntu it’s known as “Linux for Tegra” (L4T). The current JetPack version is 3.1, which can flash Ubuntu onto the Jetson…but is known as L4T 21.6 so far as the most recent release goes. JetPack itself is installed only to a PC host, so you can’t really say you have flashed JetPack (you can say you used JetPack to flash the Jetson with L4T R21.6).

The minimal requirement is to flash on command line without JetPack. This requires the driver package plus sample rootfs. JetPack automatically downloads these, but command line works from any Linux x86_64 PC host, while JetPack requires Ubuntu (either 14.04 or 16.04). For downloading see:
(the driver package contains “”, a script which can download the kernel source)

The patch in question is for the kernel. This implies you need kernel source which matches your running Jetson (hopefully L4T R21.6). This means not only do you need the same source code version, it also means that configuration before building the kernel must match the current configuration. Once you can build a kernel which exactly matches you should be able to then apply the patch and rebuild with just that change.

Within kernel configuration features can be added as integrated into the kernel (the “Image” or “zImage” file…the former is uncompressed, the latter is compressed, yet otherwise identical), or features can exist in the form of a loadable module (the existing kernel can load or unload the module without changing the kernel itself). Many features can be built as a module, not all of them can. Many features are drivers. If you are curious go to your Jetson and copy file “/proc/config.gz” somewhere, then run “gunzip” on it. You’ll be able to use a text editor (such as “nano”) to browse it. Inactive features will be commented out with a leading “#”, integrated features will show “=y”, and module features will show as “=m”. During a menu editor session the “y” key typically selects as integrated, the “m” key typically selects as a module, “n” as disabled (spacebar can toggle as well).

Before explaining too much have you flashed yet? If not, then you should start there, and after the successful flash save a copy of “/proc/config.gz” (probably save it to a unique name and don’t lose it, e.g., “config-R21.6-original.gz”).

It sounds more complicated than it is for the most part, but if you have never built a kernel a first time through can make things a lot more clear.

FYI, if you have a serial console cable for the 9-pin D-sub connector to monitor boot with from your host PC life will be much easier. The reason is that if you replace parts or all of a kernel and do it incorrectly you may need to re-flash if it fails…but with serial console you can just make alternate boot configurations instead and leave the original in place…if the test boot fails you’d just select the original configuration and repeat until it is correct (no flash for every failure).

i have flashed using jetpack 3.0 which has L4T 21.5 for TK1. i am using ubuntu 14.04

R21.5 was almost exactly the same as R21.6, but there were new bluetooth vulnerabilities discovered, and thus R21.6 had security patches. R21.6 is still advised, but if you don’t use bluetooth, then it might not matter. I suggest you flash R21.6 before starting…clone first if you want. You can keep going on R21.5 and chances are it won’t hurt anything, but I’m using R21.6 here so for example a file download name might differ slightly, plus I sometimes rename files with a version number…many files (perhaps even including the kernel) are exact matches between the two.
R21.6 URL:
R21.5 URL:

Instead of cross compiling I am going to suggest to simplify your life and do the build directly on the Jetson. Cross compiling is an extension to this (everything here still applies). If you don’t have enough disk space you might want to consider doing this on an SD card formatted to ext4 and mounted somewhere for temporary disk space, but normally this isn’t an issue. You can see what disk space you have for a partition from “df -H”…if you run “df -H .” from the location you want to add source (note that “.” is short for “the current directory”, and “…” is short for “the parent of the current directory”) and compile you’ll know how much space you have there. Normally this isn’t a problem, but I don’t know what you have on your system or if it was flashed to use the full eMMC.

Before you start you probably want to make sure you can run some of the terminal-based config utilties. For that reason you need to install package “libncurses5-dev”:

sudo apt-get install libncurses5-dev

You can login and run as non-root (no sudo) until it comes time to actually install something. Unless I use sudo below this is logged in as user “ubunut”. I have “/usr/src/kernels/” set up as owned by user “ubuntu” (if it isn’t there “sudo mkdir /usr/src/kernels; sudo chown ubuntu.ubuntu /usr/src/kernels”). I downloaded the kernel source there from the R21.6 URL (which happens to be “kernel-3.10.40_R21-4_src.tbz2”), and unpacked it, then renamed it for that version:

cd /usr/src/kernels
tar xvfj kernel-3.10.40_R21-4_src.tbz2
mv kernel kernel-3.10.40

I then set up by starting with an exact copy of my current config:

cp /proc/config.gz .
gunzip config.gz
mv config config-3.10-40-original

I made temporary output locations for intermediate results…this could be put on an SD card instead if you are worried about space (adjust what follows to some other temporary location if you want to do this):

mkdir kernel_build
mkdir kernel_modules
mkdir kernel_firmware

If you are just building the kernel, and not modules, then you don’t need “kernel_modules”. If you are not building firmware (and for your purposes you don’t need this…but it is listed in case others want this information), then you don’t need “kernel_firmware”. It doesn’t hurt to have the directories in place.

Set up some environment variables for convenience ("pwd" in the back quotes echoes the current directory…if you cd to that directory first and then use pwd for setup you are guaranteed to typographic errors):

cd kernel-3.10.40
export SRC=`pwd`
cd ../kernel_build
export TEGRA_KERNEL_OUT=`pwd`
cd ../kernel_modules
export TEGRA_MODULES_OUT=`pwd`
cd ../kernel_firmware

Just for reference, if you run “uname -r” you will see something like “3.10.40-gb271e8f”. The 3.10.40 is the version of the kernel source, the “-gb271e8f” is from a kernel option “CONFIG_LOCALVERSION”. CONFIG_LOCALVERSION is usually based on some unique value for the configuration used on that kernel…it’s entirely up to the person compiling…this does not cause a change in the kernel other than changing what the “uname -r” will respond to. This is important because the kernel modules will be searched for in “/lib/modules/$(uname -r)/”…which means if you compile a new kernel and “uname -r” differs, then the kernel won’t find any of its existing modules. Keeping “uname -r” the same implies you can re-use modules. However, if you change the config in the wrong way, your existing modules will become invalid…you would want to change “uname -r” in this case and avoid using old modules. In the case of this kernel the “-gb271e8f” is from the git source code unique identifier. You want to match it for this case.

The patch listed does not change the kernel, it changes the device tree. You should build the kernel just to be sure it is configured correctly (some device tree details will change depending on configuration), but technically speaking, “uname -r” won’t matter and only the device tree will be used. Remember though that if you don’t succeed at a build stage, then it is a sign something isn’t right…build the kernel and modules first just to see if you got it right before you use the new device tree (.dtb file). The dtb file will be built as a side-effect anyway.

The following does not include the device tree changes…see if you can build first without the changes. Then do the same thing with the changes.

Now for some actual work (note that in command line “bash” that a line starting with “#” is a comment…also sometimes a comment on the right of an actual command):

cd $SRC
# Make sure the exist kernel is completely pristine...not necessary after unpacking,
# but not a bad idea either.
make mrproper
# Make sure the output location is pristine:
make O=$TEGRA_KERNEL_OUT mrproper
# Set up config to match the existing system:
cp -f $SRC/../config-3.10.40 $TEGRA_KERNEL_OUT/.config
make O=$TEGRA_KERNEL_OUT menuconfig

One of several menu editors will open. Because the “.config” file was in place at $TEGRA_KERNEL_OUT it will reflect that existing config. All you will need to do is edit CONFIG_LOCALVERSION. To do this navigate to “General setup —>”, move down one line to “Local version - append to…”, hit the enter key, type in “-gb271e8f” (the suffix of “uname -r”), and hit the enter key. Now cursor to the right and hit “Save”, let it save to the default “.config”, and exit. Your kernel now matches exactly your running system. Try it out:

make -j4 O=$TEGRA_KERNEL_OUT zImage
# This builds the files from the device tree...this is what the patch will involve:
make -j4 O=$TEGRA_KERNEL_OUT dtbs

The “find” command will come in useful. Basically:

find TheStartDirectory -name "NameOrPatternToFind"

So to find the zImage you built:

find $TEGRA_KERNEL_OUT -name zImage

See all of the dtb files built:

find $TEGRA_KERNEL_OUT -name '*.dtb'

Each dtb file is built from a number of others and may or may not matter to you.

If this succeeded, then anything else you might build should probably work. You don’t need modules or firmware for this purpose, the dtb file relevant to the patch will be built after zImage…I’ll go back and tell you how to do that instead, but first I’ll add the last steps for building everything in case someone needs it.
cd $SRC

make -j4 O=$TEGRA_KERNEL_OUT modules
# modules will be found in $TEGRA_MODULES_OUT/lib/modules/3.10-40-gb271e8f/
ls $TEGRA_MODULES_OUT/lib/modules

Without the “INSTALL_MOD_PATH=$TEGRA_MODULES_OUT” you would be putting the modules directly on the running system in “/lib/modules/<kernel_versionCONFIG_LOCALVERSION>/”. If you are just building a module and installing it to the existing system this might be what you want.

Firmware can be installed to $TEGRA_FIRMWARE_OUT via:


Without “INSTALL_FW_PATH” this would go directly into the operating system. Building as user “ubuntu” keeps you from doing this by accident since the paths are owned by root.


Back to the dtb patch! The original names a git repository, but we do not have that. Notice though that it names this path:


The “a/” implies one set of source code, yours might be a “b/”. It’s symbolic…think of “a/” as original, and “$SRC/something/” as your version. In this case we are looking at files specific to the 32-bit ARM architecture, or just “arm”. Go there now in your source:

cd $SRC
cd <b>arch/</b>arm/boot/dts/tegra124-platforms/
ls tegra124-jetson_tk1-gpio-pm375-0000-c00-00.dtsi

You could use patch tools to apply the patch if you had a valid patch/diff file (copy and paste from that web site leaves a file in need of edits), but I’ll just go through the edits and do what the patch tool would do. You’ll need a text editor, e.g., “sudo apt-get install nano” and then “nano tegra124-jetson_tk1-gpio-pm375-0000-c00-00.dtsi”. Unfortunately this doesn’t list line numbers…I like vi, but this has a very steep learning curve. If you have a GUI, you might want “sudo apt-get install geany”, then:

geany tegra124-jetson_tk1-gpio-pm375-0000-c00-00.dtsi &

The patch starts with “@@ -36,10 +36,7 @@”, implying go to line 36, refer to 10 lines following, and when done, there will be 7 lines representing the first original 10 lines. Lines surrounding this are “context” lines to make it possible to be sure you have the right lines. The “-” lines are lines to remove, the “+” lines are lines to insert. So for example, I see line 36 in my source matches the patch context lines, and that the line with content “TEGRA_GPIO(U, 3)”, and two other lines, are to be deleted. Do so. Save the file.

The next file is named via “diff --git a/arch/arm/boot/dts/tegra124-platforms/tegra124-jetson_tk1-pinmux-pm375-0000-c00-00.dtsi b/arch/arm/boot/dts/tegra124-platforms/tegra124-jetson_tk1-pinmux-pm375-0000-c00-00.dtsi”…this is the same directory and file as before, but from the start (if you have the editor still open just keep using it):

cd $SRC/arch/arm/boot/dts/tegra124-platforms/
ls tegra124-jetson_tk1-pinmux-pm375-0000-c00-00.dtsi
geany tegra124-jetson_tk1-pinmux-pm375-0000-c00-00.dtsi &

The lines have changed, indicated by “@@ -1015,10 +1015,10 @@”. If you hadn’t deleted the 3 lines earlier the correct line is 1015, and the context lines surrounding the edits would verify this. Since you are missing 3 lines you will need to adjust. Replace the line with “nvidia,function = “gmi”;” to instead be “nvidia,function = “pwm0”;”…the same with the line three lines down…“nvidia,enable-input = <TEGRA_PIN_ENABLE>” is edited to instead be “nvidia,enable-input = <TEGRA_PIN_DISABLE>;”. Save the file.

There are four more lines to edit, the reference is via “@@ -1031,18 +1031,18 @@”. So line 1031 is the starting location if the file were the original…you must adjust for the three lines previously deleted. Within the pu5 block replace “nvidia,function = “gmi”;” with “nvidia,function = “pwm2”;”. Three lines down replace “nvidia,enable-input = <TEGRA_PIN_ENABLE>;” with “nvidia,function = “pwm2”;”. Within the pu6 block, in a similar fashion, edit those two lines…remove the “-” lines and insert the “+” lines. Save and exit.

The next patch edits “arch/arm/mach-tegra/board-ardbeg-panel.c b/arch/arm/mach-tegra/board-ardbeg-panel.c”. The procedure is the same.

If you had valid diff files then something like “patch -p1 <patch_file.diff” would apply patches for you. I’ve had issues with copy and paste from that web site so I did it the hard way.


I have not used this particular patch. One or more of the dtb files produced will be the correct file after you run the “make O=$TEGRA_KERNEL_OUT dtbs” command while the source is edited:

find $TEGRA_KERNEL_OUT -name '*.dtb'

However, if you look at “/boot/extlinux/extlinux.conf” you will see a line with a key/value pair, “FDT”. This is the device tree file. On mine it says:

FDT /boot/tegra124-jetson_tk1-pm375-000-c00-00.dtb

…so if the edits propagate into this file:

find $TEGRA_KERNEL_OUT -name tegra124-jetson_tk1-pm375-000-c00-00.dtb

…then this is the file you use from the $TEGRA_KERNEL_OUT to replace the one in “/boot”.

An alternative if you have serial console is to make an alternate boot entry and put the new file in with an alternate name…leave the original…and put the name edit in the FDT entry.

is there any option to arm apm or pixhawk using tk1 apart from mavlink?? and also how to use mavlink in tk1. if possible, please post the links for tutorial as well

I’ve never used anything needing mavlink, so I do not know. I do know pixhawk is popular though with more than one Jetson platform. Don’t let all of the details scare you if it just the kernel patch and build…just take it step by step. If a step has an issue or you want to ask, just post the question.

Someone who knows about mavlink/apm/pixhawk may be able to comment on what works best or least for a TK1.

Not sure, but if I remember correctly, pixhawk was requiring usbcore_autosuspend to be disabled at boot time in extlinux.conf, and maybe also required usb ACM modem support.