qcom-next-20230324:

* msm8916 gets proper sysreset and spin-table support
* The first new IPQ platform is added - the IPQ9574. The IPQ series are
  used in routers. The flashing process is also documented
* mach-snapdragon gains the ability to boot with an internal FDT and
  still parse memory from an externally provided one
* SC7280 gets a pinctrl driver and various clock driver improvements.
* Qualcom clock drivers will now actually return an error when
  attempting
  to enable a clock which isn't described.
* Qualcomm pinctrl drivers will now return an error when attempting to
  configure an invalid function mux
This commit is contained in:
Tom Rini
2025-03-24 12:38:48 -06:00
44 changed files with 906 additions and 119 deletions

View File

@@ -1117,6 +1117,8 @@ config ARCH_SNAPDRAGON
select OF_BOARD
select SAVE_PREV_BL_FDT_ADDR
select LINUX_KERNEL_IMAGE_HEADER if !ENABLE_ARM_SOC_BOOT0_HOOK
select SYSRESET
select SYSRESET_PSCI
imply OF_UPSTREAM
imply CMD_DM

View File

@@ -0,0 +1,25 @@
// SPDX-License-Identifier: BSD-3-Clause
/*
* Copyright (c) 2025, Qualcomm Innovation Center, Inc. All rights reserved.
*/
/ {
/* Will be removed when SMEM parsing is updated */
memory@40000000 {
device_type = "memory";
reg = <0x0 0x40000000 0x0 0x40000000>,
<0x0 0x4a500000 0x0 0x00100000>;
};
};
&sdhc_1 {
sdhci-caps-mask = <0x0 0x04000000>;
sdhci-caps = <0x0 0x04000000>; /* SDHCI_CAN_VDD_180 */
/*
* This reset is needed to clear out the settings done by
* previous boot loader. Without this the SDHCI_RESET_ALL
* reset done sdhci_init() times out.
*/
resets = <&gcc GCC_SDCC_BCR>;
};

View File

@@ -88,7 +88,29 @@ int dram_init_banksize(void)
return 0;
}
static void qcom_parse_memory(const void *fdt)
/**
* The generic memory parsing code in U-Boot lacks a few things that we
* need on Qualcomm:
*
* 1. It sets gd->ram_size and gd->ram_base to represent a single memory block
* 2. setup_dest_addr() later relocates U-Boot to ram_base + ram_size, the end
* of that first memory block.
*
* This results in all memory beyond U-Boot being unusable in Linux when booting
* with EFI.
*
* Since the ranges in the memory node may be out of order, the only way for us
* to correctly determine the relocation address for U-Boot is to parse all
* memory regions and find the highest valid address.
*
* We can't use fdtdec_setup_memory_banksize() since it stores the result in
* gd->bd, which is not yet allocated.
*
* @fdt: FDT blob to parse /memory node from
*
* Return: 0 on success or -ENODATA if /memory node is missing or incomplete
*/
static int qcom_parse_memory(const void *fdt)
{
int offset;
const fdt64_t *memory;
@@ -97,16 +119,12 @@ static void qcom_parse_memory(const void *fdt)
int i, j, banks;
offset = fdt_path_offset(fdt, "/memory");
if (offset < 0) {
log_err("No memory node found in device tree!\n");
return;
}
if (offset < 0)
return -ENODATA;
memory = fdt_getprop(fdt, offset, "reg", &memsize);
if (!memory) {
log_err("No memory configuration was provided by the previous bootloader!\n");
return;
}
if (!memory)
return -ENODATA;
banks = min(memsize / (2 * sizeof(u64)), (ulong)CONFIG_NR_DRAM_BANKS);
@@ -119,7 +137,6 @@ static void qcom_parse_memory(const void *fdt)
for (i = 0, j = 0; i < banks * 2; i += 2, j++) {
prevbl_ddr_banks[j].start = get_unaligned_be64(&memory[i]);
prevbl_ddr_banks[j].size = get_unaligned_be64(&memory[i + 1]);
/* SM8650 boards sometimes have empty regions! */
if (!prevbl_ddr_banks[j].size) {
j--;
continue;
@@ -127,13 +144,16 @@ static void qcom_parse_memory(const void *fdt)
ram_end = max(ram_end, prevbl_ddr_banks[j].start + prevbl_ddr_banks[j].size);
}
if (!banks || !prevbl_ddr_banks[0].size)
return -ENODATA;
/* Sort our RAM banks -_- */
qsort(prevbl_ddr_banks, banks, sizeof(prevbl_ddr_banks[0]), ddr_bank_cmp);
gd->ram_base = prevbl_ddr_banks[0].start;
gd->ram_size = ram_end - gd->ram_base;
debug("ram_base = %#011lx, ram_size = %#011llx, ram_end = %#011llx\n",
gd->ram_base, gd->ram_size, ram_end);
return 0;
}
static void show_psci_version(void)
@@ -142,24 +162,56 @@ static void show_psci_version(void)
arm_smccc_smc(ARM_PSCI_0_2_FN_PSCI_VERSION, 0, 0, 0, 0, 0, 0, 0, &res);
/* Some older SoCs like MSM8916 don't always support PSCI */
if ((int)res.a0 == PSCI_RET_NOT_SUPPORTED)
return;
debug("PSCI: v%ld.%ld\n",
PSCI_VERSION_MAJOR(res.a0),
PSCI_VERSION_MINOR(res.a0));
}
/**
* Most MSM8916 devices in the wild shipped without PSCI support, but the
* upstream DTs pretend that PSCI exists. If that situation is detected here,
* the /psci node is deleted. This is done very early to ensure the PSCI
* firmware driver doesn't bind (which then binds a sysreset driver that won't
* work).
*/
static void qcom_psci_fixup(void *fdt)
{
int offset, ret;
struct arm_smccc_res res;
arm_smccc_smc(ARM_PSCI_0_2_FN_PSCI_VERSION, 0, 0, 0, 0, 0, 0, 0, &res);
if ((int)res.a0 != PSCI_RET_NOT_SUPPORTED)
return;
offset = fdt_path_offset(fdt, "/psci");
if (offset < 0)
return;
debug("Found /psci DT node on device with no PSCI. Deleting.\n");
ret = fdt_del_node(fdt, offset);
if (ret)
log_err("Failed to delete /psci node: %d\n", ret);
}
/* We support booting U-Boot with an internal DT when running as a first-stage bootloader
* or for supporting quirky devices where it's easier to leave the downstream DT in place
* to improve ABL compatibility. Otherwise, we use the DT provided by ABL.
*/
int board_fdt_blob_setup(void **fdtp)
{
struct fdt_header *fdt;
struct fdt_header *external_fdt, *internal_fdt;
bool internal_valid, external_valid;
int ret = 0;
int ret = -ENODATA;
fdt = (struct fdt_header *)get_prev_bl_fdt_addr();
external_valid = fdt && !fdt_check_header(fdt);
internal_valid = !fdt_check_header(*fdtp);
internal_fdt = (struct fdt_header *)*fdtp;
external_fdt = (struct fdt_header *)get_prev_bl_fdt_addr();
external_valid = external_fdt && !fdt_check_header(external_fdt);
internal_valid = !fdt_check_header(internal_fdt);
/*
* There is no point returning an error here, U-Boot can't do anything useful in this situation.
@@ -167,31 +219,42 @@ int board_fdt_blob_setup(void **fdtp)
*/
if (!internal_valid && !external_valid)
panic("Internal FDT is invalid and no external FDT was provided! (fdt=%#llx)\n",
(phys_addr_t)fdt);
(phys_addr_t)external_fdt);
/* Prefer memory information from internal DT if it's present */
if (internal_valid)
ret = qcom_parse_memory(internal_fdt);
if (ret < 0 && external_valid) {
/* No internal FDT or it lacks a proper /memory node.
* The previous bootloader handed us something, let's try that.
*/
if (internal_valid)
debug("No memory info in internal FDT, falling back to external\n");
ret = qcom_parse_memory(external_fdt);
}
if (ret < 0)
panic("No valid memory ranges found!\n");
debug("ram_base = %#011lx, ram_size = %#011llx\n",
gd->ram_base, gd->ram_size);
if (internal_valid) {
debug("Using built in FDT\n");
ret = -EEXIST;
} else {
debug("Using external FDT\n");
/* So we can use it before returning */
*fdtp = fdt;
*fdtp = external_fdt;
ret = 0;
}
/*
* Parse the /memory node while we're here,
* this makes it easy to do other things early.
*/
qcom_parse_memory(*fdtp);
qcom_psci_fixup(*fdtp);
return ret;
}
void reset_cpu(void)
{
psci_system_reset();
}
/*
* Some Qualcomm boards require GPIO configuration when switching USB modes.
* Support setting this configuration via pinctrl state.

View File

@@ -97,6 +97,7 @@ CONFIG_PINCTRL_QCOM_APQ8016=y
CONFIG_PINCTRL_QCOM_APQ8096=y
CONFIG_PINCTRL_QCOM_QCM2290=y
CONFIG_PINCTRL_QCOM_QCS404=y
CONFIG_PINCTRL_QCOM_SC7280=y
CONFIG_PINCTRL_QCOM_SDM845=y
CONFIG_PINCTRL_QCOM_SM6115=y
CONFIG_PINCTRL_QCOM_SM8150=y
@@ -120,6 +121,7 @@ CONFIG_QCOM_RPMH=y
CONFIG_SPMI_MSM=y
CONFIG_SYSINFO=y
CONFIG_SYSINFO_SMBIOS=y
CONFIG_SYSRESET_QCOM_PSHOLD=y
CONFIG_USB=y
CONFIG_USB_XHCI_HCD=y
CONFIG_USB_XHCI_DWC3=y

View File

@@ -0,0 +1,83 @@
CONFIG_ARM=y
CONFIG_SKIP_LOWLEVEL_INIT=y
CONFIG_POSITION_INDEPENDENT=y
CONFIG_SYS_INIT_SP_BSS_OFFSET=1572864
CONFIG_ARCH_SNAPDRAGON=y
CONFIG_NR_DRAM_BANKS=24
CONFIG_DEFAULT_DEVICE_TREE="qcom/ipq9574-rdp433"
CONFIG_SYS_LOAD_ADDR=0x50000000
CONFIG_FIT=y
CONFIG_FIT_VERBOSE=y
# CONFIG_EFI_LOADER is not set
# CONFIG_EFI_BINARY_EXEC is not set
# CONFIG_EFI_VARIABLE_FILE_STORE is not set
# CONFIG_PXE_UTILS is not set
# CONFIG_BOOTSTD is not set
# CONFIG_BOOTMETH_VBE is not set
CONFIG_BOOTDELAY=2
CONFIG_OF_BOARD_SETUP=y
CONFIG_USE_PREBOOT=y
CONFIG_SYS_CBSIZE=512
CONFIG_LOG_MAX_LEVEL=9
CONFIG_LOG_DEFAULT_LEVEL=4
# CONFIG_DISPLAY_CPUINFO is not set
CONFIG_DISPLAY_BOARDINFO_LATE=y
CONFIG_CMD_MMC=y
CONFIG_CMD_USB=y
CONFIG_CMD_PART=y
CONFIG_OF_LIVE=y
CONFIG_USE_DEFAULT_ENV_FILE=y
CONFIG_DEFAULT_ENV_FILE="board/qualcomm/default.env"
CONFIG_CLK=y
CONFIG_CLK_QCOM_IPQ9574=y
CONFIG_DFU_MMC=y
CONFIG_DFU_SCSI=y
CONFIG_SYS_DFU_DATA_BUF_SIZE=0x200000
CONFIG_MSM_GPIO=y
CONFIG_PINCTRL=y
CONFIG_PINCONF=y
CONFIG_PINCTRL_QCOM_IPQ9574=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_ADMA=y
CONFIG_MMC_SDHCI_MSM=y
CONFIG_DM_MDIO=y
CONFIG_DM_ETH_PHY=y
CONFIG_DWC_ETH_QOS=y
CONFIG_DWC_ETH_QOS_QCOM=y
CONFIG_RGMII=y
CONFIG_PHY=y
CONFIG_PHY_QCOM_QMP_UFS=y
CONFIG_PHY_QCOM_QUSB2=y
CONFIG_SCSI=y
CONFIG_MSM_SERIAL=y
CONFIG_MSM_GENI_SERIAL=y
CONFIG_SOC_QCOM=y
CONFIG_DEBUG_UART=y
CONFIG_DEBUG_UART_ANNOUNCE=y
CONFIG_DEBUG_UART_BASE=0x78b1000
CONFIG_DEBUG_UART_MSM=y
CONFIG_DEBUG_UART_CLOCK=1843200
CONFIG_TEXT_BASE=0x4A240000
CONFIG_REMAKE_ELF=y
CONFIG_FIT=y
CONFIG_FIT_VERBOSE=y
CONFIG_BOOTSTD_FULL=y
CONFIG_SYS_CBSIZE=1024
CONFIG_SYS_PBSIZE=1024
CONFIG_OF_LIVE=y
CONFIG_MSM_SERIAL=y
CONFIG_DM_EVENT=y
CONFIG_ENV_IS_IN_MMC=y
CONFIG_ENV_SIZE=0x40000
CONFIG_ENV_OFFSET=0
CONFIG_PARTITIONS=y
CONFIG_PARTITION_UUIDS=y
CONFIG_MTD=y
CONFIG_MTD_PARTS=y
CONFIG_HUSH_PARSER=y
CONFIG_PARTITIONS=y
CONFIG_EFI_PARTITION=y
# CONFIG_I2C is not set
# CONFIG_INPUT is not set
# CONFIG_SCSI is not set
# CONFIG_SPMI is not set

View File

@@ -10,3 +10,4 @@ Qualcomm
rb3gen2
board
debugging
rdp

View File

@@ -0,0 +1,55 @@
.. SPDX-License-Identifier: GPL-2.0
.. sectionauthor:: Varadarajan Narayanan <quic_varada@quicinc.com>
Qualcomm Reference Design Platform (RDP)
========================================
Qualcomm RDPs are development boards based on the Qualcomm IPQ series of
SoCs. These SoCs are used as the application processors in WiFi router
platforms. RDPs come in multiple variants with differences in storage
medium (NOR, NAND, MMC), no. of USB and PCIe ports, n/w ports etc.
.. _Qualcomm's product page: https://www.qualcomm.com/products/internet-of-things/networking/wi-fi-networks/networking-pro-series/qualcomm-networking-pro-820-platform
Installation
------------
First, setup ``CROSS_COMPILE`` for aarch64. Then, build U-Boot for ``IPQ9574``::
$ export CROSS_COMPILE=<aarch64 toolchain prefix>
$ make qcom_ipq9574_mmc_defconfig
$ make -j8
This will build ``u-boot.elf`` in the configured output directory.
Although the RDPs do not have secure boot set up by default, the firmware still
expects firmware ELF images to be "signed". The signature does not provide any
security in this case, but it provides the firmware with some required metadata.
To "sign" ``u-boot.elf`` you can use e.g. `qtestsign`_::
$ qtestsign -v6 aboot -o u-boot.mbn u-boot.elf
Then install the resulting ``u-boot.mbn`` to the ``0:APPSBL`` partition
on your device with::
IPQ9574# tftpboot path/to/u-boot.mbn
IPQ9574# mmc part (note down the start & end block no.s of '0:APPSBL' partition)
IPQ9574# mmc erase <start blk no> <count>
IPQ9574# mmc write $fileaddr <blk no> <count>
U-Boot should be running after a reboot (``reset``).
.. WARNING
Boards with newer software versions would automatically go the emergency
download (EDL) mode if U-Boot is not functioning as expected. If its a
runtime failure at Uboot, the system will get reset (due to watchdog)
and XBL will try to boot from next bank and if Bank B also doesn't have
a functional image and is not booting fine, then the system will enter
EDL. A tool like bkerler's `edl`_ can be used for flashing with the
firehose loader binary appropriate for the board.
Note that the support added is very basic. Restoring the original U-Boot
on boards with older version of the software requires a debugger.
.. _qtestsign: https://github.com/msm8916-mainline/qtestsign
.. _edl: https://github.com/bkerler/edl

View File

@@ -50,6 +50,7 @@ static struct clk_ops stub_clk_ops = {
static const struct udevice_id stub_clk_ids[] = {
{ .compatible = "qcom,rpmcc" },
{ .compatible = "qcom,sc7280-rpmh-clk" },
{ .compatible = "qcom,sm8150-rpmh-clk" },
{ .compatible = "qcom,sm8250-rpmh-clk" },
{ .compatible = "qcom,sm8550-rpmh-clk" },

View File

@@ -31,6 +31,14 @@ config CLK_QCOM_IPQ4019
on the Snapdragon IPQ4019 SoC. This driver supports the clocks
and resets exposed by the GCC hardware block.
config CLK_QCOM_IPQ9574
bool "Qualcomm IPQ9574 GCC"
select CLK_QCOM
help
Say Y here to enable support for the Global Clock Controller
on the Snapdragon IPQ9574 SoC. This driver supports the clocks
and resets exposed by the GCC hardware block.
config CLK_QCOM_QCM2290
bool "Qualcomm QCM2290 GCC"
select CLK_QCOM

View File

@@ -7,6 +7,7 @@ obj-$(CONFIG_CLK_QCOM_SDM845) += clock-sdm845.o
obj-$(CONFIG_CLK_QCOM_APQ8016) += clock-apq8016.o
obj-$(CONFIG_CLK_QCOM_APQ8096) += clock-apq8096.o
obj-$(CONFIG_CLK_QCOM_IPQ4019) += clock-ipq4019.o
obj-$(CONFIG_CLK_QCOM_IPQ9574) += clock-ipq9574.o
obj-$(CONFIG_CLK_QCOM_QCM2290) += clock-qcm2290.o
obj-$(CONFIG_CLK_QCOM_QCS404) += clock-qcs404.o
obj-$(CONFIG_CLK_QCOM_SA8775P) += clock-sa8775p.o

View File

@@ -54,8 +54,9 @@ static struct vote_clk gcc_blsp1_ahb_clk = {
};
static const struct gate_clk apq8016_clks[] = {
GATE_CLK(GCC_USB_HS_AHB_CLK, 0x41008, 0x00000001),
GATE_CLK(GCC_USB_HS_SYSTEM_CLK, 0x41004, 0x00000001),
GATE_CLK(GCC_PRNG_AHB_CLK, 0x45004, BIT(8)),
GATE_CLK(GCC_USB_HS_AHB_CLK, 0x41008, BIT(0)),
GATE_CLK(GCC_USB_HS_SYSTEM_CLK, 0x41004, BIT(0)),
};
/* SDHCI */
@@ -139,15 +140,14 @@ static int apq8016_clk_enable(struct clk *clk)
{
struct msm_clk_priv *priv = dev_get_priv(clk->dev);
if (priv->data->num_clks < clk->id) {
if (priv->data->num_clks < clk->id || !apq8016_clks[clk->id].reg) {
log_warning("%s: unknown clk id %lu\n", __func__, clk->id);
return 0;
}
debug("%s: clk %s\n", __func__, apq8016_clks[clk->id].name);
qcom_gate_clk_en(priv, clk->id);
debug("%s: enabling clock %s\n", __func__, apq8016_clks[clk->id].name);
return 0;
return qcom_gate_clk_en(priv, clk->id);
}
static struct msm_clk_data apq8016_clk_data = {

View File

@@ -0,0 +1,94 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Clock drivers for Qualcomm ipq9574
*
* (C) Copyright 2025 Linaro Ltd.
*/
#include <linux/types.h>
#include <clk-uclass.h>
#include <dm.h>
#include <linux/delay.h>
#include <asm/io.h>
#include <linux/bug.h>
#include <linux/bitops.h>
#include <dt-bindings/clock/qcom,ipq9574-gcc.h>
#include <dt-bindings/reset/qcom,ipq9574-gcc.h>
#include "clock-qcom.h"
#define GCC_BLSP1_AHB_CBCR 0x1004
#define GCC_BLSP1_UART3_APPS_CMD_RCGR 0x402C
#define GCC_BLSP1_UART3_APPS_CBCR 0x4054
#define GCC_SDCC1_APPS_CBCR 0x3302C
#define GCC_SDCC1_AHB_CBCR 0x33034
#define GCC_SDCC1_APPS_CMD_RCGR 0x33004
#define GCC_SDCC1_ICE_CORE_CBCR 0x33030
static ulong ipq9574_set_rate(struct clk *clk, ulong rate)
{
struct msm_clk_priv *priv = dev_get_priv(clk->dev);
switch (clk->id) {
case GCC_BLSP1_UART3_APPS_CLK:
clk_rcg_set_rate_mnd(priv->base, GCC_BLSP1_UART3_APPS_CMD_RCGR,
0, 144, 15625, CFG_CLK_SRC_GPLL0, 16);
return rate;
case GCC_SDCC1_APPS_CLK:
clk_rcg_set_rate_mnd(priv->base, GCC_SDCC1_APPS_CMD_RCGR,
11, 0, 0, CFG_CLK_SRC_GPLL2, 16);
return rate;
default:
return -EINVAL;
}
}
static const struct gate_clk ipq9574_clks[] = {
GATE_CLK(GCC_BLSP1_UART3_APPS_CLK, 0x4054, 0x00000001),
GATE_CLK(GCC_BLSP1_AHB_CLK, 0x1004, 0x00000001),
GATE_CLK(GCC_SDCC1_AHB_CLK, 0x33034, 0x00000001),
GATE_CLK(GCC_SDCC1_APPS_CLK, 0x3302C, 0x00000001),
GATE_CLK(GCC_SDCC1_ICE_CORE_CLK, 0x33030, 0x00000001),
};
static int ipq9574_enable(struct clk *clk)
{
struct msm_clk_priv *priv = dev_get_priv(clk->dev);
debug("%s: clk %s\n", __func__, ipq9574_clks[clk->id].name);
if (!ipq9574_clks[clk->id].reg)
return -EINVAL;
qcom_gate_clk_en(priv, clk->id);
return 0;
}
static const struct qcom_reset_map ipq9574_gcc_resets[] = {
[GCC_SDCC_BCR] = { 0x33000 },
};
static struct msm_clk_data ipq9574_gcc_data = {
.resets = ipq9574_gcc_resets,
.num_resets = ARRAY_SIZE(ipq9574_gcc_resets),
.enable = ipq9574_enable,
.set_rate = ipq9574_set_rate,
};
static const struct udevice_id gcc_ipq9574_of_match[] = {
{
.compatible = "qcom,ipq9574-gcc",
.data = (ulong)&ipq9574_gcc_data,
},
{ }
};
U_BOOT_DRIVER(gcc_ipq9574) = {
.name = "gcc_ipq9574",
.id = UCLASS_NOP,
.of_match = gcc_ipq9574_of_match,
.bind = qcom_cc_bind,
.flags = DM_FLAG_PRE_RELOC | DM_FLAG_DEFAULT_PD_CTRL_OFF,
};

View File

@@ -134,9 +134,7 @@ static int qcm2290_enable(struct clk *clk)
break;
}
qcom_gate_clk_en(priv, clk->id);
return 0;
return qcom_gate_clk_en(priv, clk->id);
}
static const struct qcom_reset_map qcm2290_gcc_resets[] = {

View File

@@ -7,10 +7,12 @@
#include <asm/io.h>
#include <linux/bitfield.h>
#include <errno.h>
#define CFG_CLK_SRC_CXO (0 << 8)
#define CFG_CLK_SRC_GPLL0 (1 << 8)
#define CFG_CLK_SRC_GPLL0_AUX2 (2 << 8)
#define CFG_CLK_SRC_GPLL2 (2 << 8)
#define CFG_CLK_SRC_GPLL9 (2 << 8)
#define CFG_CLK_SRC_GPLL0_ODD (3 << 8)
#define CFG_CLK_SRC_GPLL6 (4 << 8)
@@ -105,14 +107,19 @@ void clk_rcg_set_rate(phys_addr_t base, uint32_t cmd_rcgr, int div,
int source);
void clk_phy_mux_enable(phys_addr_t base, uint32_t cmd_rcgr, bool enabled);
static inline void qcom_gate_clk_en(const struct msm_clk_priv *priv, unsigned long id)
static inline int qcom_gate_clk_en(const struct msm_clk_priv *priv, unsigned long id)
{
u32 val;
if (id >= priv->data->num_clks || priv->data->clks[id].reg == 0)
return;
if (id >= priv->data->num_clks || priv->data->clks[id].reg == 0) {
log_err("gcc@%#08llx: unknown clock ID %lu!\n",
priv->base, id);
return -ENOENT;
}
val = readl(priv->base + priv->data->clks[id].reg);
writel(val | priv->data->clks[id].en_val, priv->base + priv->data->clks[id].reg);
return 0;
}
#endif

View File

@@ -73,9 +73,7 @@ static int sa8775p_enable(struct clk *clk)
break;
}
qcom_gate_clk_en(priv, clk->id);
return 0;
return qcom_gate_clk_en(priv, clk->id);
}
static const struct qcom_reset_map sa8775p_gcc_resets[] = {

View File

@@ -16,29 +16,64 @@
#include "clock-qcom.h"
#define USB30_PRIM_MOCK_UTMI_CLK_CMD_RCGR 0xf038
#define USB30_PRIM_MASTER_CLK_CMD_RCGR 0xf020
#define USB30_PRIM_MOCK_UTMI_CLK_CMD_RCGR 0xf038
#define USB30_SEC_MASTER_CLK_CMD_RCGR 0x9e020
#define USB30_SEC_MOCK_UTMI_CLK_CMD_RCGR 0x9e038
#define PCIE_1_AUX_CLK_CMD_RCGR 0x8d058
#define PCIE1_PHY_RCHNG_CMD_RCGR 0x8d03c
#define PCIE_1_PIPE_CLK_PHY_MUX 0x8d054
static const struct freq_tbl ftbl_gcc_usb30_prim_master_clk_src[] = {
F(66666667, CFG_CLK_SRC_GPLL0_EVEN, 4.5, 0, 0),
F(133333333, CFG_CLK_SRC_GPLL0, 4.5, 0, 0),
F(200000000, CFG_CLK_SRC_GPLL0_ODD, 1, 0, 0),
F(240000000, CFG_CLK_SRC_GPLL0, 2.5, 0, 0),
{ }
};
static const struct freq_tbl ftbl_gcc_usb30_sec_master_clk_src[] = {
F(60000000, CFG_CLK_SRC_GPLL0_EVEN, 5, 0, 0),
F(120000000, CFG_CLK_SRC_GPLL0_EVEN, 2.5, 0, 0),
{ }
};
static ulong sc7280_set_rate(struct clk *clk, ulong rate)
{
struct msm_clk_priv *priv = dev_get_priv(clk->dev);
const struct freq_tbl *freq;
if (clk->id < priv->data->num_clks)
debug("%s: %s, requested rate=%ld\n", __func__, priv->data->clks[clk->id].name, rate);
switch (clk->id) {
case GCC_USB30_PRIM_MOCK_UTMI_CLK:
WARN(rate != 19200000, "Unexpected rate for USB30_PRIM_MOCK_UTMI_CLK: %lu\n", rate);
clk_rcg_set_rate(priv->base, USB30_PRIM_MASTER_CLK_CMD_RCGR, 0, CFG_CLK_SRC_CXO);
return rate;
case GCC_USB30_PRIM_MASTER_CLK:
WARN(rate != 200000000, "Unexpected rate for USB30_PRIM_MASTER_CLK: %lu\n", rate);
freq = qcom_find_freq(ftbl_gcc_usb30_prim_master_clk_src, rate);
clk_rcg_set_rate_mnd(priv->base, USB30_PRIM_MASTER_CLK_CMD_RCGR,
1, 0, 0, CFG_CLK_SRC_GPLL0_ODD, 8);
clk_rcg_set_rate(priv->base, 0xf064, 0, 0);
return rate;
freq->pre_div, freq->m, freq->n, freq->src, 8);
return freq->freq;
case GCC_USB30_PRIM_MOCK_UTMI_CLK:
clk_rcg_set_rate(priv->base, USB30_PRIM_MOCK_UTMI_CLK_CMD_RCGR, 1, 0);
return 19200000;
case GCC_USB3_PRIM_PHY_AUX_CLK_SRC:
clk_rcg_set_rate(priv->base, USB30_PRIM_MOCK_UTMI_CLK_CMD_RCGR, 1, 0);
return 19200000;
case GCC_USB30_SEC_MASTER_CLK:
freq = qcom_find_freq(ftbl_gcc_usb30_sec_master_clk_src, rate);
clk_rcg_set_rate_mnd(priv->base, USB30_SEC_MASTER_CLK_CMD_RCGR,
freq->pre_div, freq->m, freq->n, freq->src, 8);
return freq->freq;
case GCC_USB30_SEC_MOCK_UTMI_CLK:
clk_rcg_set_rate(priv->base, USB30_SEC_MOCK_UTMI_CLK_CMD_RCGR, 1, 0);
return 19200000;
case GCC_USB3_SEC_PHY_AUX_CLK_SRC:
clk_rcg_set_rate(priv->base, USB30_PRIM_MOCK_UTMI_CLK_CMD_RCGR, 1, 0);
return 19200000;
case GCC_PCIE1_PHY_RCHNG_CLK:
clk_rcg_set_rate(priv->base, PCIE1_PHY_RCHNG_CMD_RCGR, 5, CFG_CLK_SRC_GPLL0_EVEN);
return 100000000;
default:
return 0;
return rate;
}
}
@@ -50,13 +85,35 @@ static const struct gate_clk sc7280_clks[] = {
GATE_CLK(GCC_USB30_PRIM_MOCK_UTMI_CLK, 0xf01c, 1),
GATE_CLK(GCC_USB3_PRIM_PHY_AUX_CLK, 0xf054, 1),
GATE_CLK(GCC_USB3_PRIM_PHY_COM_AUX_CLK, 0xf058, 1),
GATE_CLK(GCC_CFG_NOC_USB3_SEC_AXI_CLK, 0x9e07c, 1),
GATE_CLK(GCC_USB30_SEC_MASTER_CLK, 0x9e010, 1),
GATE_CLK(GCC_AGGRE_USB3_SEC_AXI_CLK, 0x9e080, 1),
GATE_CLK(GCC_USB30_SEC_SLEEP_CLK, 0x9e018, 1),
GATE_CLK(GCC_USB30_SEC_MOCK_UTMI_CLK, 0x9e01c, 1),
GATE_CLK(GCC_USB3_SEC_PHY_AUX_CLK, 0x9e054, 1),
GATE_CLK(GCC_USB3_SEC_PHY_COM_AUX_CLK, 0x9e058, 1),
GATE_CLK(GCC_PCIE_CLKREF_EN, 0x8c004, 1),
GATE_CLK(GCC_PCIE_1_PIPE_CLK, 0x52000, BIT(30)),
GATE_CLK(GCC_PCIE_1_AUX_CLK, 0x52000, BIT(29)),
GATE_CLK(GCC_PCIE_1_CFG_AHB_CLK, 0x52000, BIT(28)),
GATE_CLK(GCC_PCIE_1_MSTR_AXI_CLK, 0x52000, BIT(27)),
GATE_CLK(GCC_PCIE_1_SLV_AXI_CLK, 0x52000, BIT(26)),
GATE_CLK(GCC_PCIE_1_SLV_Q2A_AXI_CLK, 0x52000, BIT(25)),
GATE_CLK(GCC_PCIE1_PHY_RCHNG_CLK, 0x52000, BIT(23)),
GATE_CLK(GCC_DDRSS_PCIE_SF_CLK, 0x52000, BIT(19)),
GATE_CLK(GCC_AGGRE_NOC_PCIE_TBU_CLK, 0x52000, BIT(18)),
GATE_CLK(GCC_AGGRE_NOC_PCIE_1_AXI_CLK, 0x52000, BIT(11)),
GATE_CLK(GCC_AGGRE_NOC_PCIE_CENTER_SF_AXI_CLK, 0x52008, BIT(28)),
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_S3_CLK, 0x52008, BIT(13)),
};
static int sc7280_enable(struct clk *clk)
{
struct msm_clk_priv *priv = dev_get_priv(clk->dev);
if (priv->data->num_clks < clk->id) {
if (priv->data->num_clks <= clk->id) {
debug("%s: unknown clk id %lu\n", __func__, clk->id);
return 0;
}
@@ -71,11 +128,32 @@ static int sc7280_enable(struct clk *clk)
qcom_gate_clk_en(priv, GCC_USB3_PRIM_PHY_AUX_CLK);
qcom_gate_clk_en(priv, GCC_USB3_PRIM_PHY_COM_AUX_CLK);
break;
case GCC_AGGRE_USB3_SEC_AXI_CLK:
qcom_gate_clk_en(priv, GCC_USB30_SEC_MASTER_CLK);
fallthrough;
case GCC_USB30_SEC_MASTER_CLK:
qcom_gate_clk_en(priv, GCC_USB3_SEC_PHY_AUX_CLK);
qcom_gate_clk_en(priv, GCC_USB3_SEC_PHY_COM_AUX_CLK);
break;
case GCC_PCIE_1_PIPE_CLK:
clk_phy_mux_enable(priv->base, PCIE_1_PIPE_CLK_PHY_MUX, true);
break;
case GCC_PCIE_1_AUX_CLK:
clk_rcg_set_rate_mnd(priv->base, PCIE_1_AUX_CLK_CMD_RCGR, 1, 0, 0,
CFG_CLK_SRC_CXO, 16);
break;
case GCC_QUPV3_WRAP0_S0_CLK:
clk_rcg_set_rate_mnd(priv->base, 0x17010, 1, 0, 0, CFG_CLK_SRC_CXO, 16);
break;
case GCC_QUPV3_WRAP0_S1_CLK:
clk_rcg_set_rate_mnd(priv->base, 0x17140, 1, 0, 0, CFG_CLK_SRC_CXO, 16);
break;
case GCC_QUPV3_WRAP0_S3_CLK:
clk_rcg_set_rate_mnd(priv->base, 0x173a0, 1, 0, 0, CFG_CLK_SRC_CXO, 16);
break;
}
qcom_gate_clk_en(priv, clk->id);
return 0;
return qcom_gate_clk_en(priv, clk->id);
}
static const struct qcom_reset_map sc7280_gcc_resets[] = {
@@ -100,6 +178,20 @@ static const struct qcom_reset_map sc7280_gcc_resets[] = {
static const struct qcom_power_map sc7280_gdscs[] = {
[GCC_UFS_PHY_GDSC] = { 0x77004 },
[GCC_USB30_PRIM_GDSC] = { 0xf004 },
[GCC_USB30_SEC_GDSC] = { 0x9e004 },
[GCC_PCIE_1_GDSC] = { 0x8d004 },
};
static const phys_addr_t sc7280_rcg_addrs[] = {
0x10f020, // USB30_PRIM_MASTER_CLK_CMD_RCGR
0x10f038, // USB30_PRIM_MOCK_UTMI_CLK_CMD_RCGR
0x18d058, // PCIE_1_AUX_CLK_CMD_RCGR
};
static const char *const sc7280_rcg_names[] = {
"USB30_PRIM_MASTER_CLK_SRC",
"USB30_PRIM_MOCK_UTMI_CLK_SRC",
"GCC_PCIE_1_AUX_CLK_SRC",
};
static struct msm_clk_data qcs404_gcc_data = {
@@ -113,6 +205,10 @@ static struct msm_clk_data qcs404_gcc_data = {
.enable = sc7280_enable,
.set_rate = sc7280_set_rate,
.dbg_rcg_addrs = sc7280_rcg_addrs,
.num_rcgs = ARRAY_SIZE(sc7280_rcg_addrs),
.dbg_rcg_names = sc7280_rcg_names,
};
static const struct udevice_id gcc_sc7280_of_match[] = {

View File

@@ -162,9 +162,7 @@ static int sdm845_clk_enable(struct clk *clk)
break;
}
qcom_gate_clk_en(priv, clk->id);
return 0;
return qcom_gate_clk_en(priv, clk->id);
}
static const struct qcom_reset_map sdm845_gcc_resets[] = {

View File

@@ -146,9 +146,7 @@ static int sm6115_enable(struct clk *clk)
break;
}
qcom_gate_clk_en(priv, clk->id);
return 0;
return qcom_gate_clk_en(priv, clk->id);
}
static const struct qcom_reset_map sm6115_gcc_resets[] = {

View File

@@ -243,9 +243,7 @@ static int sm8150_clk_enable(struct clk *clk)
break;
};
qcom_gate_clk_en(priv, clk->id);
return 0;
return qcom_gate_clk_en(priv, clk->id);
}
static const struct qcom_reset_map sm8150_gcc_resets[] = {

View File

@@ -195,9 +195,7 @@ static int sm8250_enable(struct clk *clk)
break;
}
qcom_gate_clk_en(priv, clk->id);
return 0;
return qcom_gate_clk_en(priv, clk->id);
}
static const struct qcom_reset_map sm8250_gcc_resets[] = {

View File

@@ -220,9 +220,7 @@ static int sm8550_enable(struct clk *clk)
break;
}
qcom_gate_clk_en(priv, clk->id);
return 0;
return qcom_gate_clk_en(priv, clk->id);
}
static const struct qcom_reset_map sm8550_gcc_resets[] = {

View File

@@ -217,9 +217,7 @@ static int sm8650_enable(struct clk *clk)
break;
}
qcom_gate_clk_en(priv, clk->id);
return 0;
return qcom_gate_clk_en(priv, clk->id);
}
static const struct qcom_reset_map sm8650_gcc_resets[] = {

View File

@@ -174,9 +174,7 @@ static int x1e80100_enable(struct clk *clk)
break;
}
qcom_gate_clk_en(priv, clk->id);
return 0;
return qcom_gate_clk_en(priv, clk->id);
}
static const struct qcom_reset_map x1e80100_gcc_resets[] = {

View File

@@ -10,6 +10,7 @@
#include <clk.h>
#include <dm.h>
#include <malloc.h>
#include <reset.h>
#include <sdhci.h>
#include <wait_bit.h>
#include <asm/global_data.h>
@@ -153,9 +154,18 @@ static int msm_sdc_probe(struct udevice *dev)
const struct msm_sdhc_variant_info *var_info;
struct sdhci_host *host = &prv->host;
u32 core_version, core_minor, core_major;
struct reset_ctl bcr_rst;
u32 caps;
int ret;
ret = reset_get_by_index(dev, 0, &bcr_rst);
if (!ret) {
reset_assert(&bcr_rst);
udelay(200);
reset_deassert(&bcr_rst);
udelay(200);
}
host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD | SDHCI_QUIRK_BROKEN_R1B;
host->max_clk = 0;

View File

@@ -7,84 +7,98 @@ config PINCTRL_QCOM
menu "Qualcomm pinctrl drivers"
config PINCTRL_QCOM_APQ8016
bool "Qualcomm APQ8016 GCC"
bool "Qualcomm APQ8016 Pinctrl"
select PINCTRL_QCOM
help
Say Y here to enable support for pinctrl on the MSM8916 / APQ8016
Snapdragon 410 SoC, as well as the associated GPIO driver.
config PINCTRL_QCOM_APQ8096
bool "Qualcomm APQ8096 GCC"
bool "Qualcomm APQ8096 Pinctrl"
select PINCTRL_QCOM
help
Say Y here to enable support for pinctrl on the MSM8996 / APQ8096
Snapdragon 820 SoC, as well as the associated GPIO driver.
config PINCTRL_QCOM_IPQ4019
bool "Qualcomm IPQ4019 GCC"
bool "Qualcomm IPQ4019 Pinctrl"
select PINCTRL_QCOM
help
Say Y here to enable support for pinctrl on the IPQ4019 SoC,
as well as the associated GPIO driver.
config PINCTRL_QCOM_IPQ9574
bool "Qualcomm IPQ9574 Pinctrl"
select PINCTRL_QCOM
help
Say Y here to enable support for pinctrl on the IPQ9574 SoC,
as well as the associated GPIO driver.
config PINCTRL_QCOM_QCM2290
bool "Qualcomm QCM2290 GCC"
bool "Qualcomm QCM2290 Pinctrl"
select PINCTRL_QCOM
help
Say Y here to enable support for pinctrl on the Snapdragon QCM2290 SoC,
as well as the associated GPIO driver.
config PINCTRL_QCOM_QCS404
bool "Qualcomm QCS404 GCC"
bool "Qualcomm QCS404 Pinctrl"
select PINCTRL_QCOM
help
Say Y here to enable support for pinctrl on the Snapdragon QCS404 SoC,
as well as the associated GPIO driver.
config PINCTRL_QCOM_SC7280
bool "Qualcomm SC7280/QCM6490 Pinctrl"
select PINCTRL_QCOM
help
Say Y here to enable support for pinctrl on the Snapdragon SC7280 SoC,
as well as the associated GPIO driver.
config PINCTRL_QCOM_SDM845
bool "Qualcomm SDM845 GCC"
bool "Qualcomm SDM845 Pinctrl"
select PINCTRL_QCOM
help
Say Y here to enable support for pinctrl on the Snapdragon 845 SoC,
as well as the associated GPIO driver.
config PINCTRL_QCOM_SM6115
bool "Qualcomm SM6115 GCC"
bool "Qualcomm SM6115 Pinctrl"
select PINCTRL_QCOM
help
Say Y here to enable support for pinctrl on the Snapdragon SM6115 SoC,
as well as the associated GPIO driver.
config PINCTRL_QCOM_SM8150
bool "Qualcomm SM8150 GCC"
bool "Qualcomm SM8150 Pinctrl"
select PINCTRL_QCOM
help
Say Y here to enable support for pinctrl on the Snapdragon SM8150 SoC,
as well as the associated GPIO driver.
config PINCTRL_QCOM_SM8250
bool "Qualcomm SM8250 GCC"
bool "Qualcomm SM8250 Pinctrl"
select PINCTRL_QCOM
help
Say Y here to enable support for pinctrl on the Snapdragon SM8250 SoC,
as well as the associated GPIO driver.
config PINCTRL_QCOM_SM8550
bool "Qualcomm SM8550 GCC"
bool "Qualcomm SM8550 Pinctrl"
select PINCTRL_QCOM
help
Say Y here to enable support for pinctrl on the Snapdragon SM8550 SoC,
as well as the associated GPIO driver.
config PINCTRL_QCOM_SM8650
bool "Qualcomm SM8650 GCC"
bool "Qualcomm SM8650 Pinctrl"
select PINCTRL_QCOM
help
Say Y here to enable support for pinctrl on the Snapdragon SM8650 SoC,
as well as the associated GPIO driver.
config PINCTRL_QCOM_X1E80100
bool "Qualcomm X1E80100 GCC"
bool "Qualcomm X1E80100 Pinctrl"
select PINCTRL_QCOM
help
Say Y here to enable support for pinctrl on the Snapdragon X1E80100 SoC,

View File

@@ -5,9 +5,11 @@
obj-$(CONFIG_PINCTRL_QCOM) += pinctrl-qcom.o
obj-$(CONFIG_PINCTRL_QCOM_APQ8016) += pinctrl-apq8016.o
obj-$(CONFIG_PINCTRL_QCOM_IPQ4019) += pinctrl-ipq4019.o
obj-$(CONFIG_PINCTRL_QCOM_IPQ9574) += pinctrl-ipq9574.o
obj-$(CONFIG_PINCTRL_QCOM_APQ8096) += pinctrl-apq8096.o
obj-$(CONFIG_PINCTRL_QCOM_QCM2290) += pinctrl-qcm2290.o
obj-$(CONFIG_PINCTRL_QCOM_QCS404) += pinctrl-qcs404.o
obj-$(CONFIG_PINCTRL_QCOM_SC7280) += pinctrl-sc7280.o
obj-$(CONFIG_PINCTRL_QCOM_SDM845) += pinctrl-sdm845.o
obj-$(CONFIG_PINCTRL_QCOM_SM6115) += pinctrl-sm6115.o
obj-$(CONFIG_PINCTRL_QCOM_SM8150) += pinctrl-sm8150.o

View File

@@ -50,8 +50,8 @@ static const char *apq8016_get_pin_name(struct udevice *dev,
}
}
static unsigned int apq8016_get_function_mux(__maybe_unused unsigned int pin,
unsigned int selector)
static int apq8016_get_function_mux(__maybe_unused unsigned int pin,
unsigned int selector)
{
return msm_pinctrl_functions[selector].val;
}

View File

@@ -43,8 +43,8 @@ static const char *apq8096_get_pin_name(struct udevice *dev,
}
}
static unsigned int apq8096_get_function_mux(__maybe_unused unsigned int pin,
unsigned int selector)
static int apq8096_get_function_mux(__maybe_unused unsigned int pin,
unsigned int selector)
{
return msm_pinctrl_functions[selector].val;
}

View File

@@ -311,8 +311,7 @@ static const char *ipq4019_get_pin_name(struct udevice *dev,
return pin_name;
}
static unsigned int ipq4019_get_function_mux(unsigned int pin,
unsigned int selector)
static int ipq4019_get_function_mux(unsigned int pin, unsigned int selector)
{
unsigned int i;
const msm_pin_function *func = ipq4019_pin_functions + pin;

View File

@@ -0,0 +1,226 @@
// SPDX-License-Identifier: GPL-2.0
/*
* pinctrl driver for Qualcomm ipq9574
*
* (C) Copyright 2025 Linaro Ltd.
*/
#include <dm.h>
#include "pinctrl-qcom.h"
#define MAX_PIN_NAME_LEN 32
static char pin_name[MAX_PIN_NAME_LEN] __section(".data");
enum ipq9574_functions {
msm_mux_blsp0_spi,
msm_mux_blsp0_uart,
msm_mux_blsp1_i2c,
msm_mux_blsp1_spi,
msm_mux_blsp1_uart,
msm_mux_blsp2_i2c,
msm_mux_blsp2_spi,
msm_mux_blsp2_uart,
msm_mux_blsp3_i2c,
msm_mux_blsp3_spi,
msm_mux_blsp3_uart,
msm_mux_blsp4_i2c,
msm_mux_blsp4_spi,
msm_mux_blsp4_uart,
msm_mux_blsp5_i2c,
msm_mux_blsp5_uart,
msm_mux_gpio,
msm_mux_mdc,
msm_mux_mdio,
msm_mux_pcie0_clk,
msm_mux_pcie0_wake,
msm_mux_pcie1_clk,
msm_mux_pcie1_wake,
msm_mux_pcie2_clk,
msm_mux_pcie2_wake,
msm_mux_pcie3_clk,
msm_mux_pcie3_wake,
msm_mux_qspi_data,
msm_mux_qspi_clk,
msm_mux_qspi_cs,
msm_mux_sdc_data,
msm_mux_sdc_clk,
msm_mux_sdc_cmd,
msm_mux_sdc_rclk,
msm_mux_NA,
};
#define MSM_PIN_FUNCTION(fname) \
[msm_mux_##fname] = {#fname, msm_mux_##fname}
static const struct pinctrl_function msm_pinctrl_functions[] = {
MSM_PIN_FUNCTION(blsp0_spi),
MSM_PIN_FUNCTION(blsp0_uart),
MSM_PIN_FUNCTION(blsp1_i2c),
MSM_PIN_FUNCTION(blsp1_spi),
MSM_PIN_FUNCTION(blsp1_uart),
MSM_PIN_FUNCTION(blsp2_i2c),
MSM_PIN_FUNCTION(blsp2_spi),
MSM_PIN_FUNCTION(blsp2_uart),
MSM_PIN_FUNCTION(blsp3_i2c),
MSM_PIN_FUNCTION(blsp3_spi),
MSM_PIN_FUNCTION(blsp3_uart),
MSM_PIN_FUNCTION(blsp4_i2c),
MSM_PIN_FUNCTION(blsp4_spi),
MSM_PIN_FUNCTION(blsp4_uart),
MSM_PIN_FUNCTION(blsp5_i2c),
MSM_PIN_FUNCTION(blsp5_uart),
MSM_PIN_FUNCTION(gpio),
MSM_PIN_FUNCTION(mdc),
MSM_PIN_FUNCTION(mdio),
MSM_PIN_FUNCTION(pcie0_clk),
MSM_PIN_FUNCTION(pcie0_wake),
MSM_PIN_FUNCTION(pcie1_clk),
MSM_PIN_FUNCTION(pcie1_wake),
MSM_PIN_FUNCTION(pcie2_clk),
MSM_PIN_FUNCTION(pcie2_wake),
MSM_PIN_FUNCTION(pcie3_clk),
MSM_PIN_FUNCTION(pcie3_wake),
MSM_PIN_FUNCTION(qspi_data),
MSM_PIN_FUNCTION(qspi_clk),
MSM_PIN_FUNCTION(qspi_cs),
MSM_PIN_FUNCTION(sdc_data),
MSM_PIN_FUNCTION(sdc_clk),
MSM_PIN_FUNCTION(sdc_cmd),
MSM_PIN_FUNCTION(sdc_rclk),
};
typedef unsigned int msm_pin_function[10];
#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9) \
[id] = { 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, \
}
static const msm_pin_function ipq9574_pin_functions[] = {
PINGROUP(0, sdc_data, qspi_data, NA, NA, NA, NA, NA, NA, NA),
PINGROUP(1, sdc_data, qspi_data, NA, NA, NA, NA, NA, NA, NA),
PINGROUP(2, sdc_data, qspi_data, NA, NA, NA, NA, NA, NA, NA),
PINGROUP(3, sdc_data, qspi_data, NA, NA, NA, NA, NA, NA, NA),
PINGROUP(4, sdc_cmd, qspi_cs, NA, NA, NA, NA, NA, NA, NA),
PINGROUP(5, sdc_clk, qspi_clk, NA, NA, NA, NA, NA, NA, NA),
PINGROUP(6, sdc_data, NA, NA, NA, NA, NA, NA, NA, NA),
PINGROUP(7, sdc_data, NA, NA, NA, NA, NA, NA, NA, NA),
PINGROUP(8, sdc_data, NA, NA, NA, NA, NA, NA, NA, NA),
PINGROUP(9, sdc_data, NA, NA, NA, NA, NA, NA, NA, NA),
PINGROUP(10, sdc_rclk, NA, NA, NA, NA, NA, NA, NA, NA),
PINGROUP(11, blsp0_spi, blsp0_uart, NA, NA, NA, NA, NA, NA, NA),
PINGROUP(12, blsp0_spi, blsp0_uart, NA, NA, NA, NA, NA, NA, NA),
PINGROUP(13, blsp0_spi, blsp0_uart, NA, NA, NA, NA, NA, NA, NA),
PINGROUP(14, blsp0_spi, blsp0_uart, NA, NA, NA, NA, NA, NA, NA),
PINGROUP(15, blsp3_spi, blsp3_i2c, blsp3_uart, NA, NA, NA, NA, NA, NA),
PINGROUP(16, blsp3_spi, blsp3_i2c, blsp3_uart, NA, NA, NA, NA, NA, NA),
PINGROUP(17, blsp3_spi, blsp3_uart, NA, NA, NA, NA, NA, NA, NA),
PINGROUP(18, blsp3_spi, blsp3_uart, NA, NA, NA, NA, NA, NA, NA),
PINGROUP(19, blsp3_spi, NA, NA, NA, NA, NA, NA, NA, NA),
PINGROUP(20, blsp3_spi, NA, NA, NA, NA, NA, NA, NA, NA),
PINGROUP(21, blsp3_spi, NA, NA, NA, NA, NA, NA, NA, NA),
PINGROUP(22, pcie0_clk, NA, NA, NA, NA, NA, NA, NA, NA),
PINGROUP(23, NA, NA, NA, NA, NA, NA, NA, NA, NA),
PINGROUP(24, pcie0_wake, NA, NA, NA, NA, NA, NA, NA, NA),
PINGROUP(25, pcie1_clk, NA, NA, NA, NA, NA, NA, NA, NA),
PINGROUP(26, NA, NA, NA, NA, NA, NA, NA, NA, NA),
PINGROUP(27, pcie1_wake, NA, NA, NA, NA, NA, NA, NA, NA),
PINGROUP(28, pcie2_clk, NA, NA, NA, NA, NA, NA, NA, NA),
PINGROUP(29, NA, NA, NA, NA, NA, NA, NA, NA, NA),
PINGROUP(30, pcie2_wake, NA, NA, NA, NA, NA, NA, NA, NA),
PINGROUP(31, pcie3_clk, NA, NA, NA, NA, NA, NA, NA, NA),
PINGROUP(32, NA, NA, NA, NA, NA, NA, NA, NA, NA),
PINGROUP(33, pcie3_wake, NA, NA, NA, NA, NA, NA, NA, NA),
PINGROUP(34, blsp2_uart, blsp2_i2c, blsp2_spi, blsp1_uart, NA, NA, NA, NA, NA),
PINGROUP(35, blsp2_uart, blsp2_i2c, blsp2_spi, blsp1_uart, NA, NA, NA, NA, NA),
PINGROUP(36, blsp1_uart, blsp1_i2c, blsp2_spi, NA, NA, NA, NA, NA, NA),
PINGROUP(37, blsp1_uart, blsp1_i2c, blsp2_spi, NA, NA, NA, NA, NA, NA),
PINGROUP(38, mdc, NA, NA, NA, NA, NA, NA, NA, NA),
PINGROUP(39, mdio, NA, NA, NA, NA, NA, NA, NA, NA),
PINGROUP(40, NA, NA, NA, NA, NA, NA, NA, NA, NA),
PINGROUP(41, NA, NA, NA, NA, NA, NA, NA, NA, NA),
PINGROUP(42, NA, NA, NA, NA, NA, NA, NA, NA, NA),
PINGROUP(43, NA, NA, NA, NA, NA, NA, NA, NA, NA),
PINGROUP(44, NA, NA, NA, NA, NA, NA, NA, NA, NA),
PINGROUP(45, NA, NA, NA, NA, NA, NA, NA, NA, NA),
PINGROUP(46, NA, NA, NA, NA, NA, NA, NA, NA, NA),
PINGROUP(47, NA, NA, NA, NA, NA, NA, NA, NA, NA),
PINGROUP(48, blsp5_i2c, blsp5_uart, NA, NA, NA, NA, NA, NA, NA),
PINGROUP(49, blsp5_i2c, blsp5_uart, NA, NA, NA, NA, NA, NA, NA),
PINGROUP(50, blsp4_uart, blsp4_i2c, blsp4_spi, NA, NA, NA, NA, NA, NA),
PINGROUP(51, blsp4_uart, blsp4_i2c, blsp4_spi, NA, NA, NA, NA, NA, NA),
PINGROUP(52, blsp4_uart, blsp4_spi, NA, NA, NA, NA, NA, NA, NA),
PINGROUP(53, blsp4_uart, blsp4_spi, NA, NA, NA, NA, NA, NA, NA),
PINGROUP(54, NA, NA, NA, NA, NA, NA, NA, NA, NA),
PINGROUP(55, NA, NA, NA, NA, NA, NA, NA, NA, NA),
PINGROUP(56, NA, NA, NA, NA, NA, NA, NA, NA, NA),
PINGROUP(57, NA, NA, NA, NA, NA, NA, NA, NA, NA),
PINGROUP(58, NA, NA, NA, NA, NA, NA, NA, NA, NA),
PINGROUP(59, NA, NA, NA, NA, NA, NA, NA, NA, NA),
PINGROUP(60, NA, NA, NA, NA, NA, NA, NA, NA, NA),
PINGROUP(61, blsp1_spi, NA, NA, NA, NA, NA, NA, NA, NA),
PINGROUP(62, blsp1_spi, NA, NA, NA, NA, NA, NA, NA, NA),
PINGROUP(63, blsp1_spi, NA, NA, NA, NA, NA, NA, NA, NA),
PINGROUP(64, blsp1_spi, NA, NA, NA, NA, NA, NA, NA, NA),
};
static const char *ipq9574_get_function_name(struct udevice *dev,
unsigned int selector)
{
return msm_pinctrl_functions[selector].name;
}
static const char *ipq9574_get_pin_name(struct udevice *dev,
unsigned int selector)
{
snprintf(pin_name, MAX_PIN_NAME_LEN, "gpio%u", selector);
return pin_name;
}
static int ipq9574_get_function_mux(unsigned int pin, unsigned int selector)
{
unsigned int i;
const msm_pin_function *func = ipq9574_pin_functions + pin;
for (i = 0; i < 10; i++)
if ((*func)[i] == selector)
return i;
debug("Can't find requested function for pin:selector %u:%u\n",
pin, selector);
return -EINVAL;
}
static const struct msm_pinctrl_data ipq9574_data = {
.pin_data = {
.pin_count = 65,
},
.functions_count = ARRAY_SIZE(msm_pinctrl_functions),
.get_function_name = ipq9574_get_function_name,
.get_function_mux = ipq9574_get_function_mux,
.get_pin_name = ipq9574_get_pin_name,
};
static const struct udevice_id msm_pinctrl_ids[] = {
{ .compatible = "qcom,ipq9574-tlmm", .data = (ulong)&ipq9574_data },
{ /* Sentinal */ }
};
U_BOOT_DRIVER(pinctrl_ipq9574) = {
.name = "pinctrl_ipq9574",
.id = UCLASS_NOP,
.of_match = msm_pinctrl_ids,
.ops = &msm_pinctrl_ops,
.bind = msm_pinctrl_bind,
.flags = DM_FLAG_PRE_RELOC,
};

View File

@@ -38,7 +38,7 @@ static const char *qcm2290_get_pin_name(struct udevice *dev, unsigned int select
return pin_name;
}
static unsigned int qcm2290_get_function_mux(__maybe_unused unsigned int pin, unsigned int selector)
static int qcm2290_get_function_mux(__maybe_unused unsigned int pin, unsigned int selector)
{
return msm_pinctrl_functions[selector].val;
}

View File

@@ -92,7 +92,10 @@ static int msm_pinmux_set(struct udevice *dev, unsigned int pin_selector,
unsigned int func_selector)
{
struct msm_pinctrl_priv *priv = dev_get_priv(dev);
u32 func = priv->data->get_function_mux(pin_selector, func_selector);
int func = priv->data->get_function_mux(pin_selector, func_selector);
if (func < 0)
return func;
/* Always NOP for special pins, assume they're in the correct state */
if (qcom_is_special_pin(&priv->data->pin_data, pin_selector))

View File

@@ -18,8 +18,7 @@ struct msm_pinctrl_data {
int functions_count;
const char *(*get_function_name)(struct udevice *dev,
unsigned int selector);
unsigned int (*get_function_mux)(unsigned int pin,
unsigned int selector);
int (*get_function_mux)(unsigned int pin, unsigned int selector);
const char *(*get_pin_name)(struct udevice *dev,
unsigned int selector);
};

View File

@@ -93,8 +93,8 @@ static const char *qcs404_get_pin_name(struct udevice *dev,
}
}
static unsigned int qcs404_get_function_mux(__maybe_unused unsigned int pin,
unsigned int selector)
static int qcs404_get_function_mux(__maybe_unused unsigned int pin,
unsigned int selector)
{
return msm_pinctrl_functions[selector].val;
}

View File

@@ -0,0 +1,106 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Qualcomm sc7280 pinctrl
*
* (C) Copyright 2024 Linaro Ltd.
*
*/
#include <dm.h>
#include "pinctrl-qcom.h"
#define WEST 0x00000000
#define SOUTH 0x00400000
#define NORTH 0x00800000
#define MAX_PIN_NAME_LEN 32
static char pin_name[MAX_PIN_NAME_LEN] __section(".data");
static const struct pinctrl_function msm_pinctrl_functions[] = {
{ "qup05", 1 },
{ "gpio", 0 },
{ "pcie1_clkreqn", 3},
};
#define SDC_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, offset) \
{ \
.name = pg_name, \
.ctl_reg = offset, \
.io_reg = offset + 0x4, \
.pull_bit = 3, \
.drv_bit = 0, \
.oe_bit = -1, \
.in_bit = -1, \
.out_bit = 0, \
}
static const struct msm_special_pin_data sc7280_special_pins_data[] = {
[0] = UFS_RESET("ufs_reset", SOUTH + 0xbe000),
[1] = SDC_PINGROUP("sdc1_rclk", 0xb3004, 0, 6),
[2] = SDC_PINGROUP("sdc1_clk", 0xb3000, 13, 6),
[3] = SDC_PINGROUP("sdc1_cmd", 0xb3000, 11, 3),
[4] = SDC_PINGROUP("sdc1_data", 0xb3000, 9, 0),
[5] = SDC_PINGROUP("sdc2_clk", 0xb4000, 14, 6),
[6] = SDC_PINGROUP("sdc2_cmd", 0xb4000, 11, 3),
[7] = SDC_PINGROUP("sdc2_data", 0xb4000, 9, 0),
};
static const char *sc7280_get_function_name(struct udevice *dev, unsigned int selector)
{
return msm_pinctrl_functions[selector].name;
}
static const char *sc7280_get_pin_name(struct udevice *dev, unsigned int selector)
{
if (selector >= 175 && selector <= 182)
snprintf(pin_name, MAX_PIN_NAME_LEN,
sc7280_special_pins_data[selector - 175].name);
else
snprintf(pin_name, MAX_PIN_NAME_LEN, "gpio%u", selector);
return pin_name;
}
static int sc7280_get_function_mux(__maybe_unused unsigned int pin, unsigned int selector)
{
return msm_pinctrl_functions[selector].val;
}
static struct msm_pinctrl_data sc7280_data = {
.pin_data = {
.pin_count = 183,
.special_pins_start = 175,
.special_pins_data = sc7280_special_pins_data,
},
.functions_count = ARRAY_SIZE(msm_pinctrl_functions),
.get_function_name = sc7280_get_function_name,
.get_function_mux = sc7280_get_function_mux,
.get_pin_name = sc7280_get_pin_name,
};
static const struct udevice_id msm_pinctrl_ids[] = {
{
.compatible = "qcom,sc7280-pinctrl",
.data = (ulong)&sc7280_data
},
{ /* Sentinel */ } };
U_BOOT_DRIVER(pinctrl_sc7280) = {
.name = "pinctrl_sc7280",
.id = UCLASS_NOP,
.of_match = msm_pinctrl_ids,
.ops = &msm_pinctrl_ops,
.bind = msm_pinctrl_bind,
};

View File

@@ -80,8 +80,8 @@ static const char *sdm845_get_pin_name(struct udevice *dev,
return pin_name;
}
static unsigned int sdm845_get_function_mux(__maybe_unused unsigned int pin,
unsigned int selector)
static int sdm845_get_function_mux(__maybe_unused unsigned int pin,
unsigned int selector)
{
return msm_pinctrl_functions[selector].val;
}

View File

@@ -167,7 +167,7 @@ static const char *sm6115_get_pin_name(struct udevice *dev, unsigned int selecto
return pin_name;
}
static unsigned int sm6115_get_function_mux(__maybe_unused unsigned int pin, unsigned int selector)
static int sm6115_get_function_mux(__maybe_unused unsigned int pin, unsigned int selector)
{
return msm_pinctrl_functions[selector].val;
}

View File

@@ -123,8 +123,8 @@ static const char *sm8150_get_pin_name(struct udevice *dev,
return pin_name;
}
static unsigned int sm8150_get_function_mux(__maybe_unused unsigned int pin,
unsigned int selector)
static int sm8150_get_function_mux(__maybe_unused unsigned int pin,
unsigned int selector)
{
return msm_pinctrl_functions[selector].val;
}

View File

@@ -99,7 +99,7 @@ static const char *sm8250_get_pin_name(struct udevice *dev, unsigned int selecto
return pin_name;
}
static unsigned int sm8250_get_function_mux(__maybe_unused unsigned int pin, unsigned int selector)
static int sm8250_get_function_mux(__maybe_unused unsigned int pin, unsigned int selector)
{
return msm_pinctrl_functions[selector].val;
}

View File

@@ -68,8 +68,8 @@ static const char *sm8550_get_pin_name(struct udevice *dev,
return pin_name;
}
static unsigned int sm8550_get_function_mux(__maybe_unused unsigned int pin,
unsigned int selector)
static int sm8550_get_function_mux(__maybe_unused unsigned int pin,
unsigned int selector)
{
return msm_pinctrl_functions[selector].val;
}

View File

@@ -69,8 +69,8 @@ static const char *sm8650_get_pin_name(struct udevice *dev,
return pin_name;
}
static unsigned int sm8650_get_function_mux(__maybe_unused unsigned int pin,
unsigned int selector)
static int sm8650_get_function_mux(__maybe_unused unsigned int pin,
unsigned int selector)
{
return msm_pinctrl_functions[selector].val;
}

View File

@@ -72,8 +72,8 @@ static const char *x1e80100_get_pin_name(struct udevice *dev,
return pin_name;
}
static unsigned int x1e80100_get_function_mux(__maybe_unused unsigned int pin,
unsigned int selector)
static int x1e80100_get_function_mux(__maybe_unused unsigned int pin,
unsigned int selector)
{
return msm_pinctrl_functions[selector].val;
}

View File

@@ -44,6 +44,11 @@ static int msm_rng_read(struct udevice *dev, void *data, size_t len)
u32 *retdata = data;
size_t maxsize;
u32 val;
int ret;
ret = clk_enable(&priv->clk);
if (ret < 0)
return ret;
/* calculate max size bytes to transfer back to caller */
maxsize = min_t(size_t, MAX_HW_FIFO_SIZE, len);
@@ -66,6 +71,8 @@ static int msm_rng_read(struct udevice *dev, void *data, size_t len)
break;
} while (currsize < maxsize);
clk_disable(&priv->clk);
return 0;
}
@@ -76,7 +83,7 @@ static int msm_rng_enable(struct msm_rng_priv *priv, int enable)
if (enable) {
/* Enable PRNG only if it is not already enabled */
val = readl_relaxed(priv->base + PRNG_CONFIG);
if (val & PRNG_CONFIG_HW_ENABLE) {
if (!(val & PRNG_CONFIG_HW_ENABLE)) {
val = readl_relaxed(priv->base + PRNG_LFSR_CFG);
val &= ~PRNG_LFSR_CFG_MASK;
val |= PRNG_LFSR_CFG_CLOCKS;
@@ -118,7 +125,9 @@ static int msm_rng_probe(struct udevice *dev)
if (ret < 0)
return ret;
return msm_rng_enable(priv, 1);
ret = msm_rng_enable(priv, 1);
clk_disable(&priv->clk);
return ret;
}
static int msm_rng_remove(struct udevice *dev)

View File

@@ -242,7 +242,6 @@ config SYSRESET_RAA215300
config SYSRESET_QCOM_PSHOLD
bool "Support sysreset for Qualcomm SoCs via PSHOLD"
depends on ARCH_IPQ40XX
help
Add support for the system reboot on Qualcomm SoCs via PSHOLD.