Configure device tree for SPI Camera

Hi everyone,

I wanted to ask is there an example device-tree for a camera connected on the SPI bus? The only one I could find is this one:

I made my dt file and the driver file based on the imx204.c driver, but when I flash the nano it’s stuck at boot. I was wondering what can cause the nano to be stuck on boot, is it the driver file or the device-tree.

This is my device-tree

/*
 * Copyright (c) 2017, NVIDIA CORPORATION.  All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

/ {
	host1x {
		vi_base: vi{
			num-channels = <1>;
			ports {
				#address-cells = <1>;
				#size-cells = <0>;
				vi_port0: port@0 {
					reg = <0>;
					status = "okay";
					imx174_vi_in0: endpoint {
						port-index = <0>;
						bus-width = <4>;
						remote-endpoint = <&imx174_csi_out0>;
					};
				};
			};
		};

		csi_base: nvcsi {
			num-channels = <1>;
			#address-cells = <1>;
            		#size-cells = <0>;
			csi_chan0: channel@0{
				reg = <0>;
				ports {
					#address-cells = <1>;
					#size-cells = <0>;
					csi_chan0_port0: port@0 {
						reg = <0>;
						imx174_csi_in0: endpoint@0 {
							port-index = <0>;
							bus-width = <4>;
							remote-endpoint = <&imx174_out0>;
						};
					};
					csi_chan0_port1: port@1 {
						reg = <1>;
						imx174_csi_out0: endpoint@1 {
							remote-endpoint = <&imx174_vi_in0>;
						};
					};
				};
			};
		};
	};

	spi@7000d400 {
		status = "okay";
		spi-max-frequency = <33000000>;
		spi_0: spi@0 {
			imx174_cam0: imx174@0 {
				compatible = "nvidia,imx174-spi";
				reg = <0>;
				status = "okay";
				spi-max-frequency = <33000000>;

				/* Physical dimensions of sensor */
				physical_w = "20.00";
				physical_h = "16.8";

				sensor_model = "imx174";

				mode0 {
					mclk_khz = "37500";
					num_lanes = "4";
					tegra_sinterface = "serial_a";
					phy_mode = "DPHY";
					discontinuous_clk = "no";
					dpcm_enable = "false";
					cil_settletime = "0";

					active_w = "1936";
					active_h = "1096";
					pixel_t = "bayer_rggb";
					readout_orientation = "0";
					line_length = "2200";
					inherent_gain = "1";
					mclk_multiplier = "2";
					pix_clk_hz = "75000000";

					min_gain_val = "0";
					max_gain_val = "240";
					step_gain_val = "1";
                			default_gain = "0";
                			min_hdr_ratio = "1";
                			max_hdr_ratio = "1";
                			min_framerate = "1500000";
                			max_framerate = "30000000"; /* 30.0 fps */
                			step_framerate = "1";
                			default_framerate = "30000000"; /* 30.0 fps */
                			min_exp_time = "30"; /* us */
                			max_exp_time = "660000"; /* us */
                			step_exp_time = "1";
                			default_exp_time = "3300"; /* us */
				};
				ports {
					#address-cells = <1>;
					#size-cells = <0>;
					port@0 {
						reg = <0>;
						imx174_out0: endpoint {
							port-index = <0>;
							bus-width = <4>;
							remote-endpoint = <&imx174_csi_in0>;
						};
					};
				};
			};
		};
	};

	tcp: tegra-camera-platform {
		compatible = "nvidia, tegra-camera-platform";
		/**
		* The general guideline for naming badge_info contains 3 parts, and is as follows,
		* The first part is the camera_board_id for the module; if the module is in a FFD
		* platform, then use the platform name for this part.
		* The second part contains the position of the module, ex. “rear” or “front”.
		* The third part contains the last 6 characters of a part number which is found
		* in the module's specsheet from the vender.
		*/
		modules {
			cam_module0: module0 {
                badge = "porg_front_IMX174";
                position = "front";
                orientation = "1";
                cam_module0_drivernode0: drivernode0 {
                    pcl_id = "v4l2_sensor";
                    devname = "imx174-spi";
                    proc-device-tree = "/proc/device-tree/spi@7000d400/imx174@0";
                };
			};
		};
	};
};

/ {
    plugin-manager {

// Fragment VC_MIPI IMX290 dual sensor
        fragement@9 {
            ids = ">=3448-0000-300", ">=3448-0002-300";
            override@0 {
                target = <&{/pcie@1003000/pci@2,0}>;
                _overlay_ {
                    nvidia,plat-gpios = <&gpio TEGRA_GPIO(CC, 7) GPIO_ACTIVE_HIGH>;
                };
            };
            override@1 {
                target = <&sdhci2>;
                _overlay_ {
                    vqmmc-supply = <&max77620_ldo6>;
                    no-sdio;
                    no-mmc;
                    sd-uhs-sdr104;
                    sd-uhs-sdr50;
                    sd-uhs-sdr25;
                    sd-uhs-sdr12;
                };
            };
            override@2 {
                target = <&throttle_oc1>;
                _overlay_ {
                    nvidia,priority = <50>;
                    nvidia,polarity-active-low = <1>;
                    nvidia,count-threshold = <1>;
                    nvidia,alarm-filter = <5100000>;
                    nvidia,alarm-period = <0>;
                    nvidia,cpu-throt-percent = <75>;
                    nvidia,gpu-throt-level =
                        <TEGRA_SOCTHERM_THROT_LEVEL_HIGH>;
                };
            };
            override@3 {
                target = <&{/leds}>;
                _overlay_ {
                    status = "okay";
                };
            };

            /* IMX290 single sensor module */
            override@4 {
                target = <&imx174_cam0>;
                _overlay_ {
                    status = "okay";
                };
            };
            override@5 {
                target = <&cam_module0>;
                _overlay_ {
                    status = "okay";
                    badge = "porg_front_IMX174";
                    position = "front";
                    orientation = "1";
                };
            };
            override@6 {
                target = <&cam_module0_drivernode0>;
                _overlay_ {
                    status = "okay";
                    pcl_id = "v4l2_sensor";
                    devname = "imx174-spi";
                    proc-device-tree = "/proc/device-tree/spi@7000d400/imx174@0";
                };
            };
            /*override@7 {
                target = <&cam_module0_drivernode1>;
                _overlay_ {
                    status = "okay";
                    pcl_id = "v4l2_lens";
                    proc-device-tree = "/proc/device-tree/lens_imx290@RBPCV2/";
                };
            };*/
            /* Enable VI ports */
            override@7 {
                target = <&vi_base>;
                _overlay_ {
                    num-channels=<1>;
                };
            };
            override@8 {
                target = <&vi_port0>;
                _overlay_ {
                    status = "okay";
                };
            };
            override@9 {
                target = <&imx174_vi_in0>;
                _overlay_ {
                    status = "okay";
                    port-index = <0>;
                    bus-width = <4>;
                    remote-endpoint = <&imx174_csi_out0>;
                };
            };
            /* Enable CSI ports */
            override@10 {
                target = <&csi_base>;
                _overlay_ {
                    num-channels = <1>;
                };
            };
            override@11 {
                target = <&csi_chan0>;
                _overlay_ {
                    status = "okay";
                };
            };
            override@12 {
                target = <&csi_chan0_port0>;
                _overlay_ {
                    status = "okay";
                };
            };
            override@13 {
                target = <&imx174_csi_in0>;
                _overlay_ {
                    status = "okay";
                    port-index = <0>;
                    bus-width = <4>;
                    remote-endpoint = <&imx174_out0>;
                };
            };
            override@14 {
                target = <&csi_chan0_port1>;
                _overlay_ {
                    status = "okay";
                };
            };
            override@15 {
                target = <&imx174_csi_out0>;
                _overlay_ {
                    status = "okay";
		    remote-endpoint = <&imx174_vi_in0>;
                };
            };
            /* tegra-camera-platform settings */
            override@16 {
                target = <&tcp>;
                _overlay_ {
                    num_csi_lanes = <4>;
                    max_lane_speed = <1500000>;
                    min_bits_per_pixel = <12>;
                    vi_peak_byte_per_pixel = <2>;
                    vi_bw_margin_pct = <25>;
                    /*max_pixel_rate = <240000>;*/
                    isp_peak_byte_per_pixel = <5>;
                    isp_bw_margin_pct = <25>;
                };
            };
            /* gpio based i2c mux */
            override@17 {
                target = <&{/spi@7000d400}>;
                _overlay_ {
                    status = "okay";
                };
            };
            override@18 {
                target = <&spi_0>;
                _overlay_ {
                    status = "okay";
                };
            };
        };

    };
};

And I also attached the .c file.

Thanks in advance!

imx174.c (23.2 KB)

Hi,
Please attach dmesg for reference. And share your release version:

$ cat /etc/nv_tegra_release

hello TeaVe,

could you please also setup the serial console to gather the boot-up logs.
we’ll need to understand what’s the failure to stuck booting.

Also you may need enable the SPI pin by add correct pin define in your device tree.

	pinmux@700008d4 {
		compatible = "nvidia,tegra210-pinmux";
...
...
		pinctrl-0 = <0x136>;
...
		header-40pin-pinmux {
			phandle = <0x136>;
			linux,phandle = <0x136>;

			pin37 {
				nvidia,enable-input = <0x1>;
				nvidia,tristate = <0x0>;
				nvidia,pull = <0x1>;
				nvidia,pins = "spi2_mosi_pb4";
				nvidia,function = "spi2";
			};

			pin28 {
				nvidia,io-high-voltage = <0x1>;
				nvidia,enable-input = <0x1>;
				nvidia,tristate = <0x0>;
				nvidia,pull = <0x0>;
				nvidia,pins = "gen1_i2c_scl_pj1";
				nvidia,function = "i2c1";
			};

			pin27 {
				nvidia,io-high-voltage = <0x1>;
				nvidia,enable-input = <0x1>;
				nvidia,tristate = <0x0>;
				nvidia,pull = <0x0>;
				nvidia,pins = "gen1_i2c_sda_pj0";
				nvidia,function = "i2c1";
			};

			pin26 {
				nvidia,enable-input = <0x1>;
				nvidia,tristate = <0x0>;
				nvidia,pull = <0x2>;
				nvidia,pins = "spi1_cs1_pc4";
				nvidia,function = "spi1";
			};

			pin24 {
				nvidia,enable-input = <0x1>;
				nvidia,tristate = <0x0>;
				nvidia,pull = <0x2>;
				nvidia,pins = "spi1_cs0_pc3";
				nvidia,function = "spi1";
			};

			pin23 {
				nvidia,enable-input = <0x1>;
				nvidia,tristate = <0x0>;
				nvidia,pull = <0x1>;
				nvidia,pins = "spi1_sck_pc2";
				nvidia,function = "spi1";
			};

			pin22 {
				nvidia,enable-input = <0x1>;
				nvidia,tristate = <0x0>;
				nvidia,pull = <0x1>;
				nvidia,pins = "spi2_miso_pb5";
				nvidia,function = "spi2";
			};

			pin21 {
				nvidia,enable-input = <0x1>;
				nvidia,tristate = <0x0>;
				nvidia,pull = <0x1>;
				nvidia,pins = "spi1_miso_pc1";
				nvidia,function = "spi1";
			};

			pin19 {
				nvidia,enable-input = <0x1>;
				nvidia,tristate = <0x0>;
				nvidia,pull = <0x1>;
				nvidia,pins = "spi1_mosi_pc0";
				nvidia,function = "spi1";
			};

			pin18 {
				nvidia,enable-input = <0x1>;
				nvidia,tristate = <0x0>;
				nvidia,pull = <0x2>;
				nvidia,pins = "spi2_cs0_pb7";
				nvidia,function = "spi2";
			};

			pin16 {
				nvidia,enable-input = <0x1>;
				nvidia,tristate = <0x0>;
				nvidia,pull = <0x2>;
				nvidia,pins = "spi2_cs1_pdd0";
				nvidia,function = "spi2";
			};

			pin13 {
				nvidia,enable-input = <0x1>;
				nvidia,tristate = <0x0>;
				nvidia,pull = <0x1>;
				nvidia,pins = "spi2_sck_pb6";
				nvidia,function = "spi2";
			};

			pin10 {
				nvidia,enable-input = <0x1>;
				nvidia,tristate = <0x1>;
				nvidia,pull = <0x2>;
				nvidia,pins = "uart2_rx_pg1";
				nvidia,function = "uartb";
			};

			pin8 {
				nvidia,enable-input = <0x0>;
				nvidia,tristate = <0x0>;
				nvidia,pull = <0x0>;
				nvidia,pins = "uart2_tx_pg0";
				nvidia,function = "uartb";
			};

			pin5 {
				nvidia,io-high-voltage = <0x1>;
				nvidia,enable-input = <0x1>;
				nvidia,tristate = <0x0>;
				nvidia,pull = <0x0>;
				nvidia,pins = "gen2_i2c_scl_pj2";
				nvidia,function = "i2c2";
			};

			pin3 {
				nvidia,io-high-voltage = <0x1>;
				nvidia,enable-input = <0x1>;
				nvidia,tristate = <0x0>;
				nvidia,pull = <0x0>;
				nvidia,pins = "gen2_i2c_sda_pj3";
				nvidia,function = "i2c2";
			};
		};

Thank you for taking the time to reply to me, I found the problem, my device tree was not correctly defined and I had some mistakes in the driver file as well.

This is the correct configuration that worked in my case:

/*
 * Copyright (c) 2017, NVIDIA CORPORATION.  All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

/ {
	host1x {
		vi_base: vi{
			num-channels = <1>;
			ports {
				#address-cells = <1>;
				#size-cells = <0>;
				vi_port0: port@0 {
					reg = <0>;
					status = "okay";
					imx174_vi_in0: endpoint {
						port-index = <0>;
						bus-width = <4>;
						remote-endpoint = <&imx174_csi_out0>;
					};
				};
			};
		};

		csi_base: nvcsi {
			num-channels = <1>;
			#address-cells = <1>;
            		#size-cells = <0>;
			csi_chan0: channel@0{
				reg = <0>;
				ports {
					#address-cells = <1>;
					#size-cells = <0>;
					csi_chan0_port0: port@0 {
						reg = <0>;
						imx174_csi_in0: endpoint@0 {
							port-index = <0>;
							bus-width = <4>;
							remote-endpoint = <&imx174_out0>;
						};
					};
					csi_chan0_port1: port@1 {
						reg = <1>;
						imx174_csi_out0: endpoint@1 {
							remote-endpoint = <&imx174_vi_in0>;
						};
					};
				};
			};
		};
	};

	spi@7000d400 {
		status = "okay";
		spi-max-frequency = <33000000>;
			imx174_cam0: imx174@0 {
				compatible = "nvidia,imx174-spi";
				reg = <0>;
				status = "okay";
				spi-max-frequency = <33000000>;

				/* Physical dimensions of sensor */
				physical_w = "20.00";
				physical_h = "16.8";

				devnode = "video0";
				devname = "imx174-spi";
				sensor_model = "imx174";

				mode0 {
					mclk_khz = "37500";
					num_lanes = "4";
					tegra_sinterface = "serial_a";
					phy_mode = "DPHY";
					discontinuous_clk = "no";
					dpcm_enable = "false";
					cil_settletime = "0";

					active_w = "1936";
					active_h = "1096";
					pixel_t = "bayer_rggb";
					readout_orientation = "0";
					line_length = "2200";
					inherent_gain = "1";
					mclk_multiplier = "2";
					pix_clk_hz = "75000000";

					min_gain_val = "0";
					max_gain_val = "240";
					step_gain_val = "1";
                			default_gain = "0";
                			min_hdr_ratio = "1";
                			max_hdr_ratio = "1";
                			min_framerate = "1500000";
                			max_framerate = "30000000"; /* 30.0 fps */
                			step_framerate = "1";
                			default_framerate = "30000000"; /* 30.0 fps */
                			min_exp_time = "30"; /* us */
                			max_exp_time = "660000"; /* us */
                			step_exp_time = "1";
                			default_exp_time = "3300"; /* us */
				};
				ports {
					#address-cells = <1>;
					#size-cells = <0>;
					port@0 {
						reg = <0>;
						imx174_out0: endpoint {
							port-index = <0>;
							bus-width = <4>;
							remote-endpoint = <&imx174_csi_in0>;
						};
					};
				};
			};
	};

	tcp: tegra-camera-platform {
		compatible = "nvidia, tegra-camera-platform";
		/**
		* The general guideline for naming badge_info contains 3 parts, and is as follows,
		* The first part is the camera_board_id for the module; if the module is in a FFD
		* platform, then use the platform name for this part.
		* The second part contains the position of the module, ex. “rear” or “front”.
		* The third part contains the last 6 characters of a part number which is found
		* in the module's specsheet from the vender.
		*/
		modules {
			cam_module0: module0 {
                badge = "porg_front_IMX174";
                position = "front";
                orientation = "1";
                cam_module0_drivernode0: drivernode0 {
                    pcl_id = "v4l2_sensor";
                    devname = "imx174_spi";
                    proc-device-tree = "/proc/device-tree/spi@7000d400/imx174@0";
                };
			};
		};
	};
};

/ {
    plugin-manager {

// Fragment VC_MIPI IMX290 dual sensor
        fragment@9 {
			ids = "3377-1000-*";
			override@0 {
				target = <&imx174_cam0>;
				_overlay_ {
					status = "okay";
				};
			};
			override@1 {
				target = <&cam_module0>;
				_overlay_ {
					status = "okay";
					badge = "porg_front_IMX174";
					position = "front";
					orientation = "1";
				};
			};
			override@2 {
				target = <&cam_module0_drivernode0>;
				_overlay_ {
					status = "okay";
					pcl_id = "v4l2_sensor";
					devname = "imx174_spi";
					proc-device-tree = "/proc/device-tree/spi@7000d400/imx174@0";
				};
			};
            /* Enable VI ports */
            override@3 {
                target = <&vi_base>;
                _overlay_ {
                    num-channels=<1>;
                };
            };
            override@4 {
                target = <&vi_port0>;
                _overlay_ {
                    status = "okay";
                };
            };
            override@5 {
                target = <&imx174_vi_in0>;
                _overlay_ {
                    status = "okay";
                    port-index = <0>;
                    bus-width = <4>;
                    remote-endpoint = <&imx174_csi_out0>;
                };
            };
            /* Enable CSI ports */
            override@6 {
                target = <&csi_base>;
                _overlay_ {
                    num-channels = <1>;
                };
            };
            override@7 {
                target = <&csi_chan0>;
                _overlay_ {
                    status = "okay";
                };
            };
            override@8 {
                target = <&csi_chan0_port0>;
                _overlay_ {
                    status = "okay";
                };
            };
            override@9 {
                target = <&imx174_csi_in0>;
                _overlay_ {
                    status = "okay";
                    port-index = <0>;
                    bus-width = <4>;
                    remote-endpoint = <&imx174_out0>;
                };
            };
            override@10 {
                target = <&csi_chan0_port1>;
                _overlay_ {
                    status = "okay";
                };
            };
            override@11 {
                target = <&imx174_csi_out0>;
                _overlay_ {
                    status = "okay";
		    remote-endpoint = <&imx174_vi_in0>;
                };
            };
            /* tegra-camera-platform settings */
            override@12 {
                target = <&tcp>;
                _overlay_ {
                    num_csi_lanes = <4>;
                    max_lane_speed = <1500000>;
                    min_bits_per_pixel = <12>;
                    vi_peak_byte_per_pixel = <2>;
                    vi_bw_margin_pct = <25>;
                    /*max_pixel_rate = <240000>;*/
                    isp_peak_byte_per_pixel = <5>;
                    isp_bw_margin_pct = <25>;
                };
            };
        };
    };
};

imx174.c (23.1 KB)

Now the camera is binded and I get /dev/video0 :)