I've added a MAX7320 i2c output chip. How can I get the kernel to load the driver for it? - c

I've added a MAX7320 i2c expander chip to i2c bus 0 on my ARM Linux board.
The chip works correctly from userspace with commands such as /usr/sbin/i2cset -y 0 0x5d 0x02 and /usr/sbin/i2cget -y 0 0x5d.
There is a drivers/gpio/gpio-max732x.c file in the kernel source, which is compiled into the kernel that I'm running. (I've built it from source.)
How do I tell the kernel that it should instantiate the gpio-max732x driver on "i2c bus 0, chip id 0x5d"?
Do I need to modify the device tree .dts file and put a new .dtb file in /boot/dtbs/?
What would the clause for instantiating a gpio-max732x module look like?
P.S. I've seen https://lkml.org/lkml/2015/1/13/305 but I can't figure out how to get the patch files.

Device Tree
There must be appropriate Device Tree definition for your chip, in order for driver to instantiate. There are 2 ways to do so:
Modify .dts Device Tree file for your board (look in arch/arm/boot/dts/), then recompile it and re-flash it to your device.
This way is preferred in case when you have access you kernel sources for your board and you are able to re-flash .dtb file to your device.
Create Device Tree Overlay file, compile it and load it on your device.
This way is preferred when you don't have access to kernel sources for your board, or you are unable to flash new device tree blob to your device.
Your device definition in Device Tree should look like (according to Documentation/devicetree/bindings/gpio/gpio-max732x.txt):
&i2c0 {
expander: max7320#5d {
compatible = "maxim,max7320";
reg = <0x5d>;
gpio-controller;
#gpio-cells = <2>;
};
};
Kernel configuration
As your expander chip (MAX7320) has no input GPIOs, you don't need IRQ support for MAX732x. So you can disable CONFIG_GPIO_MAX732X_IRQ in your kernel configuration.
Matching device with driver
Once you have your Device Tree loaded (with definition for MAX7320), MAX732x driver will be matched with device definition, and instantiated. Below is explained how matching happens.
In Device Tree file you have compatible property:
compatible = "maxim,max7320";
In MAX732x driver you can see this table:
static const struct of_device_id max732x_of_table[] = {
...
{ .compatible = "maxim,max7320" },
...
When driver is being loaded, and when Device Tree blob is being loaded, kernel tries to find the match for each driver and Device Tree definition. Just by comparing strings above. If strings are matched -- kernel instantiates driver, passing corresponding device parameters to it. Look at i2c_device_match() function for details.
Obtaining patches
The best way is to use kernel sources that already have Device Tree support of MAX732x (v4.0+). But if it's not the case, then...
You can cherry-pick patches from upstream kernel to your kernel:
$ git remote add upstream git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
$ git fetch --all
$ git cherry-pick 43c4bcf9425e
$ git cherry-pick 479f8a5744d8
$ git cherry-pick 09afa276d52e
$ git cherry-pick 996bd13f28e6
And if you still want to apply patches manually (worst option, actually), here you can find direct links to patches. Click (patch) link to get a raw patch.
Also check later patches for gpio-max732x.c here.
Hardware concerns
To be sure that your chip has 0x5d I2C address, check that configuration pins are tied to next lines (as per datasheet):
Pin Line
-----------
AD2 V+
AD0 V+

Related

Is it possible to apply a Device Tree overlay to U-boot's Device Tree via U-boot shell commands? [closed]

Closed. This question is not about programming or software development. It is not currently accepting answers.
This question does not appear to be about a specific programming problem, a software algorithm, or software tools primarily used by programmers. If you believe the question would be on-topic on another Stack Exchange site, you can leave a comment to explain where the question may be able to be answered.
Closed 8 days ago.
The community is reviewing whether to reopen this question as of 7 days ago.
Improve this question
Say I would like to make changes to the following Device Tree node in this Device Tree for U-boot:
/* SDHCI is used to control the SDIO for wireless */
&sdhci {
#address-cells = <1>;
#size-cells = <0>;
pinctrl-names = "default";
pinctrl-0 = <&emmc_gpio34>;
status = "okay";
bus-width = <4>;
non-removable;
mmc-pwrseq = <&wifi_pwrseq>;
brcmf: wifi#1 {
reg = <1>;
compatible = "brcm,bcm4329-fmac";
};
};
In my case, I would like to change the following line:
pinctrl-0 = <&emmc_gpio34>;
to
pinctrl-0 = <&sdhost_gpio48>;
Can I create a Device Tree overlay and apply this overlay via U-boot commands once U-boot is running?
My goal is that I want U-boot's device tree to be adjusted in the above manner when I run my standalone binary via U-boot's go command.
The overlay that I have created is here:
/dts-v1/;
/plugin/;
/ {
compatible = "raspberrypi,3-model-b-plus", "brcm,bcm2837";
model = "Raspberry Pi 3 Model B+";
fragment#0 {
target = <&sdhci>;
__overlay__ {
#address-cells = <1>;
#size-cells = <0>;
pinctrl-names = "default";
pinctrl-0 = <&sdhost_gpio48>;
status = "okay";
bus-width = <4>;
non-removable;
mmc-pwrseq = <&wifi_pwrseq>;
brcmf: wifi#1 {
reg = <1>;
compatible = "brcm,bcm4329-fmac";
};
};
};
};
I've been broadly following U-boot's documentation here regarding loading and applying Device Tree overlays; however, I've noticed this documentation doesn't seem applicable to what I'm trying to achieve. Below are the steps I have taken so far:
I first create the fdtovaddr environment variable like so:
U-Boot> setenv fdtovaddr 0x1000000
Then I load my compiled overlay into fdtovaddr:
U-Boot> fatload mmc 0 ${fdtovaddr} sdhci_overlay.dtbo
Then I specify the base binary device tree as U-boot's Device Tree like so:
U-Boot> fdt addr ${fdt_addr}
Then I try to apply my overlay like so:
U-Boot> fdt apply ${fdtovaddr}
However, I get the following output:
failed on fdt_overlay_apply(): FDT_ERR_BADMAGIC
base fdt does did not have a /__symbols__ node
make sure you've compiled with -#
This makes sense because as per the docs, the base U-Boot Device Tree needs to be compiled with the -# command line switch and I'm assuming U-Boot's Device Tree was not:
It requires both the base device-tree and all the overlays to be compiled with the -# command line switch of the device-tree compiler so that symbol information is included.
The second part of the docs that made me realise the docs were not addressing my needs were the commands listed for booting the system as shown below:
Boot system like you would do with a traditional dtb.
For bootm:
=> bootm ${kerneladdr} - ${fdtaddr}
For bootz:
=> bootz ${kerneladdr} - ${fdtaddr}
The above commands are for passing the resultant overlayed Device Tree to a Linux Kernel Image via either the bootm or bootz shell command. This makes sense considering Linux uses a Device Tree to determine hardware availability etc and we are passing it a modified one via the above boot commands.
However, I would like to run a standalone via U-boot's go <address> command instead, which I believe doesn't accept an argument for a Device Tree (doesn't really make sense to either).
As such, is the conclusion that I've personally reached correct that it is not possible to manipulate U-boot's device tree while U-boot is running? Is the only option to manipulate U-boot's device tree manually and compile U-boot to generate a U-boot binary with my desired U-Boot Device Tree changes?
If not, please let me know how I can overlay U-boot's device tree during U-boot's runtime.

U-Boot add node to devicetree during startup

I work on a custom board with a Cyclone V SoC.
I need to add some informations to U-Boot device tree at startup and these informations are stored in an I2C device.
It appears that U-Boot device tree is read-only during its execution but before relocation. The function board_fix_fdt (void *rw_fdt_blob) can be used to make changes on the device tree before relocation.
The problem I have is that I cannot access the I2C device at this time. The driver doesn't seem to be loaded yet.
Can someone give me any hints on how I can enable the I2C at this stage ?
U-Boot version is 2018-05.
The solution is to add in u-boot device tree the i2c driver and also the reset driver for pre-relocation states :
&rst {
status = "okay";
u-boot,dm-pre-reloc; // HERE
};
&i2c2 {
status = "okay";
u-boot,dm-pre-reloc; // and HERE
}

How to add a board file to the Linux Kernel and where to find it on "make menu config"?

I need to add some board-specific code to a Linux kernel which I am building.
(I know I should be using device-tree already, but the driver I'm inspired by doesn't and I'm already learning a dozen new things before breakfast. Adding device-tree will also add another set of changes to debug. Once I have my platform-driver/drivers working using a board file, I will convert them to device tree.)
I have a file called arch/arm/myboard/myboard.c.
Where do I find existing board files in make menuconfig? (Such as http://lxr.free-electrons.com/source/arch/arm/mach-imx/mach-mx31ads.c?v=4.4 ?)
How do I make my board appear here also.
Take a look at the Makefile in the same directory. For mach-mx31ads.c, it has,
# i.MX31 based machines
obj-$(CONFIG_MACH_MX31ADS) += mach-mx31ads.o
The Kconfig has a corresponding entry,
config MACH_MX31ADS
bool "Support MX31ADS platforms"
default y
select IMX_HAVE_PLATFORM_IMX_I2C
select IMX_HAVE_PLATFORM_IMX_SSI
select IMX_HAVE_PLATFORM_IMX_UART
select SOC_IMX31
help
Include support for MX31ADS platform. This includes specific
configurations for the board and its peripherals.
Adding these will give your board a Kconfig menu item and build the file. The only other missing piece is a machine type. You need to add this to arm/tools/mach-type which is processed by the kernel makefile, using the gen-mach-types script, to create a generated/mach-type.h. You use this in your board file to create a static machine description (put in a special section).
MACHINE_START(MX31ADS, "Freescale MX31ADS")
/* Maintainer: Freescale Semiconductor, Inc. */
.atag_offset = 0x100,
.map_io = mx31ads_map_io,
.init_early = imx31_init_early,
.init_irq = mx31ads_init_irq,
.init_time = mx31ads_timer_init,
.init_machine = mx31ads_init,
.restart = mxc_restart,
MACHINE_END
The machine_desc structure is found in arch.h. You don't need to add all the elements as they won't be called if not present. The kernel init looks a the machine ATAG and iterates through the sections to match the machine that the boot loader passes in. Locating the machine_desc is done in assembler very early in the linux boot.

Generation of RTE_Components.h

I'm working with MDK-Pro and the File System library.
In my application, I require an SPI interface to the SD card. I've managed to setup the project properly, except that in the RTE_Components.h file that Keil generates the line #define RTE_Drivers_MCI0 which subsequently triggers a preprocessor error ("SDIO not configured in RTE_Device.h").
Although I can manually comment out this line in RTE_Components.h, every so often Keil updates this file and I get the above problem. Does anyone know what exactly generates this file, and how I can stop it from adding the SDIO-related definitions into the project?
The RTE_Components.h is not supposed to be modified and will always be automatically generated. That the stack tries to connect via MCI interface is related to your configuration made in the "FS_Config_MC_0.h".
// <o>Connect to hardware via Driver_MCI# <0-255>
// <i>Select driver control block for hardware interface
#define MC0_MCI_DRIVER 0
// <o>Connect to hardware via Driver_SPI# <0-255>
// <i>Select driver control block for hardware interface when in SPI mode
#define MC0_SPI_DRIVER 0
// <o>Memory Card Interface Mode <0=>Native <1=>SPI
// <i>Native uses a SD Bus with up to 8 data lines, CLK, and CMD
// <i>SPI uses 2 data lines (MOSI and MISO), SCLK and CS
// <i>When using SPI both Driver_SPI# and Driver_MCI# must be specified
// <i>since the MCI driver provides the control interface lines.
#define MC0_SPI 1

Can't boot basic OpenEmbedded-Core on Freescale i.MX28

I've been trying to build and boot OpenEmbedded-Core on the evaluation kit for Freescale's ARM i.MX28, using the Freescale ARM layer for OpenEmbedded-Core. Unfortunately, I can't find a basic "Getting Started" guide (though there is a Yocto getting-started guide). Unfortunately, I haven't been able to "get started", to the point of successfully booting to a basic command prompt on the board's debug serial port.
Here is what I've been able to piece together, and as far as I've managed to get so far.
Fetch sources
mkdir -p oe-core/freescale-arm
cd oe-core/freescale-arm
git clone git://git.openembedded.org/openembedded-core oe-core
git clone git://github.com/Freescale/meta-fsl-arm.git
cd oe-core
git clone git://git.openembedded.org/meta-openembedded
git clone git://git.openembedded.org/bitbake bitbake
Set up environment
. ./oe-init-build-env
That puts us in a new sub-directory build and sets certain environment variables.
Edit configuration
Edit the conf/bblayers.conf and local.conf files:
conf/bblayers.conf should have the meta-fls-arm and meta-oe layers added for BBLAYERS. E.g.:
BBLAYERS ?= " \
/home/craigm/oe-core/freescale-arm/oe-core/meta \
/home/craigm/oe-core/freescale-arm/oe-core/meta-openembedded/meta-oe \
${TOPDIR}/../../meta-fsl-arm \
"
In conf/local.conf, I set:
BB_NUMBER_THREADS = "4"
PARALLEL_MAKE = "-j 4"
MACHINE = "imx28evk"
Build
bitbake core-image-minimal
I ran this build overnight, and it has completed successfully for me. Output files were in ~/oe-core/freescale-arm/oe-core/build/tmp-eglibc/deploy/images.
There are two boot options that I'd like to try, as described below. Boot from SD card is simpler, but takes quite a long time (~30 min) to write the image to the SD card. Booting from TFTP + NFS is faster, but requires more set-up.
Boot from SD Card
Write image to SD card:
sudo dd if=tmp-eglibc/deploy/images/core-image-minimal-imx28evk.sdcard of=/dev/sdc
It took something like 30 minutes (3.5 GB file). Then I put it in the board's SD card slot 0, and powered-up. It got as far as loading the kernel, then stopped:
U-Boot 2012.04.01-00059-g4e6e824 (Aug 23 2012 - 18:08:54)
Freescale i.MX28 family at 454 MHz
BOOT: SSP SD/MMC #0, 3V3
DRAM: 128 MiB
MMC: MXS MMC: 0
*** Warning - bad CRC, using default environment
In: serial
Out: serial
Err: serial
Net: FEC0, FEC1
Hit any key to stop autoboot: 0
reading boot.scr
** Unable to read "boot.scr" from mmc 0:2 **
reading uImage
2598200 bytes read
Booting from mmc ...
## Booting kernel from Legacy Image at 42000000 ...
Image Name: Linux-2.6.35.3-11.09.01+yocto-20
Created: 2012-08-23 7:53:40 UTC
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 2598136 Bytes = 2.5 MiB
Load Address: 40008000
Entry Point: 40008000
Verifying Checksum ... OK
Loading Kernel Image ... OK
OK
Starting kernel ...
Uncompressing Linux... done, booting the kernel.
Boot from TFTP + NFS
First, I tried to write U-Boot onto an SD card:
sudo dd if=tmp-eglibc/deploy/images/u-boot-imx28evk.mxsboot-sdcard of=/dev/sdc
Then I put it in the board's SD card slot 0, and powered-up. But all I got in the debug serial port was:
0x8020a01d
So, I decided to use Freescale's distribution of U-Boot for i.MX28 (from their LTIB distribution) onto an SD card. I set suitable U-Boot parameters for NFS booting with parameters from DHCP.
setenv bootargs console=ttyAMA0,115200n8
setenv bootargs_nfs setenv bootargs ${bootargs} root=/dev/nfs ip=dhcp nfsroot=,v3,tcp fec_mac=${ethaddr}
saveenv
I connected to a DD-WRT router with the following DNSmasq settings:
dhcp-boot=,,192.168.250.106
dhcp-option=17,"192.168.250.106:/home/craigm/rootfs"
On my host PC, I set up a TFTP server to serve the uImage file from ~/oe-core/freescale-arm/oe-core/build/tmp-eglibc/deploy/images/.
I also set up a root NFS server to serve the root file system. I edited /etc/exports to serve /home/craigm/rootfs. I extracted the root file system:
bitbake meta-ide-support
rm -Rf ~/rootfs
runqemu-extract-sdk tmp-eglibc/deploy/images/core-image-minimal-imx28evk.tar.bz2 ~/rootfs
Then I put the U-Boot SD card in the board's SD card slot 0, and powered-up. It got as far as this, then stopped:
...
TCP cubic registered
NET: Registered protocol family 17
can: controller area network core (rev 20090105 abi 8)
NET: Registered protocol family 29
can: raw protocol (rev 20090105)
mxs-rtc mxs-rtc.0: setting system clock to 1970-01-01 00:03:33 UTC (213)
eth0: Freescale FEC PHY driver [Generic PHY] (mii_bus:phy_addr=0:00, irq=-1)
eth1: Freescale FEC PHY driver [Generic PHY] (mii_bus:phy_addr=0:01, irq=-1)
Sending DHCP requests .
PHY: 0:00 - Link is Up - 100/Full
., OK
IP-Config: Got DHCP answer from 192.168.250.106, my address is 192.168.250.142
IP-Config: Complete:
device=eth0, addr=192.168.250.142, mask=255.255.255.0, gw=192.168.250.1,
host=192.168.250.142, domain=, nis-domain=(none),
bootserver=192.168.250.106, rootserver=192.168.250.106, rootpath=/home/craigm/rootfs
Looking up port of RPC 100003/3 on 192.168.250.106
Looking up port of RPC 100005/3 on 192.168.250.106
VFS: Mounted root (nfs filesystem) on device 0:15.
Freeing init memory: 160K
I'm not sure if it's running without a serial console, or some other problem. I can ping it on 192.168.250.142, but I can't Telnet or SSH to it.
Questions
Is there any sort of "getting started" guide for OpenEmbedded-Core on Freescale's i.MX28?
Is the Freescale ARM layer really intended for use with OpenEmbedded-Core, Yocto, or what? I don't really understand how those projects relate.
Has anyone else had success booting a minimal image of OpenEmbedded-Core on Freescale's i.MX28? If so, how did your procedure differ from mine?
I'm not sure at this stage whether the problem is just a non-functional serial console, or some other sort of issue. It's hard to diagnose these problems that prevent even getting a basic system running. Any pointers on how to diagnose at this point?
Why would the U-Boot be broken so it can't even boot?
From the boot message it looks like U-boot is working fine. U-boot is not broken.
The following boot message
2598200 bytes read
Booting from mmc ...
## Booting kernel from Legacy Image at 42000000 ...
Image Name: Linux-2.6.35.3-11.09.01+yocto-20
Created: 2012-08-23 7:53:40 UTC
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 2598136 Bytes = 2.5 MiB
Load Address: 40008000
Entry Point: 40008000
Verifying Checksum ... OK
Loading Kernel Image ... OK
OK
Starting kernel ...
Uncompressing Linux... done, booting the kernel.
By the above log u-boot has done its job.
"Booting the kernel" is the point where bootloader given the control to the kernel.
I guess the problem might be in kernel image or in memory.
To eliminate the problem of memory, try to check the manual and try to read and write in the RAM using the board's reference manual.
From the boot log RAM looks like has no problem. It has been initialized.
DRAM: 128 MiB
Check if the following message is not causing any problem.
* Warning - bad CRC, using default environment
Check if all the devices have been initialized and nothing is skipped after the bad crc warning.

Resources