Qualcomm changes for v2025.07

-----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEtlGhRjxqvtBpDFXNBYMxKxlfZLYFAmf5HL8ACgkQBYMxKxlf
 ZLaY6A//Ry5wkX1f/WTVFUO6gBJQom6hsEpkNgYwtgzaWOWhqvR53e5sbsiMPKnO
 5BRtKhrs0Jp2/kl06+k5tsGQbr3rogvwNS9m8DFyF2Hfq7uT2ooQKzxeBM9MaGhI
 p+7d92JjcHeYP7ejWcoAnag0ZvM/3iofdsrRcGsFjbYbcbAkBtAUDj2RqaZFIAFk
 A6g6/IZ62K6QH24oAMPv5yR4ru2tfzRMJHdZh79FHMXNp9wOLgMsHAV8NToQ/ZHU
 ACn9EHc4g9aI8h8gXPTEjCzOx6saYcmV+zzn0mSeICCSbOqvJ/C2/96NUlD5BW8/
 XFIeuBNgnHyxv4O3idFpyaxF34SMp2j2dDAIQFLN+0lG1M1Zi75pqf9UzlSvvSjm
 d1xd/LbrOEwNEyTKG7Ss0e3nf03lP22s2COpFUPJAijkfRZ8K/Y8RISeQv+MJKwa
 AZqYofLua0Uo0kuKTiHuOdD5oWUxmEcjtisaP/X9hcXWteTillntp120qm/a93s2
 X015V56B/e2+uf9xAQW+iqnrcgpMGKffqbs7tVhVr3SDTDa+c4/c6EXX2naqzgDQ
 T/S0hetOONuNXZvyAguUq5HKNI0IoC+OZQhA1uIgq+JyV/7qgENyrERlt29435cg
 NAr+410m0OKYUGHz5xwLSUh2j68v/4fZj7I4nZt4eYjEfYk/2dI=
 =Ep2x
 -----END PGP SIGNATURE-----

Merge tag 'qcom-for-2025.07' of https://source.denx.de/u-boot/custodians/u-boot-snapdragon

Qualcomm changes for v2025.07:

CI: https://source.denx.de/u-boot/custodians/u-boot-snapdragon/-/pipelines/25653

There's been a surprising amount of activity lately on the Qualcomm
side with the two oldest boards getting some fresh attention and a lot
of cleanup and polish going on across the board.

* SDM660 gets USB phy fixes and a pinctrl driver
* The recently added SA8775P/QCS9100 SoC gets a pinctrl driver
* The Qualcomm pinctrl driver now handles reserved pins correctly,
  fixing crashes on some boards when running "gpio status -a"
* OF_UPSTREAM_BUILD_VENDOR is enabled in qcom_defconfig
* SDM845 and SC7280 get missing clocks added (since we're now stricter
  about those). This gets USB working more reliably in more cases.
* DM_USB_GADGET is enabled for all boards using DWC3 and fasbtoot is
  enabled too
* A bug in the livetree fixup code is fixed (making USB work on a lot
  more platforms)
* Button label lookup is made case insensitive* bootretry becomes more dynamic, allowing it to be hijacked to make a
  "persistent" boot menu that allows dropping to U-Boot shell later on
* A new qcom-phone.config fragment is added along with a phone-specific
  default environment and phone-specific debugging/bringup docs. These
  make U-Boot more usable on devices without a serial port or keyboard.
* The db820c gets fixed up and updated documentation
* The db410c also gets some love and modernisation as well as a new
  reviewer.
* A new driver is added for the USB VBUS regulator found on various
  Qualcomm PMICs
* The Qualcomm SPMI driver gets some fixes and cleanup for SPMI v5 and
  v7 support.
This commit is contained in:
Tom Rini 2025-04-11 09:12:16 -06:00
commit ff0b7d741d
41 changed files with 1598 additions and 164 deletions

View file

@ -1120,12 +1120,13 @@ config ARCH_SNAPDRAGON
select SPMI select SPMI
select BOARD_LATE_INIT select BOARD_LATE_INIT
select OF_BOARD select OF_BOARD
select SAVE_PREV_BL_FDT_ADDR select SAVE_PREV_BL_FDT_ADDR if !ENABLE_ARM_SOC_BOOT0_HOOK
select LINUX_KERNEL_IMAGE_HEADER if !ENABLE_ARM_SOC_BOOT0_HOOK select LINUX_KERNEL_IMAGE_HEADER if !ENABLE_ARM_SOC_BOOT0_HOOK
select SYSRESET select SYSRESET
select SYSRESET_PSCI select SYSRESET_PSCI
imply OF_UPSTREAM imply OF_UPSTREAM
imply CMD_DM imply CMD_DM
imply DM_USB_GADGET
config ARCH_SOCFPGA config ARCH_SOCFPGA
bool "Altera SOCFPGA family" bool "Altera SOCFPGA family"

View file

@ -6,7 +6,7 @@
/ { / {
/* When running as a first-stage bootloader this isn't filled in automatically */ /* When running as a first-stage bootloader this isn't filled in automatically */
memory@80000000 { memory@80000000 {
reg = <0 0x80000000 0 0x3da00000>; reg = <0 0x80000000 0 0x40000000>;
}; };
}; };

View file

@ -46,4 +46,19 @@ static inline bool qcom_is_special_pin(const struct msm_pin_data *pindata, unsig
return pindata->special_pins_start && pin >= pindata->special_pins_start; return pindata->special_pins_start && pin >= pindata->special_pins_start;
} }
struct udevice;
/**
* msm_pinctrl_is_reserved() - Check if a pin lies in a reserved range
*
* @dev: pinctrl device
* @pin: Pin number
*
* Returns: true if pin is reserved, otherwise false
*
* Call using dev_get_parent() from the GPIO device, it is a child of
* the pinctrl device.
*/
bool msm_pinctrl_is_reserved(struct udevice *dev, unsigned int pin);
#endif /* _QCOM_GPIO_H_ */ #endif /* _QCOM_GPIO_H_ */

View file

@ -86,13 +86,13 @@ static int fixup_qcom_dwc3(struct device_node *glue_np)
} }
/* Overwrite "phy-names" to only contain a single entry */ /* Overwrite "phy-names" to only contain a single entry */
ret = of_write_prop(dwc3, "phy-names", strlen("usb2-phy"), "usb2-phy"); ret = of_write_prop(dwc3, "phy-names", strlen("usb2-phy") + 1, "usb2-phy");
if (ret) { if (ret) {
log_err("Failed to overwrite 'phy-names' property: %d\n", ret); log_err("Failed to overwrite 'phy-names' property: %d\n", ret);
return ret; return ret;
} }
ret = of_write_prop(dwc3, "maximum-speed", strlen("high-speed"), "high-speed"); ret = of_write_prop(dwc3, "maximum-speed", strlen("high-speed") + 1, "high-speed");
if (ret) { if (ret) {
log_err("Failed to set 'maximum-speed' property: %d\n", ret); log_err("Failed to set 'maximum-speed' property: %d\n", ret);
return ret; return ret;
@ -161,14 +161,14 @@ int ft_board_setup(void *blob, struct bd_info __maybe_unused *bd)
struct fdt_header *fdt = blob; struct fdt_header *fdt = blob;
int node; int node;
/* We only want to do this fix-up for the RB1 board, quick return for all others */ /* On RB1/2 we need to fix-up the dr_mode */
if (!fdt_node_check_compatible(fdt, 0, "qcom,qrb4210-rb2")) if (!fdt_node_check_compatible(fdt, 0, "qcom,qrb4210-rb2") ||
return 0; !fdt_node_check_compatible(fdt, 0, "qcom,qrb2210-rb1")) {
fdt_for_each_node_by_compatible(node, blob, 0, "snps,dwc3") {
fdt_for_each_node_by_compatible(node, blob, 0, "snps,dwc3") { log_debug("%s: Setting 'dr_mode' to OTG\n", fdt_get_name(blob, node, NULL));
log_debug("%s: Setting 'dr_mode' to OTG\n", fdt_get_name(blob, node, NULL)); fdt_setprop_string(fdt, node, "dr_mode", "otg");
fdt_setprop_string(fdt, node, "dr_mode", "otg"); break;
break; }
} }
return 0; return 0;

View file

@ -1,5 +1,6 @@
DRAGONBOARD410C BOARD DRAGONBOARD410C BOARD
M: Ramon Fried <rfried.dev@gmail.com> M: Stephan Gerhold <stephan@gerhold.net>
R: Sam Day <me@samcday.com>
S: Maintained S: Maintained
F: board/qualcomm/dragonboard410c/ F: board/qualcomm/dragonboard410c/
F: include/configs/dragonboard410c.h F: include/configs/dragonboard410c.h

View file

@ -22,21 +22,6 @@
DECLARE_GLOBAL_DATA_PTR; DECLARE_GLOBAL_DATA_PTR;
/* UNSTUFF_BITS macro taken from Linux Kernel: drivers/mmc/core/sd.c */
#define UNSTUFF_BITS(resp, start, size) \
({ \
const int __size = size; \
const u32 __mask = (__size < 32 ? 1 << __size : 0) - 1; \
const int __off = 3 - ((start) / 32); \
const int __shft = (start) & 31; \
u32 __res; \
\
__res = resp[__off] >> __shft; \
if (__size + __shft > 32) \
__res |= resp[__off - 1] << ((32 - __shft) % 32); \
__res & __mask; \
})
static u32 msm_board_serial(void) static u32 msm_board_serial(void)
{ {
struct mmc *mmc_dev; struct mmc *mmc_dev;
@ -48,7 +33,8 @@ static u32 msm_board_serial(void)
if (mmc_init(mmc_dev)) if (mmc_init(mmc_dev))
return 0; return 0;
return UNSTUFF_BITS(mmc_dev->cid, 16, 32); /* MMC serial number */
return mmc_dev->cid[2] << 16 | mmc_dev->cid[3] >> 16;
} }
static void msm_generate_mac_addr(u8 *mac) static void msm_generate_mac_addr(u8 *mac)
@ -65,28 +51,6 @@ static void msm_generate_mac_addr(u8 *mac)
put_unaligned_be32(msm_board_serial(), &mac[2]); put_unaligned_be32(msm_board_serial(), &mac[2]);
} }
/* Check for vol- button - if pressed - stop autoboot */
int misc_init_r(void)
{
struct udevice *btn;
int ret;
enum button_state_t state;
ret = button_get_by_label("vol_down", &btn);
if (ret < 0) {
printf("Couldn't find power button!\n");
return ret;
}
state = button_get_state(btn);
if (state == BUTTON_ON) {
env_set("preboot", "setenv preboot; fastboot 0");
printf("vol_down pressed - Starting fastboot.\n");
}
return 0;
}
int qcom_late_init(void) int qcom_late_init(void)
{ {
char serial[16]; char serial[16];
@ -97,9 +61,9 @@ int qcom_late_init(void)
return 0; return 0;
} }
/* Fixup of DTB for Linux Kernel /*
* 1. Fixup installed DRAM. * Fixup of DTB for Linux Kernel
* 2. Fixup WLAN/BT Mac address: * 1. Fixup WLAN/BT Mac address:
* First, check if MAC addresses for WLAN/BT exists as environemnt * First, check if MAC addresses for WLAN/BT exists as environemnt
* variables wlanaddr,btaddr. if not, generate a unique address. * variables wlanaddr,btaddr. if not, generate a unique address.
*/ */
@ -107,6 +71,7 @@ int qcom_late_init(void)
int ft_board_setup(void *blob, struct bd_info *bd) int ft_board_setup(void *blob, struct bd_info *bd)
{ {
u8 mac[ARP_HLEN]; u8 mac[ARP_HLEN];
int i;
if (!eth_env_get_enetaddr("wlanaddr", mac)) { if (!eth_env_get_enetaddr("wlanaddr", mac)) {
msm_generate_mac_addr(mac); msm_generate_mac_addr(mac);
@ -118,12 +83,24 @@ int ft_board_setup(void *blob, struct bd_info *bd)
if (!eth_env_get_enetaddr("btaddr", mac)) { if (!eth_env_get_enetaddr("btaddr", mac)) {
msm_generate_mac_addr(mac); msm_generate_mac_addr(mac);
/* The BD address is same as WLAN MAC address but with /*
* least significant bit flipped. * The BD address is same as WLAN MAC address but with
*/ * least significant bit flipped.
mac[0] ^= 0x01; */
mac[ARP_HLEN - 1] ^= 0x01;
}; };
/*
* Reverse array since local-bd-address is formatted with least
* significant byte first (little endian).
*/
for (i = 0; i < ARP_HLEN / 2; ++i) {
u8 tmp = mac[i];
mac[i] = mac[ARP_HLEN - 1 - i];
mac[ARP_HLEN - 1 - i] = tmp;
}
do_fixup_by_compat(blob, "qcom,wcnss-bt", do_fixup_by_compat(blob, "qcom,wcnss-bt",
"local-bd-address", mac, ARP_HLEN, 1); "local-bd-address", mac, ARP_HLEN, 1);
return 0; return 0;

View file

@ -1,36 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0+ */ /* SPDX-License-Identifier: GPL-2.0+ */
/* Does what recovery does */
#define REFLASH(file, partnum) \
part start mmc 0 partnum start && \
part size mmc 0 partnum size && \
tftp $loadaddr file && \
mmc write $loadaddr $start $size &&
reflash=
mmc dev 0 &&
usb start &&
dhcp &&
tftp $loadaddr dragonboard/rescue/gpt_both0.bin &&
mmc write $loadaddr 0 43 &&
mmc rescan &&
REFLASH(dragonboard/rescue/NON-HLOS.bin, 1)
REFLASH(dragonboard/rescue/sbl1.mbn, 2)
REFLASH(dragonboard/rescue/rpm.mbn, 3)
REFLASH(dragonboard/rescue/tz.mbn, 4)
REFLASH(dragonboard/rescue/hyp.mbn, 5)
REFLASH(dragonboard/rescue/sec.dat, 6)
REFLASH(dragonboard/rescue/emmc_appsboot.mbn, 7)
REFLASH(dragonboard/u-boot.img, 8)
usb stop &&
echo Reflash completed
loadaddr=0x81000000
initrd_high=0xffffffffffffffff initrd_high=0xffffffffffffffff
linux_image=Image fastboot=fastboot -l $fastboot_addr_r usb 0
kernel_addr_r=0x81000000 boot_targets=usb mmc1 mmc0 pxe
fdtfile=qcom/apq8016-sbc.dtb button_cmd_0_name=vol_down
fdt_addr_r=0x83000000 button_cmd_0=run fastboot
ramdisk_addr_r=0x84000000
scriptaddr=0x90000000
pxefile_addr_r=0x90100000

View file

@ -106,7 +106,7 @@ int misc_init_r(void)
int ret; int ret;
enum button_state_t state; enum button_state_t state;
ret = button_get_by_label("pwrkey", &btn); ret = button_get_by_label("Power Button", &btn);
if (ret < 0) { if (ret < 0) {
printf("Couldn't find power button!\n"); printf("Couldn't find power button!\n");
return ret; return ret;

View file

@ -16,10 +16,7 @@
Build & Run instructions Build & Run instructions
================================================================================ ================================================================================
1) Install mkbootimg and dtbTool from Codeaurora: 1) Install mkbootimg
git://codeaurora.org/quic/kernel/skales
commit 8492547e404e969262d9070dee9bdd15668bb70f worked for me.
2) Setup CROSS_COMPILE to aarch64 compiler or if you use ccache just do 2) Setup CROSS_COMPILE to aarch64 compiler or if you use ccache just do
CROSS_COMPILE="ccache aarch64-linux-gnu-" CROSS_COMPILE="ccache aarch64-linux-gnu-"
@ -33,15 +30,15 @@
$ touch rd $ touch rd
5) Generate qualcomm device tree table with dtbTool 5) Append the dtb to the u-boot binary discarding the internal dtb.
$ dtbTool -o dt.img arch/arm/dts $ gzip u-boot-nodtb.bin
$ cat u-boot.dtb >> u-boot-nodtb.bin.gz
6) Generate Android boot image with mkbootimg: 6) Generate Android boot image with mkbootimg:
$ mkbootimg --kernel=u-boot-dtb.bin \ $ mkbootimg --kernel=u-boot-nodtb.bin.gz \
--output=u-boot.img \ --output=u-boot.img \
--dt=dt.img \
--pagesize 4096 \ --pagesize 4096 \
--base 0x80000000 \ --base 0x80000000 \
--ramdisk=rd \ --ramdisk=rd \
@ -251,44 +248,42 @@ Wait for 5 seconds before proceeding
[5300] booting linux @ 0x80080000, ramdisk @ 0x82200000 (0), tags/device tree @ 0x82000000 [5300] booting linux @ 0x80080000, ramdisk @ 0x82200000 (0), tags/device tree @ 0x82000000
[5310] Jumping to kernel via monitor [5310] Jumping to kernel via monitor
U-Boot 2017.11-00145-ge895117 (Nov 29 2017 - 10:04:06 +0100) U-Boot 2025.04-rc5-00020-g40a61ca0e7eb-dirty (Apr 07 2025 - 09:37:03 +0200)
Qualcomm-DragonBoard 820C Qualcomm-DragonBoard 820C
DRAM: 3 GiB DRAM: 3.5 GiB (effective 3 GiB)
PSCI: v1.0 Core: 136 devices, 18 uclasses, devicetree: board
MMC: sdhci@74a4900: 0 MMC: Bulk clocks not available (-19), trying core clock
mmc@74a4900: 0
Loading Environment from EXT4... OK
In: serial@75b0000 In: serial@75b0000
Out: serial@75b0000 Out: serial@75b0000
Err: serial@75b0000 Err: serial@75b0000
Net: Net Initialization Skipped Net: No ethernet found.
No ethernet found.
Hit any key to stop autoboot: 0 Hit any key to stop autoboot: 0
switch to partitions #0, OK switch to partitions #0, OK
mmc0 is current device mmc0 is current device
Scanning mmc 0:1... Scanning mmc 0:1...
Found /extlinux/extlinux.conf Found /extlinux/extlinux.conf
Retrieving file: /extlinux/extlinux.conf Retrieving file: /extlinux/extlinux.conf
433 bytes read in 71 ms (5.9 KiB/s)
1: nfs root 1: nfs root
Enter choice: 1: nfs root
Retrieving file: /uImage Retrieving file: /uImage
19397184 bytes read in 2024 ms (9.1 MiB/s) append: root=/dev/nfs rw nfsroot=192.168.1.6:/home/jramirez/Src/qualcomm-lt/db820c/rootfs,v3,tcp rootwait ip=dhcp consoleblank=0 console=tty0 console=ttyMSM0,115200n8 earlyprintk earlyco0
append: root=/dev/nfs rw nfsroot=192.168.1.2:/db820c/rootfs,v3,tcp rootwait ip=dhcp consoleblank=0 console=tty0 console=ttyMSM0,115200n8 earlyprintk earlycon=msm_serial_dm,0x75b0000 androidboot.bootdevice=624000.ufshc androidboot.verifiedbootstate=orange androidboot.ver0
Retrieving file: /apq8096-db820c.dtb Retrieving file: /apq8096-db820c.dtb
38134 bytes read in 37 ms (1005.9 KiB/s) ## Booting kernel from Legacy Image at 155000000 ...
## Booting kernel from Legacy Image at 95000000 ...
Image Name: Dragonboard820c Image Name: Dragonboard820c
Image Type: AArch64 Linux Kernel Image (uncompressed) Image Type: AArch64 Linux Kernel Image (uncompressed)
Data Size: 19397120 Bytes = 18.5 MiB Data Size: 19397120 Bytes = 18.5 MiB
Load Address: 80080000 Load Address: 80080000
Entry Point: 80080000 Entry Point: 80080000
Verifying Checksum ... OK Verifying Checksum ... OK
## Flattened Device Tree blob at 93000000 ## Flattened Device Tree blob at 148600000
Booting using the fdt blob at 0x93000000 Booting using the fdt blob at 0x148600000
Loading Kernel Image ... OK Working FDT set to 148600000
Using Device Tree in place at 0000000093000000, end 000000009300c4f5 Loading Kernel Image to 80080000
Using Device Tree in place at 0000000148600000, end 000000014860c4f5
Working FDT set to 148600000
Starting kernel ... Starting kernel ...

View file

@ -0,0 +1,29 @@
# Settings for phones
CONFIG_DEFAULT_ENV_FILE="board/qualcomm/qcom-phone.env"
# Hang on panic so the error message can be read
CONFIG_PANIC_HANG=y
# We use pause in various places to allow text to be read
# before it scrolls off the screen
CONFIG_CMD_PAUSE=y
CONFIG_BOOT_RETRY=y
CONFIG_BOOT_RETRY_TIME=1
CONFIG_BUTTON_REMAP_PHONE_KEYS=y
CONFIG_RETRY_BOOTCMD=y
CONFIG_FASTBOOT_BUF_ADDR=0x1A000000
CONFIG_USB_FUNCTION_FASTBOOT=y
CONFIG_USB_FUNCTION_ACM=y
CONFIG_CMD_UMS_ABORT_KEYED=y
# Record all console output and let it be dumped via fastboot
CONFIG_CONSOLE_RECORD=y
CONFIG_CONSOLE_RECORD_INIT_F=y
CONFIG_CONSOLE_RECORD_OUT_SIZE=0x6000
CONFIG_FASTBOOT_CMD_OEM_CONSOLE=y
# Only MMC is supported by fastboot currently, but this is still useful.
CONFIG_FASTBOOT_FLASH=y
CONFIG_FASTBOOT_FLASH_MMC_DEV=0
CONFIG_FASTBOOT_OEM_RUN=y
# Many phones don't actually define a serial port in their DTS
# CONFIG_REQUIRE_SERIAL_CONSOLE is not set

View file

@ -0,0 +1,47 @@
bootdelay=0
bootretry=1
stdin=serial,button-kbd
stdout=serial,vidconsole
stderr=serial,vidconsole
# Fastboot is keen to use the address from kconfig, but we
# allocate its buffer at runtime.
fastboot=fastboot -l $fastboot_addr_r usb 0
# Always probe for UFS storage, though it should be done by board code.
preboot=scsi scan
# Shortcut to enable USB serial gadget and disable bootretry
serial_gadget=setenv stdin serial,button-kbd,usbacm; \
setenv stdout serial,vidconsole,usbacm; \
setenv stderr serial,vidconsole,usbacm; \
setenv bootretry -1; \
echo Enabled U-Boot console serial gadget
# bootretry will run this command over and over, if we fail once
# then bail out to the boot menu instead (with a pause to read
# the error message)
bootcmd=bootefi bootmgr; pause; run menucmd
# When entering the menu (either from button press or failed boot)
# remap bootcmd so it will re-open the menu and we won't get stuck
# at the console with no way to type
menucmd=setenv bootcmd run menucmd; bootmenu -1
# Pause is used so the output can be read on the display
bootmenu_0=Boot=bootefi bootmgr; pause
bootmenu_1=Enable serial console gadget=run serial_gadget
bootmenu_2=Enable USB mass storage=echo "Press any key to exit UMS mode"; ums 0 scsi 0
bootmenu_3=Enable fastboot mode=run fastboot
# Disabling bootretry means we'll just drop the shell
bootmenu_4=Drop to shell=setenv bootretry -1
bootmenu_5=Reset device=reset
bootmenu_6=Dump clocks=clk dump; pause
bootmenu_7=Dump environment=printenv; pause
bootmenu_8=Board info=bdinfo; pause
bootmenu_9=Dump bootargs=fdt print /chosen bootargs; pause
# Allow holding the volume down button while U-Boot loads to enter
# the boot menu
button_cmd_0_name=Volume Down
button_cmd_0=run menucmd

View file

@ -1704,6 +1704,13 @@ config RESET_TO_RETRY
After the countdown timed out, the board will be reset to restart After the countdown timed out, the board will be reset to restart
again. again.
config RETRY_BOOTCMD
bool "Run bootcmd on retry"
depends on BOOT_RETRY && HUSH_PARSER && !RESET_TO_RETRY
help
If this option is enabled, the "bootcmd" will be run after the
countdown times out.
endmenu endmenu
menu "Image support" menu "Image support"

View file

@ -37,6 +37,8 @@ void bootretry_init_cmd_timeout(void)
*/ */
void bootretry_reset_cmd_timeout(void) void bootretry_reset_cmd_timeout(void)
{ {
/* Parse changes to bootretry */
bootretry_init_cmd_timeout();
endtime = endtick(retry_time); endtime = endtick(retry_time);
} }

View file

@ -1028,8 +1028,10 @@ static void get_user_input(struct in_str *i)
puts("\nTimeout waiting for command\n"); puts("\nTimeout waiting for command\n");
# ifdef CONFIG_RESET_TO_RETRY # ifdef CONFIG_RESET_TO_RETRY
do_reset(NULL, 0, 0, NULL); do_reset(NULL, 0, 0, NULL);
# else # elif IS_ENABLED(CONFIG_RETRY_BOOTCMD)
# error "This currently only works with CONFIG_RESET_TO_RETRY enabled" strcpy(console_buffer, "run bootcmd\n");
# else
# error "This only works with CONFIG_RESET_TO_RETRY or CONFIG_BOOT_RETRY_COMMAND enabled"
# endif # endif
} }
#endif #endif

View file

@ -2907,8 +2907,10 @@ static void get_user_input(struct in_str *i)
puts("\nTimeout waiting for command\n"); puts("\nTimeout waiting for command\n");
# ifdef CONFIG_RESET_TO_RETRY # ifdef CONFIG_RESET_TO_RETRY
do_reset(NULL, 0, 0, NULL); do_reset(NULL, 0, 0, NULL);
# else # elif IS_ENABLED(CONFIG_RETRY_BOOTCMD)
# error "This currently only works with CONFIG_RESET_TO_RETRY enabled" strcpy(console_buffer, "run bootcmd\n");
# else
# error "This only works with CONFIG_RESET_TO_RETRY or CONFIG_BOOT_RETRY_COMMAND enabled"
# endif # endif
} }
# endif # endif

View file

@ -1,6 +1,6 @@
CONFIG_ARM=y CONFIG_ARM=y
CONFIG_SYS_BOARD="dragonboard410c" CONFIG_SYS_BOARD="dragonboard410c"
CONFIG_COUNTER_FREQUENCY=19000000 CONFIG_COUNTER_FREQUENCY=19200000
CONFIG_ENABLE_ARM_SOC_BOOT0_HOOK=y CONFIG_ENABLE_ARM_SOC_BOOT0_HOOK=y
CONFIG_ARCH_SNAPDRAGON=y CONFIG_ARCH_SNAPDRAGON=y
CONFIG_TEXT_BASE=0x8f600000 CONFIG_TEXT_BASE=0x8f600000
@ -14,18 +14,16 @@ CONFIG_OF_LIBFDT_OVERLAY=y
CONFIG_SYS_LOAD_ADDR=0x80080000 CONFIG_SYS_LOAD_ADDR=0x80080000
CONFIG_IDENT_STRING="\nQualcomm-DragonBoard 410C" CONFIG_IDENT_STRING="\nQualcomm-DragonBoard 410C"
CONFIG_REMAKE_ELF=y CONFIG_REMAKE_ELF=y
# CONFIG_ANDROID_BOOT_IMAGE is not set CONFIG_BUTTON_CMD=y
CONFIG_FIT=y CONFIG_FIT=y
CONFIG_DISTRO_DEFAULTS=y CONFIG_BOOTSTD_FULL=y
CONFIG_OF_BOARD_SETUP=y CONFIG_OF_BOARD_SETUP=y
CONFIG_USE_PREBOOT=y CONFIG_USE_PREBOOT=y
CONFIG_SYS_CBSIZE=512 CONFIG_SYS_CBSIZE=512
CONFIG_SYS_PBSIZE=548 CONFIG_SYS_PBSIZE=548
# CONFIG_DISPLAY_CPUINFO is not set # CONFIG_DISPLAY_CPUINFO is not set
# CONFIG_DISPLAY_BOARDINFO is not set # CONFIG_DISPLAY_BOARDINFO is not set
CONFIG_MISC_INIT_R=y
CONFIG_SYS_PROMPT="dragonboard410c => " CONFIG_SYS_PROMPT="dragonboard410c => "
# CONFIG_CMD_IMI is not set
CONFIG_CMD_MD5SUM=y CONFIG_CMD_MD5SUM=y
CONFIG_CMD_MEMINFO=y CONFIG_CMD_MEMINFO=y
CONFIG_CMD_GPIO=y CONFIG_CMD_GPIO=y
@ -35,6 +33,7 @@ CONFIG_CMD_USB=y
CONFIG_BOOTP_BOOTFILESIZE=y CONFIG_BOOTP_BOOTFILESIZE=y
CONFIG_CMD_CACHE=y CONFIG_CMD_CACHE=y
CONFIG_CMD_TIMER=y CONFIG_CMD_TIMER=y
CONFIG_CMD_SYSBOOT=y
CONFIG_ENV_IS_IN_MMC=y CONFIG_ENV_IS_IN_MMC=y
CONFIG_SYS_RELOC_GD_ENV_ADDR=y CONFIG_SYS_RELOC_GD_ENV_ADDR=y
CONFIG_SYS_MMC_ENV_PART=2 CONFIG_SYS_MMC_ENV_PART=2
@ -60,6 +59,7 @@ CONFIG_PMIC_QCOM=y
CONFIG_MSM_SERIAL=y CONFIG_MSM_SERIAL=y
CONFIG_SPMI_MSM=y CONFIG_SPMI_MSM=y
CONFIG_USB=y CONFIG_USB=y
# CONFIG_DM_USB_GADGET is not set
CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_MSM=y CONFIG_USB_EHCI_MSM=y
CONFIG_USB_ULPI_VIEWPORT=y CONFIG_USB_ULPI_VIEWPORT=y
@ -68,6 +68,7 @@ CONFIG_USB_HOST_ETHER=y
CONFIG_USB_ETHER_ASIX=y CONFIG_USB_ETHER_ASIX=y
CONFIG_USB_ETHER_ASIX88179=y CONFIG_USB_ETHER_ASIX88179=y
CONFIG_USB_ETHER_MCS7830=y CONFIG_USB_ETHER_MCS7830=y
CONFIG_USB_ETHER_RTL8152=y
CONFIG_USB_ETHER_SMSC95XX=y CONFIG_USB_ETHER_SMSC95XX=y
CONFIG_USB_GADGET=y CONFIG_USB_GADGET=y
CONFIG_USB_GADGET_VENDOR_NUM=0x18d1 CONFIG_USB_GADGET_VENDOR_NUM=0x18d1

View file

@ -45,4 +45,6 @@ CONFIG_PINCTRL_QCOM_APQ8096=y
CONFIG_DM_PMIC=y CONFIG_DM_PMIC=y
CONFIG_PMIC_QCOM=y CONFIG_PMIC_QCOM=y
CONFIG_MSM_SERIAL=y CONFIG_MSM_SERIAL=y
CONFIG_MSM_GPIO=y
CONFIG_SPMI_MSM=y CONFIG_SPMI_MSM=y
CONFIG_CLK_STUB=y

View file

@ -70,6 +70,7 @@ CONFIG_PMIC_QCOM=y
CONFIG_MSM_SERIAL=y CONFIG_MSM_SERIAL=y
CONFIG_SPMI_MSM=y CONFIG_SPMI_MSM=y
CONFIG_USB=y CONFIG_USB=y
# CONFIG_DM_USB_GADGET is not set
CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_MSM=y CONFIG_USB_EHCI_MSM=y
CONFIG_USB_ULPI_VIEWPORT=y CONFIG_USB_ULPI_VIEWPORT=y

View file

@ -41,6 +41,7 @@ CONFIG_CMD_RNG=y
CONFIG_CMD_REGULATOR=y CONFIG_CMD_REGULATOR=y
CONFIG_CMD_LOG=y CONFIG_CMD_LOG=y
CONFIG_OF_LIVE=y CONFIG_OF_LIVE=y
CONFIG_OF_UPSTREAM_BUILD_VENDOR=y
CONFIG_USE_DEFAULT_ENV_FILE=y CONFIG_USE_DEFAULT_ENV_FILE=y
CONFIG_DEFAULT_ENV_FILE="board/qualcomm/default.env" CONFIG_DEFAULT_ENV_FILE="board/qualcomm/default.env"
CONFIG_BUTTON_QCOM_PMIC=y CONFIG_BUTTON_QCOM_PMIC=y
@ -62,6 +63,11 @@ CONFIG_CLK_QCOM_X1E80100=y
CONFIG_DFU_MMC=y CONFIG_DFU_MMC=y
CONFIG_DFU_SCSI=y CONFIG_DFU_SCSI=y
CONFIG_SYS_DFU_DATA_BUF_SIZE=0x200000 CONFIG_SYS_DFU_DATA_BUF_SIZE=0x200000
CONFIG_USB_FUNCTION_FASTBOOT=y
CONFIG_FASTBOOT_BUF_ADDR=0x0
CONFIG_FASTBOOT_FLASH=y
CONFIG_FASTBOOT_FLASH_MMC_DEV=0
CONFIG_FASTBOOT_MMC_USER_SUPPORT=y
CONFIG_MSM_GPIO=y CONFIG_MSM_GPIO=y
CONFIG_QCOM_PMIC_GPIO=y CONFIG_QCOM_PMIC_GPIO=y
CONFIG_DM_I2C=y CONFIG_DM_I2C=y
@ -75,7 +81,6 @@ CONFIG_QCOM_HYP_SMMU=y
CONFIG_MISC=y CONFIG_MISC=y
CONFIG_NVMEM=y CONFIG_NVMEM=y
CONFIG_I2C_EEPROM=y CONFIG_I2C_EEPROM=y
CONFIG_MMC_HS200_SUPPORT=y
CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_ADMA=y CONFIG_MMC_SDHCI_ADMA=y
CONFIG_MMC_SDHCI_MSM=y CONFIG_MMC_SDHCI_MSM=y
@ -97,6 +102,7 @@ CONFIG_PINCTRL_QCOM_APQ8016=y
CONFIG_PINCTRL_QCOM_APQ8096=y CONFIG_PINCTRL_QCOM_APQ8096=y
CONFIG_PINCTRL_QCOM_QCM2290=y CONFIG_PINCTRL_QCOM_QCM2290=y
CONFIG_PINCTRL_QCOM_QCS404=y CONFIG_PINCTRL_QCOM_QCS404=y
CONFIG_PINCTRL_QCOM_SA8775P=y
CONFIG_PINCTRL_QCOM_SC7280=y CONFIG_PINCTRL_QCOM_SC7280=y
CONFIG_PINCTRL_QCOM_SDM845=y CONFIG_PINCTRL_QCOM_SDM845=y
CONFIG_PINCTRL_QCOM_SM6115=y CONFIG_PINCTRL_QCOM_SM6115=y

View file

@ -90,6 +90,11 @@ Or for db410c (and other boards not supported by the generic target)::
make CROSS_COMPILE=aarch64-linux-gnu- O=.output dragonboard410c_defconfig make CROSS_COMPILE=aarch64-linux-gnu- O=.output dragonboard410c_defconfig
make O=.output -j$(nproc) make O=.output -j$(nproc)
Or for smartphones::
make CROSS_COMPILE=aarch64-linux-gnu- O=.output qcom_defconfig qcom-phone.config
make O=.output -j$(nproc)
- gzip u-boot:: - gzip u-boot::
gzip u-boot-nodtb.bin gzip u-boot-nodtb.bin

View file

@ -9,5 +9,6 @@ Qualcomm
dragonboard410c dragonboard410c
rb3gen2 rb3gen2
board board
phones
debugging debugging
rdp rdp

View file

@ -0,0 +1,144 @@
.. SPDX-License-Identifier: GPL-2.0+
.. sectionauthor:: Caleb Connolly <caleb.connolly@linaro.org>
======================================
Booting U-Boot on Qualcomm smartphones
======================================
About this
----------
This page attempts to the describe U-Boot support for Qualcomm phones, as a user guide but also a
technical introduction to How Stuff Works to help new porters.
In broad strokes, U-Boot should boot if the SoC is supported, and the device is already capable of
booting an upstream Linux kernel.
The list of supported Qualcomm SoCs changes often, for now it is best to look in
``drivers/clk/qcom/`` to get a rough idea.
For building instructions, see :doc:`board`.
Phone bringup
-------------
It is usually easier to get Linux booting first, there are many good resources for this such as the
`postmarketOS wiki`_. Once the device can boot Linux with logs on the display and ideally USB gadget
support, it is highly likely that U-Boot will boot as well.
For logs on display, you should have a simple framebuffer node defined in your DT, newer devices
require that this follow the downstream naming scheme (that the DTB is compiled with labels enabled
and the framebuffer reserved-memory region is labelled ``cont_splash``). Once this is working in
Linux it should also work in U-Boot.
In practise, U-Boot still has many more papercuts than Linux, which can be sticking points when
porting a new device. In particular, drivers failing to bind/probe (especially pre-relocation) can
be tricky to debug without UART since U-Boot will simply panic with no way to inform you of
the error. As a result, bringing up a new device can be quite frustrating, but there are quite a few
things you can try.
The phone config
^^^^^^^^^^^^^^^^
Since most phones lack a physical keyboard or serial port, a special config fragment and environment
file can be used to provide a more seamless experience. This can be enabled by generating the config
with::
make CROSS_COMPILE=aarch64-linux-gnu- O=.output qcom_defconfig qcom-phone.config
The config and associated environment file can be found in board/qualcomm/. The main changes are:
- Panic on hang (so the panic message can be read on the display)
- Boot retry (to automatically open and re-open the bootmenu)
- A boot menu with helpful shortcuts (including USB console gadget)
- Launch the boot menu if power is held during boot or on boot failure
Fastboot mode
-------------
U-Boot's fastboot implementation is much more limited than Qualcomm's, and currently does not have a
backend for UFS storage. If your device uses eMMC or has an sdcard slot, fastboot will use that by
default.
You may need to run the fastboot command on your PC as root since the USB product/vendor ID may not
match the android udev rules.
You can also use fastboot to run arbitrary U-Boot commands with ``fastboot oem run``
Retrieving early logs
^^^^^^^^^^^^^^^^^^^^^
U-Boot is configured to save it's internal log to a buffer, this can help with debugging some driver
bind/probe issues. If your device can boot and has working USB, you can enable fastboot mode (either
via the U-Boot menu or by adding ``run fastboot`` to the end of the ``preboot=`` config in
``board/qualcomm/qcom-phone.env``).
You can then retrieve U-Boot's log buffer with the ``fastboot oem log`` command on your PC.
Hang/crash bisection
--------------------
Without a way to get logs, we can still get quite far with only a few bits of information: what
happens when you ``fastboot boot u-boot.img``?
Does the device disconnect?
^^^^^^^^^^^^^^^^^^^^^^^^^^^
This can be verified by watching ``dmesg -w``. If it stays connected, it likely means the boot image
doesn't match what the bootloader expected, use ``unpack_bootimg`` to compare it with a known-good
boot image (ideally one with an upstream kernel).
Does the device hang?
^^^^^^^^^^^^^^^^^^^^^
If it stays on a black screen and does nothing, then that's a hang! Since ``qcom-phone.config``
enables CONFIG_PANIC_HANG, this likely means that you're successfully executing U-Boot code (yay!),
but something is causing a panic.
It could also be due to a bad memory or register access triggering a secure interrupt, it's worth
waiting for around a minute to see if the device eventually reboots or goes to crashdump mode. You
can also disable CONFIG_PANIC_HANG and see if that causes the device to reboot instead, if so then
it is definitely a U-Boot panic.
With enough time and patience, it should be possible to narrow down the cause of the panic by
inserting calls to ``reset_cpu()`` (with CONFIG_PANIC_HANG enabled). Then if the device resets you
know it executed the ``reset_cpu()`` call.
A good place to start is ``board_fdt_blob_setup()`` in ``arch/arm/mach-snapdragon/board.c``, this
function is called extremely early so adding a reset call is a good way to validate that U-Boot is
definitely running.
You can then do a binary search starting from the end of ``board_init_f()`` / start of
``board_init_r()`` and work from there using the init sequences for reference.
The Qualcomm RAM parsing code is a likely culprit, as ABL is known to sometimes give bogus entries
in the memory node which can trip U-Boot up.
To rule out crashes that might be caused by specific drivers, it's a good idea to disable them and
re-enable them one by one. Here is a non-exhaustive list of drivers to disable:
- pinctrl
- mmc
- scsi/ufs
- usb (dwc3)
- phy (usb, ufs)
- clk (remove clock references from your framebuffer node in DT)
Ideally, it would be possible to use the framebuffer as an early console / debug output, at the time
of writing there are out of tree patches for this but they haven't been submitted upstream yet.
Does the device reboot or go to crashdump mode?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
On many devices crashdump mode is disabled, so they will reboot instead (maybe after some delay).
The same approach as suggested above can be used to figure out where the crash occurs.
If the device is rebooting, you can insert calls to ``hang()`` instead of ``reset_cpu()`` when
following the instructions above.
The most likely cause of a crashdump is the pinctrl/gpio driver or the SMMU driver, ensure that the
``apps_smmu`` node in your SoCs devicetree file has one of its compatible strings referenced in
``drivers/iommu/qcom-hyp-smmu.c``, you can also try disabling the pinctrl driver for your SoC (or
``CONFIG_PINCTRL`` altogether).
.. _`postmarketOS wiki`: https://wiki.postmarketos.org/wiki/Mainlining

View file

@ -73,25 +73,25 @@ static const struct qcom_pmic_btn_data qcom_pmic_btn_data_table[] = {
.compatible = "qcom,pm8941-pwrkey", .compatible = "qcom,pm8941-pwrkey",
.status_bit = PON_KPDPWR_N_SET, .status_bit = PON_KPDPWR_N_SET,
.code = KEY_ENTER, .code = KEY_ENTER,
.label = "pwrkey", .label = "Power Button",
}, },
{ {
.compatible = "qcom,pm8941-resin", .compatible = "qcom,pm8941-resin",
.status_bit = PON_RESIN_N_SET, .status_bit = PON_RESIN_N_SET,
.code = KEY_DOWN, .code = KEY_DOWN,
.label = "vol_down", .label = "Volume Down",
}, },
{ {
.compatible = "qcom,pmk8350-pwrkey", .compatible = "qcom,pmk8350-pwrkey",
.status_bit = PON_GEN3_KPDPWR_N_SET, .status_bit = PON_GEN3_KPDPWR_N_SET,
.code = KEY_ENTER, .code = KEY_ENTER,
.label = "pwrkey", .label = "Power Button",
}, },
{ {
.compatible = "qcom,pmk8350-resin", .compatible = "qcom,pmk8350-resin",
.status_bit = PON_GEN3_RESIN_N_SET, .status_bit = PON_GEN3_RESIN_N_SET,
.code = KEY_DOWN, .code = KEY_DOWN,
.label = "vol_down", .label = "Volume Down",
}, },
}; };

View file

@ -21,7 +21,7 @@ int button_get_by_label(const char *label, struct udevice **devp)
struct button_uc_plat *uc_plat = dev_get_uclass_plat(dev); struct button_uc_plat *uc_plat = dev_get_uclass_plat(dev);
/* Ignore the top-level button node */ /* Ignore the top-level button node */
if (uc_plat->label && !strcmp(label, uc_plat->label)) if (uc_plat->label && !strcasecmp(label, uc_plat->label))
return uclass_get_device_tail(dev, 0, devp); return uclass_get_device_tail(dev, 0, devp);
} }

View file

@ -14,7 +14,7 @@
static const struct udevice_id nop_parent_ids[] = { static const struct udevice_id nop_parent_ids[] = {
{ .compatible = "qcom,rpm-proc" }, { .compatible = "qcom,rpm-proc" },
{ .compatible = "qcom,glink-rpm" }, { .compatible = "qcom,glink-rpm" },
{ .compatible = "qcom,rpm-sm6115" }, { .compatible = "qcom,glink-smd-rpm" },
{ } { }
}; };
@ -50,6 +50,7 @@ static struct clk_ops stub_clk_ops = {
static const struct udevice_id stub_clk_ids[] = { static const struct udevice_id stub_clk_ids[] = {
{ .compatible = "qcom,rpmcc" }, { .compatible = "qcom,rpmcc" },
{ .compatible = "qcom,sdm845-rpmh-clk" },
{ .compatible = "qcom,sc7280-rpmh-clk" }, { .compatible = "qcom,sc7280-rpmh-clk" },
{ .compatible = "qcom,sm8150-rpmh-clk" }, { .compatible = "qcom,sm8150-rpmh-clk" },
{ .compatible = "qcom,sm8250-rpmh-clk" }, { .compatible = "qcom,sm8250-rpmh-clk" },

View file

@ -83,11 +83,12 @@ static ulong apq8096_clk_set_rate(struct clk *clk, ulong rate)
struct msm_clk_priv *priv = dev_get_priv(clk->dev); struct msm_clk_priv *priv = dev_get_priv(clk->dev);
switch (clk->id) { switch (clk->id) {
case GCC_SDCC1_APPS_CLK: /* SDC1 */ case GCC_SDCC2_APPS_CLK: /* SDC2 */
return clk_init_sdc(priv, rate); return clk_init_sdc(priv, rate);
break; break;
case GCC_BLSP2_UART2_APPS_CLK: /*UART2*/ case GCC_BLSP2_UART2_APPS_CLK: /*UART2*/
return clk_init_uart(priv); clk_init_uart(priv);
return 7372800;
default: default:
return 0; return 0;
} }

View file

@ -107,6 +107,17 @@ static const struct gate_clk sc7280_clks[] = {
GATE_CLK(GCC_QUPV3_WRAP0_S0_CLK, 0x52008, BIT(10)), GATE_CLK(GCC_QUPV3_WRAP0_S0_CLK, 0x52008, BIT(10)),
GATE_CLK(GCC_QUPV3_WRAP0_S1_CLK, 0x52008, BIT(11)), GATE_CLK(GCC_QUPV3_WRAP0_S1_CLK, 0x52008, BIT(11)),
GATE_CLK(GCC_QUPV3_WRAP0_S3_CLK, 0x52008, BIT(13)), GATE_CLK(GCC_QUPV3_WRAP0_S3_CLK, 0x52008, BIT(13)),
GATE_CLK(GCC_UFS_PHY_AXI_CLK, 0x77010, BIT(0)),
GATE_CLK(GCC_AGGRE_UFS_PHY_AXI_CLK, 0x770cc, BIT(0)),
GATE_CLK(GCC_UFS_PHY_AHB_CLK, 0x77018, BIT(0)),
GATE_CLK(GCC_UFS_PHY_UNIPRO_CORE_CLK, 0x7705c, BIT(0)),
GATE_CLK(GCC_UFS_PHY_PHY_AUX_CLK, 0x7709c, BIT(0)),
GATE_CLK(GCC_UFS_PHY_TX_SYMBOL_0_CLK, 0x7701c, BIT(0)),
GATE_CLK(GCC_UFS_PHY_RX_SYMBOL_0_CLK, 0x77020, BIT(0)),
GATE_CLK(GCC_UFS_PHY_RX_SYMBOL_1_CLK, 0x770b8, BIT(0)),
GATE_CLK(GCC_UFS_1_CLKREF_EN, 0x8c000, BIT(0)),
GATE_CLK(GCC_SDCC2_AHB_CLK, 0x14008, BIT(0)),
GATE_CLK(GCC_SDCC2_APPS_CLK, 0x14004, BIT(0)),
}; };
static int sc7280_enable(struct clk *clk) static int sc7280_enable(struct clk *clk)

View file

@ -77,7 +77,9 @@ static ulong sdm845_clk_set_rate(struct clk *clk, ulong rate)
} }
static const struct gate_clk sdm845_clks[] = { static const struct gate_clk sdm845_clks[] = {
GATE_CLK(GCC_AGGRE_USB3_PRIM_AXI_CLK, 0x8201c, 0x00000001),
GATE_CLK(GCC_AGGRE_USB3_SEC_AXI_CLK, 0x82020, 0x00000001), GATE_CLK(GCC_AGGRE_USB3_SEC_AXI_CLK, 0x82020, 0x00000001),
GATE_CLK(GCC_CFG_NOC_USB3_PRIM_AXI_CLK, 0x0502c, 0x00000001),
GATE_CLK(GCC_CFG_NOC_USB3_SEC_AXI_CLK, 0x05030, 0x00000001), GATE_CLK(GCC_CFG_NOC_USB3_SEC_AXI_CLK, 0x05030, 0x00000001),
GATE_CLK(GCC_QUPV3_WRAP0_S0_CLK, 0x5200c, 0x00000400), GATE_CLK(GCC_QUPV3_WRAP0_S0_CLK, 0x5200c, 0x00000400),
GATE_CLK(GCC_QUPV3_WRAP0_S1_CLK, 0x5200c, 0x00000800), GATE_CLK(GCC_QUPV3_WRAP0_S1_CLK, 0x5200c, 0x00000800),
@ -112,6 +114,7 @@ static const struct gate_clk sdm845_clks[] = {
GATE_CLK(GCC_UFS_CARD_TX_SYMBOL_0_CLK, 0x75014, 0x00000001), GATE_CLK(GCC_UFS_CARD_TX_SYMBOL_0_CLK, 0x75014, 0x00000001),
GATE_CLK(GCC_UFS_CARD_UNIPRO_CORE_CLK, 0x75054, 0x00000001), GATE_CLK(GCC_UFS_CARD_UNIPRO_CORE_CLK, 0x75054, 0x00000001),
GATE_CLK(GCC_UFS_MEM_CLKREF_CLK, 0x8c000, 0x00000001), GATE_CLK(GCC_UFS_MEM_CLKREF_CLK, 0x8c000, 0x00000001),
GATE_CLK(GCC_AGGRE_UFS_PHY_AXI_CLK, 0x82024, 0x00000001),
GATE_CLK(GCC_UFS_PHY_AHB_CLK, 0x77010, 0x00000001), GATE_CLK(GCC_UFS_PHY_AHB_CLK, 0x77010, 0x00000001),
GATE_CLK(GCC_UFS_PHY_AXI_CLK, 0x7700c, 0x00000001), GATE_CLK(GCC_UFS_PHY_AXI_CLK, 0x7700c, 0x00000001),
GATE_CLK(GCC_UFS_PHY_ICE_CORE_CLK, 0x77058, 0x00000001), GATE_CLK(GCC_UFS_PHY_ICE_CORE_CLK, 0x77058, 0x00000001),

View file

@ -151,6 +151,9 @@ static int msm_gpio_direction_output(struct udevice *dev, unsigned int gpio,
static int msm_gpio_set_flags(struct udevice *dev, unsigned int gpio, ulong flags) static int msm_gpio_set_flags(struct udevice *dev, unsigned int gpio, ulong flags)
{ {
if (msm_pinctrl_is_reserved(dev_get_parent(dev), gpio))
return -EPERM;
if (flags & GPIOD_IS_OUT_ACTIVE) { if (flags & GPIOD_IS_OUT_ACTIVE) {
return msm_gpio_direction_output(dev, gpio, 1); return msm_gpio_direction_output(dev, gpio, 1);
} else if (flags & GPIOD_IS_OUT) { } else if (flags & GPIOD_IS_OUT) {
@ -172,12 +175,19 @@ static int msm_gpio_get_value_special(struct msm_gpio_bank *priv, unsigned int g
const struct msm_special_pin_data *data; const struct msm_special_pin_data *data;
if (!priv->pin_data->special_pins_data) if (!priv->pin_data->special_pins_data)
return 0; return -EINVAL;
data = &priv->pin_data->special_pins_data[offset]; data = &priv->pin_data->special_pins_data[offset];
if (!data->io_reg || data->in_bit >= 31) if (!data->io_reg)
return 0; return -EINVAL;
if (data->in_bit >= 31) {
if (data->out_bit >= 31)
return -EINVAL;
return !!(readl(priv->base + data->io_reg) >> data->out_bit);
}
return !!(readl(priv->base + data->io_reg) >> data->in_bit); return !!(readl(priv->base + data->io_reg) >> data->in_bit);
} }
@ -186,19 +196,54 @@ static int msm_gpio_get_value(struct udevice *dev, unsigned int gpio)
{ {
struct msm_gpio_bank *priv = dev_get_priv(dev); struct msm_gpio_bank *priv = dev_get_priv(dev);
if (msm_pinctrl_is_reserved(dev_get_parent(dev), gpio))
return -EPERM;
if (qcom_is_special_pin(priv->pin_data, gpio)) if (qcom_is_special_pin(priv->pin_data, gpio))
return msm_gpio_get_value_special(priv, gpio); return msm_gpio_get_value_special(priv, gpio);
return !!(readl(priv->base + GPIO_IN_OUT_REG(dev, gpio)) >> GPIO_IN); return !!(readl(priv->base + GPIO_IN_OUT_REG(dev, gpio)) >> GPIO_IN);
} }
static int msm_gpio_get_function_special(struct msm_gpio_bank *priv,
unsigned int gpio)
{
unsigned int offset = gpio - priv->pin_data->special_pins_start;
const struct msm_special_pin_data *data;
if (!priv->pin_data->special_pins_data)
return GPIOF_UNKNOWN;
data = &priv->pin_data->special_pins_data[offset];
/* No I/O fields, cannot control/read the I/O value */
if (!data->io_reg || (data->out_bit >= 31 && data->in_bit >= 31))
return GPIOF_FUNC;
/* No Output-Enable register, cannot control I/O direction */
if (!data->ctl_reg || data->oe_bit >= 31) {
if (data->out_bit >= 31)
return GPIOF_INPUT;
else
return GPIOF_OUTPUT;
}
if (readl(priv->base + data->ctl_reg) & BIT(data->oe_bit))
return GPIOF_OUTPUT;
return GPIOF_INPUT;
}
static int msm_gpio_get_function(struct udevice *dev, unsigned int gpio) static int msm_gpio_get_function(struct udevice *dev, unsigned int gpio)
{ {
struct msm_gpio_bank *priv = dev_get_priv(dev); struct msm_gpio_bank *priv = dev_get_priv(dev);
if (msm_pinctrl_is_reserved(dev_get_parent(dev), gpio))
return GPIOF_UNKNOWN;
/* Always NOP for special pins, assume they're in the correct state */ /* Always NOP for special pins, assume they're in the correct state */
if (qcom_is_special_pin(priv->pin_data, gpio)) if (qcom_is_special_pin(priv->pin_data, gpio))
return 0; return msm_gpio_get_function_special(priv, gpio);
if (readl(priv->base + GPIO_CONFIG_REG(dev, gpio)) & GPIO_OE_ENABLE) if (readl(priv->base + GPIO_CONFIG_REG(dev, gpio)) & GPIO_OE_ENABLE)
return GPIOF_OUTPUT; return GPIOF_OUTPUT;

View file

@ -122,6 +122,9 @@ struct qusb2_phy_cfg {
/* true if PHY has PLL_CORE_INPUT_OVERRIDE register to reset PLL */ /* true if PHY has PLL_CORE_INPUT_OVERRIDE register to reset PLL */
bool has_pll_override; bool has_pll_override;
/* true if PHY default clk scheme is single-ended */
bool se_clk_scheme_default;
}; };
/* set of registers with offsets different per-PHY */ /* set of registers with offsets different per-PHY */
@ -173,6 +176,19 @@ static const unsigned int sm6115_regs_layout[] = {
[QUSB2PHY_PORT_POWERDOWN] = 0xb4, [QUSB2PHY_INTR_CTRL] = 0xbc, [QUSB2PHY_PORT_POWERDOWN] = 0xb4, [QUSB2PHY_INTR_CTRL] = 0xbc,
}; };
static const struct qusb2_phy_init_tbl msm8996_init_tbl[] = {
QUSB2_PHY_INIT_CFG_L(QUSB2PHY_PORT_TUNE1, 0xf8),
QUSB2_PHY_INIT_CFG_L(QUSB2PHY_PORT_TUNE2, 0xb3),
QUSB2_PHY_INIT_CFG_L(QUSB2PHY_PORT_TUNE3, 0x83),
QUSB2_PHY_INIT_CFG_L(QUSB2PHY_PORT_TUNE4, 0xc0),
QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_TUNE, 0x30),
QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_USER_CTL1, 0x79),
QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_USER_CTL2, 0x21),
QUSB2_PHY_INIT_CFG_L(QUSB2PHY_PORT_TEST2, 0x14),
QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_AUTOPGM_CTL1, 0x9f),
QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_PWR_CTRL, 0x00),
};
static const struct qusb2_phy_init_tbl qusb2_v2_init_tbl[] = { static const struct qusb2_phy_init_tbl qusb2_v2_init_tbl[] = {
QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_ANALOG_CONTROLS_TWO, 0x03), QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_ANALOG_CONTROLS_TWO, 0x03),
QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_CLOCK_INVERTERS, 0x7c), QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_CLOCK_INVERTERS, 0x7c),
@ -214,6 +230,19 @@ static const struct qusb2_phy_cfg sm6115_phy_cfg = {
.regs = sm6115_regs_layout, .regs = sm6115_regs_layout,
.has_pll_test = true, .has_pll_test = true,
.se_clk_scheme_default = true,
.disable_ctrl = (CLAMP_N_EN | FREEZIO_N | POWER_DOWN),
.mask_core_ready = PLL_LOCKED,
.autoresume_en = BIT(3),
};
static const struct qusb2_phy_cfg sdm660_phy_cfg = {
.tbl = msm8996_init_tbl,
.tbl_num = ARRAY_SIZE(msm8996_init_tbl),
.regs = sm6115_regs_layout,
.has_pll_test = true,
.se_clk_scheme_default = false,
.disable_ctrl = (CLAMP_N_EN | FREEZIO_N | POWER_DOWN), .disable_ctrl = (CLAMP_N_EN | FREEZIO_N | POWER_DOWN),
.mask_core_ready = PLL_LOCKED, .mask_core_ready = PLL_LOCKED,
.autoresume_en = BIT(3), .autoresume_en = BIT(3),
@ -228,6 +257,7 @@ static const struct qusb2_phy_cfg qusb2_v2_phy_cfg = {
POWER_DOWN), POWER_DOWN),
.mask_core_ready = CORE_READY_STATUS, .mask_core_ready = CORE_READY_STATUS,
.has_pll_override = true, .has_pll_override = true,
.se_clk_scheme_default = true,
.autoresume_en = BIT(0), .autoresume_en = BIT(0),
.update_tune1_with_efuse = true, .update_tune1_with_efuse = true,
}; };
@ -316,8 +346,18 @@ static int qusb2phy_power_on(struct phy *phy)
/* Required to get phy pll lock successfully */ /* Required to get phy pll lock successfully */
udelay(150); udelay(150);
/*
* Not all the SoCs have got a readable TCSR_PHY_CLK_SCHEME
* register in the TCSR so, if there's none, use the default
* value hardcoded in the configuration.
*/
qphy->has_se_clk_scheme = cfg->se_clk_scheme_default;
if (cfg->has_pll_test) { if (cfg->has_pll_test) {
val |= CLK_REF_SEL; if (!qphy->has_se_clk_scheme)
val &= ~CLK_REF_SEL;
else
val |= CLK_REF_SEL;
writel(val, qphy->base + QUSB2PHY_PLL_TEST); writel(val, qphy->base + QUSB2PHY_PLL_TEST);
@ -413,6 +453,8 @@ static const struct udevice_id qusb2phy_ids[] = {
{ .compatible = "qcom,qusb2-phy" }, { .compatible = "qcom,qusb2-phy" },
{ .compatible = "qcom,qcm2290-qusb2-phy", { .compatible = "qcom,qcm2290-qusb2-phy",
.data = (ulong)&sm6115_phy_cfg }, .data = (ulong)&sm6115_phy_cfg },
{ .compatible = "qcom,sdm660-qusb2-phy",
.data = (ulong)&sdm660_phy_cfg },
{ .compatible = "qcom,sm6115-qusb2-phy", { .compatible = "qcom,sm6115-qusb2-phy",
.data = (ulong)&sm6115_phy_cfg }, .data = (ulong)&sm6115_phy_cfg },
{ .compatible = "qcom,qusb2-v2-phy", .data = (ulong)&qusb2_v2_phy_cfg }, { .compatible = "qcom,qusb2-v2-phy", .data = (ulong)&qusb2_v2_phy_cfg },

View file

@ -48,12 +48,25 @@ config PINCTRL_QCOM_QCS404
Say Y here to enable support for pinctrl on the Snapdragon QCS404 SoC, Say Y here to enable support for pinctrl on the Snapdragon QCS404 SoC,
as well as the associated GPIO driver. as well as the associated GPIO driver.
config PINCTRL_QCOM_SA8775P
bool "Qualcomm SA8775P Pinctrl"
select PINCTRL_QCOM
help
Say Y here to enable support for pinctrl on the Snapdragon SA8775P SoC,
as well as the associated GPIO driver.
config PINCTRL_QCOM_SC7280 config PINCTRL_QCOM_SC7280
bool "Qualcomm SC7280/QCM6490 Pinctrl" bool "Qualcomm SC7280/QCM6490 Pinctrl"
select PINCTRL_QCOM select PINCTRL_QCOM
help help
Say Y here to enable support for pinctrl on the Snapdragon SC7280 SoC, Say Y here to enable support for pinctrl on the Snapdragon SC7280 SoC,
as well as the associated GPIO driver.
config PINCTRL_QCOM_SDM660
bool "Qualcomm SDM630/660 Pinctrl"
select PINCTRL_QCOM
help
Say Y here to enable support for pinctrl on the Snapdragon 630/636/660
SoCs, as well as the associated GPIO driver.
config PINCTRL_QCOM_SDM845 config PINCTRL_QCOM_SDM845
bool "Qualcomm SDM845 Pinctrl" bool "Qualcomm SDM845 Pinctrl"

View file

@ -9,7 +9,9 @@ obj-$(CONFIG_PINCTRL_QCOM_IPQ9574) += pinctrl-ipq9574.o
obj-$(CONFIG_PINCTRL_QCOM_APQ8096) += pinctrl-apq8096.o obj-$(CONFIG_PINCTRL_QCOM_APQ8096) += pinctrl-apq8096.o
obj-$(CONFIG_PINCTRL_QCOM_QCM2290) += pinctrl-qcm2290.o obj-$(CONFIG_PINCTRL_QCOM_QCM2290) += pinctrl-qcm2290.o
obj-$(CONFIG_PINCTRL_QCOM_QCS404) += pinctrl-qcs404.o obj-$(CONFIG_PINCTRL_QCOM_QCS404) += pinctrl-qcs404.o
obj-$(CONFIG_PINCTRL_QCOM_SA8775P) += pinctrl-sa8775p.o
obj-$(CONFIG_PINCTRL_QCOM_SC7280) += pinctrl-sc7280.o obj-$(CONFIG_PINCTRL_QCOM_SC7280) += pinctrl-sc7280.o
obj-$(CONFIG_PINCTRL_QCOM_SDM660) += pinctrl-sdm660.o
obj-$(CONFIG_PINCTRL_QCOM_SDM845) += pinctrl-sdm845.o obj-$(CONFIG_PINCTRL_QCOM_SDM845) += pinctrl-sdm845.o
obj-$(CONFIG_PINCTRL_QCOM_SM6115) += pinctrl-sm6115.o obj-$(CONFIG_PINCTRL_QCOM_SM6115) += pinctrl-sm6115.o
obj-$(CONFIG_PINCTRL_QCOM_SM8150) += pinctrl-sm8150.o obj-$(CONFIG_PINCTRL_QCOM_SM8150) += pinctrl-sm8150.o

View file

@ -15,14 +15,18 @@
#include <asm/gpio.h> #include <asm/gpio.h>
#include <dm/pinctrl.h> #include <dm/pinctrl.h>
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/bitmap.h>
#include <linux/bug.h> #include <linux/bug.h>
#include <mach/gpio.h> #include <mach/gpio.h>
#include "pinctrl-qcom.h" #include "pinctrl-qcom.h"
#define MSM_PINCTRL_MAX_PINS 256
struct msm_pinctrl_priv { struct msm_pinctrl_priv {
phys_addr_t base; phys_addr_t base;
struct msm_pinctrl_data *data; struct msm_pinctrl_data *data;
DECLARE_BITMAP(reserved_map, MSM_PINCTRL_MAX_PINS);
}; };
#define GPIO_CONFIG_REG(priv, x) \ #define GPIO_CONFIG_REG(priv, x) \
@ -71,13 +75,60 @@ static const char *msm_get_function_name(struct udevice *dev,
return priv->data->get_function_name(dev, selector); return priv->data->get_function_name(dev, selector);
} }
static int msm_pinctrl_parse_ranges(struct udevice *dev)
{
struct msm_pinctrl_priv *priv = dev_get_priv(dev);
ofnode node = dev_ofnode(dev);
int ret, count, i;
u32 *ranges;
if (ofnode_read_prop(node, "gpio-reserved-ranges", &count)) {
if (count % 2 == 1) {
dev_err(dev, "gpio-reserved-ranges must be a multiple of 2\n");
return -EINVAL;
}
ranges = malloc(count);
if (!ranges)
return -ENOMEM;
ret = ofnode_read_u32_array(node, "gpio-reserved-ranges", ranges, count / 4);
if (ret) {
dev_err(dev, "failed to read gpio-reserved-ranges array (%d)\n", ret);
return ret;
}
for (i = 0; i < count / 4; i += 2) {
if (ranges[i] >= MSM_PINCTRL_MAX_PINS ||
(ranges[i] + ranges[i + 1]) >= MSM_PINCTRL_MAX_PINS) {
dev_err(dev, "invalid reserved-range (%d;%d)\n",
ranges[i], ranges[i + 1]);
return -EINVAL;
}
bitmap_set(priv->reserved_map, ranges[i], ranges[i + 1]);
}
free(ranges);
}
return 0;
}
static int msm_pinctrl_probe(struct udevice *dev) static int msm_pinctrl_probe(struct udevice *dev)
{ {
struct msm_pinctrl_priv *priv = dev_get_priv(dev); struct msm_pinctrl_priv *priv = dev_get_priv(dev);
int ret;
priv->base = dev_read_addr(dev); priv->base = dev_read_addr(dev);
priv->data = (struct msm_pinctrl_data *)dev_get_driver_data(dev); priv->data = (struct msm_pinctrl_data *)dev_get_driver_data(dev);
ret = msm_pinctrl_parse_ranges(dev);
if (ret) {
printf("Couldn't parse reserved GPIO ranges!\n");
return ret;
}
return priv->base == FDT_ADDR_T_NONE ? -EINVAL : 0; return priv->base == FDT_ADDR_T_NONE ? -EINVAL : 0;
} }
@ -97,6 +148,9 @@ static int msm_pinmux_set(struct udevice *dev, unsigned int pin_selector,
if (func < 0) if (func < 0)
return func; return func;
if (msm_pinctrl_is_reserved(dev, pin_selector))
return -EPERM;
/* Always NOP for special pins, assume they're in the correct state */ /* Always NOP for special pins, assume they're in the correct state */
if (qcom_is_special_pin(&priv->data->pin_data, pin_selector)) if (qcom_is_special_pin(&priv->data->pin_data, pin_selector))
return 0; return 0;
@ -145,6 +199,9 @@ static int msm_pinconf_set(struct udevice *dev, unsigned int pin_selector,
{ {
struct msm_pinctrl_priv *priv = dev_get_priv(dev); struct msm_pinctrl_priv *priv = dev_get_priv(dev);
if (msm_pinctrl_is_reserved(dev, pin_selector))
return -EPERM;
if (qcom_is_special_pin(&priv->data->pin_data, pin_selector)) if (qcom_is_special_pin(&priv->data->pin_data, pin_selector))
return msm_pinconf_set_special(priv, pin_selector, param, argument); return msm_pinconf_set_special(priv, pin_selector, param, argument);
@ -241,3 +298,13 @@ U_BOOT_DRIVER(pinctrl_qcom) = {
.ops = &msm_pinctrl_ops, .ops = &msm_pinctrl_ops,
.probe = msm_pinctrl_probe, .probe = msm_pinctrl_probe,
}; };
bool msm_pinctrl_is_reserved(struct udevice *dev, unsigned int pin)
{
struct msm_pinctrl_priv *priv = dev_get_priv(dev);
if (pin >= MSM_PINCTRL_MAX_PINS)
return false;
return test_bit(pin, priv->reserved_map);
}

View file

@ -0,0 +1,623 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) 2023, Linaro Limited
*/
#include <dm.h>
#include "pinctrl-qcom.h"
#define MAX_PIN_NAME_LEN 32
static char pin_name[MAX_PIN_NAME_LEN] __section(".data");
typedef unsigned int msm_pin_function[10];
#define SA8775_PIN_OFFSET 0x100000
#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9)\
{ \
msm_mux_gpio, /* gpio mode */ \
msm_mux_##f1, \
msm_mux_##f2, \
msm_mux_##f3, \
msm_mux_##f4, \
msm_mux_##f5, \
msm_mux_##f6, \
msm_mux_##f7, \
msm_mux_##f8, \
msm_mux_##f9 \
}
#define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \
{ \
.name = pg_name, \
.ctl_reg = ctl, \
.io_reg = 0, \
.pull_bit = pull, \
.drv_bit = drv, \
.oe_bit = -1, \
.in_bit = -1, \
.out_bit = -1, \
}
#define UFS_RESET(pg_name, ctl) \
{ \
.name = pg_name, \
.ctl_reg = ctl, \
.io_reg = ctl + 0x4, \
.pull_bit = 3, \
.drv_bit = 0, \
.oe_bit = -1, \
.in_bit = -1, \
.out_bit = 0, \
}
enum sa8775p_functions {
msm_mux_gpio,
msm_mux_atest_char,
msm_mux_atest_usb2,
msm_mux_audio_ref,
msm_mux_cam_mclk,
msm_mux_cci_async,
msm_mux_cci_i2c,
msm_mux_cci_timer0,
msm_mux_cci_timer1,
msm_mux_cci_timer2,
msm_mux_cci_timer3,
msm_mux_cci_timer4,
msm_mux_cci_timer5,
msm_mux_cci_timer6,
msm_mux_cci_timer7,
msm_mux_cci_timer8,
msm_mux_cci_timer9,
msm_mux_cri_trng,
msm_mux_cri_trng0,
msm_mux_cri_trng1,
msm_mux_dbg_out,
msm_mux_ddr_bist,
msm_mux_ddr_pxi0,
msm_mux_ddr_pxi1,
msm_mux_ddr_pxi2,
msm_mux_ddr_pxi3,
msm_mux_ddr_pxi4,
msm_mux_ddr_pxi5,
msm_mux_edp0_hot,
msm_mux_edp0_lcd,
msm_mux_edp1_hot,
msm_mux_edp1_lcd,
msm_mux_edp2_hot,
msm_mux_edp2_lcd,
msm_mux_edp3_hot,
msm_mux_edp3_lcd,
msm_mux_emac0_mcg0,
msm_mux_emac0_mcg1,
msm_mux_emac0_mcg2,
msm_mux_emac0_mcg3,
msm_mux_emac0_mdc,
msm_mux_emac0_mdio,
msm_mux_emac0_ptp_aux,
msm_mux_emac0_ptp_pps,
msm_mux_emac1_mcg0,
msm_mux_emac1_mcg1,
msm_mux_emac1_mcg2,
msm_mux_emac1_mcg3,
msm_mux_emac1_mdc,
msm_mux_emac1_mdio,
msm_mux_emac1_ptp_aux,
msm_mux_emac1_ptp_pps,
msm_mux_gcc_gp1,
msm_mux_gcc_gp2,
msm_mux_gcc_gp3,
msm_mux_gcc_gp4,
msm_mux_gcc_gp5,
msm_mux_hs0_mi2s,
msm_mux_hs1_mi2s,
msm_mux_hs2_mi2s,
msm_mux_ibi_i3c,
msm_mux_jitter_bist,
msm_mux_mdp0_vsync0,
msm_mux_mdp0_vsync1,
msm_mux_mdp0_vsync2,
msm_mux_mdp0_vsync3,
msm_mux_mdp0_vsync4,
msm_mux_mdp0_vsync5,
msm_mux_mdp0_vsync6,
msm_mux_mdp0_vsync7,
msm_mux_mdp0_vsync8,
msm_mux_mdp1_vsync0,
msm_mux_mdp1_vsync1,
msm_mux_mdp1_vsync2,
msm_mux_mdp1_vsync3,
msm_mux_mdp1_vsync4,
msm_mux_mdp1_vsync5,
msm_mux_mdp1_vsync6,
msm_mux_mdp1_vsync7,
msm_mux_mdp1_vsync8,
msm_mux_mdp_vsync,
msm_mux_mi2s1_data0,
msm_mux_mi2s1_data1,
msm_mux_mi2s1_sck,
msm_mux_mi2s1_ws,
msm_mux_mi2s2_data0,
msm_mux_mi2s2_data1,
msm_mux_mi2s2_sck,
msm_mux_mi2s2_ws,
msm_mux_mi2s_mclk0,
msm_mux_mi2s_mclk1,
msm_mux_pcie0_clkreq,
msm_mux_pcie1_clkreq,
msm_mux_phase_flag,
msm_mux_pll_bist,
msm_mux_pll_clk,
msm_mux_prng_rosc0,
msm_mux_prng_rosc1,
msm_mux_prng_rosc2,
msm_mux_prng_rosc3,
msm_mux_qdss_cti,
msm_mux_qdss_gpio,
msm_mux_qup0_se0,
msm_mux_qup0_se1,
msm_mux_qup0_se2,
msm_mux_qup0_se3,
msm_mux_qup0_se4,
msm_mux_qup0_se5,
msm_mux_qup1_se0,
msm_mux_qup1_se1,
msm_mux_qup1_se2,
msm_mux_qup1_se3,
msm_mux_qup1_se4,
msm_mux_qup1_se5,
msm_mux_qup1_se6,
msm_mux_qup2_se0,
msm_mux_qup2_se1,
msm_mux_qup2_se2,
msm_mux_qup2_se3,
msm_mux_qup2_se4,
msm_mux_qup2_se5,
msm_mux_qup2_se6,
msm_mux_qup3_se0,
msm_mux_sail_top,
msm_mux_sailss_emac0,
msm_mux_sailss_ospi,
msm_mux_sgmii_phy,
msm_mux_tb_trig,
msm_mux_tgu_ch0,
msm_mux_tgu_ch1,
msm_mux_tgu_ch2,
msm_mux_tgu_ch3,
msm_mux_tgu_ch4,
msm_mux_tgu_ch5,
msm_mux_tsense_pwm1,
msm_mux_tsense_pwm2,
msm_mux_tsense_pwm3,
msm_mux_tsense_pwm4,
msm_mux_usb2phy_ac,
msm_mux_vsense_trigger,
msm_mux__,
};
#define MSM_PIN_FUNCTION(fname) \
[msm_mux_##fname] = {#fname, msm_mux_##fname}
static const struct pinctrl_function msm_pinctrl_functions[] = {
MSM_PIN_FUNCTION(gpio),
MSM_PIN_FUNCTION(atest_char),
MSM_PIN_FUNCTION(atest_usb2),
MSM_PIN_FUNCTION(audio_ref),
MSM_PIN_FUNCTION(cam_mclk),
MSM_PIN_FUNCTION(cci_async),
MSM_PIN_FUNCTION(cci_i2c),
MSM_PIN_FUNCTION(cci_timer0),
MSM_PIN_FUNCTION(cci_timer1),
MSM_PIN_FUNCTION(cci_timer2),
MSM_PIN_FUNCTION(cci_timer3),
MSM_PIN_FUNCTION(cci_timer4),
MSM_PIN_FUNCTION(cci_timer5),
MSM_PIN_FUNCTION(cci_timer6),
MSM_PIN_FUNCTION(cci_timer7),
MSM_PIN_FUNCTION(cci_timer8),
MSM_PIN_FUNCTION(cci_timer9),
MSM_PIN_FUNCTION(cri_trng),
MSM_PIN_FUNCTION(cri_trng0),
MSM_PIN_FUNCTION(cri_trng1),
MSM_PIN_FUNCTION(dbg_out),
MSM_PIN_FUNCTION(ddr_bist),
MSM_PIN_FUNCTION(ddr_pxi0),
MSM_PIN_FUNCTION(ddr_pxi1),
MSM_PIN_FUNCTION(ddr_pxi2),
MSM_PIN_FUNCTION(ddr_pxi3),
MSM_PIN_FUNCTION(ddr_pxi4),
MSM_PIN_FUNCTION(ddr_pxi5),
MSM_PIN_FUNCTION(edp0_hot),
MSM_PIN_FUNCTION(edp0_lcd),
MSM_PIN_FUNCTION(edp1_hot),
MSM_PIN_FUNCTION(edp1_lcd),
MSM_PIN_FUNCTION(edp2_hot),
MSM_PIN_FUNCTION(edp2_lcd),
MSM_PIN_FUNCTION(edp3_hot),
MSM_PIN_FUNCTION(edp3_lcd),
MSM_PIN_FUNCTION(emac0_mcg0),
MSM_PIN_FUNCTION(emac0_mcg1),
MSM_PIN_FUNCTION(emac0_mcg2),
MSM_PIN_FUNCTION(emac0_mcg3),
MSM_PIN_FUNCTION(emac0_mdc),
MSM_PIN_FUNCTION(emac0_mdio),
MSM_PIN_FUNCTION(emac0_ptp_aux),
MSM_PIN_FUNCTION(emac0_ptp_pps),
MSM_PIN_FUNCTION(emac1_mcg0),
MSM_PIN_FUNCTION(emac1_mcg1),
MSM_PIN_FUNCTION(emac1_mcg2),
MSM_PIN_FUNCTION(emac1_mcg3),
MSM_PIN_FUNCTION(emac1_mdc),
MSM_PIN_FUNCTION(emac1_mdio),
MSM_PIN_FUNCTION(emac1_ptp_aux),
MSM_PIN_FUNCTION(emac1_ptp_pps),
MSM_PIN_FUNCTION(gcc_gp1),
MSM_PIN_FUNCTION(gcc_gp2),
MSM_PIN_FUNCTION(gcc_gp3),
MSM_PIN_FUNCTION(gcc_gp4),
MSM_PIN_FUNCTION(gcc_gp5),
MSM_PIN_FUNCTION(hs0_mi2s),
MSM_PIN_FUNCTION(hs1_mi2s),
MSM_PIN_FUNCTION(hs2_mi2s),
MSM_PIN_FUNCTION(ibi_i3c),
MSM_PIN_FUNCTION(jitter_bist),
MSM_PIN_FUNCTION(mdp0_vsync0),
MSM_PIN_FUNCTION(mdp0_vsync1),
MSM_PIN_FUNCTION(mdp0_vsync2),
MSM_PIN_FUNCTION(mdp0_vsync3),
MSM_PIN_FUNCTION(mdp0_vsync4),
MSM_PIN_FUNCTION(mdp0_vsync5),
MSM_PIN_FUNCTION(mdp0_vsync6),
MSM_PIN_FUNCTION(mdp0_vsync7),
MSM_PIN_FUNCTION(mdp0_vsync8),
MSM_PIN_FUNCTION(mdp1_vsync0),
MSM_PIN_FUNCTION(mdp1_vsync1),
MSM_PIN_FUNCTION(mdp1_vsync2),
MSM_PIN_FUNCTION(mdp1_vsync3),
MSM_PIN_FUNCTION(mdp1_vsync4),
MSM_PIN_FUNCTION(mdp1_vsync5),
MSM_PIN_FUNCTION(mdp1_vsync6),
MSM_PIN_FUNCTION(mdp1_vsync7),
MSM_PIN_FUNCTION(mdp1_vsync8),
MSM_PIN_FUNCTION(mdp_vsync),
MSM_PIN_FUNCTION(mi2s1_data0),
MSM_PIN_FUNCTION(mi2s1_data1),
MSM_PIN_FUNCTION(mi2s1_sck),
MSM_PIN_FUNCTION(mi2s1_ws),
MSM_PIN_FUNCTION(mi2s2_data0),
MSM_PIN_FUNCTION(mi2s2_data1),
MSM_PIN_FUNCTION(mi2s2_sck),
MSM_PIN_FUNCTION(mi2s2_ws),
MSM_PIN_FUNCTION(mi2s_mclk0),
MSM_PIN_FUNCTION(mi2s_mclk1),
MSM_PIN_FUNCTION(pcie0_clkreq),
MSM_PIN_FUNCTION(pcie1_clkreq),
MSM_PIN_FUNCTION(phase_flag),
MSM_PIN_FUNCTION(pll_bist),
MSM_PIN_FUNCTION(pll_clk),
MSM_PIN_FUNCTION(prng_rosc0),
MSM_PIN_FUNCTION(prng_rosc1),
MSM_PIN_FUNCTION(prng_rosc2),
MSM_PIN_FUNCTION(prng_rosc3),
MSM_PIN_FUNCTION(qdss_cti),
MSM_PIN_FUNCTION(qdss_gpio),
MSM_PIN_FUNCTION(qup0_se0),
MSM_PIN_FUNCTION(qup0_se1),
MSM_PIN_FUNCTION(qup0_se2),
MSM_PIN_FUNCTION(qup0_se3),
MSM_PIN_FUNCTION(qup0_se4),
MSM_PIN_FUNCTION(qup0_se5),
MSM_PIN_FUNCTION(qup1_se0),
MSM_PIN_FUNCTION(qup1_se1),
MSM_PIN_FUNCTION(qup1_se2),
MSM_PIN_FUNCTION(qup1_se3),
MSM_PIN_FUNCTION(qup1_se4),
MSM_PIN_FUNCTION(qup1_se5),
MSM_PIN_FUNCTION(qup1_se6),
MSM_PIN_FUNCTION(qup2_se0),
MSM_PIN_FUNCTION(qup2_se1),
MSM_PIN_FUNCTION(qup2_se2),
MSM_PIN_FUNCTION(qup2_se3),
MSM_PIN_FUNCTION(qup2_se4),
MSM_PIN_FUNCTION(qup2_se5),
MSM_PIN_FUNCTION(qup2_se6),
MSM_PIN_FUNCTION(qup3_se0),
MSM_PIN_FUNCTION(sail_top),
MSM_PIN_FUNCTION(sailss_emac0),
MSM_PIN_FUNCTION(sailss_ospi),
MSM_PIN_FUNCTION(sgmii_phy),
MSM_PIN_FUNCTION(tb_trig),
MSM_PIN_FUNCTION(tgu_ch0),
MSM_PIN_FUNCTION(tgu_ch1),
MSM_PIN_FUNCTION(tgu_ch2),
MSM_PIN_FUNCTION(tgu_ch3),
MSM_PIN_FUNCTION(tgu_ch4),
MSM_PIN_FUNCTION(tgu_ch5),
MSM_PIN_FUNCTION(tsense_pwm1),
MSM_PIN_FUNCTION(tsense_pwm2),
MSM_PIN_FUNCTION(tsense_pwm3),
MSM_PIN_FUNCTION(tsense_pwm4),
MSM_PIN_FUNCTION(usb2phy_ac),
MSM_PIN_FUNCTION(vsense_trigger),
};
static const msm_pin_function sa8775p_pin_functions[] = {
[0] = PINGROUP(0, _, _, _, _, _, _, _, _, _),
[1] = PINGROUP(1, pcie0_clkreq, _, _, _, _, _, _, _, _),
[2] = PINGROUP(2, _, _, _, _, _, _, _, _, _),
[3] = PINGROUP(3, pcie1_clkreq, _, _, _, _, _, _, _, _),
[4] = PINGROUP(4, _, _, _, _, _, _, _, _, _),
[5] = PINGROUP(5, _, _, _, _, _, _, _, _, _),
[6] = PINGROUP(6, emac0_ptp_aux, emac0_ptp_pps, emac1_ptp_aux,
emac1_ptp_pps, _, _, _, _, _),
[7] = PINGROUP(7, sgmii_phy, _, _, _, _, _, _, _, _),
[8] = PINGROUP(8, emac0_mdc, _, _, _, _, _, _, _, _),
[9] = PINGROUP(9, emac0_mdio, _, _, _, _, _, _, _, _),
[10] = PINGROUP(10, usb2phy_ac, emac0_ptp_aux, emac0_ptp_pps,
emac1_ptp_aux, emac1_ptp_pps, _, _, _, _),
[11] = PINGROUP(11, usb2phy_ac, emac0_ptp_aux, emac0_ptp_pps,
emac1_ptp_aux, emac1_ptp_pps, _, _, _, _),
[12] = PINGROUP(12, usb2phy_ac, emac0_ptp_aux, emac0_ptp_pps,
emac1_ptp_aux, emac1_ptp_pps, emac0_mcg0, _, _, _),
[13] = PINGROUP(13, qup3_se0, emac0_mcg1, _, _, sail_top, _, _, _, _),
[14] = PINGROUP(14, qup3_se0, emac0_mcg2, _, _, sail_top, _, _, _, _),
[15] = PINGROUP(15, qup3_se0, emac0_mcg3, _, _, sail_top, _, _, _, _),
[16] = PINGROUP(16, qup3_se0, emac1_mcg0, _, _, sail_top, _, _, _, _),
[17] = PINGROUP(17, qup3_se0, tb_trig, tb_trig, emac1_mcg1, _, _, _, _, _),
[18] = PINGROUP(18, qup3_se0, emac1_mcg2, _, _, sailss_ospi, sailss_emac0, _, _, _),
[19] = PINGROUP(19, qup3_se0, emac1_mcg3, _, _, sailss_ospi, sailss_emac0, _, _, _),
[20] = PINGROUP(20, qup0_se0, emac1_mdc, qdss_gpio, _, _, _, _, _, _),
[21] = PINGROUP(21, qup0_se0, emac1_mdio, qdss_gpio, _, _, _, _, _, _),
[22] = PINGROUP(22, qup0_se0, qdss_gpio, _, _, _, _, _, _, _),
[23] = PINGROUP(23, qup0_se0, qdss_gpio, _, _, _, _, _, _, _),
[24] = PINGROUP(24, qup0_se1, qdss_gpio, _, _, _, _, _, _, _),
[25] = PINGROUP(25, qup0_se1, phase_flag, _, qdss_gpio, _, _, _, _, _),
[26] = PINGROUP(26, sgmii_phy, qup0_se1, qdss_cti, phase_flag, _, _, _, _, _),
[27] = PINGROUP(27, qup0_se1, qdss_cti, phase_flag, _, atest_char, _, _, _, _),
[28] = PINGROUP(28, qup0_se3, phase_flag, _, qdss_gpio, _, _, _, _, _),
[29] = PINGROUP(29, qup0_se3, phase_flag, _, qdss_gpio, _, _, _, _, _),
[30] = PINGROUP(30, qup0_se3, phase_flag, _, qdss_gpio, _, _, _, _, _),
[31] = PINGROUP(31, qup0_se3, phase_flag, _, qdss_gpio, _, _, _, _, _),
[32] = PINGROUP(32, qup0_se4, phase_flag, _, _, _, _, _, _, _),
[33] = PINGROUP(33, qup0_se4, gcc_gp4, _, ddr_pxi0, _, _, _, _, _),
[34] = PINGROUP(34, qup0_se4, gcc_gp5, _, ddr_pxi0, _, _, _, _, _),
[35] = PINGROUP(35, qup0_se4, phase_flag, _, _, _, _, _, _, _),
[36] = PINGROUP(36, qup0_se2, qup0_se5, phase_flag, tgu_ch2, _, _, _, _, _),
[37] = PINGROUP(37, qup0_se2, qup0_se5, phase_flag, tgu_ch3, _, _, _, _, _),
[38] = PINGROUP(38, qup0_se5, qup0_se2, qdss_cti, phase_flag, tgu_ch4, _, _, _, _),
[39] = PINGROUP(39, qup0_se5, qup0_se2, qdss_cti, phase_flag, tgu_ch5, _, _, _, _),
[40] = PINGROUP(40, qup1_se0, qup1_se1, ibi_i3c, mdp1_vsync0, _, _, _, _, _),
[41] = PINGROUP(41, qup1_se0, qup1_se1, ibi_i3c, mdp1_vsync1, _, _, _, _, _),
[42] = PINGROUP(42, qup1_se1, qup1_se0, ibi_i3c, mdp1_vsync2, gcc_gp5, _, _, _, _),
[43] = PINGROUP(43, qup1_se1, qup1_se0, ibi_i3c, mdp1_vsync3, _, _, _, _, _),
[44] = PINGROUP(44, qup1_se2, qup1_se3, edp0_lcd, _, _, _, _, _, _),
[45] = PINGROUP(45, qup1_se2, qup1_se3, edp1_lcd, _, _, _, _, _, _),
[46] = PINGROUP(46, qup1_se3, qup1_se2, mdp1_vsync4, tgu_ch0, _, _, _, _, _),
[47] = PINGROUP(47, qup1_se3, qup1_se2, mdp1_vsync5, tgu_ch1, _, _, _, _, _),
[48] = PINGROUP(48, qup1_se4, qdss_cti, edp2_lcd, _, _, _, _, _, _),
[49] = PINGROUP(49, qup1_se4, qdss_cti, edp3_lcd, _, _, _, _, _, _),
[50] = PINGROUP(50, qup1_se4, cci_async, qdss_cti, mdp1_vsync8, _, _, _, _, _),
[51] = PINGROUP(51, qup1_se4, qdss_cti, mdp1_vsync6, gcc_gp1, _, _, _, _, _),
[52] = PINGROUP(52, qup1_se5, cci_timer4, cci_i2c, mdp1_vsync7, gcc_gp2, _, ddr_pxi1, _, _),
[53] = PINGROUP(53, qup1_se5, cci_timer5, cci_i2c, gcc_gp3, _, ddr_pxi1, _, _, _),
[54] = PINGROUP(54, qup1_se5, cci_timer6, cci_i2c, _, _, _, _, _, _),
[55] = PINGROUP(55, qup1_se5, cci_timer7, cci_i2c, gcc_gp4, _, ddr_pxi2, _, _, _),
[56] = PINGROUP(56, qup1_se6, qup1_se6, cci_timer8, cci_i2c, phase_flag, ddr_bist, _, _, _),
[57] = PINGROUP(57, qup1_se6, qup1_se6, cci_timer9, cci_i2c,
mdp0_vsync0, phase_flag, ddr_bist, _, _),
[58] = PINGROUP(58, cci_i2c, mdp0_vsync1, ddr_bist, _, atest_usb2, atest_char, _, _, _),
[59] = PINGROUP(59, cci_i2c, mdp0_vsync2, ddr_bist, _, atest_usb2, atest_char, _, _, _),
[60] = PINGROUP(60, cci_i2c, qdss_gpio, _, _, _, _, _, _, _),
[61] = PINGROUP(61, cci_i2c, qdss_gpio, _, _, _, _, _, _, _),
[62] = PINGROUP(62, cci_i2c, qdss_gpio, _, _, _, _, _, _, _),
[63] = PINGROUP(63, cci_i2c, qdss_gpio, _, _, _, _, _, _, _),
[64] = PINGROUP(64, cci_i2c, qdss_gpio, _, _, _, _, _, _, _),
[65] = PINGROUP(65, cci_i2c, qdss_gpio, _, _, _, _, _, _, _),
[66] = PINGROUP(66, cci_i2c, cci_async, qdss_gpio, _, _, _, _, _, _),
[67] = PINGROUP(67, cci_i2c, qdss_gpio, _, _, _, _, _, _, _),
[68] = PINGROUP(68, cci_timer0, cci_async, _, _, _, _, _, _, _),
[69] = PINGROUP(69, cci_timer1, cci_async, _, _, _, _, _, _, _),
[70] = PINGROUP(70, cci_timer2, cci_async, _, _, _, _, _, _, _),
[71] = PINGROUP(71, cci_timer3, cci_async, _, _, _, _, _, _, _),
[72] = PINGROUP(72, cam_mclk, _, _, _, _, _, _, _, _),
[73] = PINGROUP(73, cam_mclk, _, _, _, _, _, _, _, _),
[74] = PINGROUP(74, cam_mclk, _, _, _, _, _, _, _, _),
[75] = PINGROUP(75, cam_mclk, _, _, _, _, _, _, _, _),
[76] = PINGROUP(76, _, _, _, _, _, _, _, _, _),
[77] = PINGROUP(77, _, _, _, _, _, _, _, _, _),
[78] = PINGROUP(78, _, _, _, _, _, _, _, _, _),
[79] = PINGROUP(79, _, _, _, _, _, _, _, _, _),
[80] = PINGROUP(80, qup2_se0, ibi_i3c, mdp0_vsync3, _, _, _, _, _, _),
[81] = PINGROUP(81, qup2_se0, ibi_i3c, mdp0_vsync4, _, _, _, _, _, _),
[82] = PINGROUP(82, qup2_se0, mdp_vsync, gcc_gp1, _, _, _, _, _, _),
[83] = PINGROUP(83, qup2_se0, mdp_vsync, gcc_gp2, _, _, _, _, _, _),
[84] = PINGROUP(84, qup2_se1, qup2_se5, ibi_i3c, mdp_vsync, gcc_gp3, _, _, _, _),
[85] = PINGROUP(85, qup2_se1, qup2_se5, ibi_i3c, _, _, _, _, _, _),
[86] = PINGROUP(86, qup2_se2, jitter_bist, atest_usb2, ddr_pxi2, _, _, _, _, _),
[87] = PINGROUP(87, qup2_se2, pll_clk, atest_usb2, ddr_pxi3, _, _, _, _, _),
[88] = PINGROUP(88, qup2_se2, _, atest_usb2, ddr_pxi3, _, _, _, _, _),
[89] = PINGROUP(89, qup2_se2, _, atest_usb2, ddr_pxi4, atest_char, _, _, _, _),
[90] = PINGROUP(90, qup2_se2, _, atest_usb2, ddr_pxi4, atest_char, _, _, _, _),
[91] = PINGROUP(91, qup2_se3, mdp0_vsync5, _, atest_usb2, _, _, _, _, _),
[92] = PINGROUP(92, qup2_se3, mdp0_vsync6, _, atest_usb2, _, _, _, _, _),
[93] = PINGROUP(93, qup2_se3, mdp0_vsync7, _, atest_usb2, _, _, _, _, _),
[94] = PINGROUP(94, qup2_se3, mdp0_vsync8, _, atest_usb2, _, _, _, _, _),
[95] = PINGROUP(95, qup2_se4, qup2_se6, _, atest_usb2, _, _, _, _, _),
[96] = PINGROUP(96, qup2_se4, qup2_se6, _, atest_usb2, _, _, _, _, _),
[97] = PINGROUP(97, qup2_se6, qup2_se4, cri_trng0, _, atest_usb2, _, _, _, _),
[98] = PINGROUP(98, qup2_se6, qup2_se4, phase_flag, cri_trng1, _, _, _, _, _),
[99] = PINGROUP(99, qup2_se5, qup2_se1, phase_flag, cri_trng, _, _, _, _, _),
[100] = PINGROUP(100, qup2_se5, qup2_se1, _, _, _, _, _, _, _),
[101] = PINGROUP(101, edp0_hot, prng_rosc0, tsense_pwm4, _, _, _, _, _, _),
[102] = PINGROUP(102, edp1_hot, prng_rosc1, tsense_pwm3, _, _, _, _, _, _),
[103] = PINGROUP(103, edp3_hot, prng_rosc2, tsense_pwm2, _, _, _, _, _, _),
[104] = PINGROUP(104, edp2_hot, prng_rosc3, tsense_pwm1, _, _, _, _, _, _),
[105] = PINGROUP(105, mi2s_mclk0, _, qdss_gpio, atest_usb2, _, _, _, _, _),
[106] = PINGROUP(106, mi2s1_sck, phase_flag, _, qdss_gpio, _, _, _, _, _),
[107] = PINGROUP(107, mi2s1_ws, phase_flag, _, qdss_gpio, _, _, _, _, _),
[108] = PINGROUP(108, mi2s1_data0, phase_flag, _, qdss_gpio, _, _, _, _, _),
[109] = PINGROUP(109, mi2s1_data1, phase_flag, _, qdss_gpio, _, _, _, _, _),
[110] = PINGROUP(110, mi2s2_sck, phase_flag, _, qdss_gpio, _, _, _, _, _),
[111] = PINGROUP(111, mi2s2_ws, phase_flag, _, qdss_gpio, vsense_trigger, _, _, _, _),
[112] = PINGROUP(112, mi2s2_data0, phase_flag, _, qdss_gpio, _, _, _, _, _),
[113] = PINGROUP(113, mi2s2_data1, audio_ref, phase_flag, _, qdss_gpio, _, _, _, _),
[114] = PINGROUP(114, hs0_mi2s, pll_bist, phase_flag, _, qdss_gpio, _, _, _, _),
[115] = PINGROUP(115, hs0_mi2s, _, qdss_gpio, _, _, _, _, _, _),
[116] = PINGROUP(116, hs0_mi2s, _, qdss_gpio, _, _, _, _, _, _),
[117] = PINGROUP(117, hs0_mi2s, mi2s_mclk1, _, qdss_gpio, _, _, _, _, _),
[118] = PINGROUP(118, hs1_mi2s, _, qdss_gpio, ddr_pxi5, _, _, _, _, _),
[119] = PINGROUP(119, hs1_mi2s, _, qdss_gpio, ddr_pxi5, _, _, _, _, _),
[120] = PINGROUP(120, hs1_mi2s, phase_flag, _, qdss_gpio, _, _, _, _, _),
[121] = PINGROUP(121, hs1_mi2s, phase_flag, _, qdss_gpio, _, _, _, _, _),
[122] = PINGROUP(122, hs2_mi2s, phase_flag, _, qdss_gpio, _, _, _, _, _),
[123] = PINGROUP(123, hs2_mi2s, phase_flag, _, _, _, _, _, _, _),
[124] = PINGROUP(124, hs2_mi2s, phase_flag, _, _, _, _, _, _, _),
[125] = PINGROUP(125, hs2_mi2s, phase_flag, _, _, _, _, _, _, _),
[126] = PINGROUP(126, _, _, _, _, _, _, _, _, _),
[127] = PINGROUP(127, _, _, _, _, _, _, _, _, _),
[128] = PINGROUP(128, _, _, _, _, _, _, _, _, _),
[129] = PINGROUP(129, _, _, _, _, _, _, _, _, _),
[130] = PINGROUP(130, _, _, _, _, _, _, _, _, _),
[131] = PINGROUP(131, _, _, _, _, _, _, _, _, _),
[132] = PINGROUP(132, _, _, _, _, _, _, _, _, _),
[133] = PINGROUP(133, _, _, _, _, _, _, _, _, _),
[134] = PINGROUP(134, _, _, _, _, _, _, _, _, _),
[135] = PINGROUP(135, _, _, _, _, _, _, _, _, _),
[136] = PINGROUP(136, _, _, _, _, _, _, _, _, _),
[137] = PINGROUP(137, _, _, _, _, _, _, _, _, _),
[138] = PINGROUP(138, _, _, _, _, _, _, _, _, _),
[139] = PINGROUP(139, _, _, _, _, _, _, _, _, _),
[140] = PINGROUP(140, _, _, _, _, _, _, _, _, _),
[141] = PINGROUP(141, _, _, _, _, _, _, _, _, _),
[142] = PINGROUP(142, _, _, _, _, _, _, _, _, _),
[143] = PINGROUP(143, _, _, _, _, _, _, _, _, _),
[144] = PINGROUP(144, dbg_out, _, _, _, _, _, _, _, _),
[145] = PINGROUP(145, _, _, _, _, _, _, _, _, _),
[146] = PINGROUP(146, _, _, _, _, _, _, _, _, _),
[147] = PINGROUP(147, _, _, _, _, _, _, _, _, _),
[148] = PINGROUP(148, _, _, _, _, _, _, _, _, _),
};
static const struct msm_special_pin_data msm_special_pins_data[] = {
[0] = UFS_RESET("ufs_reset", 0x1a2000),
[1] = SDC_QDSD_PINGROUP("sdc1_rclk", 0x199000, 15, 0),
[2] = SDC_QDSD_PINGROUP("sdc1_clk", 0x199000, 13, 6),
[3] = SDC_QDSD_PINGROUP("sdc1_cmd", 0x199000, 11, 3),
[4] = SDC_QDSD_PINGROUP("sdc1_data", 0x199000, 9, 0),
};
static const char *sa8775p_get_function_name(struct udevice *dev,
unsigned int selector)
{
return msm_pinctrl_functions[selector].name;
}
static const char *sa8775p_get_pin_name(struct udevice *dev,
unsigned int selector)
{
if (selector >= 149 && selector <= 155)
snprintf(pin_name, MAX_PIN_NAME_LEN,
msm_special_pins_data[selector - 149].name);
else
snprintf(pin_name, MAX_PIN_NAME_LEN, "gpio%u", selector);
return pin_name;
}
static int sa8775p_get_function_mux(__maybe_unused unsigned int pin,
unsigned int selector)
{
unsigned int i;
const msm_pin_function *func = sa8775p_pin_functions + pin;
for (i = 0; i < 10; i++)
if ((*func)[i] == selector)
return i;
pr_err("Can't find requested function for pin %u pin\n", pin);
return -EINVAL;
}
static const unsigned int sa8775p_pin_offsets[] = {
[0] = SA8775_PIN_OFFSET, [1] = SA8775_PIN_OFFSET, [2] = SA8775_PIN_OFFSET,
[3] = SA8775_PIN_OFFSET, [4] = SA8775_PIN_OFFSET, [5] = SA8775_PIN_OFFSET,
[6] = SA8775_PIN_OFFSET, [7] = SA8775_PIN_OFFSET, [8] = SA8775_PIN_OFFSET,
[9] = SA8775_PIN_OFFSET, [10] = SA8775_PIN_OFFSET, [11] = SA8775_PIN_OFFSET,
[12] = SA8775_PIN_OFFSET, [13] = SA8775_PIN_OFFSET, [14] = SA8775_PIN_OFFSET,
[15] = SA8775_PIN_OFFSET, [16] = SA8775_PIN_OFFSET, [17] = SA8775_PIN_OFFSET,
[18] = SA8775_PIN_OFFSET, [19] = SA8775_PIN_OFFSET, [20] = SA8775_PIN_OFFSET,
[21] = SA8775_PIN_OFFSET, [22] = SA8775_PIN_OFFSET, [23] = SA8775_PIN_OFFSET,
[24] = SA8775_PIN_OFFSET, [25] = SA8775_PIN_OFFSET, [26] = SA8775_PIN_OFFSET,
[27] = SA8775_PIN_OFFSET, [28] = SA8775_PIN_OFFSET, [29] = SA8775_PIN_OFFSET,
[30] = SA8775_PIN_OFFSET, [31] = SA8775_PIN_OFFSET, [32] = SA8775_PIN_OFFSET,
[33] = SA8775_PIN_OFFSET, [34] = SA8775_PIN_OFFSET, [35] = SA8775_PIN_OFFSET,
[36] = SA8775_PIN_OFFSET, [37] = SA8775_PIN_OFFSET, [38] = SA8775_PIN_OFFSET,
[39] = SA8775_PIN_OFFSET, [40] = SA8775_PIN_OFFSET, [41] = SA8775_PIN_OFFSET,
[42] = SA8775_PIN_OFFSET, [43] = SA8775_PIN_OFFSET, [44] = SA8775_PIN_OFFSET,
[45] = SA8775_PIN_OFFSET, [46] = SA8775_PIN_OFFSET, [47] = SA8775_PIN_OFFSET,
[48] = SA8775_PIN_OFFSET, [49] = SA8775_PIN_OFFSET, [50] = SA8775_PIN_OFFSET,
[51] = SA8775_PIN_OFFSET, [52] = SA8775_PIN_OFFSET, [53] = SA8775_PIN_OFFSET,
[54] = SA8775_PIN_OFFSET, [55] = SA8775_PIN_OFFSET, [56] = SA8775_PIN_OFFSET,
[57] = SA8775_PIN_OFFSET, [58] = SA8775_PIN_OFFSET, [59] = SA8775_PIN_OFFSET,
[60] = SA8775_PIN_OFFSET, [61] = SA8775_PIN_OFFSET, [62] = SA8775_PIN_OFFSET,
[63] = SA8775_PIN_OFFSET, [64] = SA8775_PIN_OFFSET, [65] = SA8775_PIN_OFFSET,
[66] = SA8775_PIN_OFFSET, [67] = SA8775_PIN_OFFSET, [68] = SA8775_PIN_OFFSET,
[69] = SA8775_PIN_OFFSET, [70] = SA8775_PIN_OFFSET, [71] = SA8775_PIN_OFFSET,
[72] = SA8775_PIN_OFFSET, [73] = SA8775_PIN_OFFSET, [74] = SA8775_PIN_OFFSET,
[75] = SA8775_PIN_OFFSET, [76] = SA8775_PIN_OFFSET, [77] = SA8775_PIN_OFFSET,
[78] = SA8775_PIN_OFFSET, [79] = SA8775_PIN_OFFSET, [80] = SA8775_PIN_OFFSET,
[81] = SA8775_PIN_OFFSET, [82] = SA8775_PIN_OFFSET, [83] = SA8775_PIN_OFFSET,
[84] = SA8775_PIN_OFFSET, [85] = SA8775_PIN_OFFSET, [86] = SA8775_PIN_OFFSET,
[87] = SA8775_PIN_OFFSET, [88] = SA8775_PIN_OFFSET, [89] = SA8775_PIN_OFFSET,
[90] = SA8775_PIN_OFFSET, [91] = SA8775_PIN_OFFSET, [92] = SA8775_PIN_OFFSET,
[93] = SA8775_PIN_OFFSET, [94] = SA8775_PIN_OFFSET, [95] = SA8775_PIN_OFFSET,
[96] = SA8775_PIN_OFFSET, [97] = SA8775_PIN_OFFSET, [98] = SA8775_PIN_OFFSET,
[99] = SA8775_PIN_OFFSET, [100] = SA8775_PIN_OFFSET, [101] = SA8775_PIN_OFFSET,
[102] = SA8775_PIN_OFFSET, [103] = SA8775_PIN_OFFSET, [104] = SA8775_PIN_OFFSET,
[105] = SA8775_PIN_OFFSET, [106] = SA8775_PIN_OFFSET, [107] = SA8775_PIN_OFFSET,
[108] = SA8775_PIN_OFFSET, [109] = SA8775_PIN_OFFSET, [110] = SA8775_PIN_OFFSET,
[111] = SA8775_PIN_OFFSET, [112] = SA8775_PIN_OFFSET, [113] = SA8775_PIN_OFFSET,
[114] = SA8775_PIN_OFFSET, [115] = SA8775_PIN_OFFSET, [116] = SA8775_PIN_OFFSET,
[117] = SA8775_PIN_OFFSET, [118] = SA8775_PIN_OFFSET, [119] = SA8775_PIN_OFFSET,
[120] = SA8775_PIN_OFFSET, [121] = SA8775_PIN_OFFSET, [122] = SA8775_PIN_OFFSET,
[123] = SA8775_PIN_OFFSET, [124] = SA8775_PIN_OFFSET, [125] = SA8775_PIN_OFFSET,
[126] = SA8775_PIN_OFFSET, [127] = SA8775_PIN_OFFSET, [128] = SA8775_PIN_OFFSET,
[129] = SA8775_PIN_OFFSET, [130] = SA8775_PIN_OFFSET, [131] = SA8775_PIN_OFFSET,
[132] = SA8775_PIN_OFFSET, [133] = SA8775_PIN_OFFSET, [134] = SA8775_PIN_OFFSET,
[135] = SA8775_PIN_OFFSET, [136] = SA8775_PIN_OFFSET, [137] = SA8775_PIN_OFFSET,
[138] = SA8775_PIN_OFFSET, [139] = SA8775_PIN_OFFSET, [140] = SA8775_PIN_OFFSET,
[141] = SA8775_PIN_OFFSET, [142] = SA8775_PIN_OFFSET, [143] = SA8775_PIN_OFFSET,
[144] = SA8775_PIN_OFFSET, [145] = SA8775_PIN_OFFSET, [146] = SA8775_PIN_OFFSET,
[147] = SA8775_PIN_OFFSET, [148] = SA8775_PIN_OFFSET, [148] = SA8775_PIN_OFFSET,
[149] = SA8775_PIN_OFFSET, [150] = SA8775_PIN_OFFSET, [151] = SA8775_PIN_OFFSET,
[152] = SA8775_PIN_OFFSET, [153] = SA8775_PIN_OFFSET, [154] = SA8775_PIN_OFFSET,
};
static const struct msm_pinctrl_data sa8775p_data = {
.pin_data = {
.pin_count = 155,
.special_pins_start = 149,
.special_pins_data = msm_special_pins_data,
.pin_offsets = sa8775p_pin_offsets,
},
.functions_count = ARRAY_SIZE(msm_pinctrl_functions),
.get_function_name = sa8775p_get_function_name,
.get_function_mux = sa8775p_get_function_mux,
.get_pin_name = sa8775p_get_pin_name,
};
static const struct udevice_id msm_pinctrl_ids[] = {
{ .compatible = "qcom,sa8775p-tlmm", .data = (ulong)&sa8775p_data },
{ /* Sentinal */ }
};
U_BOOT_DRIVER(pinctrl_sa8775p) = {
.name = "pinctrl_sa8775p",
.id = UCLASS_NOP,
.of_match = msm_pinctrl_ids,
.ops = &msm_pinctrl_ops,
.bind = msm_pinctrl_bind,
.flags = DM_FLAG_PRE_RELOC,
};

View file

@ -0,0 +1,226 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Qualcomm SDM630/660 TLMM pinctrl
*
*/
#include <dm.h>
#include "pinctrl-qcom.h"
#define TLMM_BASE 0x03100000
#define SOUTH (0x03100000 - TLMM_BASE) /* 0x0 */
#define CENTER (0x03500000 - TLMM_BASE) /* 0x400000 */
#define NORTH (0x03900000 - TLMM_BASE) /* 0x800000 */
#define MAX_PIN_NAME_LEN 32
static char pin_name[MAX_PIN_NAME_LEN] __section(".data");
static const struct pinctrl_function sdm660_pinctrl_functions[] = {
{ "gpio", 0 },
{ "blsp_uart2", 3 }, /* gpio 4 and 5, used for debug uart */
};
static const unsigned int sdm660_pin_offsets[] = {
[0] = SOUTH,
[1] = SOUTH,
[2] = SOUTH,
[3] = SOUTH,
[4] = NORTH,
[5] = SOUTH,
[6] = SOUTH,
[7] = SOUTH,
[8] = NORTH,
[9] = NORTH,
[10] = NORTH,
[11] = NORTH,
[12] = NORTH,
[13] = NORTH,
[14] = NORTH,
[15] = NORTH,
[16] = CENTER,
[17] = CENTER,
[18] = CENTER,
[19] = CENTER,
[20] = SOUTH,
[21] = SOUTH,
[22] = CENTER,
[23] = CENTER,
[24] = NORTH,
[25] = NORTH,
[26] = NORTH,
[27] = NORTH,
[28] = CENTER,
[29] = CENTER,
[30] = CENTER,
[31] = CENTER,
[32] = SOUTH,
[33] = SOUTH,
[34] = SOUTH,
[35] = SOUTH,
[36] = SOUTH,
[37] = SOUTH,
[38] = SOUTH,
[39] = SOUTH,
[40] = SOUTH,
[41] = SOUTH,
[42] = SOUTH,
[43] = SOUTH,
[44] = SOUTH,
[45] = SOUTH,
[46] = SOUTH,
[47] = SOUTH,
[48] = SOUTH,
[49] = SOUTH,
[50] = SOUTH,
[51] = SOUTH,
[52] = SOUTH,
[53] = NORTH,
[54] = NORTH,
[55] = SOUTH,
[56] = SOUTH,
[57] = SOUTH,
[58] = SOUTH,
[59] = NORTH,
[60] = NORTH,
[61] = NORTH,
[62] = NORTH,
[63] = NORTH,
[64] = SOUTH,
[65] = SOUTH,
[66] = NORTH,
[67] = NORTH,
[68] = NORTH,
[69] = NORTH,
[70] = NORTH,
[71] = NORTH,
[72] = NORTH,
[73] = NORTH,
[74] = NORTH,
[75] = NORTH,
[76] = NORTH,
[77] = NORTH,
[78] = NORTH,
[79] = SOUTH,
[80] = SOUTH,
[81] = CENTER,
[82] = CENTER,
[83] = SOUTH,
[84] = SOUTH,
[85] = SOUTH,
[86] = SOUTH,
[87] = SOUTH,
[88] = SOUTH,
[89] = SOUTH,
[90] = SOUTH,
[91] = SOUTH,
[92] = SOUTH,
[93] = SOUTH,
[94] = SOUTH,
[95] = SOUTH,
[96] = SOUTH,
[97] = SOUTH,
[98] = SOUTH,
[99] = SOUTH,
[100] = SOUTH,
[101] = SOUTH,
[102] = SOUTH,
[103] = SOUTH,
[104] = SOUTH,
[105] = SOUTH,
[106] = SOUTH,
[107] = SOUTH,
[108] = SOUTH,
[109] = SOUTH,
[110] = SOUTH,
[111] = SOUTH,
[112] = SOUTH,
[113] = SOUTH,
};
/*
* Special pins - eMMC/SD related: [114..120], in total 7 special pins
*/
#define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \
{ \
.name = pg_name, \
.ctl_reg = ctl, \
.io_reg = 0, \
.pull_bit = pull, \
.drv_bit = drv, \
.oe_bit = -1, \
.in_bit = -1, \
.out_bit = -1, \
}
/* All SDC pins are in the NORTH tile */
static const struct msm_special_pin_data sdm660_special_pins_data[] = {
SDC_QDSD_PINGROUP("sdc1_clk", NORTH + 0x9a000, 13, 6),
SDC_QDSD_PINGROUP("sdc1_cmd", NORTH + 0x9a000, 11, 3),
SDC_QDSD_PINGROUP("sdc1_data", NORTH + 0x9a000, 9, 0),
SDC_QDSD_PINGROUP("sdc2_clk", NORTH + 0x9b000, 14, 6),
SDC_QDSD_PINGROUP("sdc2_cmd", NORTH + 0x9b000, 11, 3),
SDC_QDSD_PINGROUP("sdc2_data", NORTH + 0x9b000, 9, 0),
SDC_QDSD_PINGROUP("sdc1_rclk", NORTH + 0x9a000, 15, 0),
};
static const char *sdm660_get_function_name(struct udevice *dev, unsigned int selector)
{
return sdm660_pinctrl_functions[selector].name;
}
static const char *sdm660_get_pin_name(struct udevice *dev, unsigned int selector)
{
static const char * const special_pins_names[] = {
"sdc1_clk", "sdc1_cmd", "sdc1_data",
"sdc2_clk", "sdc2_cmd", "sdc2_data",
"sdc1_rclk"
};
if (selector >= 114 && selector <= 120)
snprintf(pin_name, MAX_PIN_NAME_LEN, special_pins_names[selector - 114]);
else
snprintf(pin_name, MAX_PIN_NAME_LEN, "gpio%u", selector);
return pin_name;
}
static int sdm660_get_function_mux(__maybe_unused unsigned int pin, unsigned int selector)
{
if (selector >= 0 && selector < ARRAY_SIZE(sdm660_pinctrl_functions))
return sdm660_pinctrl_functions[selector].val;
return -EINVAL;
}
struct msm_pinctrl_data sdm660_data = {
.pin_data = {
.pin_offsets = sdm660_pin_offsets,
.pin_count = ARRAY_SIZE(sdm660_pin_offsets) + ARRAY_SIZE(sdm660_special_pins_data),
.special_pins_start = 114,
.special_pins_data = sdm660_special_pins_data,
},
.functions_count = ARRAY_SIZE(sdm660_pinctrl_functions),
.get_function_name = sdm660_get_function_name,
.get_function_mux = sdm660_get_function_mux,
.get_pin_name = sdm660_get_pin_name,
};
static const struct udevice_id msm_pinctrl_ids[] = {
{
.compatible = "qcom,sdm630-pinctrl",
.data = (ulong)&sdm660_data
},
{
.compatible = "qcom,sdm660-pinctrl",
.data = (ulong)&sdm660_data
},
{ /* Sentinel */ }
};
U_BOOT_DRIVER(pinctrl_ssdm660) = {
.name = "pinctrl_sdm660",
.id = UCLASS_NOP,
.of_match = msm_pinctrl_ids,
.ops = &msm_pinctrl_ops,
.bind = msm_pinctrl_bind,
};

View file

@ -224,6 +224,13 @@ config DM_REGULATOR_QCOM_RPMH
implements get/set api for a limited set of regulators used implements get/set api for a limited set of regulators used
by u-boot. by u-boot.
config DM_REGULATOR_QCOM_USB_VBUS
bool "Enable driver model for Qualcomm USB vbus regulator"
depends on DM_REGULATOR
---help---
Enable support for the Qualcomm USB Vbus regulator. The driver
implements get/set api for the regulator to be used by u-boot.
config SPL_DM_REGULATOR_GPIO config SPL_DM_REGULATOR_GPIO
bool "Enable Driver Model for GPIO REGULATOR in SPL" bool "Enable Driver Model for GPIO REGULATOR in SPL"
depends on DM_REGULATOR_GPIO && SPL_GPIO depends on DM_REGULATOR_GPIO && SPL_GPIO

View file

@ -22,6 +22,7 @@ obj-$(CONFIG_$(XPL_)DM_REGULATOR_COMMON) += regulator_common.o
obj-$(CONFIG_$(XPL_)DM_REGULATOR_FIXED) += fixed.o obj-$(CONFIG_$(XPL_)DM_REGULATOR_FIXED) += fixed.o
obj-$(CONFIG_$(XPL_)DM_REGULATOR_GPIO) += gpio-regulator.o obj-$(CONFIG_$(XPL_)DM_REGULATOR_GPIO) += gpio-regulator.o
obj-$(CONFIG_DM_REGULATOR_QCOM_RPMH) += qcom-rpmh-regulator.o obj-$(CONFIG_DM_REGULATOR_QCOM_RPMH) += qcom-rpmh-regulator.o
obj-$(CONFIG_DM_REGULATOR_QCOM_USB_VBUS) += qcom_usb_vbus_regulator.o
obj-$(CONFIG_$(PHASE_)REGULATOR_RK8XX) += rk8xx.o obj-$(CONFIG_$(PHASE_)REGULATOR_RK8XX) += rk8xx.o
obj-$(CONFIG_DM_REGULATOR_S2MPS11) += s2mps11_regulator.o obj-$(CONFIG_DM_REGULATOR_S2MPS11) += s2mps11_regulator.o
obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o

View file

@ -466,6 +466,25 @@ static const struct rpmh_vreg_hw_data pmic5_nldo515 = {
.n_modes = ARRAY_SIZE(pmic_mode_map_pmic5_ldo), .n_modes = ARRAY_SIZE(pmic_mode_map_pmic5_ldo),
}; };
static const struct rpmh_vreg_hw_data pmic5_ftsmps527 = {
.regulator_type = VRM,
.ops = &rpmh_regulator_vrm_drms_ops,
.voltage_range = REGULATOR_LINEAR_RANGE(320000, 0, 215, 8000),
.n_voltages = 215,
.pmic_mode_map = pmic_mode_map_pmic5_smps,
.n_modes = ARRAY_SIZE(pmic_mode_map_pmic5_smps),
};
static const struct rpmh_vreg_hw_data pmic5_pldo515_mv = {
.regulator_type = VRM,
.ops = &rpmh_regulator_vrm_drms_ops,
.voltage_range = REGULATOR_LINEAR_RANGE(1800000, 0, 187, 8000),
.n_voltages = 188,
.hpm_min_load_uA = 10000,
.pmic_mode_map = pmic_mode_map_pmic5_ldo,
.n_modes = ARRAY_SIZE(pmic_mode_map_pmic5_ldo),
};
#define RPMH_VREG(_name, _resource_name, _hw_data, _supply_name) \ #define RPMH_VREG(_name, _resource_name, _hw_data, _supply_name) \
{ \ { \
.name = _name, \ .name = _name, \
@ -558,6 +577,28 @@ static const struct rpmh_vreg_init_data pmc8380_vreg_data[] = {
{} {}
}; };
static const struct rpmh_vreg_init_data pmm8654au_vreg_data[] = {
RPMH_VREG("smps1", "smp%s1", &pmic5_ftsmps527, "vdd-s1"),
RPMH_VREG("smps2", "smp%s2", &pmic5_ftsmps527, "vdd-s2"),
RPMH_VREG("smps3", "smp%s3", &pmic5_ftsmps527, "vdd-s3"),
RPMH_VREG("smps4", "smp%s4", &pmic5_ftsmps527, "vdd-s4"),
RPMH_VREG("smps5", "smp%s5", &pmic5_ftsmps527, "vdd-s5"),
RPMH_VREG("smps6", "smp%s6", &pmic5_ftsmps527, "vdd-s6"),
RPMH_VREG("smps7", "smp%s7", &pmic5_ftsmps527, "vdd-s7"),
RPMH_VREG("smps8", "smp%s8", &pmic5_ftsmps527, "vdd-s8"),
RPMH_VREG("smps9", "smp%s9", &pmic5_ftsmps527, "vdd-s9"),
RPMH_VREG("ldo1", "ldo%s1", &pmic5_nldo515, "vdd-s9"),
RPMH_VREG("ldo2", "ldo%s2", &pmic5_nldo515, "vdd-l2-l3"),
RPMH_VREG("ldo3", "ldo%s3", &pmic5_nldo515, "vdd-l2-l3"),
RPMH_VREG("ldo4", "ldo%s4", &pmic5_nldo515, "vdd-s9"),
RPMH_VREG("ldo5", "ldo%s5", &pmic5_nldo515, "vdd-s9"),
RPMH_VREG("ldo6", "ldo%s6", &pmic5_nldo515, "vdd-l6-l7"),
RPMH_VREG("ldo7", "ldo%s7", &pmic5_nldo515, "vdd-l6-l7"),
RPMH_VREG("ldo8", "ldo%s8", &pmic5_pldo515_mv, "vdd-l8-l9"),
RPMH_VREG("ldo9", "ldo%s9", &pmic5_pldo, "vdd-l8-l9"),
{}
};
/* probe an individual regulator */ /* probe an individual regulator */
static int rpmh_regulator_probe(struct udevice *dev) static int rpmh_regulator_probe(struct udevice *dev)
{ {
@ -688,6 +729,10 @@ static const struct udevice_id rpmh_regulator_ids[] = {
.compatible = "qcom,pmc8380-rpmh-regulators", .compatible = "qcom,pmc8380-rpmh-regulators",
.data = (ulong)pmc8380_vreg_data, .data = (ulong)pmc8380_vreg_data,
}, },
{
.compatible = "qcom,pmm8654au-rpmh-regulators",
.data = (ulong)pmm8654au_vreg_data,
},
{ /* sentinal */ }, { /* sentinal */ },
}; };

View file

@ -0,0 +1,111 @@
// SPDX-License-Identifier: BSD-3-Clause
/*
* Copyright (c) 2025, Linaro Limited
*/
#define pr_fmt(fmt) "qcom_usb_vbus: " fmt
#include <bitfield.h>
#include <errno.h>
#include <dm.h>
#include <fdtdec.h>
#include <log.h>
#include <asm/gpio.h>
#include <linux/bitops.h>
#include <linux/printk.h>
#include <power/pmic.h>
#include <power/regulator.h>
#define CMD_OTG 0x50
#define OTG_EN BIT(0)
// The 0 bit in this register's bit field is undocumented
#define OTG_CFG 0x56
#define OTG_EN_SRC_CFG BIT(1)
struct qcom_usb_vbus_priv {
phys_addr_t base;
};
static int qcom_usb_vbus_regulator_of_to_plat(struct udevice *dev)
{
struct qcom_usb_vbus_priv *priv = dev_get_priv(dev);
priv->base = dev_read_addr(dev);
if (priv->base == FDT_ADDR_T_NONE)
return -EINVAL;
return 0;
}
static int qcom_usb_vbus_regulator_get_enable(struct udevice *dev)
{
struct qcom_usb_vbus_priv *priv = dev_get_priv(dev);
int otg_en_reg = priv->base + CMD_OTG;
int ret;
ret = pmic_reg_read(dev->parent, otg_en_reg);
if (ret < 0)
log_err("failed to read usb vbus: %d\n", ret);
else
ret &= OTG_EN;
return ret;
}
static int qcom_usb_vbus_regulator_set_enable(struct udevice *dev, bool enable)
{
struct qcom_usb_vbus_priv *priv = dev_get_priv(dev);
int otg_en_reg = priv->base + CMD_OTG;
int ret;
if (enable) {
ret = pmic_clrsetbits(dev->parent, otg_en_reg, 0, OTG_EN);
if (ret < 0) {
log_err("error enabling: %d\n", ret);
return ret;
}
} else {
ret = pmic_clrsetbits(dev->parent, otg_en_reg, OTG_EN, 0);
if (ret < 0) {
log_err("error disabling: %d\n", ret);
return ret;
}
}
return 0;
}
static int qcom_usb_vbus_regulator_probe(struct udevice *dev)
{
struct qcom_usb_vbus_priv *priv = dev_get_priv(dev);
int otg_cfg_reg = priv->base + OTG_CFG;
int ret;
/* Disable HW logic for VBUS enable */
ret = pmic_clrsetbits(dev->parent, otg_cfg_reg, OTG_EN_SRC_CFG, 0);
if (ret < 0) {
log_err("error setting EN_SRC_CFG: %d\n", ret);
return ret;
}
return 0;
}
static const struct dm_regulator_ops qcom_usb_vbus_regulator_ops = {
.get_enable = qcom_usb_vbus_regulator_get_enable,
.set_enable = qcom_usb_vbus_regulator_set_enable,
};
static const struct udevice_id qcom_usb_vbus_regulator_ids[] = {
{ .compatible = "qcom,pm8150b-vbus-reg"},
{ },
};
U_BOOT_DRIVER(qcom_usb_vbus_regulator) = {
.name = "qcom-usb-vbus-regulator",
.id = UCLASS_REGULATOR,
.of_match = qcom_usb_vbus_regulator_ids,
.of_to_plat = qcom_usb_vbus_regulator_of_to_plat,
.ops = &qcom_usb_vbus_regulator_ops,
.probe = qcom_usb_vbus_regulator_probe,
.priv_auto = sizeof(struct qcom_usb_vbus_priv),
};

View file

@ -24,6 +24,9 @@ DECLARE_GLOBAL_DATA_PTR;
#define PMIC_ARB_VERSION_V5_MIN 0x50000000 #define PMIC_ARB_VERSION_V5_MIN 0x50000000
#define PMIC_ARB_VERSION_V7_MIN 0x70000000 #define PMIC_ARB_VERSION_V7_MIN 0x70000000
#define PMIC_ARB_FEATURES 0x0004
#define PMIC_ARB_FEATURES_PERIPH_MASK GENMASK(10, 0)
#define APID_MAP_OFFSET_V1_V2_V3 (0x800) #define APID_MAP_OFFSET_V1_V2_V3 (0x800)
#define APID_MAP_OFFSET_V5 (0x900) #define APID_MAP_OFFSET_V5 (0x900)
#define APID_MAP_OFFSET_V7 (0x2000) #define APID_MAP_OFFSET_V7 (0x2000)
@ -60,6 +63,7 @@ DECLARE_GLOBAL_DATA_PTR;
#define SPMI_MAX_PERIPH 256 #define SPMI_MAX_PERIPH 256
#define SPMI_CHANNEL_READ_ONLY BIT(31) #define SPMI_CHANNEL_READ_ONLY BIT(31)
#define SPMI_CHANNEL_VALID BIT(30)
#define SPMI_CHANNEL_MASK 0xffff #define SPMI_CHANNEL_MASK 0xffff
enum arb_ver { enum arb_ver {
@ -114,6 +118,8 @@ static int msm_spmi_write(struct udevice *dev, int usid, int pid, int off,
return -EIO; return -EIO;
if (pid >= SPMI_MAX_PERIPH) if (pid >= SPMI_MAX_PERIPH)
return -EIO; return -EIO;
if (!(priv->channel_map[usid][pid] & SPMI_CHANNEL_VALID))
return -EINVAL;
if (priv->channel_map[usid][pid] & SPMI_CHANNEL_READ_ONLY) if (priv->channel_map[usid][pid] & SPMI_CHANNEL_READ_ONLY)
return -EPERM; return -EPERM;
@ -183,6 +189,8 @@ static int msm_spmi_read(struct udevice *dev, int usid, int pid, int off)
return -EIO; return -EIO;
if (pid >= SPMI_MAX_PERIPH) if (pid >= SPMI_MAX_PERIPH)
return -EIO; return -EIO;
if (!(priv->channel_map[usid][pid] & SPMI_CHANNEL_VALID))
return -EINVAL;
channel = priv->channel_map[usid][pid] & SPMI_CHANNEL_MASK; channel = priv->channel_map[usid][pid] & SPMI_CHANNEL_MASK;
@ -246,6 +254,32 @@ static struct dm_spmi_ops msm_spmi_ops = {
.write = msm_spmi_write, .write = msm_spmi_write,
}; };
/*
* In order to allow multiple EEs to write to a single PPID in arbiter
* version 5 and 7, there is more than one APID mapped to each PPID.
* The owner field for each of these mappings specifies the EE which is
* allowed to write to the APID.
*/
static void msm_spmi_channel_map_v5(struct msm_spmi_priv *priv, unsigned int i,
uint8_t slave_id, uint8_t pid)
{
/* Mark channels read-only when from different owner */
uint32_t cnfg = readl(priv->spmi_cnfg + ARB_CHANNEL_OFFSET(i));
uint8_t owner = SPMI_OWNERSHIP_PERIPH2OWNER(cnfg);
bool prev_valid = priv->channel_map[slave_id][pid] & SPMI_CHANNEL_VALID;
uint32_t prev_read_only = priv->channel_map[slave_id][pid] & SPMI_CHANNEL_READ_ONLY;
if (!prev_valid) {
/* First PPID mapping */
priv->channel_map[slave_id][pid] = i | SPMI_CHANNEL_VALID;
if (owner != priv->owner)
priv->channel_map[slave_id][pid] |= SPMI_CHANNEL_READ_ONLY;
} else if ((owner == priv->owner) && prev_read_only) {
/* Read only and we found one we own, switch */
priv->channel_map[slave_id][pid] = i | SPMI_CHANNEL_VALID;
}
}
static int msm_spmi_probe(struct udevice *dev) static int msm_spmi_probe(struct udevice *dev)
{ {
struct msm_spmi_priv *priv = dev_get_priv(dev); struct msm_spmi_priv *priv = dev_get_priv(dev);
@ -271,13 +305,17 @@ static int msm_spmi_probe(struct udevice *dev)
} else if (hw_ver < PMIC_ARB_VERSION_V7_MIN) { } else if (hw_ver < PMIC_ARB_VERSION_V7_MIN) {
priv->arb_ver = V5; priv->arb_ver = V5;
priv->arb_chnl = core_addr + APID_MAP_OFFSET_V5; priv->arb_chnl = core_addr + APID_MAP_OFFSET_V5;
priv->max_channels = SPMI_MAX_CHANNELS_V5; priv->max_channels = min_t(u32, readl(core_addr + PMIC_ARB_FEATURES) &
PMIC_ARB_FEATURES_PERIPH_MASK,
SPMI_MAX_CHANNELS_V5);
priv->spmi_cnfg = dev_read_addr_name(dev, "cnfg"); priv->spmi_cnfg = dev_read_addr_name(dev, "cnfg");
} else { } else {
/* TOFIX: handle second bus */ /* TOFIX: handle second bus */
priv->arb_ver = V7; priv->arb_ver = V7;
priv->arb_chnl = core_addr + APID_MAP_OFFSET_V7; priv->arb_chnl = core_addr + APID_MAP_OFFSET_V7;
priv->max_channels = SPMI_MAX_CHANNELS_V7; priv->max_channels = min_t(u32, readl(core_addr + PMIC_ARB_FEATURES) &
PMIC_ARB_FEATURES_PERIPH_MASK,
SPMI_MAX_CHANNELS_V7);
priv->spmi_cnfg = dev_read_addr_name(dev, "cnfg"); priv->spmi_cnfg = dev_read_addr_name(dev, "cnfg");
} }
@ -297,15 +335,16 @@ static int msm_spmi_probe(struct udevice *dev)
uint8_t slave_id = (periph & 0xf0000) >> 16; uint8_t slave_id = (periph & 0xf0000) >> 16;
uint8_t pid = (periph & 0xff00) >> 8; uint8_t pid = (periph & 0xff00) >> 8;
priv->channel_map[slave_id][pid] = i; switch (priv->arb_ver) {
case V2:
case V3:
priv->channel_map[slave_id][pid] = i | SPMI_CHANNEL_VALID;
break;
/* Mark channels read-only when from different owner */ case V5:
if (priv->arb_ver == V5 || priv->arb_ver == V7) { case V7:
uint32_t cnfg = readl(priv->spmi_cnfg + ARB_CHANNEL_OFFSET(i)); msm_spmi_channel_map_v5(priv, i, slave_id, pid);
uint8_t owner = SPMI_OWNERSHIP_PERIPH2OWNER(cnfg); break;
if (owner != priv->owner)
priv->channel_map[slave_id][pid] |= SPMI_CHANNEL_READ_ONLY;
} }
} }
return 0; return 0;

View file

@ -18,15 +18,4 @@
#define PHYS_SDRAM_1_SIZE SZ_1G #define PHYS_SDRAM_1_SIZE SZ_1G
#define CFG_SYS_SDRAM_BASE PHYS_SDRAM_1 #define CFG_SYS_SDRAM_BASE PHYS_SDRAM_1
/* Environment */
#define BOOT_TARGET_DEVICES(func) \
func(USB, usb, 0) \
func(MMC, mmc, 1) \
func(MMC, mmc, 0) \
func(DHCP, dhcp, na)
#include <config_distro_bootcmd.h>
#define CFG_EXTRA_ENV_SETTINGS BOOTENV
#endif #endif