Tegra X1 System Address Map


I have what I hope is a simple question - when referencing the System Address Map in the Tegra X1 Technical Reference Manual, are the address values given physical memory addresses or virtual? I am working on writing a Linux Kernel Module to implement some interrupt functionality and was wondering if passing an address from this map to the phys_to_virt() function would be appropriate.

Thank you

I don’t know about specific use cases here, but in general all i2c controller addresses (there will be more than one of any controller type) are physical addresses, and TRMs refer to a unified set of “offset” addresses relative to the base physical address of whichever controller you are working with.

Controller setup and mapping is normally done in the device tree. The default device tree is unlikely to need modification to work with, but if for example you used a different carrier board which is wired differently, then the device tree would be how the driver finds the controller, and the device tree would have certain enable or disable functions available for the specific controller.

This is a subset of a TX2 device tree (I have a TX2 running next to me, I don’t happen to have a Nano running at the moment) for one i2c controller (just to illustrate):

        i2c@c240000 {
                compatible = "nvidia,tegra186-i2c";
                clocks = <0x10 0xda 0x10 0x10d 0x10 0xdd>;
                resets = <0x10 0x14>;
                scl-gpio = <0x28 0x30 0x0>;
                sda-gpio = <0x28 0x31 0x0>;
                clock-names = "div-clk", "parent", "slow-clk";
                status = "okay";
                #address-cells = <0x1>;
                interrupts = <0x0 0x1a 0x4>;
                #size-cells = <0x0>;
                dma-names = "rx", "tx";
                phandle = <0x17e>;
                reg = <0x0 0xc240000 0x0 0x100>;
                iommus = <0x11 0x20>;
                clock-frequency = <0x61a80>;
                dmas = <0x25 0x16 0x25 0x16>;
                reset-names = "i2c";
                linux,phandle = <0x17e>;

In that example the base physical address of the controller is “0xc240000”, and you might find this referred to as i2c@c240000 to name the specific controller. If the TRM lists a function for a controller, and names an offset of 0x10, then all controllers would have that same function at 0x10 offset above 0xc240000 (assuming the controller is in a state for that function).

If you want something interesting just to explore, consider that file content in “/sys” is really purely in RAM and not a real file. The files there are a direct reflection of drivers. Do this to see interesting i2c files:

sudo -s
find /sys -name '*i2c*'

Notice that a large number of i2c devices have what is a hexadecimal base address along with “i2c”, and this is from the i2c controller at that physical address (in kernel space the drivers normally refer to physical addresses…DMA operations after setup, and user space operations usually refer to virtual addresses).

If you want to see what your current device tree is, then explore “/proc/device-tree/”. The file structure is the same tree structure as in the device tree. You can create a source code extract of the current device tree via:

sudo apt-get install device-tree-compiler
dtc -I fs -O dts -o extracted.dts /proc/device-tree

Note that some files in “/sys” are read-only, and you can “cat” that file to see content. Others are write-only, and you cannot cat, but you can echo a value in and the driver will do whatever it is programmed for when that value is written in (if in a state capable of honoring that write). Other “/sys” files are read-write. Often there are debug files in “/sys” which would tell you what a certain controller is set up to work as. As an example, on a TX2, I have this:


…this is a strong hint that the i2c controller at physical address 0x31e0000 is doing something with audio. If I then look at this directory:


…I can find file “status”, and “cat status” (after I cd there) says:


This means the i2c controller at that address was told to try to run with whatever initial state that block of the device tree was set up with. If this had instead been this, then the controller would more or less be inert and without setup (useful if you have a controller with no wiring to the outside world):

status = "disabled";

As for specific i2c controllers and setup, someone else will need to answer that.

Thank you for the informative answer, this was very helpful. Exploring my device tree on the Nano, I see I2C controllers starting at “i2c@7000c000”, which is the address start listed in the TRM for the Tegra X1’s first I2C controller.