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

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.

Related

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
}

Uboot adding new serial driver on arm

I'm trying to add my own serial driver to uboot. That what I've been achieved so far are those messages:
U-Boot SPL 2017.09-gdc4fd1d6eb-dirty (Dec 30 2017 - 09:13:03)
DRAM: 2048 MiB
Trying to boot from FEL
but that is all. I know that there should be other messages also, but there are not any.
I suspect that my serial driver is working only in uboot SPL, but after that there is "uboot device model" driver compatible needed to run. Am I right?
To register my driver in "uboot device model" I introduced two invocations:
U_BOOT_DEVICE(sun8i_serials) = {
.name = "serial_sun8i",
.platdata = &sun8i_serial_plat,
};
U_BOOT_DRIVER(serial_sun8i) = {
.name = "serial_sun8i",
.id = UCLASS_SERIAL,
.ops = &sun8i_serial_ops,
.probe = sun8i_serial_probe,
};
With those two structures I expected that my procedure "sun8i_serial_probe" will be executed but it isn't. In this procedure I'm just turning on some LED, but this LED is still off, so my conclusion is that it is not invocated.
What should I do to proper register my driver and achieve call to my sun8i_serial_probe procedure?
Maybe after the SPL there is another step (third program loader?) and it is working in arm virtual memory space and that is why my procedure is not able to turn on the LED?
Any suggestions?
Edit1: I discovered that proc list_bind_drivers() issues "No match for driver serial_sun8i". So seems like U_BOOT_DEVICE is working fine while U_BOOT_DRIVER for some reasons not.
Edit2: Seems like I fixed the bug. The bug was in Makefile.

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

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+

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.

How to change device (LCD) parameters dynamically on Android Linux ARM device [duplicate]

Problem: I have to configure various LCD displays to be used by Android Platform. Almost in all cases there are no electrical specifications freely available for LCD displays on interest. But through experience and reverse engineering the parameters can be guessed reasonably well. I am trying to use Loadable Kernel Modules to fine tune the display parameters (any other suggestions are welcome too). Please find the relevant information below.
HW: Atmel SAMA5D31-EK (ARM 5 processor)
SW: Andriod Linux (Target), Ubuntu (Host System), Sourcery CodeBench (Cross Compiler)
Code Snippets from board-dt.c file
static struct fb_videomode at91_tft_vga_modes[] = {
.....
.xres =435;
.yres =235;
....
}
static struct fb_monspecs at91fb_default_monspecs = {
.........
.modedb = at91_tft_vga_modes,
......
}
static struct atmel_lcd_fb_info __initdata ek_lcdc_data = {
..........
.default_monspecs = & at91fb_default_monspecs;
.........
}
I added this code so the Loadable Kernel Module has access to lcdc_data structure
extern void set_fb_video(struct fb_videomode *mg_set_tft_vga_modes)
{
ek_lcdc_data.default_monspecs->modedb->xres = mg_set_tft_vga_modes->xres;
}
EXPORT_SYMBOL(set_fb_video);
When I execute the loadable kernel module I don’t notice any change in the display. I suspect although I am changing the variable (memory) but registers are not been affected.
Question: What am I missing? I have read about making calls to platform_driver_register() and platform_driver_unregister().
Thank you for your help in advance.

Resources