I have built a simple driver for a custom camera in the TX2 developer kit carrier board. Here is the driver:
/*
* ar1335.c - ar1335 sensor driver
*
*/
#define DEBUG
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/gpio.h>
#include <linux/module.h>
#include <linux/seq_file.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_gpio.h>
#include <media/tegra_v4l2_camera.h>
#include <media/tegracam_core.h>
#define CREATE_TRACE_POINTS
static const struct of_device_id ar1335_of_match[] = {
{ .compatible = "nvidia,ar1335",},
{ },
};
MODULE_DEVICE_TABLE(of, ar1335_of_match);
static const struct regmap_config sensor_regmap_config = {
.reg_bits = 16,
.val_bits = 8,
};
struct ar1335 {
struct i2c_client *i2c_client;
struct v4l2_subdev *subdev;
struct camera_common_data *s_data;
struct tegracam_device *tc_dev;
};
static struct tegracam_ctrl_ops ar1335_ctrl_ops = {
};
static struct camera_common_sensor_ops ar1335_common_ops = {
};
static int ar1335_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
{
return 0;
}
static const struct v4l2_subdev_internal_ops ar1335_subdev_internal_ops = {
.open = ar1335_open,
};
static int ar1335_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct device *dev = &client->dev;
struct device_node *node = dev->of_node;
struct tegracam_device *tc_dev;
struct ar1335 *priv;
int err;
dev_info(dev, "ar1335 probing v4l2 sensor.\n");
if (!IS_ENABLED(CONFIG_OF) || !node)
return -EINVAL;
priv = devm_kzalloc(dev, sizeof(struct ar1335), GFP_KERNEL);
if (!priv) {
dev_err(dev, "unable to allocate memory!\n");
return -ENOMEM;
}
tc_dev = devm_kzalloc(dev,
sizeof(struct tegracam_device), GFP_KERNEL);
if (!tc_dev)
return -ENOMEM;
priv->i2c_client = tc_dev->client = client;
tc_dev->dev = dev;
strncpy(tc_dev->name, "ar1335", sizeof(tc_dev->name));
tc_dev->dev_regmap_config = &sensor_regmap_config;
tc_dev->sensor_ops = &ar1335_common_ops;
tc_dev->v4l2sd_internal_ops = &ar1335_subdev_internal_ops;
tc_dev->tcctrl_ops = &ar1335_ctrl_ops;
err = tegracam_device_register(tc_dev);
if (err) {
dev_info(dev, "tegra camera driver registration failed\n");
dev_err(dev, "tegra camera driver registration failed\n");
return err;
}
priv->tc_dev = tc_dev;
priv->s_data = tc_dev->s_data;
priv->subdev = &tc_dev->s_data->subdev;
tegracam_set_privdata(tc_dev, (void *)priv);
err = tegracam_v4l2subdev_register(tc_dev, true);
if (err) {
dev_info(dev, "tegra camera subdev registration failed\n");
dev_err(dev, "tegra camera subdev registration failed\n");
return err;
}
dev_info(&client->dev, "Detected AR1335 sensor\n");
return 0;
}
static int
ar1335_remove(struct i2c_client *client)
{
return 0;
}
static const struct i2c_device_id ar1335_id[] = {
{ "ar1335", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, ar1335_id);
static struct i2c_driver ar1335_i2c_driver = {
.driver = {
.name = "ar1335",
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(ar1335_of_match),
},
.probe = ar1335_probe,
.remove = ar1335_remove,
.id_table = ar1335_id,
};
module_i2c_driver(ar1335_i2c_driver);
MODULE_DESCRIPTION("Media Controller driver for AR1335");
MODULE_AUTHOR("NVIDIA Corporation");
MODULE_LICENSE("GPL v2");
When not registering the tegracam_device, the module can be successfully loaded and removed. I’ve modified the device tree too and flashed the kernel-dtb. Anyway, when registering the tegracam_device, I get the following error in the kernel:
[ 1205.850982] mar jul 23 12:55:58 CEST 2019
[ 1243.731901] ar1335 1-003c: ar1335 probing v4l2 sensor.
[ 1243.731967] Internal error: Attempting to execute userspace memory: 86000005 [#1] PREEMPT SMP
[ 1243.740495] Modules linked in: ar1335(O+) bnep fuse zram bcmdhd cfg80211 nvgpu bluedroid_pm ip_tables x_tables [last unloaded: ar1335]
[ 1243.752693] CPU: 4 PID: 9699 Comm: insmod Tainted: G O 4.9.140-tegra #1
[ 1243.760420] Hardware name: quill (DT)
[ 1243.764074] task: ffffffc1564b2a00 task.stack: ffffffc1d9d44000
[ 1243.769983] PC is at 0x0
[ 1243.772514] LR is at tegracam_device_register+0xac/0x298
[ 1243.777815] pc : [<0000000000000000>] lr : [<ffffff8008b3e974>] pstate: 80400045
[ 1243.785194] sp : ffffffc1d9d47a30
[ 1243.788500] x29: ffffffc1d9d47a30 x28: 0000000000000018
[ 1243.793823] x27: 0000000000000053 x26: 0000000000000030
[ 1243.799142] x25: 0000000000000000 x24: ffffff8008f6b958
[ 1243.804464] x23: ffffff8000f69040 x22: ffffffc1eb55b020
[ 1243.809783] x21: ffffffc14fd7f458 x20: ffffffc1881adc18
[ 1243.815102] x19: ffffffc1927a5018 x18: 0000000000000001
[ 1243.820420] x17: 0000000000000000 x16: 0000000000000000
[ 1243.825738] x15: ffffffffffffffff x14: ffffffc14fd7f68a
[ 1243.831058] x13: 0000000000000000 x12: 0000000000000030
[ 1243.836378] x11: 0101010101010101 x10: 7f7f7f7f7f7f7f7f
[ 1243.839601] x9 : 6364626d60756340
[ 1243.839602] x8 : ffffffc14fd7f140
[ 1243.839603] x7 : 0000000000000000
[ 1243.839606] x6 : ffffff8009e5cf38
[ 1243.839608] x5 : ffffffc1564b2a00 x4 : ffffffc1eb55b220
[ 1243.839610] x3 : ffffffc14fd7f100 x2 : ffffffc14fd7f680
[ 1243.839612] x1 : 0000000000000000 x0 : ffffffc1881adc18
[ 1243.839616] Process insmod (pid: 9699, stack limit = 0xffffffc1d9d44000)
[ 1243.839617] Call trace:
[ 1243.839621] [< (null)>] (null)
[ 1243.839628] [<ffffff8000f690ec>] ar1335_probe+0xac/0x1b0 [ar1335]
[ 1243.839634] [<ffffff8008acf75c>] i2c_device_probe+0x144/0x258
[ 1243.839641] [<ffffff800876cdf8>] driver_probe_device+0xd8/0x408
[ 1243.839643] [<ffffff800876d204>] __driver_attach+0xdc/0x128
[ 1243.839646] [<ffffff800876a874>] bus_for_each_dev+0x5c/0xa8
[ 1243.839649] [<ffffff800876c5f8>] driver_attach+0x30/0x40
[ 1243.839651] [<ffffff800876c02c>] bus_add_driver+0x20c/0x2a8
[ 1243.839653] [<ffffff800876e13c>] driver_register+0x6c/0x110
[ 1243.839656] [<ffffff8008acfe4c>] i2c_register_driver+0x4c/0xb0
[ 1243.839660] [<ffffff8000f6c014>] ar1335_i2c_driver_init+0x14/0x30 [ar1335]
[ 1243.839663] [<ffffff8008083afc>] do_one_initcall+0x44/0x130
[ 1243.839667] [<ffffff80081c2ddc>] do_init_module+0x64/0x1a8
[ 1243.839670] [<ffffff80081581dc>] load_module+0x10a4/0x12d8
[ 1243.839672] [<ffffff80081586c0>] SyS_finit_module+0xd8/0xf0
[ 1243.839674] [<ffffff80080838c0>] el0_svc_naked+0x34/0x38
[ 1243.839678] ---[ end trace 6a0f6031f93cf57d ]---
Any idea why is this happening?