Voltage regulator setup in jetson tx2

Hi. All,

I debug custom camera board in Jetson Tx2.
I want to supply DVDD_CAM_IO_1V8 voltage in custom camera board.

i refered to sample code"tegra186-quill-camera-imx274-dual.dtsi" as shown below.

i2c@3180000 {
tca9546@70 {
compatible = “nxp,pca9546”;
reg = <0x70>;
#address-cells = <1>;
#size-cells = <0>;
skip_mux_detect = “yes”;
vcc-supply = <&en_vdd_cam>;
vcc_lp = “vcc”;
force_bus_start = <CAMERA_I2C_MUX_BUS(0)>;

  	i2c@0 {
  		reg = <0>;
  		i2c-mux,deselect-on-exit;
  		#address-cells = <1>;
  		#size-cells = <0>;
  		imx274_a@1a {
  			/* Define any required hw resources needed by driver */
  			/* ie. clocks, io pins, power sources */
  			clocks = <&tegra_car TEGRA186_CLK_EXTPERIPH1>,
  					 <&tegra_car TEGRA186_CLK_PLLP_OUT0>;
  			clock-names = "extperiph1", "pllp_grtba";
  			mclk = "extperiph1";
  			reset-gpios = <&tegra_main_gpio CAM0_RST_L GPIO_ACTIVE_HIGH>;
  			vana-supply = <&en_vdd_cam_hv_2v8>;
  			vif-supply = <&en_vdd_cam>;
  		};
  	};
  	i2c@1 {
  		reg = <1>;
  		i2c-mux,deselect-on-exit;
  		#address-cells = <1>;
  		#size-cells = <0>;
  		imx274_c@1a {
  			/* Define any required hw resources needed by driver */
  			/* ie. clocks, io pins, power sources */
  			clocks = <&tegra_car TEGRA186_CLK_EXTPERIPH1>,
  					 <&tegra_car TEGRA186_CLK_PLLP_OUT0>;
  			clock-names = "extperiph1", "pllp_grtba";
  			mclk = "extperiph1";
  			reset-gpios = <&tegra_main_gpio CAM0_PWDN GPIO_ACTIVE_HIGH>;
  			vana-supply = <&en_vdd_cam_hv_2v8>;
  			vif-supply = <&en_vdd_cam>;
  		};
  	};
  };

};

what is stand for “DVDD_CAM_IO_1V8” ?
i think it is “vcc-supply = <&en_vdd_cam>;”
where do i place 1v8 supply define in device tree?

and then i add function “regulator_get” in parse_dt of device driver as shown below.

/* digital 1.8v */
if (of_get_property(np, “vdd-supply”, NULL)) {
priv->vdd_cam = regulator_get(&priv->client->dev, “vdd_cam”);
if (IS_ERR(priv->vdd_cam)) {
dev_err(&priv->client->dev,
“vdd_cam_1v8 regulator get failed\n”);
err = PTR_ERR(priv->vdd_cam);
priv->vdd_cam = NULL;
return err;
}
else
dev_info(dev, “%s: - vdd_cam_1v8 regulator get sucessed\n”, func);
} else {
priv->vdd_cam = NULL;
}

I loaded kernel module and then it occured segment fault.
What am i miss the setting for regulator_get?

hello jpchae,

please access Jetson TX2 Series Camera Module Hardware Design Guide via download center.
you may check chapter-4 for the power sources from the Jetson connector,
thanks

Hi JerryChang,

As you recommend , I checked Camera Module Hardware Design Guide.
I found that DVDD_CAM_1V8 is from 1.8V digital IO power.

but, i don’t know how to use DVDD_CAM_1V8 in custom device driver.
please, how to setup DVDD_CAM_1V8 power in my device tree, device driver.

Thanks,

hello jpchae,

please access L4T sources via download center.

please check below paragraph for regulator definition and also the usage from low-level driver side.

  1. you may check the device tree sources for the regulator definitions,
    for example,
    $L4T_Sources/r32.4.4/Linux_for_Tegra/source/public/hardware/nvidia/platform/t18x/common/kernel-dts/t18x-common-platforms/tegra186-cvb-prod-p2597-b00-p3489-1000-a00-00.dtsi
        fixed-regulators {
                ...
                en_vdd_cam: regulator@2 {
                        compatible = "regulator-fixed-sync";
                        reg = <2>;
                        regulator-name = "en-vdd-cam";
                        regulator-min-microvolt = <1800000>;
                        regulator-max-microvolt = <1800000>;
                        gpio = <&gpio_i2c_0_77 9 1>;
                        enable-active-high;
                };
  1. here’s en_vdd_cam for 1.8V voltage, it has been reported as vif-supply within sensor device tree.
    for example,
    $L4T_Sources/r32.4.4/Linux_for_Tegra/source/public/hardware/nvidia/platform/t18x/common/kernel-dts/t18x-common-platforms/tegra186-quill-camera-e3333-a00.dtsi
                        i2c@0 {
                                ov5693_a@36 {
                                        ...
                                        vana-supply = <&en_vdd_cam_hv_2v8>;
                                        vif-supply = <&en_vdd_cam>;
  1. here’s sensor mode device tree property that having definition.
    for example,
    $L4T_Sources/r32.4.4/Linux_for_Tegra/source/public/hardware/nvidia/platform/t18x/common/kernel-dts/t18x-common-modules/tegra186-camera-e3333-a00.dtsi
        i2c@3180000 {
                tca9548@77 {
                        i2c@0 {
                                ov5693_a@36 {
                                         ...
                                        /* Define any required hw resources needed by driver */
                                        /* ie. clocks, io pins, power sources */
                                        avdd-reg = "vana";
                                        iovdd-reg = "vif";
  1. it’s sensor driver to parse DT for regulators.
    for example,
    $L4T_Sources/r32.4.4/Linux_for_Tegra/source/public/kernel/nvidia/drivers/media/i2c/ov5693.c
static struct camera_common_pdata *ov5693_parse_dt(struct tegracam_device *tc_dev)
{
..
        err = of_property_read_string(node, "iovdd-reg",
                        &board_priv_pdata->regulators.iovdd);
  1. after that,
    you’ll able to get the regulator and having power control from driver side.
static int ov5693_power_get(struct tegracam_device *tc_dev)
{
...
        /* IO 1.8v */
        err |= camera_common_regulator_get(dev,
                        &pw->iovdd, pdata->regulators.iovdd);

Hi JerryChang,
As you recommend , I checked step by step.

  1. I was confirm device tree sources for the regulator definitions.
    /hardware/nvidia/platform/t18x/common/kernel-dts/t18x-common-platforms/tegra186-cvb-prod-p2597-b00-p3489-1000-a00-00.dtsi
    /hardware/nvidia/platform/t18x/common/kernel-dts/t18x-common-platforms/tegra186-cvb-prod-p2597-b00-p3310-1000-a00-00.dtsi

fixed-regulators {

en_vdd_cam: regulator@2 {
compatible = “regulator-fixed-sync”;
reg = <2>;
regulator-name = “en-vdd-cam”;
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
gpio = <&gpio_i2c_0_77 9 1>;
enable-active-high;
};

  1. I was refer to tegra186-quill-camera-e3333-a00.dtsi and my device tree was modified.

i2c@3180000 {
thcv242@0b {
compatible = “thine,thcv242”;
vif-supply = <&en_vdd_cam>;
vdig-supply = <&en_vdd_cam_1v2>;

  1. I was refer to tegra186-camera-e3333-a00.dtsi and my device tree was modified.

i2c@3180000 {
thcv242@0b {
compatible = “thine,thcv242”;
reg = <0x0b>; //<0x16>

vdd-reg = “vana”;
ovdd-reg = “vif”;
vdd-reg = “vdig”;

  1. My serdes driver added to parse DT for regulators.

static int thcv242_parse_dt(struct thcv242_priv *priv)
{
// digital 1.8v
err = of_property_read_string(np, “iovdd-reg”,&priv->regulators.iovdd);
if (err) {
dev_err(dev, “iovdd-reg not in DT\n”);
goto error;
}

  1. I added to power control function.

static int thcv242_power_get(struct tegracam_device *tc_dev)
{
struct camera_common_data *s_data = tc_dev->s_data;
struct camera_common_power_rail *pw = s_data->power;
struct camera_common_pdata *pdata = s_data->pdata;
struct device dev = tc_dev->dev;
int err = 0;
dev_info(dev, “%s power_get\n”, func);
if (!pdata) {
dev_err(dev, “pdata missing\n”);
return -EFAULT;
}
/
analog 2.8v /
err |= camera_common_regulator_get(dev,
&pw->avdd, pdata->regulators.avdd);
/
IO 1.8v */
err |= camera_common_regulator_get(dev,
&pw->iovdd, pdata->regulators.iovdd);
pw->state = SWITCH_OFF;
return err;
}

  1. I added board_setup function for recall thcv242_power_get function.
    Board_setup function recall by device probe function.

static int thcv242_board_setup(struct thcv242_priv *priv)
{
// struct camera_common_data *s_data = priv->s_data;
struct device *dev = dev;
int err = 0;

dev_info(dev, “%s: Board Setup \n”, func);

err = thcv242_power_get(priv->tc_dev);
if (err) {
dev_err(dev,
“Error %d during power on sensor\n”, err);
return err;
}

err = thcv242_init(priv);
if (err) {
dev_err(dev,
“Error %d during thcv242 init\n”, err);
return err;
}

err = thcv242_init_gpio(priv);
if (err) {
dev_err(dev,
“Error %d during thcv242 gpio init\n”, err);
return err;
}

return err;
}

I loaded device driver module in jetson TX2.
step1 to step4 is okay.
but step6 occured kernel panic when thcv242_power_get function was recall.
i’m developing custom serdes device driver.
so i’m difficult to refer sample camera device driver.
Is it possible to supply power by just calling the Power get function?
Or do i need other functions and settings?
Please, advise me which part of the power function call method was used incorrectly.

Thanks.

hello jpchae,

could you please also share the error messages,

Hello JerryChang,

I attached error log as shown below.

[ 36.488656] i2c-thcv242 2-000b: thcv242_probe: start
[ 36.488662] i2c-thcv242 2-000b: thcv242_parse_dt: deserializer:
[ 36.488665] i2c-thcv242 2-000b: pass-gpio not found, ignoring
[ 36.488667] i2c-thcv242 2-000b: lock-gpio not found, ignoring
[ 36.488670] i2c-thcv242 2-000b: pdb-gpio not found, ignoring
[ 36.488673] i2c-thcv242 2-000b: thcv242_parse_dt: - csi-lane-count 4
[ 36.488677] i2c-thcv242 2-000b: thcv242_parse_dt: - csi-lane-speed 1047
[ 36.488679] i2c-thcv242 2-000b: thcv242_parse_dt: - continuous clock enabled
[ 36.488682] i2c-thcv242 2-000b: thcv242_parse_dt: DT finished
[ 36.488684] (NULL device *): thcv242_board_setup: Board Setup
[ 36.488692] Internal error: Accessing user space memory outside uaccess.h routines: 96000005 [#1] PREEMPT SMP
[ 36.498595] Modules linked in: thcv242(+) bnep fuse zram overlay bcmdhd cfg80211 spidev nvgpu bluedroid_pm ip_tables x_tables
[ 36.510019] CPU: 5 PID: 7687 Comm: insmod Not tainted 4.9.140-tegra #6
[ 36.516534] Hardware name: quill (DT)
[ 36.520187] task: ffffffc19d6ad400 task.stack: ffffffc1c35b0000
[ 36.526103] PC is at thcv242_probe+0x204/0x8b8 [thcv242]
[ 36.531408] LR is at thcv242_probe+0x1f8/0x8b8 [thcv242]
[ 36.536708] pc : [] lr : [] pstate: 40400045
[ 36.544095] sp : ffffffc1c35b3a50
[ 36.544098] x29: ffffffc1c35b3a50 x28: 0000000000000018
[ 36.544101] x27: 0000000000000108 x26: 0000000000000030
[ 36.544109] x25: 0000000000000000 x24: ffffffc1eb0dd000
[ 36.544112] x23: ffffffc1f70f4000 x22: ffffff8001139568
[ 36.544114] x21: ffffffc1eb0dd020 x20: ffffffc1b5f13018
[ 36.544116] x19: 00000000fffffffe x18: 0000000000000001
[ 36.544118] x17: 0000000000000001 x16: 0000000000000007
[ 36.544120] x15: ffffffffffffffff x14: ffffffffffffffff
[ 36.544122] x13: 0000000000000000 x12: 0000000000000006
[ 36.544123] x11: 0000000000000006 x10: 00000000000003d7
[ 36.544125] x9 : 0000000000000001 x8 : ffffffc1f67d46c0
[ 36.544127] x7 : 0000000000000000 x6 : 0000000010b3d19a
[ 36.544129] x5 : 0000000000000000 x4 : ffffffc1f70adbe8
[ 36.544131] x3 : ffffffc1f70adbe8 x2 : ffffff8001139880
[ 36.544133] x1 : ffffff800113a7c0 x0 : 0000000000000000

[ 36.544136] Process insmod (pid: 7687, stack limit = 0xffffffc1c35b0000)
[ 36.544137] Call trace:
[ 36.544146] [] thcv242_probe+0x204/0x8b8 [thcv242]
[ 36.544153] [] i2c_device_probe+0x144/0x258
[ 36.544158] [] driver_probe_device+0xd8/0x408
[ 36.544161] [] __driver_attach+0xdc/0x128
[ 36.544166] [] bus_for_each_dev+0x5c/0xa8
[ 36.544168] [] driver_attach+0x30/0x40
[ 36.544169] [] bus_add_driver+0x20c/0x2a8
[ 36.544171] [] driver_register+0x6c/0x110
[ 36.544173] [] i2c_register_driver+0x4c/0xb0
[ 36.544178] [] thcv242_driver_init+0x14/0x30 [thcv242]
[ 36.544182] [] do_one_initcall+0x44/0x130
[ 36.544186] [] do_init_module+0x64/0x1a8
[ 36.544190] [] load_module+0x10a4/0x12d8
[ 36.544192] [] SyS_finit_module+0xd8/0xf0
[ 36.544193] [] el0_svc_naked+0x34/0x38
[ 36.544197] —[ end trace 9133a6f930d19caf ]—

hello jpchae,

are you building your sensor driver as kernel module? please also check Loadable Kernel Module (LKM) chapter for reference,

in addition,
please also add debug prints to check you’d got regulator correctly here.

/* analog 2.8v */
err |= camera_common_regulator_get(dev, &pw->avdd, pdata->regulators.avdd);
/* IO 1.8v */
err |= camera_common_regulator_get(dev, &pw->iovdd, pdata->regulators.iovdd);

thanks

Hello JerryChang,

Yes, I’m building sensor driver as kernel module.

I added debug print in power_get function as shown above.
Before printing debug print, error message was printed.
I think error occured before camera_common_regulator_get function was recall.

thanks.

hello jpchae,

please also check whether these regulator were NULL.
you might also enable debug prints in camera_common.c for gather more details.
for example,

$ sudo -i
# echo file camera_common.c +p > /sys/kernel/debug/dynamic_debug/control

Hello JerryChang,

Is the debugging command you informed me running on the terminal of jetson tx2 board?
Please tell me in detail how to use the debugging command.

The return value of the camera_common_regulator_get function is output for debugging, but the same symptom as the above error message appears, and the debugging value is not output.

hello jpchae,

yes, that’s steps to enable dynamic debug prints (i.e. dev_dbg(…)) inside the camera_common.c sources.

Hello JerryChyang,

I compared between ov5693.c and my driver code.

ov5693 code has struct as shown below.

static struct camera_common_sensor_ops ov5693_common_ops = {
.numfrmfmts = ARRAY_SIZE(ov5693_frmfmt),
.frmfmt_table = ov5693_frmfmt,
.power_on = ov5693_power_on,
.power_off = ov5693_power_off,
.write_reg = ov5693_write_reg,
.read_reg = ov5693_read_reg,
.parse_dt = ov5693_parse_dt,
.power_get = ov5693_power_get,
.power_put = ov5693_power_put,
.set_mode = ov5693_set_mode,
.start_streaming = ov5693_start_streaming,
.stop_streaming = ov5693_stop_streaming,
};

Do i need this structure for my driver code ?

thanks,