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
}
Related
The Raspberry Pi 3 Model B+ has two SD card controllers.
There is custom controller called sdhost as shown by the device tree node:
/* SDHOST is used to drive the SD card */
&sdhost {
pinctrl-names = "default";
pinctrl-0 = <&sdhost_gpio48>;
status = "okay";
bus-width = <4>;
};
And an SDHCI-compliant controller as shown by the following device tree node:
/* 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";
};
};
As referenced by the U-boot comments, U-boot is using SDHOST as the SD card controller and SDHCI as the WiFi controller.
/* SDHOST is used to drive the SD card */
...
/* SDHCI is used to control the SDIO for wireless */
The problem I'm facing is that I'm unable to run this SD card driver (source code here) via U-boot, which uses the Pi's SDHCI controller to interact with SD cards.
The SD card driver runs successfully bare-metal via the Pi's existing bootloader as shown by the output below:
EMMC: GPIO set up
EMMC: reset OK
sd_clk divisor 00000068, shift 00000006
EMMC: Sending command 00000000 arg 00000000
EMMC: Sending command 08020000 arg 000001AA
EMMC: Sending command 37000000 arg 00000000
EMMC: Sending command 29020000 arg 51FF8000
EMMC: CMD_SEND_OP_COND returned VOLTAGE CCS 0000000040F98000
...
However, when I try to run the binary via U-Boot using the go command, the code is stuck during the initialisation phase of the SDHCI controller (exact line in source code here) as shown below:
EMMC: GPIO set up
EMMC: reset OK
sd_clk divisor 00000068, shift 00000006
EMMC: Sending command 00000000 arg 00000000
EMMC: Sending command 08020000 arg 000001AA
ERROR: failed to send EMMC command
My suspicion is that since U-boot has configured the SDHCI controller for Wifi (and not for SD cards), I can no longer use it as an SD card controller. However, I want to use the SDHCI controller as the SD Card controller.
What is the best way to get my SD card binary running via U-boot?
Is the only option to configure/recompile U-boot to use the SDHCI controller as the main SD card controller (and forget about WiFi)?
If so, some pointers on how to go about this would be much appreciated.
Alternatively, is there a U-boot shell command (like some sort of reset command) that give binaries a runtime environment similar to a bare-metal environment that has been un-modified by U-boot?
Edit:
Here is my progress so far. I've figured out how to exclude the custom SDHOST driver from being initialised via two methods:
Modifying the DTS file by replacing status = "okay" with status = "disabled" for the custom SDHOST driver.
Adding CONFIG_MMC_BCM2835=n to U-Boot's configs/rpi_3_b_plus_defconfig file.
When I launch U-boot, and run mmc list, I see only the SDHCI controller, which is great:
U-Boot> mmc list
mmc#7e300000: 0
I know the above is the SDHCI controller because its device registers are mapped to the physical address of 7e300000 as shown in arch/arm/dts/bcm283x.dtsi below:
sdhci: mmc#7e300000 {
compatible = "brcm,bcm2835-sdhci";
reg = <0x7e300000 0x100>;
interrupts = <2 30>;
clocks = <&clocks BCM2835_CLOCK_EMMC>;
status = "disabled";
};
However, as shown in the following boot logs, U-boot is still not happy to use this controller as the SD card controller:
MMC: mmc#7e300000: 0
Loading Environment from FAT... Card did not respond to voltage select! : -110
** Bad device specification mmc 0 **
Below is the entire boot log:
U-Boot 2023.01-00790-g8c80619653-dirty (Feb 11 2023 - 10:04:49 +1100)
DRAM: 948 MiB
RPI 3 Model B+ (0xa020d3)
Core: 63 devices, 14 uclasses, devicetree: embed
MMC: mmc#7e300000: 0
Loading Environment from FAT... Card did not respond to voltage select! : -110
** Bad device specification mmc 0 **
In: serial
Out: vidconsole
Err: vidconsole
Net: No ethernet found.
starting USB...
Bus usb#7e980000: USB DWC2
scanning bus usb#7e980000 for devices... 4 USB Device(s) found
scanning usb for storage devices... 0 Storage Device(s) found
Hit any key to stop autoboot: 0
U-Boot> mmc list
mmc#7e300000: 0
My suspicion is that the SDHCI controller is still being treated by U-Boot as a WiFi controller (I can't tell for sure). What are some troubleshooting steps I can take to figure out what is going on?
My solution is to change the following line in the sdhci node of the DT located at arch/arm/dts/bcm2837-rpi-3-b-plus.dts from
pinctrl-0 = <&emmc_gpio34>;
to
pinctrl-0 = <&sdhost_gpio48>;
Then I recompile U-boot and use the resultant U-boot binary as the Pi’s bootloader.
The final and desired result is that:
U-boot can still use the sdhost driver and controller to access the SD card when it is running (which is U-boot’s default preference).
The binary run by U-boot (via the go command) can also manipulate the sdhci controller’s device registers to interact with the SD card.
For additional context around the solution, the sdhost_gpio48 reference above is located in this DTSI file located at arch/arm/dts/bcm283x.dtsi:
sdhost_gpio48: sdhost_gpio48 {
brcm,pins = <48 49 50 51 52 53>;
brcm,function = <BCM2835_FSEL_ALT0>;
};
The pinctrl-0 parameter we have changed refers to “Pin Control” and detailed documentation about this parameter can be found here.
From my understanding, our change specifies the same GPIO pins that are being used for the SDHOST controller for the SDHCI controller, which enables us to use the SDHCI controller as an SD card controller.
I use a chip from MTK7628,Currently, the kernel supports pps processing. Because the pps of my ublox is connected to gpio, i use make menuconfig and choose gpio mode
enter image description here
Because my chip does not support modifying the device tree,so i creat a dev-pps.c file in /home/luke/MtkOpenwrt/build_dir/target-mipsel_24kec+dsp_uClibc-0.9.33.2/linux-ramips_mt7628/linux-3.10.14/arch/mips/ralink, write the following code and compiled it into the firmware
enter image description here
When I write the firmware into the chip, the system will prompt the following error
enter image description here
Gpio 11 is connected to PPS and has been set to GPIO mode,this pin is not occupied either.I don't understand why the error "failed to request GPIO 11" is displayed.
About "probe of pps-gpio failed with error -22",I can not find a solution online.
Later, i use make kernel_menuconfig and choose gpio mode, turn off the PPS option in make menuconfig, as a result, after burning the firmware, the system will prompt the same error as before.
enter image description here
How do I resolve these two errors now?
I have an STM32 lorawan discovery board with an attached x_nucleo_iks02a1 shield. I'm trying to run the microphone sample, and I get an error at line 52
const struct device *mic_dev = device_get_binding(DT_LABEL(DT_INST(0, st_mpxxdtyy)));
// identifier "DT_N_INST_0_st_mpxxdtyy_P_label" is undefined
I looked at the zephyr.dts file and noticed that there is no compat listed with the string st_mpxxdtyy so I suppose that is the reason for the failure. The board I am using is not a nucleo but does have the same arduino compatible headers. Do I need to port this shield to this board?
Copy the overlay file x_nucleo_iks02a1_mic.overlay from /zephyrproject/zephyr/boards/shields/x_nucleo_iks02a1 to the root of your projectfolder.
Now you should be able to retrieve the device structure with:
const struct device *mic_dev = device_get_binding("MP34DT05");
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+
The STM32F2 micro-controller has build in capabilities to prevent readout of application code using a debug interface. It works fine and is accomplished pretty easily by configuring the read protection(RDP) level to '1' (!0xAA || !0xCC) or '2' (0xCC which is irreversible). Except trying to turn it off is where i run in to issues.
The expected behavior when the RDP level is lowered back to 0:
The chip will perform a mass flash erase.
Followed by clearing the protection flag.
System reset
Except after a power cycle the flash has been successfully erased but the protection flag remains on level '1' (0x55) keeping the debug interface disabled. And thus preventing me from writing any new application code. It is possible to fiddle around with the debugger and force the flag to level 0 (0xAA) manually though..
Is there anyone who have had the same or similar issues with the STM32F2xx series that can help me out? I'm using the STM32 standard peripheral drivers for programming the flash.
Enable
// Enable read out protection
FLASH_OB_Unlock();
FLASH_OB_RDPConfig(OB_RDP_Level_1);
FLASH_OB_Launch();
FLASH_OB_Lock();
// Restart platform
NVIC_SystemReset();
Disable
// Disable read out protection
FLASH_OB_Unlock();
FLASH_OB_RDPConfig(OB_RDP_Level_0);
FLASH_OB_Launch();
FLASH_OB_Lock();
// Restart platform
NVIC_SystemReset();
This is because before the clearing the protection flag, and in the middle of mass flash erase, you restart the chip.
The only way to recover the chip is to use the system bootloader.
Force boot0 pin to be 1 and force boot1 pin to be 0 at power up, start bootloader then connect USB and program the chip with DFU programmer.
You can download the DFU programmer here.
I used the library as follows (it was not working without FLASH_Unlock();):
// Flash Readout Protection Level 1
if (FLASH_OB_GetRDP() != SET) {
FLASH_Unlock(); // this line is critical!
FLASH_OB_Unlock();
FLASH_OB_RDPConfig(OB_RDP_Level_1);
FLASH_OB_Launch(); // Option Bytes programming
FLASH_OB_Lock();
FLASH_Lock();
}
No need for NVIC_SystemReset();.
Checking functionality worked best with STM32 ST-LINK utility CLI for me:
> "C:\Program Files (x86)\STMicroelectronics\STM32 ST-LINK Utility\ST-LINK Utility\ST-LINK_CLI.exe" -c SWD -rOB
STM32 ST-LINK CLI v3.0.0.0
STM32 ST-LINK Command Line Interface
ST-LINK SN : 51FF6D064989525019422287
ST-LINK Firmware version : V2J27S0
Connected via SWD.
SWD Frequency = 4000K.
Target voltage = 2.9 V.
Connection mode : Normal.
Device ID:0x422
Device flash Size : 256 Kbytes
Device family :STM32F302xB-xC/F303xB-xC/F358xx
Option bytes:
RDP : Level 1
IWDG_SW : 1
nRST_STOP : 1
nRST_STDBY : 1
nBoot1 : 1
VDDA : 1
Data0 : 0xFF
Data1 : 0xFF
nSRAM_Parity: 1
WRP : 0xFFFFFFFF
Not really a solution, but I hope this saves someone some time.