ADF4350/ADF4351 Linux driver issues
Started by 8 years ago●5 replies●latest reply 8 years ago●916 viewsHello everyone,
I am trying to work with the adf4350 driver (its documentation by Analog Devices can be found here) on my Beaglebone board but I am experiencing some issues.
The problem I am facing is that when I load the driver, the folder
/sys/bus/iio/devices/
remains empty, and it doesn't agree to what is written in the section Driver testing, so anything is working fine.
If I am not wrong, I have two options to make it work:
Option # 1: modifying the driver source code adding the code listed into the section Declaring SPI slave devices.
Including that code into the beginning of adf4350.c driver is causing compile errors:
<code><span class="operator token"> CC [M] drivers/iio/frequency/adf4350.o In file included from drivers/iio/frequency/adf4350.c:16:0: include/linux/module.h:128:27: error: redefinition of '__inittest' static inline initcall_t __inittest(void) \ ^ include/linux/device.h:1329:1: note: in expansion of macro 'module_init' module_init(__driver##_init); \ ^ include/linux/spi/spi.h:284:2: note: in expansion of macro 'module_driver' module_driver(__spi_driver, spi_register_driver, \ ^ drivers/iio/frequency/adf4350.c:670:1: note: in expansion of macro 'module_spi_driver' module_spi_driver(adf4350_driver); ^ include/linux/module.h:128:27: note: previous definition of '__inittest' was here static inline initcall_t __inittest(void) \ ^ include/linux/module.h:112:28: note: in expansion of macro 'module_init' #define arch_initcall(fn) module_init(fn) ^ drivers/iio/frequency/adf4350.c:54:1: note: in expansion of macro 'arch_initcall' arch_initcall(board_init); ^ include/linux/module.h:130:6: error: redefinition of 'init_module' int init_module(void) __attribute__((alias(#initfn))); ^ include/linux/device.h:1329:1: note: in expansion of macro 'module_init' module_init(__driver##_init); \ ^ include/linux/spi/spi.h:284:2: note: in expansion of macro 'module_driver' module_driver(__spi_driver, spi_register_driver, \ ^ drivers/iio/frequency/adf4350.c:670:1: note: in expansion of macro 'module_spi_driver' module_spi_driver(adf4350_driver); ^ include/linux/module.h:130:6: note: previous definition of 'init_module' was here int init_module(void) __attribute__((alias(#initfn))); ^ include/linux/module.h:112:28: note: in expansion of macro 'module_init' #define arch_initcall(fn) module_init(fn) ^ drivers/iio/frequency/adf4350.c:54:1: note: in expansion of macro 'arch_initcall' arch_initcall(board_init); ^ make[3]: *** [drivers/iio/frequency/adf4350.o] Error 1 scripts/Makefile.build:264: recipe for target 'drivers/iio/frequency/adf4350.o' failed make[2]: *** [drivers/iio/frequency] Error 2 make[1]: *** [drivers/iio] Error 2 make: *** [drivers] Error 2 scripts/Makefile.build:403: recipe for target 'drivers/iio/frequency' failed scripts/Makefile.build:403: recipe for target 'drivers/iio' failed Makefile:947: recipe for target 'drivers' failed</span><span class="punctuation token"></span></code>
I tried other ways to use that code but no way. I can't compile it. So it's not clear to me how to use that code..
Option # 2: working with devicetree taking the example from the section Devicetree bindings. But I am not familiar with devicetree (bad !) and the example posted is incomplete or wrong because dtc refuses to compile, so I tried editing it as so:
/dts-v1/;
/ { part-number = "adf4350";
lo_pll0_rx_adf4351: adf4351-rx-lpc@4
{
compatible = "adi,adf4351";
reg = <4>;
spi-max-frequency = <10000000>;
/* clocks = <&clk0_ad9523 9>;*/
clock-names = "clkin";
adi,channel-spacing = <10000>;
adi,power-up-frequency = <2400000000>;
adi,phase-detector-polarity-positive-enable;
adi,charge-pump-current = <2500>;
adi,output-power = <3>;
adi,mute-till-lock-enable;
};
};
I compile it with:
dtc -I dts -O dtb adf4350.dts -o adf4350.dtb
dtc returns the following warnings:
Warning (reg_format): "reg" property in /adf4351-rx-lpc@4 has invalid length (4 bytes) (#address-cells == 2, #size-cells == 1)
Warning (avoid_default_addr_size): Relying on default #address-cells value for /adf4351-rx-lpc@4
Warning (avoid_default_addr_size): Relying on default #size-cells value for /adf4351-rx-lpc@4
Copying the dtb file to
/lib/firmware
and executing
echo adf4350 > /sys/devices/platform/bone_capemgr/slots
it returns the error
bash: echo: write error: No such file or directory
Of course the file slots exists.
After this large post (I tried to explain the situation the best I can), I am stuck on how to make the driver works.
Do you have any suggestion about how to solve it ?
Thank you in advance.
Regards,
Simon
#arm #linux
Hi Simon,
It looks that it is trying to initialise twice
redefinition of '__inittest'
static inline initcall_t __inittest(void) \
The driver can only initialise once.
The second error is related may be relate with file access permissions or unexisting folder.
Check if the file exists in the specified location :
$ls /sys/devices/platform/bone_capemgr/
And if exists try to execute the command again but logged in as root.
"and executing
echo adf4350 > /sys/devices/platform/bone_capemgr/slots
it returns the error
bash: echo: write error: No such file or directory
Of course the file slots exists."
Hope that helps,
Pedro.
Hi Pedro,
Regarding the devicetree modification (2nd error), I did all with root permissions.
So I think the problem is strictly related with the dts code.
Regarding the compilation error (1st error), I understand that the driver cannot be loaded twice.
Also, inserting the code
#define GPIO_PF10 10 #define MAX_CTRL_CS 8 static struct spi_board_info board_spi_board_info[] __initdata = { #if defined(CONFIG_ADF4350) || defined(CONFIG_ADF4350_MODULE) { .modalias = "adf4351", .max_speed_hz = 1000000, .bus_num = 0, .chip_select = GPIO_PF10 + MAX_CTRL_CS, .platform_data = NULL, .mode = SPI_MODE_0, }, #endif }; static int __init board_init(void) { spi_register_board_info(board_spi_board_info, ARRAY_SIZE(board_spi_board_info)); return 0; } arch_initcall(board_init);
into the adf4350.c file is not the correct way to do use it.
I think this code should be included in a board dedicated C file.
Simon
Hi Simon,
Great that your sort out the second problem. Regarding the first problem, I think the problem is related with this:
"Unlike PCI or USB devices, SPI devices are not enumerated at the hardware level. Instead, the software must know which devices are connected on each SPI bus segment, and what slave selects these devices are using. For this reason, the kernel code must instantiate SPI devices explicitly. The most common method is to declare the SPI devices by bus number.
This method is appropriate when the SPI bus is a system bus, as in many embedded systems, wherein each SPI bus has a number which is known in advance. It is thus possible to pre-declare the SPI devices that inhabit this bus. This is done with an array of struct spi_board_info, which is registered by calling spi_register_board_info().
For more information see: Documentation/spi/spi-summary
Adding Linux driver support
Configure kernel with “make menuconfig” (alternatively use “make xconfig” or “make qconfig”)
https://wiki.analog.com/resources/tools-software/l...
"
Basically you will have to recompile the Kernel.
Good luck,
Pedro
Yes, I did not pay attention to the SPI documentation (my bad).
Thank you Pedro.
Hi Simon,
Let me know if you managed to sort it.
Take care,
Pedro