Sorry, this is long. The most important questions are in bold/italic.
Does the “/proc/config.gz” show the feature is added as integrated (“=y”), or does it show as a module (“=m”)? If “=y”, then the Image file contains everything and you can be sure the feature is there. If “=m”, then you need to be sure that all modules can be found somewhere in “/lib/modules/$(uname -r)/”. Example:
find /lib/modules/$(uname -r) -name 'whatever_it_is.*'
Once that is verified, any device tree change becomes the next topic and is independent of kernel build and kernel install. Normal kernel feature changes do not touch the device tree, this would be a separate config and build step. It happens that device tree and device tree compiler ships with the Linux kernel source, and this is useful due to the relationship between device tree and drivers, but the actual build of kernel and device tree is more or less independent and working on one does not usually change the other.
Think of device tree as a way of abstracting the registers needed to route or glue the hardware to a generic driver interface…unless the driver interface changes (and many drivers can use the same interface) or the method of wiring/routing the hardware changes you won’t need to worry about device tree. A driver’s API basically is told how to find hardware by a device tree, and the firmware loaded to the hardware matches the driver’s API (not all hardware has firmware…if no firmware, then there is a single hardware concept which can’t be changed…regulated hardware, e.g., WiFi, tends to have firmware, and other hardware tends to not have firmware). Finding the hardware (device tree), and having the hardware match the API (firmware matching driver version) is the complete circle of requirements.
You can expect custom carrier boards to need device tree changes…such boards alter how the wiring is routed even when two boards sitting next to each other implement the same features using the same drivers.
Custom sensors most likely also need a device tree change. Sensors have registers and configuration to change which is only known in an abstract way to drivers…the device tree translates the specific register changes needed to follow the abstract concept the driver knows about and the way the wiring is routed.
On a lower level, a device tree is just an abstracted list of name to value mappings a driver uses in order to initialize and find hardware. A name and value are mapped together like an associative array which causes hardware registers to change. If those changes occur as the driver expects, then the driver can find and use the hardware.
Note that lspci shows if PCIe sees your card. Once PCIe sees the card and tells the driver what is there its job is done. If no driver takes ownership, then PCIe is functioning 100% correct and the driver can be blamed. Having lspci show the card means PCIe worked.
If a driver is loaded as a module (“=m”), then “lsmod” would show the driver. If the driver is integrated (“=y”), then the driver is always available. How did you build the driver (module versus integrated)? As a module? If external to the kernel source tree this is what I’d expect.
Even if a module is in place it may be the system has to either reboot or be told to look for the module. This is what “sudo depmod -a” is for (and run right after installing the module to “/lib/modules/$(uname -r)/”).
Regardless of depmod it should be possible to force a module to load as a test with the “sudo insmod ”. Or a more gentle “sudo modprobe ”. “insmod” does not search for dependencies, whereas “modprobe” does. “insmod” will fail if a dependency is not met, but “modprobe” will attempt to work with dependencies. Individual modules without dependencies won’t care.
Look at your driver source. If you see “.c” or “.h” files, then this is purely kernel source and no device tree involved (config files, e.g., Kconfig and Makefile, are always there and don’t say much). If you see “.dts” or “.dtsi” files, then this is device tree code. What kind of source code is the driver you are working with? Answering will require knowing if this is purely kernel code, purely device tree, or some mix. In the case of kernel code, answering will also require knowing if it is module or integrated.