diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 1a6b77cb2b5..39749ea9e8c 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1143,6 +1143,7 @@ config ARCH_SNAPDRAGON select SYSRESET select SYSRESET_PSCI select ANDROID_BOOT_IMAGE_IGNORE_BLOB_ADDR + select MMU_PGPROT imply OF_UPSTREAM imply CMD_DM imply DM_USB_GADGET diff --git a/arch/arm/mach-snapdragon/capsule_update.c b/arch/arm/mach-snapdragon/capsule_update.c index 3699d91852d..586682434b7 100644 --- a/arch/arm/mach-snapdragon/capsule_update.c +++ b/arch/arm/mach-snapdragon/capsule_update.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -80,6 +81,23 @@ static enum ab_slot get_part_slot(const char *partname) return SLOT_NONE; } +/* Shamelessly copied from lib/efi_loader/efi_device_path.c @ 33 */ +/* + * Determine if an MMC device is an SD card. + * + * @desc block device descriptor + * Return: true if the device is an SD card + */ +static bool is_sd(struct blk_desc *desc) +{ + struct mmc *mmc = find_mmc_device(desc->devnum); + + if (!mmc) + return false; + + return IS_SD(mmc) != 0U; +} + /* * Determine which partition U-Boot is flashed to based on the boot source (ABL/XBL), * the slot status, and prioritizing the uefi partition over xbl if found. @@ -109,19 +127,21 @@ static int find_target_partition(int *devnum, enum uclass_id *uclass, if (device_get_uclass_id(dev) != UCLASS_BLK) continue; + desc = dev_get_uclass_plat(dev); + /* If we have a UFS then don't look at any other block devices */ if (have_ufs) { if (device_get_uclass_id(dev->parent->parent) != UCLASS_UFS) continue; + } /* - * If we don't have UFS, then U-Boot must be on the eMMC which is always the first - * MMC device. + * If we don't have UFS, then U-Boot must be on the eMMC */ - } else if (dev->parent->seq_ > 0) { + else if (IS_ENABLED(CONFIG_MMC) && is_sd(desc)) { + log_debug("skipped SD-Card (devnum %d)\n", desc->devnum); continue; } - desc = dev_get_uclass_plat(dev); if (!desc || desc->part_type == PART_TYPE_UNKNOWN) continue; for (partnum = 1;; partnum++) { diff --git a/arch/arm/mach-snapdragon/of_fixup.c b/arch/arm/mach-snapdragon/of_fixup.c index eec2c0c757e..5b6076ea8e5 100644 --- a/arch/arm/mach-snapdragon/of_fixup.c +++ b/arch/arm/mach-snapdragon/of_fixup.c @@ -32,7 +32,7 @@ * DT here. This improves compatibility with upstream DT and simplifies the * porting process for new devices. */ -static int fixup_qcom_dwc3(struct device_node *root, struct device_node *glue_np) +static int fixup_qcom_dwc3(struct device_node *root, struct device_node *glue_np, bool flat) { struct device_node *dwc3; int ret, len, hsphy_idx = 1; @@ -41,6 +41,19 @@ static int fixup_qcom_dwc3(struct device_node *root, struct device_node *glue_np debug("Fixing up %s\n", glue_np->name); + /* New DT flattens the glue and controller into a single node. */ + if (flat) { + dwc3 = glue_np; + debug("%s uses flat DT\n", glue_np->name); + } else { + /* Find the DWC3 node itself */ + dwc3 = of_find_compatible_node(glue_np, NULL, "snps,dwc3"); + if (!dwc3) { + log_err("Failed to find dwc3 node\n"); + return -ENOENT; + } + } + /* Tell the glue driver to configure the wrapper for high-speed only operation */ ret = of_write_prop(glue_np, "qcom,select-utmi-as-pipe-clk", 0, NULL); if (ret) { @@ -48,13 +61,6 @@ static int fixup_qcom_dwc3(struct device_node *root, struct device_node *glue_np return ret; } - /* Find the DWC3 node itself */ - dwc3 = of_find_compatible_node(glue_np, NULL, "snps,dwc3"); - if (!dwc3) { - log_err("Failed to find dwc3 node\n"); - return -ENOENT; - } - phandles = of_get_property(dwc3, "phys", &len); len /= sizeof(*phandles); if (len == 1) { @@ -104,13 +110,25 @@ static int fixup_qcom_dwc3(struct device_node *root, struct device_node *glue_np static void fixup_usb_nodes(struct device_node *root) { - struct device_node *glue_np = root; + struct device_node *glue_np = root, *tmp; int ret; + bool flat; + + while (true) { + flat = false; + /* First check for the old DT format with glue node then the new flattened format */ + tmp = of_find_compatible_node(glue_np, NULL, "qcom,dwc3"); + if (!tmp) { + tmp = of_find_compatible_node(glue_np, NULL, "qcom,snps-dwc3"); + flat = !!tmp; + } + if (!tmp) + break; + glue_np = tmp; - while ((glue_np = of_find_compatible_node(glue_np, NULL, "qcom,dwc3"))) { if (!of_device_is_available(glue_np)) continue; - ret = fixup_qcom_dwc3(root, glue_np); + ret = fixup_qcom_dwc3(root, glue_np, flat); if (ret) log_warning("Failed to fixup node %s: %d\n", glue_np->name, ret); } diff --git a/board/qualcomm/google-pixel.config b/board/qualcomm/google-pixel.config new file mode 100644 index 00000000000..999d4e45268 --- /dev/null +++ b/board/qualcomm/google-pixel.config @@ -0,0 +1,5 @@ +# Enables chainloading of U-Boot on Google Pixel phones using +# newer bootloaders (Android Q/R) +# Use for following devices: Pixel 3 (blueline), Pixel 3 XL (crosshatch), +# Pixel 5 (redfin)... +CONFIG_TEXT_BASE=0x80080000 diff --git a/configs/qcm6490_defconfig b/configs/qcm6490_defconfig index 54eb5dedaec..618098c8860 100644 --- a/configs/qcm6490_defconfig +++ b/configs/qcm6490_defconfig @@ -13,3 +13,5 @@ CONFIG_TEXT_BASE=0x9fc00000 CONFIG_REMAKE_ELF=y CONFIG_DEFAULT_DEVICE_TREE="qcom/qcs6490-rb3gen2" + +CONFIG_FASTBOOT_BUF_ADDR=0xd8800000 diff --git a/configs/qcom_defconfig b/configs/qcom_defconfig index a210f4dc5e6..fe5880de1fd 100644 --- a/configs/qcom_defconfig +++ b/configs/qcom_defconfig @@ -113,23 +113,7 @@ CONFIG_PHY_QCOM_USB_SNPS_FEMTO_V2=y CONFIG_PHY_QCOM_SNPS_EUSB2=y CONFIG_PINCTRL=y CONFIG_PINCONF=y -CONFIG_PINCTRL_QCOM_APQ8016=y -CONFIG_PINCTRL_QCOM_APQ8096=y -CONFIG_PINCTRL_QCOM_QCM2290=y -CONFIG_PINCTRL_QCOM_QCS404=y -CONFIG_PINCTRL_QCOM_SA8775P=y -CONFIG_PINCTRL_QCOM_SC7280=y -CONFIG_PINCTRL_QCOM_SDM670=y -CONFIG_PINCTRL_QCOM_SDM660=y -CONFIG_PINCTRL_QCOM_SDM845=y -CONFIG_PINCTRL_QCOM_SM6115=y -CONFIG_PINCTRL_QCOM_SM6350=y -CONFIG_PINCTRL_QCOM_SM7150=y -CONFIG_PINCTRL_QCOM_SM8150=y -CONFIG_PINCTRL_QCOM_SM8250=y -CONFIG_PINCTRL_QCOM_SM8550=y -CONFIG_PINCTRL_QCOM_SM8650=y -CONFIG_PINCTRL_QCOM_X1E80100=y +CONFIG_PINCTRL_QCOM_GENERIC=y CONFIG_DM_PMIC=y CONFIG_PMIC_QCOM=y CONFIG_DM_REGULATOR=y diff --git a/configs/qcom_qcs615_defconfig b/configs/qcom_qcs615_defconfig index 2468267b955..27666a8129d 100644 --- a/configs/qcom_qcs615_defconfig +++ b/configs/qcom_qcs615_defconfig @@ -12,7 +12,7 @@ CONFIG_DEBUG_UART=y CONFIG_DEBUG_UART_ANNOUNCE=y CONFIG_DEBUG_UART_BASE=0x880000 CONFIG_DEBUG_UART_MSM_GENI=y -CONFIG_DEBUG_UART_CLOCK=14745600 +CONFIG_DEBUG_UART_CLOCK=7372800 CONFIG_DEFAULT_DEVICE_TREE="qcom/qcs615-ride" @@ -20,3 +20,5 @@ CONFIG_REMAKE_ELF=y # Address where U-Boot will be loaded CONFIG_TEXT_BASE=0x9fc00000 + +CONFIG_FASTBOOT_BUF_ADDR=0xa1600000 diff --git a/configs/qcs9100_defconfig b/configs/qcom_qcs9100_defconfig similarity index 93% rename from configs/qcs9100_defconfig rename to configs/qcom_qcs9100_defconfig index 216dfa3211e..371448b8b1b 100644 --- a/configs/qcs9100_defconfig +++ b/configs/qcom_qcs9100_defconfig @@ -8,6 +8,7 @@ # Address where U-Boot will be loaded CONFIG_TEXT_BASE=0xaf000000 CONFIG_REMAKE_ELF=y +CONFIG_FASTBOOT_BUF_ADDR=0xdb300000 CONFIG_DEFAULT_DEVICE_TREE="qcom/qcs9100-ride-r3" CONFIG_ENV_IS_IN_SCSI=y CONFIG_SCSI_ENV_PART_UUID="71cb9cd0-acf1-b6cb-ad91-be9572fe11a9" diff --git a/doc/board/qualcomm/board.rst b/doc/board/qualcomm/board.rst index 642c5095261..e5dbc9816b9 100644 --- a/doc/board/qualcomm/board.rst +++ b/doc/board/qualcomm/board.rst @@ -38,6 +38,25 @@ with appended dtb, so let's mimic linux to satisfy stock bootloader. Boards ------ +Pixel 3 (blueline) and Pixel 3 XL (crosshatch) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +blueline refers to the Google Pixel 3, and crosshatch to the Pixel 3 XL, both +powered by the Qualcomm SDM845 SoC. + +These devices use the common qcom_defconfig with the google-pixel.config +fragment for configuration. + +Use the following commands:: + + make CROSS_COMPILE=aarch64-linux-gnu- O=.output qcom_defconfig google-pixel.config qcom-phone.config + +The DTB is called: + + - "sdm845-google-blueline.dtb" (Pixel 3) + - "sdm845-google-crosshatch.dtb" (Pixel 3 XL) + +More information can be found on the `Google Pixel 3 page`_. + starqlte ^^^^^^^^ @@ -131,5 +150,6 @@ Other devices with boot image version 2 can be built like this example:: fastboot flash boot boot.img fastboot erase dtbo +.. _Google Pixel 3 page: https://en.wikipedia.org/wiki/Pixel_3 .. _Samsung S9 page: https://en.wikipedia.org/wiki/Samsung_Galaxy_S9 .. _DragonBoard 845c page: https://www.96boards.org/product/rb3-platform/ diff --git a/drivers/clk/qcom/clock-qcm2290.c b/drivers/clk/qcom/clock-qcm2290.c index fad104fb91a..5a599085b50 100644 --- a/drivers/clk/qcom/clock-qcm2290.c +++ b/drivers/clk/qcom/clock-qcm2290.c @@ -17,6 +17,8 @@ #define QUPV3_WRAP0_S4_CMD_RCGR 0x1f608 #define SDCC2_APPS_CLK_CMD_RCGR 0x1e00c +#define SDCC1_APPS_CLK_CMD_RCGR 0x38028 + static const struct freq_tbl ftbl_gcc_qupv3_wrap0_s0_clk_src[] = { F(7372800, CFG_CLK_SRC_GPLL0_AUX2, 1, 384, 15625), @@ -55,6 +57,25 @@ static const struct pll_vote_clk gpll7_clk = { .vote_bit = BIT(7), }; +static const struct freq_tbl ftbl_gcc_sdcc1_apps_clk_src[] = { + F(144000, CFG_CLK_SRC_CXO, 16, 3, 25), + F(400000, CFG_CLK_SRC_CXO, 12, 1, 4), + F(20000000, CFG_CLK_SRC_GPLL0_AUX2, 5, 1, 3), + F(25000000, CFG_CLK_SRC_GPLL0_AUX2, 6, 1, 2), + F(50000000, CFG_CLK_SRC_GPLL0_AUX2, 6, 0, 0), + F(100000000, CFG_CLK_SRC_GPLL0_AUX2, 3, 0, 0), + F(192000000, CFG_CLK_SRC_GPLL6, 2, 0, 0), + F(384000000, CFG_CLK_SRC_GPLL6, 1, 0, 0), + {} +}; + +static const struct pll_vote_clk gpll6_clk = { + .status = 0x6000, + .status_bit = BIT(31), + .ena_vote = 0x79000, + .vote_bit = BIT(7), +}; + static const struct gate_clk qcm2290_clks[] = { GATE_CLK(GCC_AHB2PHY_USB_CLK, 0x1d008, 0x00000001), GATE_CLK(GCC_CFG_NOC_USB3_PRIM_AXI_CLK, 0x1a084, 0x00000001), @@ -109,8 +130,12 @@ static ulong qcm2290_set_rate(struct clk *clk, ulong rate) 8); return freq->freq; case GCC_SDCC1_APPS_CLK: - /* The firmware turns this on for us and always sets it to this rate */ - return 384000000; + clk_enable_gpll0(priv->base, &gpll6_clk); + freq = qcom_find_freq(ftbl_gcc_sdcc1_apps_clk_src, rate); + clk_rcg_set_rate_mnd(priv->base, SDCC1_APPS_CLK_CMD_RCGR, + freq->pre_div, freq->m, freq->n, freq->src, + 8); + return freq->freq; default: return 0; } diff --git a/drivers/clk/qcom/clock-sa8775p.c b/drivers/clk/qcom/clock-sa8775p.c index 527cecf5c82..4957abf6f58 100644 --- a/drivers/clk/qcom/clock-sa8775p.c +++ b/drivers/clk/qcom/clock-sa8775p.c @@ -15,8 +15,34 @@ #include #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 0x1b040 +#define USB30_PRIM_MASTER_CLK_CMD_RCGR 0x1b028 +#define USB3_PRIM_PHY_AUX_CMD_RCGR 0x1b06c + +#define GCC_QUPV3_WRAP0_S0_CLK_ENA_BIT BIT(10) +#define GCC_QUPV3_WRAP0_S1_CLK_ENA_BIT BIT(11) +#define GCC_QUPV3_WRAP0_S2_CLK_ENA_BIT BIT(12) +#define GCC_QUPV3_WRAP0_S3_CLK_ENA_BIT BIT(13) +#define GCC_QUPV3_WRAP0_S4_CLK_ENA_BIT BIT(14) +#define GCC_QUPV3_WRAP0_S5_CLK_ENA_BIT BIT(15) + +#define GCC_QUPV3_WRAP1_S0_CLK_ENA_BIT BIT(22) +#define GCC_QUPV3_WRAP1_S1_CLK_ENA_BIT BIT(23) +#define GCC_QUPV3_WRAP1_S2_CLK_ENA_BIT BIT(24) +#define GCC_QUPV3_WRAP1_S3_CLK_ENA_BIT BIT(25) +#define GCC_QUPV3_WRAP1_S4_CLK_ENA_BIT BIT(26) +#define GCC_QUPV3_WRAP1_S5_CLK_ENA_BIT BIT(27) +#define GCC_QUPV3_WRAP1_S6_CLK_ENA_BIT BIT(27) + +#define GCC_QUPV3_WRAP2_S0_CLK_ENA_BIT BIT(4) +#define GCC_QUPV3_WRAP2_S1_CLK_ENA_BIT BIT(5) +#define GCC_QUPV3_WRAP2_S2_CLK_ENA_BIT BIT(6) +#define GCC_QUPV3_WRAP2_S3_CLK_ENA_BIT BIT(7) +#define GCC_QUPV3_WRAP2_S4_CLK_ENA_BIT BIT(8) +#define GCC_QUPV3_WRAP2_S5_CLK_ENA_BIT BIT(9) +#define GCC_QUPV3_WRAP2_S6_CLK_ENA_BIT BIT(29) + +#define GCC_QUPV3_WRAP3_S0_CLK_ENA_BIT BIT(25) static ulong sa8775p_set_rate(struct clk *clk, ulong rate) { @@ -34,8 +60,8 @@ static ulong sa8775p_set_rate(struct clk *clk, ulong rate) case GCC_USB30_PRIM_MASTER_CLK: WARN(rate != 200000000, "Unexpected rate for USB30_PRIM_MASTER_CLK: %lu\n", 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); + 5, 0, 0, CFG_CLK_SRC_GPLL0, 8); + clk_rcg_set_rate(priv->base, USB3_PRIM_PHY_AUX_CMD_RCGR, 0, 0); return rate; default: return 0; @@ -50,6 +76,36 @@ static const struct gate_clk sa8775p_clks[] = { GATE_CLK(GCC_USB30_PRIM_MOCK_UTMI_CLK, 0x1b024, 1), GATE_CLK(GCC_USB3_PRIM_PHY_AUX_CLK, 0x1b05c, 1), GATE_CLK(GCC_USB3_PRIM_PHY_COM_AUX_CLK, 0x1b060, 1), + GATE_CLK(GCC_USB3_PRIM_PHY_PIPE_CLK, 0x1b064, 1), + + /* QUP Wrapper 0 clocks */ + GATE_CLK(GCC_QUPV3_WRAP0_S0_CLK, 0x4b008, GCC_QUPV3_WRAP0_S0_CLK_ENA_BIT), + GATE_CLK(GCC_QUPV3_WRAP0_S1_CLK, 0x4b008, GCC_QUPV3_WRAP0_S1_CLK_ENA_BIT), + GATE_CLK(GCC_QUPV3_WRAP0_S2_CLK, 0x4b008, GCC_QUPV3_WRAP0_S2_CLK_ENA_BIT), + GATE_CLK(GCC_QUPV3_WRAP0_S3_CLK, 0x4b008, GCC_QUPV3_WRAP0_S3_CLK_ENA_BIT), + GATE_CLK(GCC_QUPV3_WRAP0_S4_CLK, 0x4b008, GCC_QUPV3_WRAP0_S4_CLK_ENA_BIT), + GATE_CLK(GCC_QUPV3_WRAP0_S5_CLK, 0x4b008, GCC_QUPV3_WRAP0_S5_CLK_ENA_BIT), + + /* QUP Wrapper 1 clocks (includes uart10) */ + GATE_CLK(GCC_QUPV3_WRAP1_S0_CLK, 0x4b008, GCC_QUPV3_WRAP1_S0_CLK_ENA_BIT), + GATE_CLK(GCC_QUPV3_WRAP1_S1_CLK, 0x4b008, GCC_QUPV3_WRAP1_S1_CLK_ENA_BIT), + GATE_CLK(GCC_QUPV3_WRAP1_S2_CLK, 0x4b008, GCC_QUPV3_WRAP1_S2_CLK_ENA_BIT), + GATE_CLK(GCC_QUPV3_WRAP1_S3_CLK, 0x4b008, GCC_QUPV3_WRAP1_S3_CLK_ENA_BIT), /* uart10 */ + GATE_CLK(GCC_QUPV3_WRAP1_S4_CLK, 0x4b008, GCC_QUPV3_WRAP1_S4_CLK_ENA_BIT), + GATE_CLK(GCC_QUPV3_WRAP1_S5_CLK, 0x4b008, GCC_QUPV3_WRAP1_S5_CLK_ENA_BIT), + GATE_CLK(GCC_QUPV3_WRAP1_S6_CLK, 0x4b018, GCC_QUPV3_WRAP1_S6_CLK_ENA_BIT), + + /* QUP Wrapper 2 clocks */ + GATE_CLK(GCC_QUPV3_WRAP2_S0_CLK, 0x4b010, GCC_QUPV3_WRAP2_S0_CLK_ENA_BIT), + GATE_CLK(GCC_QUPV3_WRAP2_S1_CLK, 0x4b010, GCC_QUPV3_WRAP2_S1_CLK_ENA_BIT), + GATE_CLK(GCC_QUPV3_WRAP2_S2_CLK, 0x4b010, GCC_QUPV3_WRAP2_S2_CLK_ENA_BIT), + GATE_CLK(GCC_QUPV3_WRAP2_S3_CLK, 0x4b010, GCC_QUPV3_WRAP2_S3_CLK_ENA_BIT), + GATE_CLK(GCC_QUPV3_WRAP2_S4_CLK, 0x4b010, GCC_QUPV3_WRAP2_S4_CLK_ENA_BIT), + GATE_CLK(GCC_QUPV3_WRAP2_S5_CLK, 0x4b010, GCC_QUPV3_WRAP2_S5_CLK_ENA_BIT), + GATE_CLK(GCC_QUPV3_WRAP2_S6_CLK, 0x4b018, GCC_QUPV3_WRAP2_S6_CLK_ENA_BIT), + + /* QUP Wrapper 3 clocks */ + GATE_CLK(GCC_QUPV3_WRAP3_S0_CLK, 0x4b000, GCC_QUPV3_WRAP3_S0_CLK_ENA_BIT), }; static int sa8775p_enable(struct clk *clk) @@ -103,6 +159,24 @@ static const struct qcom_reset_map sa8775p_gcc_resets[] = { [GCC_TSCSS_BCR] = { 0x21000 }, [GCC_UFS_CARD_BCR] = { 0x81000 }, [GCC_UFS_PHY_BCR] = { 0x83000 }, + [GCC_USB20_PRIM_BCR] = {0x1c000}, + [GCC_USB2_PHY_PRIM_BCR] = {0x5c028}, + [GCC_USB2_PHY_SEC_BCR] = {0x5c02c}, + [GCC_USB30_PRIM_BCR] = {0x1b000}, + [GCC_USB30_SEC_BCR] = {0x2f000}, + [GCC_USB3_DP_PHY_PRIM_BCR] = {0x5c008}, + [GCC_USB3_DP_PHY_SEC_BCR] = {0x5c014}, + [GCC_USB3_PHY_PRIM_BCR] = {0x5c000}, + [GCC_USB3_PHY_SEC_BCR] = {0x5c00c}, + [GCC_USB3_PHY_TERT_BCR] = {0x5c030}, + [GCC_USB3_UNIPHY_MP0_BCR] = {0x5c018}, + [GCC_USB3_UNIPHY_MP1_BCR] = {0x5c01c}, + [GCC_USB3PHY_PHY_PRIM_BCR] = {0x5c004}, + [GCC_USB3PHY_PHY_SEC_BCR] = {0x5c010}, + [GCC_USB3UNIPHY_PHY_MP0_BCR] = {0x5c020}, + [GCC_USB3UNIPHY_PHY_MP1_BCR] = {0x5c024}, + [GCC_USB_PHY_CFG_AHB2PHY_BCR] = {0x76000}, + [GCC_VIDEO_BCR] = {0x34000} }; static const struct qcom_power_map sa8775p_gdscs[] = { diff --git a/drivers/clk/qcom/clock-sc7280.c b/drivers/clk/qcom/clock-sc7280.c index 55a233df394..7b6ed826023 100644 --- a/drivers/clk/qcom/clock-sc7280.c +++ b/drivers/clk/qcom/clock-sc7280.c @@ -63,6 +63,11 @@ static ulong sc7280_set_rate(struct clk *clk, ulong rate) debug("%s: %s, requested rate=%ld\n", __func__, priv->data->clks[clk->id].name, rate); switch (clk->id) { + case GCC_QUPV3_WRAP0_S2_CLK: /* UART2 */ + freq = qcom_find_freq(ftbl_gcc_qupv3_wrap0_s2_clk_src, rate); + clk_rcg_set_rate_mnd(priv->base, 0x17270, + freq->pre_div, freq->m, freq->n, freq->src, 16); + return freq->freq; case GCC_QUPV3_WRAP0_S5_CLK: /* UART5 */ freq = qcom_find_freq(ftbl_gcc_qupv3_wrap0_s2_clk_src, rate); clk_rcg_set_rate_mnd(priv->base, 0x17600, @@ -132,9 +137,13 @@ static const struct gate_clk sc7280_clks[] = { 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_S2_CLK, 0x52008, BIT(12)), GATE_CLK(GCC_QUPV3_WRAP0_S3_CLK, 0x52008, BIT(13)), + GATE_CLK(GCC_QUPV3_WRAP0_S4_CLK, 0x52008, BIT(14)), GATE_CLK(GCC_QUPV3_WRAP0_S5_CLK, 0x52008, BIT(15)), + GATE_CLK(GCC_QUPV3_WRAP0_S6_CLK, 0x52008, BIT(16)), GATE_CLK(GCC_QUPV3_WRAP0_S7_CLK, 0x52008, BIT(17)), + GATE_CLK(GCC_QUPV3_WRAP1_S1_CLK, 0x52008, BIT(23)), 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)), @@ -190,6 +199,9 @@ static int sc7280_enable(struct clk *clk) case GCC_QUPV3_WRAP0_S3_CLK: clk_rcg_set_rate_mnd(priv->base, 0x173a0, 1, 0, 0, CFG_CLK_SRC_CXO, 16); break; + case GCC_QUPV3_WRAP1_S1_CLK: + clk_rcg_set_rate_mnd(priv->base, 0x18140, 1, 0, 0, CFG_CLK_SRC_CXO, 16); + break; } return qcom_gate_clk_en(priv, clk->id); diff --git a/drivers/i2c/geni_i2c.c b/drivers/i2c/geni_i2c.c index d29e00fdf41..fbe5ab0ad0c 100644 --- a/drivers/i2c/geni_i2c.c +++ b/drivers/i2c/geni_i2c.c @@ -494,7 +494,9 @@ static int geni_i2c_probe(struct udevice *dev) return ret; } - geni_i2c_enable_clocks(dev, geni); + ret = geni_i2c_enable_clocks(dev, geni); + if (ret) + return ret; proto = readl(geni->base + GENI_FW_REVISION_RO); proto &= FW_REV_PROTOCOL_MSK; diff --git a/drivers/mmc/msm_sdhci.c b/drivers/mmc/msm_sdhci.c index ac77fb06bf7..38dc36a2194 100644 --- a/drivers/mmc/msm_sdhci.c +++ b/drivers/mmc/msm_sdhci.c @@ -36,6 +36,11 @@ #define CORE_VENDOR_SPEC_POR_VAL 0xa9c +#define CORE_DLL_PDN BIT(29) +#define CORE_DLL_RST BIT(30) + +#define MHZ(X) ((X) * 1000000UL) + struct msm_sdhc_plat { struct mmc_config cfg; struct mmc mmc; @@ -51,6 +56,7 @@ struct msm_sdhc { struct msm_sdhc_variant_info { bool mci_removed; + u32 core_dll_config; u32 core_vendor_spec; u32 core_vendor_spec_capabilities0; }; @@ -114,6 +120,9 @@ static int msm_sdc_clk_init(struct udevice *dev) return -EINVAL; } + /* This is the base clock sdhci core will use to configure the SDCLK */ + prv->host.max_clk = clk_rate; + writel_relaxed(CORE_VENDOR_SPEC_POR_VAL, prv->host.ioaddr + var_info->core_vendor_spec); @@ -146,6 +155,34 @@ static int msm_sdc_mci_init(struct msm_sdhc *prv) return 0; } +static int msm_sdhci_config_dll(struct sdhci_host *host, u32 clock, bool enable) +{ + struct udevice *dev = mmc_to_dev(host->mmc); + const struct msm_sdhc_variant_info *var_info = (void *)dev_get_driver_data(dev); + u32 config; + + if (enable && clock < MHZ(100)) { + /* + * DLL is not required for clock <= 100MHz + * Thus, make sure DLL is disabled when not required + */ + config = readl(host->ioaddr + var_info->core_dll_config); + config |= CORE_DLL_RST; + writel(config, host->ioaddr + var_info->core_dll_config); + + config = readl(host->ioaddr + var_info->core_dll_config); + config |= CORE_DLL_PDN; + writel(config, host->ioaddr + var_info->core_dll_config); + } + + return 0; +} + +struct sdhci_ops msm_sdhci_ops = { + .config_dll = &msm_sdhci_config_dll, + .set_control_reg = &sdhci_set_control_reg, +}; + static int msm_sdc_probe(struct udevice *dev) { struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); @@ -220,6 +257,7 @@ static int msm_sdc_probe(struct udevice *dev) host->mmc = &plat->mmc; host->mmc->dev = dev; + host->ops = &msm_sdhci_ops; ret = sdhci_setup_cfg(&plat->cfg, host, 0, 0); if (ret) return ret; @@ -285,6 +323,7 @@ static int msm_sdc_bind(struct udevice *dev) static const struct msm_sdhc_variant_info msm_sdhc_mci_var = { .mci_removed = false, + .core_dll_config = 0x100, .core_vendor_spec = 0x10c, .core_vendor_spec_capabilities0 = 0x11c, }; @@ -292,6 +331,7 @@ static const struct msm_sdhc_variant_info msm_sdhc_mci_var = { static const struct msm_sdhc_variant_info msm_sdhc_v5_var = { .mci_removed = true, + .core_dll_config = 0x200, .core_vendor_spec = 0x20c, .core_vendor_spec_capabilities0 = 0x21c, }; diff --git a/drivers/phy/qcom/phy-qcom-qusb2.c b/drivers/phy/qcom/phy-qcom-qusb2.c index d98f6108e69..9e821365c15 100644 --- a/drivers/phy/qcom/phy-qcom-qusb2.c +++ b/drivers/phy/qcom/phy-qcom-qusb2.c @@ -224,6 +224,18 @@ static const unsigned int qusb2_v2_regs_layout[] = { [QUSB2PHY_INTR_CTRL] = 0x230, }; +static const struct qusb2_phy_cfg msm8996_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 = 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 sm6115_phy_cfg = { .tbl = sm6115_init_tbl, .tbl_num = ARRAY_SIZE(sm6115_init_tbl), @@ -450,6 +462,8 @@ static struct phy_ops qusb2phy_ops = { }; static const struct udevice_id qusb2phy_ids[] = { + { .compatible = "qcom,msm8996-qusb2-phy", + .data = (ulong)&msm8996_phy_cfg }, { .compatible = "qcom,qusb2-phy" }, { .compatible = "qcom,qcm2290-qusb2-phy", .data = (ulong)&sm6115_phy_cfg }, diff --git a/drivers/phy/qcom/phy-qcom-snps-femto-v2.c b/drivers/phy/qcom/phy-qcom-snps-femto-v2.c index 04f0f0e7817..e782de07ebc 100644 --- a/drivers/phy/qcom/phy-qcom-snps-femto-v2.c +++ b/drivers/phy/qcom/phy-qcom-snps-femto-v2.c @@ -174,7 +174,7 @@ static int qcom_snps_hsphy_phy_probe(struct udevice *dev) return ret; } - reset_deassert_bulk(&priv->resets); + reset_assert_bulk(&priv->resets); return 0; } diff --git a/drivers/pinctrl/qcom/Kconfig b/drivers/pinctrl/qcom/Kconfig index 320aba33347..580308621b1 100644 --- a/drivers/pinctrl/qcom/Kconfig +++ b/drivers/pinctrl/qcom/Kconfig @@ -6,8 +6,17 @@ config PINCTRL_QCOM menu "Qualcomm pinctrl drivers" +config PINCTRL_QCOM_GENERIC + bool "Enable all Qualcomm pinctrl drivers by default" + select PINCTRL_QCOM + help + Say Y here to enable all Qualcomm pinctrl drivers by default. + This is useful for generic Qualcomm defconfigs that support + multiple SoCs. Individual drivers can still be disabled if needed. + config PINCTRL_QCOM_APQ8016 bool "Qualcomm APQ8016 Pinctrl" + default y if PINCTRL_QCOM_GENERIC select PINCTRL_QCOM help Say Y here to enable support for pinctrl on the MSM8916 / APQ8016 @@ -15,6 +24,7 @@ config PINCTRL_QCOM_APQ8016 config PINCTRL_QCOM_APQ8096 bool "Qualcomm APQ8096 Pinctrl" + default y if PINCTRL_QCOM_GENERIC select PINCTRL_QCOM help Say Y here to enable support for pinctrl on the MSM8996 / APQ8096 @@ -22,6 +32,7 @@ config PINCTRL_QCOM_APQ8096 config PINCTRL_QCOM_IPQ4019 bool "Qualcomm IPQ4019 Pinctrl" + default y if PINCTRL_QCOM_GENERIC select PINCTRL_QCOM help Say Y here to enable support for pinctrl on the IPQ4019 SoC, @@ -29,6 +40,7 @@ config PINCTRL_QCOM_IPQ4019 config PINCTRL_QCOM_IPQ5424 bool "Qualcomm IPQ5424 Pinctrl" + default y if PINCTRL_QCOM_GENERIC select PINCTRL_QCOM help Say Y here to enable support for pinctrl on the IPQ5424 SoC, @@ -36,6 +48,7 @@ config PINCTRL_QCOM_IPQ5424 config PINCTRL_QCOM_IPQ9574 bool "Qualcomm IPQ9574 Pinctrl" + default y if PINCTRL_QCOM_GENERIC select PINCTRL_QCOM help Say Y here to enable support for pinctrl on the IPQ9574 SoC, @@ -43,6 +56,7 @@ config PINCTRL_QCOM_IPQ9574 config PINCTRL_QCOM_QCM2290 bool "Qualcomm QCM2290 Pinctrl" + default y if PINCTRL_QCOM_GENERIC select PINCTRL_QCOM help Say Y here to enable support for pinctrl on the Snapdragon QCM2290 SoC, @@ -50,13 +64,23 @@ config PINCTRL_QCOM_QCM2290 config PINCTRL_QCOM_QCS404 bool "Qualcomm QCS404 Pinctrl" + default y if PINCTRL_QCOM_GENERIC 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_QCS615 + bool "Qualcomm QCS615 Pinctrl" + default y if PINCTRL_QCOM_GENERIC + select PINCTRL_QCOM + help + Say Y here to enable support for pinctrl on the Snapdragon QCS615 SoC, + as well as the associated GPIO driver. + config PINCTRL_QCOM_SA8775P bool "Qualcomm SA8775P Pinctrl" + default y if PINCTRL_QCOM_GENERIC select PINCTRL_QCOM help Say Y here to enable support for pinctrl on the Snapdragon SA8775P SoC, @@ -64,12 +88,14 @@ config PINCTRL_QCOM_SA8775P config PINCTRL_QCOM_SC7280 bool "Qualcomm SC7280/QCM6490 Pinctrl" + default y if PINCTRL_QCOM_GENERIC select PINCTRL_QCOM help Say Y here to enable support for pinctrl on the Snapdragon SC7280 SoC, config PINCTRL_QCOM_SDM670 bool "Qualcomm SDM670 Pinctrl" + default y if PINCTRL_QCOM_GENERIC select PINCTRL_QCOM help Say Y here to enable support for pinctrl on the Snapdragon SDM670 SoC, @@ -77,6 +103,7 @@ config PINCTRL_QCOM_SDM670 config PINCTRL_QCOM_SDM660 bool "Qualcomm SDM630/660 Pinctrl" + default y if PINCTRL_QCOM_GENERIC select PINCTRL_QCOM help Say Y here to enable support for pinctrl on the Snapdragon 630/636/660 @@ -84,6 +111,7 @@ config PINCTRL_QCOM_SDM660 config PINCTRL_QCOM_SDM845 bool "Qualcomm SDM845 Pinctrl" + default y if PINCTRL_QCOM_GENERIC select PINCTRL_QCOM help Say Y here to enable support for pinctrl on the Snapdragon 845 SoC, @@ -91,6 +119,7 @@ config PINCTRL_QCOM_SDM845 config PINCTRL_QCOM_SM6115 bool "Qualcomm SM6115 Pinctrl" + default y if PINCTRL_QCOM_GENERIC select PINCTRL_QCOM help Say Y here to enable support for pinctrl on the Snapdragon SM6115 SoC, @@ -98,12 +127,14 @@ config PINCTRL_QCOM_SM6115 config PINCTRL_QCOM_SM6350 bool "Qualcomm SM6350 Pinctrl" + default y if PINCTRL_QCOM_GENERIC select PINCTRL_QCOM help Say Y here to enable support for pinctrl on the Snapdragon SM6350 SoC, config PINCTRL_QCOM_SM7150 bool "Qualcomm SM7150 GCC" + default y if PINCTRL_QCOM_GENERIC select PINCTRL_QCOM help Say Y here to enable support for pinctrl on the Snapdragon SM7150 SoC, @@ -111,6 +142,7 @@ config PINCTRL_QCOM_SM7150 config PINCTRL_QCOM_SM8150 bool "Qualcomm SM8150 Pinctrl" + default y if PINCTRL_QCOM_GENERIC select PINCTRL_QCOM help Say Y here to enable support for pinctrl on the Snapdragon SM8150 SoC, @@ -118,6 +150,7 @@ config PINCTRL_QCOM_SM8150 config PINCTRL_QCOM_SM8250 bool "Qualcomm SM8250 Pinctrl" + default y if PINCTRL_QCOM_GENERIC select PINCTRL_QCOM help Say Y here to enable support for pinctrl on the Snapdragon SM8250 SoC, @@ -125,6 +158,7 @@ config PINCTRL_QCOM_SM8250 config PINCTRL_QCOM_SM8550 bool "Qualcomm SM8550 Pinctrl" + default y if PINCTRL_QCOM_GENERIC select PINCTRL_QCOM help Say Y here to enable support for pinctrl on the Snapdragon SM8550 SoC, @@ -132,6 +166,7 @@ config PINCTRL_QCOM_SM8550 config PINCTRL_QCOM_SM8650 bool "Qualcomm SM8650 Pinctrl" + default y if PINCTRL_QCOM_GENERIC select PINCTRL_QCOM help Say Y here to enable support for pinctrl on the Snapdragon SM8650 SoC, @@ -139,6 +174,7 @@ config PINCTRL_QCOM_SM8650 config PINCTRL_QCOM_X1E80100 bool "Qualcomm X1E80100 Pinctrl" + default y if PINCTRL_QCOM_GENERIC select PINCTRL_QCOM help Say Y here to enable support for pinctrl on the Snapdragon X1E80100 SoC, diff --git a/drivers/pinctrl/qcom/Makefile b/drivers/pinctrl/qcom/Makefile index 06582ac2068..b5a111605ed 100644 --- a/drivers/pinctrl/qcom/Makefile +++ b/drivers/pinctrl/qcom/Makefile @@ -10,6 +10,7 @@ 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_QCS615) += pinctrl-qcs615.o obj-$(CONFIG_PINCTRL_QCOM_SA8775P) += pinctrl-sa8775p.o obj-$(CONFIG_PINCTRL_QCOM_SC7280) += pinctrl-sc7280.o obj-$(CONFIG_PINCTRL_QCOM_SDM660) += pinctrl-sdm660.o diff --git a/drivers/pinctrl/qcom/pinctrl-qcs615.c b/drivers/pinctrl/qcom/pinctrl-qcs615.c new file mode 100644 index 00000000000..1a66cf73456 --- /dev/null +++ b/drivers/pinctrl/qcom/pinctrl-qcs615.c @@ -0,0 +1,473 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include + +#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 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, \ + } + +#define EAST 0x000000 +#define SOUTH 0xc00000 +#define WEST 0x400000 + +enum qcs615_functions { + msm_mux_gpio, + msm_mux_adsp_ext, + msm_mux_agera_pll, + msm_mux_aoss_cti, + msm_mux_atest_char, + msm_mux_atest_tsens, + msm_mux_atest_usb, + msm_mux_cam_mclk, + msm_mux_cci_async, + msm_mux_cci_i2c, + msm_mux_cci_timer, + msm_mux_copy_gp, + msm_mux_copy_phase, + msm_mux_cri_trng, + msm_mux_dbg_out_clk, + msm_mux_ddr_bist, + msm_mux_ddr_pxi, + msm_mux_dp_hot, + msm_mux_edp_hot, + msm_mux_edp_lcd, + msm_mux_emac_gcc, + msm_mux_emac_phy_intr, + msm_mux_forced_usb, + msm_mux_gcc_gp, + msm_mux_gp_pdm, + msm_mux_gps_tx, + msm_mux_hs0_mi2s, + msm_mux_hs1_mi2s, + msm_mux_jitter_bist, + msm_mux_ldo_en, + msm_mux_ldo_update, + msm_mux_m_voc, + msm_mux_mclk1, + msm_mux_mclk2, + msm_mux_mdp_vsync, + msm_mux_mdp_vsync0_out, + msm_mux_mdp_vsync1_out, + msm_mux_mdp_vsync2_out, + msm_mux_mdp_vsync3_out, + msm_mux_mdp_vsync4_out, + msm_mux_mdp_vsync5_out, + msm_mux_mi2s_1, + msm_mux_mss_lte, + msm_mux_nav_pps_in, + msm_mux_nav_pps_out, + msm_mux_pa_indicator_or, + msm_mux_pcie_clk_req, + msm_mux_pcie_ep_rst, + msm_mux_phase_flag, + msm_mux_pll_bist, + msm_mux_pll_bypassnl, + msm_mux_pll_reset_n, + msm_mux_prng_rosc, + msm_mux_qdss_cti, + msm_mux_qdss_gpio, + msm_mux_qlink_enable, + msm_mux_qlink_request, + msm_mux_qspi, + msm_mux_qup0, + msm_mux_qup1, + msm_mux_rgmii, + msm_mux_sd_write_protect, + msm_mux_sp_cmu, + msm_mux_ter_mi2s, + msm_mux_tgu_ch, + msm_mux_uim1, + msm_mux_uim2, + msm_mux_usb0_hs, + msm_mux_usb1_hs, + msm_mux_usb_phy_ps, + msm_mux_vfr_1, + msm_mux_vsense_trigger_mirnat, + msm_mux_wlan, + msm_mux_wsa_clk, + msm_mux_wsa_data, + 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(adsp_ext), + MSM_PIN_FUNCTION(agera_pll), + MSM_PIN_FUNCTION(aoss_cti), + MSM_PIN_FUNCTION(atest_char), + MSM_PIN_FUNCTION(atest_tsens), + MSM_PIN_FUNCTION(atest_usb), + MSM_PIN_FUNCTION(cam_mclk), + MSM_PIN_FUNCTION(cci_async), + MSM_PIN_FUNCTION(cci_i2c), + MSM_PIN_FUNCTION(cci_timer), + MSM_PIN_FUNCTION(copy_gp), + MSM_PIN_FUNCTION(copy_phase), + MSM_PIN_FUNCTION(cri_trng), + MSM_PIN_FUNCTION(dbg_out_clk), + MSM_PIN_FUNCTION(ddr_bist), + MSM_PIN_FUNCTION(ddr_pxi), + MSM_PIN_FUNCTION(dp_hot), + MSM_PIN_FUNCTION(edp_hot), + MSM_PIN_FUNCTION(edp_lcd), + MSM_PIN_FUNCTION(emac_gcc), + MSM_PIN_FUNCTION(emac_phy_intr), + MSM_PIN_FUNCTION(forced_usb), + MSM_PIN_FUNCTION(gcc_gp), + MSM_PIN_FUNCTION(gp_pdm), + MSM_PIN_FUNCTION(gps_tx), + MSM_PIN_FUNCTION(hs0_mi2s), + MSM_PIN_FUNCTION(hs1_mi2s), + MSM_PIN_FUNCTION(jitter_bist), + MSM_PIN_FUNCTION(ldo_en), + MSM_PIN_FUNCTION(ldo_update), + MSM_PIN_FUNCTION(m_voc), + MSM_PIN_FUNCTION(mclk1), + MSM_PIN_FUNCTION(mclk2), + MSM_PIN_FUNCTION(mdp_vsync), + MSM_PIN_FUNCTION(mdp_vsync0_out), + MSM_PIN_FUNCTION(mdp_vsync1_out), + MSM_PIN_FUNCTION(mdp_vsync2_out), + MSM_PIN_FUNCTION(mdp_vsync3_out), + MSM_PIN_FUNCTION(mdp_vsync4_out), + MSM_PIN_FUNCTION(mdp_vsync5_out), + MSM_PIN_FUNCTION(mi2s_1), + MSM_PIN_FUNCTION(mss_lte), + MSM_PIN_FUNCTION(nav_pps_in), + MSM_PIN_FUNCTION(nav_pps_out), + MSM_PIN_FUNCTION(pa_indicator_or), + MSM_PIN_FUNCTION(pcie_clk_req), + MSM_PIN_FUNCTION(pcie_ep_rst), + MSM_PIN_FUNCTION(phase_flag), + MSM_PIN_FUNCTION(pll_bist), + MSM_PIN_FUNCTION(pll_bypassnl), + MSM_PIN_FUNCTION(pll_reset_n), + MSM_PIN_FUNCTION(prng_rosc), + MSM_PIN_FUNCTION(qdss_cti), + MSM_PIN_FUNCTION(qdss_gpio), + MSM_PIN_FUNCTION(qlink_enable), + MSM_PIN_FUNCTION(qlink_request), + MSM_PIN_FUNCTION(qspi), + MSM_PIN_FUNCTION(qup0), + MSM_PIN_FUNCTION(qup1), + MSM_PIN_FUNCTION(rgmii), + MSM_PIN_FUNCTION(sd_write_protect), + MSM_PIN_FUNCTION(sp_cmu), + MSM_PIN_FUNCTION(ter_mi2s), + MSM_PIN_FUNCTION(tgu_ch), + MSM_PIN_FUNCTION(uim1), + MSM_PIN_FUNCTION(uim2), + MSM_PIN_FUNCTION(usb0_hs), + MSM_PIN_FUNCTION(usb1_hs), + MSM_PIN_FUNCTION(usb_phy_ps), + MSM_PIN_FUNCTION(vfr_1), + MSM_PIN_FUNCTION(vsense_trigger_mirnat), + MSM_PIN_FUNCTION(wlan), + MSM_PIN_FUNCTION(wsa_clk), + MSM_PIN_FUNCTION(wsa_data), +}; + +static const msm_pin_function qcs615_pin_functions[] = { + [0] = PINGROUP(0, qup0, _, qdss_gpio, _, _, _, _, _, _), + [1] = PINGROUP(1, qup0, _, qdss_gpio, _, _, _, _, _, _), + [2] = PINGROUP(2, qup0, _, qdss_gpio, _, _, _, _, _, _), + [3] = PINGROUP(3, qup0, _, qdss_gpio, _, _, _, _, _, _), + [4] = PINGROUP(4, qup0, _, _, _, _, _, _, _, _), + [5] = PINGROUP(5, qup0, _, _, _, _, _, _, _, _), + [6] = PINGROUP(6, qup1, qdss_gpio, ddr_pxi, _, _, _, _, _, _), + [7] = PINGROUP(7, qup1, ddr_bist, qdss_gpio, atest_tsens, + vsense_trigger_mirnat, atest_usb, ddr_pxi, _, _), + [8] = PINGROUP(8, qup1, gp_pdm, ddr_bist, qdss_gpio, _, _, _, _, _), + [9] = PINGROUP(9, qup1, ddr_bist, qdss_gpio, _, _, _, _, _, _), + [10] = PINGROUP(10, qup1, ddr_bist, _, phase_flag, atest_usb, ddr_pxi, _, _, _), + [11] = PINGROUP(11, qup1, dbg_out_clk, atest_usb, ddr_pxi, _, _, _, _, _), + [12] = PINGROUP(12, qup1, jitter_bist, ddr_pxi, _, _, _, _, _, _), + [13] = PINGROUP(13, qup1, pll_bypassnl, _, ddr_pxi, _, _, _, _, _), + [14] = PINGROUP(14, qup1, pll_reset_n, _, qdss_gpio, _, _, _, _, _), + [15] = PINGROUP(15, qup1, qdss_gpio, _, _, _, _, _, _, _), + [16] = PINGROUP(16, qup0, _, wlan, _, _, _, _, _, _), + [17] = PINGROUP(17, qup0, _, wlan, _, _, _, _, _, _), + [18] = PINGROUP(18, qup0, _, phase_flag, _, _, _, _, _, _), + [19] = PINGROUP(19, qup0, _, phase_flag, _, _, _, _, _, _), + [20] = PINGROUP(20, qup1, _, phase_flag, qdss_gpio, _, _, _, _, _), + [21] = PINGROUP(21, qup1, gcc_gp, _, qdss_gpio, _, _, _, _, _), + [22] = PINGROUP(22, qup1, gcc_gp, _, _, _, _, _, _, _), + [23] = PINGROUP(23, qup1, _, phase_flag, _, _, _, _, _, _), + [24] = PINGROUP(24, hs1_mi2s, sd_write_protect, _, phase_flag, _, _, _, _, _), + [25] = PINGROUP(25, hs1_mi2s, _, phase_flag, _, _, _, _, _, _), + [26] = PINGROUP(26, cci_async, hs1_mi2s, jitter_bist, _, _, _, _, _, _), + [27] = PINGROUP(27, hs1_mi2s, pll_bist, _, _, _, _, _, _, _), + [28] = PINGROUP(28, cam_mclk, agera_pll, qdss_gpio, _, _, _, _, _, _), + [29] = PINGROUP(29, cam_mclk, _, qdss_gpio, atest_tsens, _, _, _, _, _), + [30] = PINGROUP(30, cam_mclk, qdss_gpio, _, _, _, _, _, _, _), + [31] = PINGROUP(31, cam_mclk, _, qdss_gpio, _, _, _, _, _, _), + [32] = PINGROUP(32, cci_i2c, _, qdss_gpio, _, _, _, _, _, _), + [33] = PINGROUP(33, cci_i2c, _, qdss_gpio, _, _, _, _, _, _), + [34] = PINGROUP(34, cci_i2c, _, qdss_gpio, _, _, _, _, _, _), + [35] = PINGROUP(35, cci_i2c, _, qdss_gpio, _, _, _, _, _, _), + [36] = PINGROUP(36, hs0_mi2s, _, _, _, _, _, _, _, _), + [37] = PINGROUP(37, cci_timer, hs0_mi2s, _, _, _, _, _, _, _), + [38] = PINGROUP(38, cci_timer, hs0_mi2s, _, phase_flag, _, _, _, _, _), + [39] = PINGROUP(39, cci_timer, hs0_mi2s, _, _, _, _, _, _, _), + [40] = PINGROUP(40, _, phase_flag, _, _, _, _, _, _, _), + [41] = PINGROUP(41, cci_async, cci_timer, _, phase_flag, _, _, _, _, _), + [42] = PINGROUP(42, cci_async, cci_timer, _, phase_flag, _, _, _, _, _), + [43] = PINGROUP(43, _, phase_flag, forced_usb, _, _, _, _, _, _), + [44] = PINGROUP(44, qspi, _, phase_flag, qdss_gpio, _, _, _, _, _), + [45] = PINGROUP(45, qspi, _, phase_flag, qdss_gpio, _, _, _, _, _), + [46] = PINGROUP(46, qspi, _, qdss_gpio, _, _, _, _, _, _), + [47] = PINGROUP(47, qspi, _, qdss_gpio, wlan, _, _, _, _, _), + [48] = PINGROUP(48, qspi, _, wlan, _, _, _, _, _, _), + [49] = PINGROUP(49, qspi, _, _, _, _, _, _, _, _), + [50] = PINGROUP(50, qspi, _, _, _, _, _, _, _, _), + [51] = PINGROUP(51, qlink_request, _, _, _, _, _, _, _, _), + [52] = PINGROUP(52, qlink_enable, _, _, _, _, _, _, _, _), + [53] = PINGROUP(53, pa_indicator_or, nav_pps_in, nav_pps_out, gps_tx, _, + phase_flag, _, _, _), + [54] = PINGROUP(54, _, gps_tx, gp_pdm, _, phase_flag, atest_usb, ddr_pxi, _, _), + [55] = PINGROUP(55, _, _, phase_flag, atest_usb, ddr_pxi, _, _, _, _), + [56] = PINGROUP(56, _, nav_pps_in, nav_pps_out, gps_tx, _, _, _, _, _), + [57] = PINGROUP(57, _, nav_pps_in, gps_tx, nav_pps_out, gcc_gp, _, _, _, _), + [58] = PINGROUP(58, _, gcc_gp, _, _, _, _, _, _, _), + [59] = PINGROUP(59, _, nav_pps_in, nav_pps_out, gps_tx, gcc_gp, _, _, _, _), + [60] = PINGROUP(60, _, nav_pps_in, nav_pps_out, gps_tx, cri_trng, _, _, _, _), + [61] = PINGROUP(61, _, cri_trng, _, _, _, _, _, _, _), + [62] = PINGROUP(62, _, cri_trng, _, _, _, _, _, _, _), + [63] = PINGROUP(63, _, _, gp_pdm, _, _, _, _, _, _), + [64] = PINGROUP(64, _, sp_cmu, _, _, _, _, _, _, _), + [65] = PINGROUP(65, _, _, _, _, _, _, _, _, _), + [66] = PINGROUP(66, _, gp_pdm, _, _, _, _, _, _, _), + [67] = PINGROUP(67, _, _, _, phase_flag, atest_usb, _, _, _, _), + [68] = PINGROUP(68, _, _, _, phase_flag, atest_usb, _, _, _, _), + [69] = PINGROUP(69, _, _, _, _, _, _, _, _, _), + [70] = PINGROUP(70, _, _, _, _, _, _, _, _, _), + [71] = PINGROUP(71, _, _, _, _, _, _, _, _, _), + [72] = PINGROUP(72, _, _, _, _, _, _, _, _, _), + [73] = PINGROUP(73, uim2, _, _, _, _, _, _, _, _), + [74] = PINGROUP(74, uim2, _, _, _, _, _, _, _, _), + [75] = PINGROUP(75, uim2, _, phase_flag, atest_usb, _, _, _, _, _), + [76] = PINGROUP(76, uim2, _, phase_flag, atest_usb, aoss_cti, _, _, _, _), + [77] = PINGROUP(77, uim1, _, phase_flag, atest_usb, _, _, _, _, _), + [78] = PINGROUP(78, uim1, gcc_gp, _, phase_flag, _, _, _, _, _), + [79] = PINGROUP(79, uim1, gp_pdm, _, phase_flag, _, _, _, _, _), + [80] = PINGROUP(80, uim1, _, phase_flag, _, _, _, _, _, _), + [81] = PINGROUP(81, rgmii, mdp_vsync, _, qdss_gpio, _, _, _, _, _), + [82] = PINGROUP(82, rgmii, mdp_vsync, _, phase_flag, qdss_gpio, _, _, _, _), + [83] = PINGROUP(83, rgmii, mdp_vsync, _, qdss_cti, _, _, _, _, _), + [84] = PINGROUP(84, _, phase_flag, atest_char, _, _, _, _, _, _), + [85] = PINGROUP(85, _, atest_char, _, _, _, _, _, _, _), + [86] = PINGROUP(86, copy_gp, _, atest_char, _, _, _, _, _, _), + [87] = PINGROUP(87, _, atest_char, _, _, _, _, _, _, _), + [88] = PINGROUP(88, _, usb0_hs, _, _, _, _, _, _, _), + [89] = PINGROUP(89, emac_phy_intr, pcie_ep_rst, tgu_ch, usb1_hs, _, _, _, _, _), + [90] = PINGROUP(90, mdp_vsync, mdp_vsync0_out, mdp_vsync1_out, + mdp_vsync2_out, mdp_vsync3_out, mdp_vsync4_out, mdp_vsync5_out, + pcie_clk_req, tgu_ch), + [91] = PINGROUP(91, rgmii, tgu_ch, _, _, _, _, _, _, _), + [92] = PINGROUP(92, rgmii, vfr_1, tgu_ch, _, phase_flag, qdss_gpio, _, _, _), + [93] = PINGROUP(93, rgmii, qdss_gpio, _, _, _, _, _, _, _), + [94] = PINGROUP(94, rgmii, qdss_gpio, _, _, _, _, _, _, _), + [95] = PINGROUP(95, rgmii, gp_pdm, qdss_gpio, _, _, _, _, _, _), + [96] = PINGROUP(96, rgmii, qdss_cti, _, _, _, _, _, _, _), + [97] = PINGROUP(97, rgmii, mdp_vsync, ldo_en, qdss_cti, _, _, _, _, _), + [98] = PINGROUP(98, mdp_vsync, ldo_update, qdss_cti, _, _, _, _, _, _), + [99] = PINGROUP(99, prng_rosc, _, _, _, _, _, _, _, _), + [100] = PINGROUP(100, _, _, _, _, _, _, _, _, _), + [101] = PINGROUP(101, emac_gcc, _, _, _, _, _, _, _, _), + [102] = PINGROUP(102, rgmii, dp_hot, emac_gcc, prng_rosc, _, _, _, _, _), + [103] = PINGROUP(103, rgmii, dp_hot, copy_phase, qdss_cti, _, _, _, _, _), + [104] = PINGROUP(104, usb_phy_ps, _, qdss_cti, dp_hot, _, _, _, _, _), + [105] = PINGROUP(105, _, _, _, _, _, _, _, _, _), + [106] = PINGROUP(106, mss_lte, _, _, _, _, _, _, _, _), + [107] = PINGROUP(107, mss_lte, _, _, _, _, _, _, _, _), + [108] = PINGROUP(108, mi2s_1, _, qdss_gpio, _, _, _, _, _, _), + [109] = PINGROUP(109, mi2s_1, _, qdss_gpio, _, _, _, _, _, _), + [110] = PINGROUP(110, wsa_data, mi2s_1, _, _, _, _, _, _, _), + [111] = PINGROUP(111, wsa_clk, mi2s_1, _, _, _, _, _, _, _), + [112] = PINGROUP(112, rgmii, _, qdss_cti, _, _, _, _, _, _), + [113] = PINGROUP(113, rgmii, edp_hot, _, qdss_cti, _, _, _, _, _), + [114] = PINGROUP(114, rgmii, _, _, _, _, _, _, _, _), + [115] = PINGROUP(115, ter_mi2s, atest_char, _, _, _, _, _, _, _), + [116] = PINGROUP(116, ter_mi2s, _, phase_flag, _, _, _, _, _, _), + [117] = PINGROUP(117, ter_mi2s, _, phase_flag, qdss_gpio, atest_char, _, _, _, _), + [118] = PINGROUP(118, ter_mi2s, adsp_ext, _, phase_flag, qdss_gpio, atest_char, + _, _, _), + [119] = PINGROUP(119, edp_lcd, _, phase_flag, qdss_gpio, atest_char, _, _, _, _), + [120] = PINGROUP(120, m_voc, qdss_gpio, atest_char, _, _, _, _, _, _), + [121] = PINGROUP(121, mclk1, atest_char, _, _, _, _, _, _, _), + [122] = PINGROUP(122, mclk2, _, _, _, _, _, _, _, _), +}; + +static const struct msm_special_pin_data qcs615_special_pins_data[] = { + [0] = UFS_RESET("ufs_reset", 0x9f000 + WEST), + [1] = SDC_QDSD_PINGROUP("sdc1_rclk", 0x9a000 + WEST, 15, 0), + [2] = SDC_QDSD_PINGROUP("sdc1_clk", 0x9a000 + WEST, 13, 6), + [3] = SDC_QDSD_PINGROUP("sdc1_cmd", 0x9a000 + WEST, 11, 3), + [4] = SDC_QDSD_PINGROUP("sdc1_data", 0x9a000 + WEST, 9, 0), + [5] = SDC_QDSD_PINGROUP("sdc2_clk", 0x98000 + SOUTH, 14, 6), + [6] = SDC_QDSD_PINGROUP("sdc2_cmd", 0x98000 + SOUTH, 11, 3), + [7] = SDC_QDSD_PINGROUP("sdc2_data", 0x98000 + SOUTH, 9, 0), +}; + +static const unsigned int qcs615_pin_offsets[] = { + [0] = WEST, [1] = WEST, [2] = WEST, + [3] = WEST, [4] = WEST, [5] = WEST, + [6] = EAST, [7] = EAST, [8] = EAST, + [9] = EAST, [10] = EAST, [11] = EAST, + [12] = EAST, [13] = EAST, [14] = EAST, + [15] = EAST, [16] = WEST, [17] = WEST, + [18] = WEST, [19] = WEST, [20] = SOUTH, + [21] = SOUTH, [22] = SOUTH, [23] = SOUTH, + [24] = EAST, [25] = EAST, [26] = EAST, + [27] = EAST, [28] = EAST, [29] = EAST, + [30] = EAST, [31] = EAST, [32] = EAST, + [33] = EAST, [34] = EAST, [35] = EAST, + [36] = EAST, [37] = EAST, [38] = EAST, + [39] = EAST, [40] = EAST, [41] = EAST, + [42] = EAST, [43] = SOUTH, [44] = EAST, + [45] = EAST, [46] = EAST, [47] = EAST, + [48] = EAST, [49] = EAST, [50] = EAST, + [51] = SOUTH, [52] = SOUTH, [53] = SOUTH, + [54] = SOUTH, [55] = SOUTH, [56] = SOUTH, + [57] = SOUTH, [58] = SOUTH, [59] = SOUTH, + [60] = SOUTH, [61] = SOUTH, [62] = SOUTH, + [63] = SOUTH, [64] = SOUTH, [65] = SOUTH, + [66] = SOUTH, [67] = SOUTH, [68] = SOUTH, + [69] = SOUTH, [70] = SOUTH, [71] = SOUTH, + [72] = SOUTH, [73] = SOUTH, [74] = SOUTH, + [75] = SOUTH, [76] = SOUTH, [77] = SOUTH, + [78] = SOUTH, [79] = SOUTH, [80] = SOUTH, + [81] = WEST, [82] = WEST, [83] = WEST, + [84] = SOUTH, [85] = SOUTH, [86] = SOUTH, + [87] = SOUTH, [88] = WEST, [89] = WEST, + [90] = WEST, [91] = WEST, [92] = WEST, + [93] = WEST, [94] = WEST, [95] = WEST, + [96] = WEST, [97] = WEST, [98] = WEST, + [99] = EAST, [100] = WEST, [101] = WEST, + [102] = WEST, [103] = WEST, [104] = WEST, + [105] = SOUTH, [106] = EAST, [107] = EAST, + [108] = SOUTH, [109] = SOUTH, [110] = SOUTH, + [111] = SOUTH, [112] = WEST, [113] = WEST, + [114] = WEST, [115] = SOUTH, [116] = SOUTH, + [117] = SOUTH, [118] = SOUTH, [119] = SOUTH, + [120] = SOUTH, [121] = SOUTH, [122] = SOUTH, +}; + +static const char *qcs615_get_function_name(struct udevice *dev, + unsigned int selector) + +{ + return msm_pinctrl_functions[selector].name; +} + +static const char *qcs615_get_pin_name(struct udevice *dev, + unsigned int selector) +{ + struct msm_pinctrl_data *data = (struct msm_pinctrl_data *)dev_get_driver_data(dev); + unsigned int special_pins_start = data->pin_data.special_pins_start; + + if (selector > (data->pin_data.pin_count - 1)) + snprintf(pin_name, MAX_PIN_NAME_LEN, "unknown"); + else if (selector >= special_pins_start) + + snprintf(pin_name, MAX_PIN_NAME_LEN, + qcs615_special_pins_data[selector - special_pins_start].name); + else + snprintf(pin_name, MAX_PIN_NAME_LEN, "gpio%u", selector); + + return pin_name; +} + +static int qcs615_get_function_mux(__maybe_unused unsigned int pin, + unsigned int selector) +{ + unsigned int i; + const msm_pin_function *func = NULL; + + if (pin >= ARRAY_SIZE(qcs615_pin_functions)) + return -EINVAL; + + func = qcs615_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 struct msm_pinctrl_data qcs615_data = { + .pin_data = { + .pin_count = 131, + .special_pins_start = 123, + .special_pins_data = qcs615_special_pins_data, + .pin_offsets = qcs615_pin_offsets, + }, + .functions_count = ARRAY_SIZE(msm_pinctrl_functions), + .get_function_name = qcs615_get_function_name, + .get_function_mux = qcs615_get_function_mux, + .get_pin_name = qcs615_get_pin_name, +}; + +static const struct udevice_id msm_pinctrl_ids[] = { + { .compatible = "qcom,qcs615-tlmm", .data = (ulong)&qcs615_data}, + { } +}; + +U_BOOT_DRIVER(qcs615_pinctrl) = { + .name = "qcs615_pinctrl", + .id = UCLASS_NOP, + .of_match = msm_pinctrl_ids, + .ops = &msm_pinctrl_ops, + .bind = msm_pinctrl_bind, + .flags = DM_FLAG_PRE_RELOC, + +}; diff --git a/drivers/power/regulator/qcom-rpmh-regulator.c b/drivers/power/regulator/qcom-rpmh-regulator.c index 06466142560..3f0f1845469 100644 --- a/drivers/power/regulator/qcom-rpmh-regulator.c +++ b/drivers/power/regulator/qcom-rpmh-regulator.c @@ -37,8 +37,11 @@ enum rpmh_regulator_mode { }; #define RPMH_REGULATOR_REG_VRM_VOLTAGE 0x0 +#define RPMH_REGULATOR_VOLTAGE_MASK 0x1FFF #define RPMH_REGULATOR_REG_ENABLE 0x4 +#define RPMH_REGULATOR_ENABLE_MASK 0x1 #define RPMH_REGULATOR_REG_VRM_MODE 0x8 +#define RPMH_REGULATOR_MODE_MASK 0x7 #define PMIC4_LDO_MODE_RETENTION 4 #define PMIC4_LDO_MODE_LPM 5 @@ -205,6 +208,38 @@ static int rpmh_regulator_send_request(struct rpmh_vreg *vreg, return ret; } +static int rpmh_regulator_read_data(struct rpmh_vreg *vreg, struct tcs_cmd *cmd) +{ + return rpmh_read(vreg->dev->parent, RPMH_ACTIVE_ONLY_STATE, cmd); +} + +static int rpmh_regulator_vrm_get_voltage(struct udevice *rdev, int *uV) +{ + struct rpmh_vreg *vreg = dev_get_priv(rdev); + struct tcs_cmd cmd = { + .addr = vreg->addr + RPMH_REGULATOR_REG_VRM_VOLTAGE, + }; + const struct linear_range *uv_range = &vreg->hw_data->voltage_range; + int min_uV = uv_range->min; + int max_uV = uv_range->min + uv_range->max_sel * uv_range->step; + + int ret, _uV = 0; + + ret = rpmh_regulator_read_data(vreg, &cmd); + if (!ret) + _uV = (cmd.data & RPMH_REGULATOR_VOLTAGE_MASK) * 1000; + else + dev_err(vreg->dev, "failed to read VOLTAGE ret = %d\n", ret); + + if (!_uV || (_uV >= min_uV && _uV <= max_uV)) + *uV = _uV; + else + dev_info(vreg->dev, "read voltage %d is out-of-range[%d:%d]\n", + _uV, min_uV, max_uV); + + return ret; +} + static int _rpmh_regulator_vrm_set_value(struct udevice *rdev, int uv, bool wait_for_ack) { @@ -249,8 +284,13 @@ static int rpmh_regulator_vrm_set_value(struct udevice *rdev, static int rpmh_regulator_vrm_get_value(struct udevice *rdev) { struct rpmh_vreg *vreg = dev_get_priv(rdev); + int ret, uV; - debug("%s: get_value %d\n", rdev->name, vreg->uv); + if (vreg->uv < 0) { + ret = rpmh_regulator_vrm_get_voltage(rdev, &uV); + if (!ret && uV != 0) + vreg->uv = uV; + } return vreg->uv; } @@ -258,9 +298,23 @@ static int rpmh_regulator_vrm_get_value(struct udevice *rdev) static int rpmh_regulator_is_enabled(struct udevice *rdev) { struct rpmh_vreg *vreg = dev_get_priv(rdev); + int ret; debug("%s: is_enabled %d\n", rdev->name, vreg->enabled); + if (vreg->enabled < 0) { + struct tcs_cmd cmd = { + .addr = vreg->addr + RPMH_REGULATOR_REG_ENABLE, + }; + ret = rpmh_regulator_read_data(vreg, &cmd); + /* + * Don't override if disabled since we will also vote the right voltage + * while enabling + */ + if (!ret && cmd.data) + vreg->enabled = cmd.data & RPMH_REGULATOR_ENABLE_MASK; + } + return vreg->enabled > 0; } @@ -315,9 +369,11 @@ static int rpmh_regulator_vrm_set_mode_bypass(struct rpmh_vreg *vreg, } if (bypassed) - cmd.data = PMIC4_BOB_MODE_PASS; + // XXX: should have a version check for PMIC4 but we don't have any yet + // and we don't use bypass mode + cmd.data = PMIC5_BOB_MODE_PASS; else - cmd.data = pmic_mode->id; + cmd.data = pmic_mode->register_value; return rpmh_regulator_send_request(vreg, &cmd, true); } @@ -340,12 +396,40 @@ static int rpmh_regulator_vrm_set_mode(struct udevice *rdev, return ret; } +static int rpmh_regulator_vrm_get_pmic_mode(struct rpmh_vreg *vreg, int *pmic_mode) +{ + struct tcs_cmd cmd = { + .addr = vreg->addr + RPMH_REGULATOR_REG_VRM_MODE, + }; + struct dm_regulator_mode *pmic_mode_map = vreg->hw_data->pmic_mode_map; + int ret, register_value; + + ret = rpmh_regulator_read_data(vreg, &cmd); + if (!ret) + register_value = cmd.data & RPMH_REGULATOR_MODE_MASK; + else + return -EINVAL; + + for (int i = 0; i < vreg->hw_data->n_modes; i++) { + if (pmic_mode_map[i].register_value == register_value) { + *pmic_mode = pmic_mode_map[i].id; + return 0; + } + } + + return -EINVAL; +} + static int rpmh_regulator_vrm_get_mode(struct udevice *rdev) { struct rpmh_vreg *vreg = dev_get_priv(rdev); + int mode; debug("%s: get_mode %d\n", rdev->name, vreg->mode); + if (!rpmh_regulator_vrm_get_pmic_mode(vreg, &mode)) + vreg->mode = mode; + return vreg->mode; } static const struct dm_regulator_ops rpmh_regulator_vrm_drms_ops = { @@ -402,6 +486,42 @@ static const struct rpmh_vreg_hw_data pmic5_bob = { .n_modes = ARRAY_SIZE(pmic_mode_map_pmic5_bob), }; +static const struct rpmh_vreg_hw_data pmic5_hfsmps510 = { + .regulator_type = VRM, + .ops = &rpmh_regulator_vrm_drms_ops, + .voltage_range = REGULATOR_LINEAR_RANGE(320000, 0, 215, 8000), + .n_voltages = 216, + .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_hfsmps515 = { + .regulator_type = VRM, + .ops = &rpmh_regulator_vrm_drms_ops, + .voltage_range = REGULATOR_LINEAR_RANGE(320000, 0, 235, 16000), + .n_voltages = 236, + .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_ftsmps510 = { + .regulator_type = VRM, + .ops = &rpmh_regulator_vrm_drms_ops, + .voltage_range = REGULATOR_LINEAR_RANGE(300000, 0, 263, 4000), + .n_voltages = 264, + .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_ftsmps520 = { + .regulator_type = VRM, + .ops = &rpmh_regulator_vrm_drms_ops, + .voltage_range = REGULATOR_LINEAR_RANGE(300000, 0, 263, 4000), + .n_voltages = 264, + .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_ftsmps525_lv = { .regulator_type = VRM, .ops = &rpmh_regulator_vrm_drms_ops, @@ -521,7 +641,34 @@ static const struct rpmh_vreg_init_data pm6150l_vreg_data[] = { }; static const struct rpmh_vreg_init_data pm8150_vreg_data[] = { + RPMH_VREG("smps1", "smp%s1", &pmic5_ftsmps510, "vdd-s1"), + RPMH_VREG("smps2", "smp%s2", &pmic5_ftsmps510, "vdd-s2"), + RPMH_VREG("smps3", "smp%s3", &pmic5_ftsmps510, "vdd-s3"), + RPMH_VREG("smps4", "smp%s4", &pmic5_hfsmps510, "vdd-s4"), + RPMH_VREG("smps5", "smp%s5", &pmic5_hfsmps510, "vdd-s5"), + RPMH_VREG("smps6", "smp%s6", &pmic5_ftsmps510, "vdd-s6"), + RPMH_VREG("smps7", "smp%s7", &pmic5_ftsmps510, "vdd-s7"), + RPMH_VREG("smps8", "smp%s8", &pmic5_ftsmps510, "vdd-s8"), + RPMH_VREG("smps9", "smp%s9", &pmic5_ftsmps510, "vdd-s9"), + RPMH_VREG("smps10", "smp%s10", &pmic5_ftsmps510, "vdd-s10"), + RPMH_VREG("ldo1", "ldo%s1", &pmic5_nldo, "vdd-l1-l8-l11"), + RPMH_VREG("ldo2", "ldo%s2", &pmic5_pldo, "vdd-l2-l10"), + RPMH_VREG("ldo3", "ldo%s3", &pmic5_nldo, "vdd-l3-l4-l5-l18"), + RPMH_VREG("ldo4", "ldo%s4", &pmic5_nldo, "vdd-l3-l4-l5-l18"), + RPMH_VREG("ldo5", "ldo%s5", &pmic5_nldo, "vdd-l3-l4-l5-l18"), + RPMH_VREG("ldo6", "ldo%s6", &pmic5_nldo, "vdd-l6-l9"), + RPMH_VREG("ldo7", "ldo%s7", &pmic5_pldo, "vdd-l7-l12-l14-l15"), + RPMH_VREG("ldo8", "ldo%s8", &pmic5_nldo, "vdd-l1-l8-l11"), + RPMH_VREG("ldo9", "ldo%s9", &pmic5_nldo, "vdd-l6-l9"), + RPMH_VREG("ldo10", "ldo%s10", &pmic5_pldo, "vdd-l2-l10"), + RPMH_VREG("ldo11", "ldo%s11", &pmic5_nldo, "vdd-l1-l8-l11"), + RPMH_VREG("ldo12", "ldo%s12", &pmic5_pldo_lv, "vdd-l7-l12-l14-l15"), RPMH_VREG("ldo13", "ldo%s13", &pmic5_pldo, "vdd-l13-l16-l17"), + RPMH_VREG("ldo14", "ldo%s14", &pmic5_pldo_lv, "vdd-l7-l12-l14-l15"), + RPMH_VREG("ldo15", "ldo%s15", &pmic5_pldo_lv, "vdd-l7-l12-l14-l15"), + RPMH_VREG("ldo16", "ldo%s16", &pmic5_pldo, "vdd-l13-l16-l17"), + RPMH_VREG("ldo17", "ldo%s17", &pmic5_pldo, "vdd-l13-l16-l17"), + RPMH_VREG("ldo18", "ldo%s18", &pmic5_nldo, "vdd-l3-l4-l5-l18"), {} }; @@ -626,6 +773,65 @@ static const struct rpmh_vreg_init_data pmm8654au_vreg_data[] = { {} }; +static const struct rpmh_vreg_init_data pm8350c_vreg_data[] = { + RPMH_VREG("smps1", "smp%s1", &pmic5_hfsmps515, "vdd-s1"), + RPMH_VREG("smps2", "smp%s2", &pmic5_ftsmps510, "vdd-s2"), + RPMH_VREG("smps3", "smp%s3", &pmic5_ftsmps510, "vdd-s3"), + RPMH_VREG("smps4", "smp%s4", &pmic5_ftsmps510, "vdd-s4"), + RPMH_VREG("smps5", "smp%s5", &pmic5_ftsmps510, "vdd-s5"), + RPMH_VREG("smps6", "smp%s6", &pmic5_ftsmps510, "vdd-s6"), + RPMH_VREG("smps7", "smp%s7", &pmic5_ftsmps510, "vdd-s7"), + RPMH_VREG("smps8", "smp%s8", &pmic5_ftsmps510, "vdd-s8"), + RPMH_VREG("smps9", "smp%s9", &pmic5_ftsmps510, "vdd-s9"), + RPMH_VREG("smps10", "smp%s10", &pmic5_ftsmps510, "vdd-s10"), + RPMH_VREG("ldo1", "ldo%s1", &pmic5_pldo_lv, "vdd-l1-l12"), + RPMH_VREG("ldo2", "ldo%s2", &pmic5_pldo_lv, "vdd-l2-l8"), + RPMH_VREG("ldo3", "ldo%s3", &pmic5_pldo, "vdd-l3-l4-l5-l7-l13"), + RPMH_VREG("ldo4", "ldo%s4", &pmic5_pldo, "vdd-l3-l4-l5-l7-l13"), + RPMH_VREG("ldo5", "ldo%s5", &pmic5_pldo, "vdd-l3-l4-l5-l7-l13"), + RPMH_VREG("ldo6", "ldo%s6", &pmic5_pldo, "vdd-l6-l9-l11"), + RPMH_VREG("ldo7", "ldo%s7", &pmic5_pldo, "vdd-l3-l4-l5-l7-l13"), + RPMH_VREG("ldo8", "ldo%s8", &pmic5_pldo_lv, "vdd-l2-l8"), + RPMH_VREG("ldo9", "ldo%s9", &pmic5_pldo, "vdd-l6-l9-l11"), + RPMH_VREG("ldo10", "ldo%s10", &pmic5_nldo, "vdd-l10"), + RPMH_VREG("ldo11", "ldo%s11", &pmic5_pldo, "vdd-l6-l9-l11"), + RPMH_VREG("ldo12", "ldo%s12", &pmic5_pldo_lv, "vdd-l1-l12"), + RPMH_VREG("ldo13", "ldo%s13", &pmic5_pldo, "vdd-l3-l4-l5-l7-l13"), + RPMH_VREG("bob", "bob%s1", &pmic5_bob, "vdd-bob"), + {} +}; + +static const struct rpmh_vreg_init_data pm7325_vreg_data[] = { + RPMH_VREG("smps1", "smp%s1", &pmic5_hfsmps510, "vdd-s1"), + RPMH_VREG("smps2", "smp%s2", &pmic5_ftsmps520, "vdd-s2"), + RPMH_VREG("smps3", "smp%s3", &pmic5_ftsmps520, "vdd-s3"), + RPMH_VREG("smps4", "smp%s4", &pmic5_ftsmps520, "vdd-s4"), + RPMH_VREG("smps5", "smp%s5", &pmic5_ftsmps520, "vdd-s5"), + RPMH_VREG("smps6", "smp%s6", &pmic5_ftsmps520, "vdd-s6"), + RPMH_VREG("smps7", "smp%s7", &pmic5_ftsmps520, "vdd-s7"), + RPMH_VREG("smps8", "smp%s8", &pmic5_hfsmps510, "vdd-s8"), + RPMH_VREG("ldo1", "ldo%s1", &pmic5_nldo, "vdd-l1-l4-l12-l15"), + RPMH_VREG("ldo2", "ldo%s2", &pmic5_pldo, "vdd-l2-l7"), + RPMH_VREG("ldo3", "ldo%s3", &pmic5_nldo, "vdd-l3"), + RPMH_VREG("ldo4", "ldo%s4", &pmic5_nldo, "vdd-l1-l4-l12-l15"), + RPMH_VREG("ldo5", "ldo%s5", &pmic5_nldo, "vdd-l5"), + RPMH_VREG("ldo6", "ldo%s6", &pmic5_nldo, "vdd-l6-l9-l10"), + RPMH_VREG("ldo7", "ldo%s7", &pmic5_pldo, "vdd-l2-l7"), + RPMH_VREG("ldo8", "ldo%s8", &pmic5_nldo, "vdd-l8"), + RPMH_VREG("ldo9", "ldo%s9", &pmic5_nldo, "vdd-l6-l9-l10"), + RPMH_VREG("ldo10", "ldo%s10", &pmic5_nldo, "vdd-l6-l9-l10"), + RPMH_VREG("ldo11", "ldo%s11", &pmic5_pldo_lv, "vdd-l11-l17-l18-l19"), + RPMH_VREG("ldo12", "ldo%s12", &pmic5_nldo, "vdd-l1-l4-l12-l15"), + RPMH_VREG("ldo13", "ldo%s13", &pmic5_nldo, "vdd-l13"), + RPMH_VREG("ldo14", "ldo%s14", &pmic5_nldo, "vdd-l14-l16"), + RPMH_VREG("ldo15", "ldo%s15", &pmic5_nldo, "vdd-l1-l4-l12-l15"), + RPMH_VREG("ldo16", "ldo%s16", &pmic5_nldo, "vdd-l14-l16"), + RPMH_VREG("ldo17", "ldo%s17", &pmic5_pldo_lv, "vdd-l11-l17-l18-l19"), + RPMH_VREG("ldo18", "ldo%s18", &pmic5_pldo_lv, "vdd-l11-l17-l18-l19"), + RPMH_VREG("ldo19", "ldo%s19", &pmic5_pldo_lv, "vdd-l11-l17-l18-l19"), + {} +}; + /* probe an individual regulator */ static int rpmh_regulator_probe(struct udevice *dev) { @@ -736,6 +942,10 @@ static const struct udevice_id rpmh_regulator_ids[] = { .compatible = "qcom,pm6150l-rpmh-regulators", .data = (ulong)pm6150l_vreg_data, }, + { + .compatible = "qcom,pm7325-rpmh-regulators", + .data = (ulong)pm7325_vreg_data, + }, { .compatible = "qcom,pm8150-rpmh-regulators", .data = (ulong)pm8150_vreg_data, @@ -744,6 +954,10 @@ static const struct udevice_id rpmh_regulator_ids[] = { .compatible = "qcom,pm8150l-rpmh-regulators", .data = (ulong)pm8150l_vreg_data, }, + { + .compatible = "qcom,pm8350c-rpmh-regulators", + .data = (ulong)pm8350c_vreg_data, + }, { .compatible = "qcom,pm8550-rpmh-regulators", .data = (ulong)pm8550_vreg_data, diff --git a/drivers/smem/msm_smem.c b/drivers/smem/msm_smem.c index ccd145f9afb..b6b92d3530d 100644 --- a/drivers/smem/msm_smem.c +++ b/drivers/smem/msm_smem.c @@ -88,7 +88,7 @@ DECLARE_GLOBAL_DATA_PTR; #define SMEM_GLOBAL_HOST 0xfffe /* Max number of processors/hosts in a system */ -#define SMEM_HOST_COUNT 10 +#define SMEM_HOST_COUNT 25 /** * struct smem_proc_comm - proc_comm communication struct (legacy) @@ -821,23 +821,34 @@ static int qcom_smem_enumerate_partitions(struct qcom_smem *smem, static int qcom_smem_map_memory(struct qcom_smem *smem, struct udevice *dev, const char *name, int i) { - struct fdt_resource r; int ret; - int node = dev_of_offset(dev); + struct ofnode_phandle_args args; + struct resource r; - ret = fdtdec_lookup_phandle(gd->fdt_blob, node, name); - if (ret < 0) { - dev_err(dev, "No %s specified\n", name); + if (!dev_read_prop(dev, name, NULL)) { + dev_err(dev, "%s prop not found\n", name); return -EINVAL; } - ret = fdt_get_resource(gd->fdt_blob, ret, "reg", 0, &r); - if (ret) - return ret; + ret = dev_read_phandle_with_args(dev, name, NULL, 0, 0, &args); + if (ret) { + dev_err(dev, "%s phandle read failed\n", name); + return -EINVAL; + } + if (!ofnode_valid(args.node)) { + dev_err(dev, "Invalid node from phandle args\n"); + return -EINVAL; + } + + ret = ofnode_read_resource(args.node, 0, &r); + if (ret) { + dev_err(dev, "Can't get mmap base address(%d)\n", ret); + return ret; + } smem->regions[i].aux_base = (u32)r.start; - smem->regions[i].size = fdt_resource_size(&r); - smem->regions[i].virt_base = devm_ioremap(dev, r.start, fdt_resource_size(&r)); + smem->regions[i].size = resource_size(&r); + smem->regions[i].virt_base = devm_ioremap(dev, r.start, resource_size(&r)); if (!smem->regions[i].virt_base) return -ENOMEM; @@ -852,10 +863,14 @@ static int qcom_smem_probe(struct udevice *dev) int num_regions; u32 version; int ret; - int node = dev_of_offset(dev); + fdt_addr_t addr; + fdt_size_t size; + + if (__smem) + return 0; num_regions = 1; - if (fdtdec_lookup_phandle(gd->fdt_blob, node, "qcomrpm-msg-ram") >= 0) + if (dev_read_prop(dev, "qcom,rpm-msg-ram", NULL)) num_regions++; array_size = num_regions * sizeof(struct smem_region); @@ -866,9 +881,18 @@ static int qcom_smem_probe(struct udevice *dev) smem->dev = dev; smem->num_regions = num_regions; - ret = qcom_smem_map_memory(smem, dev, "memory-region", 0); - if (ret) - return ret; + addr = dev_read_addr_size(dev, &size); + if (addr == FDT_ADDR_T_NONE) { + ret = qcom_smem_map_memory(smem, dev, "memory-region", 0); + if (ret) + return ret; + } else { + smem->regions[0].aux_base = (u32)addr; + smem->regions[0].size = size; + smem->regions[0].virt_base = devm_ioremap(dev, addr, size); + if (!smem->regions[0].virt_base) + return -ENOMEM; + } if (num_regions > 1) { ret = qcom_smem_map_memory(smem, dev, diff --git a/drivers/soc/qcom/rpmh-rsc.c b/drivers/soc/qcom/rpmh-rsc.c index aee9e55194e..dce61f26229 100644 --- a/drivers/soc/qcom/rpmh-rsc.c +++ b/drivers/soc/qcom/rpmh-rsc.c @@ -36,15 +36,31 @@ enum { RSC_DRV_TCS_OFFSET, RSC_DRV_CMD_OFFSET, +/* DRV HW Solver Configuration Information Register */ DRV_SOLVER_CONFIG, +/* DRV TCS Configuration Information Register */ DRV_PRNT_CHLD_CONFIG, +/* Offsets for common TCS Registers, one bit per TCS */ RSC_DRV_IRQ_ENABLE, RSC_DRV_IRQ_STATUS, - RSC_DRV_IRQ_CLEAR, - RSC_DRV_CMD_WAIT_FOR_CMPL, + RSC_DRV_IRQ_CLEAR, /* w/o; write 1 to clear */ +/* + * Offsets for per TCS Registers. + * + * TCSes start at 0x10 from tcs_base and are stored one after another. + * Multiply tcs_id by RSC_DRV_TCS_OFFSET to find a given TCS and add one + * of the below to find a register. + */ + RSC_DRV_CMD_WAIT_FOR_CMPL, /* 1 bit per command */ RSC_DRV_CONTROL, - RSC_DRV_STATUS, - RSC_DRV_CMD_ENABLE, + RSC_DRV_STATUS, /* zero if tcs is busy */ + RSC_DRV_CMD_ENABLE, /* 1 bit per command */ +/* + * Offsets for per command in a TCS. + * + * Commands (up to 16) start at 0x30 in a TCS; multiply command index + * by RSC_DRV_CMD_OFFSET and add one of the below to find a register. + */ RSC_DRV_CMD_MSGID, RSC_DRV_CMD_ADDR, RSC_DRV_CMD_DATA, @@ -266,31 +282,41 @@ static void __tcs_buffer_write(struct rsc_drv *drv, int tcs_id, int cmd_id, const struct tcs_request *msg) { u32 msgid; - u32 cmd_msgid = CMD_MSGID_LEN | CMD_MSGID_WRITE; + u32 cmd_msgid = CMD_MSGID_LEN; u32 cmd_enable = 0; + u32 cmd_complete = 0; struct tcs_cmd *cmd; int i, j; + if (!msg->is_read) + cmd_msgid |= CMD_MSGID_WRITE; + + if (msg->wait_for_compl) + cmd_msgid |= CMD_MSGID_RESP_REQ; + + cmd_complete = read_tcs_reg(drv, drv->regs[RSC_DRV_CMD_WAIT_FOR_CMPL], tcs_id); + for (i = 0, j = cmd_id; i < msg->num_cmds; i++, j++) { cmd = &msg->cmds[i]; cmd_enable |= BIT(j); + /* U-Boot: always wait for completion */ + cmd_complete |= (!!msg->wait_for_compl) << j; msgid = cmd_msgid; - /* - * Additionally, if the cmd->wait is set, make the command - * response reqd even if the overall request was fire-n-forget. - */ - msgid |= cmd->wait ? CMD_MSGID_RESP_REQ : 0; write_tcs_cmd(drv, drv->regs[RSC_DRV_CMD_MSGID], tcs_id, j, msgid); write_tcs_cmd(drv, drv->regs[RSC_DRV_CMD_ADDR], tcs_id, j, cmd->addr); - write_tcs_cmd(drv, drv->regs[RSC_DRV_CMD_DATA], tcs_id, j, cmd->data); - debug("tcs(m): %d [%s] cmd(n): %d msgid: %#x addr: %#x data: %#x complete: %d\n", + if (!msg->is_read) + write_tcs_cmd(drv, drv->regs[RSC_DRV_CMD_DATA], tcs_id, j, cmd->data); + debug("tcs(%d): [%s] cmd_id: %d: msgid: %#x addr: %#x data: %#x complete: %#x\n", tcs_id, msg->state == RPMH_ACTIVE_ONLY_STATE ? "active" : "?", j, msgid, - cmd->addr, cmd->data, cmd->wait); + cmd->addr, cmd->data, cmd_complete); } cmd_enable |= read_tcs_reg(drv, drv->regs[RSC_DRV_CMD_ENABLE], tcs_id); write_tcs_reg(drv, drv->regs[RSC_DRV_CMD_ENABLE], tcs_id, cmd_enable); + /* U-Boot: Tell the DRV to wait for completion (?) so we can poll on DRV_STATUS */ + /* This register applies to the entire TCS group not per command */ + write_tcs_reg(drv, drv->regs[RSC_DRV_CMD_WAIT_FOR_CMPL], tcs_id, cmd_complete); } /** @@ -360,26 +386,22 @@ static void __tcs_set_trigger(struct rsc_drv *drv, int tcs_id, bool trigger) int rpmh_rsc_send_data(struct rsc_drv *drv, const struct tcs_request *msg) { struct tcs_group *tcs; - int tcs_id, i; - u32 addr; + int tcs_id, i = 0; + u32 val; tcs = get_tcs_for_msg(drv, msg); if (IS_ERR(tcs)) return PTR_ERR(tcs); - /* u-boot is single-threaded, always use the first TCS as we'll never conflict */ + /* U-Boot is single-threaded, always use the first TCS as we'll never conflict */ tcs_id = tcs->offset; + if (!read_tcs_reg(drv, drv->regs[RSC_DRV_STATUS], tcs_id)) { + pr_err("%s: TCS %d is busy!\n", __func__, tcs_id); + return -EBUSY; + } tcs->req[tcs_id - tcs->offset] = msg; generic_set_bit(tcs_id, drv->tcs_in_use); - if (msg->state == RPMH_ACTIVE_ONLY_STATE && tcs->type != ACTIVE_TCS) { - /* - * Clear previously programmed WAKE commands in selected - * repurposed TCS to avoid triggering them. tcs->slots will be - * cleaned from rpmh_flush() by invoking rpmh_rsc_invalidate() - */ - write_tcs_reg_sync(drv, drv->regs[RSC_DRV_CMD_ENABLE], tcs_id, 0); - } /* * These two can be done after the lock is released because: @@ -392,14 +414,27 @@ int rpmh_rsc_send_data(struct rsc_drv *drv, const struct tcs_request *msg) __tcs_buffer_write(drv, tcs_id, 0, msg); __tcs_set_trigger(drv, tcs_id, true); - /* U-Boot: Now wait for the TCS to be cleared, indicating that we're done */ + /* U-Boot: Now wait for the TCS to be cleared, indicating that we're done. */ for (i = 0; i < USEC_PER_SEC; i++) { - addr = read_tcs_cmd(drv, drv->regs[RSC_DRV_CMD_ADDR], i, 0); - if (addr != msg->cmds[0].addr) + val = read_tcs_cmd(drv, drv->regs[RSC_DRV_CMD_STATUS], tcs_id, 0); + if (val & CMD_STATUS_COMPL) break; udelay(1); } + /* U-Boot: read the response now we know it's available */ + if (msg->is_read) { + msg->cmds[0].data = read_tcs_cmd(drv, drv->regs[RSC_DRV_CMD_RESP_DATA], tcs_id, 0); + log_debug("data response: %#x\n", msg->cmds[0].data); + } + + __tcs_set_trigger(drv, tcs_id, false); + + /* Reclaim the TCS */ + write_tcs_reg(drv, drv->regs[RSC_DRV_CMD_ENABLE], tcs_id, 0); + writel_relaxed(BIT(tcs_id), drv->tcs_base + drv->regs[RSC_DRV_IRQ_CLEAR]); + generic_clear_bit(tcs_id, drv->tcs_in_use); + if (i == USEC_PER_SEC) { log_err("%s: error writing %#x to %d:%#x\n", drv->name, msg->cmds[0].addr, tcs_id, drv->regs[RSC_DRV_CMD_ADDR]); diff --git a/drivers/soc/qcom/rpmh.c b/drivers/soc/qcom/rpmh.c index 96f14a9afdf..8c222324c66 100644 --- a/drivers/soc/qcom/rpmh.c +++ b/drivers/soc/qcom/rpmh.c @@ -22,6 +22,7 @@ .state = s, \ .cmds = name.cmd, \ .num_cmds = 0, \ + .wait_for_compl = true \ }, \ .cmd = { { 0 } }, \ .dev = device, \ @@ -67,7 +68,7 @@ static int __rpmh_write(const struct udevice *dev, enum rpmh_state state, } static int __fill_rpmh_msg(struct rpmh_request *req, enum rpmh_state state, - const struct tcs_cmd *cmd, u32 n) + const struct tcs_cmd *cmd, u32 n, bool is_read) { if (!cmd || !n || n > MAX_RPMH_PAYLOAD) return -EINVAL; @@ -77,12 +78,45 @@ static int __fill_rpmh_msg(struct rpmh_request *req, enum rpmh_state state, req->msg.state = state; req->msg.cmds = req->cmd; req->msg.num_cmds = n; + req->msg.is_read = is_read; debug("rpmh_msg: %d, %d cmds [first %#x/%#x]\n", state, n, cmd->addr, cmd->data); return 0; } +/** + * rpmh_read: Read a resource value + * + * @dev: The device making the request + * @cmd: The payload having address of resource to read + * + * Reads the value for the resource address given in tcs_cmd->addr + * and returns the tcs_cmd->data filled with same. + * + * May sleep. Do not call from atomic contexts. + * + * Return: 0 on success, negative errno on failure + */ +int rpmh_read(const struct udevice *dev, enum rpmh_state state, struct tcs_cmd *cmd) +{ + DEFINE_RPMH_MSG_ONSTACK(dev, state, rpm_msg); + int ret; + + ret = __fill_rpmh_msg(&rpm_msg, state, cmd, 1, true); + if (ret) + return ret; + + ret = __rpmh_write(dev, state, &rpm_msg); + if (ret) + return ret; + + /* Read back the response into the cmd data structure */ + cmd->data = rpm_msg.cmd[0].data; + + return (ret > 0) ? 0 : ret; +} + /** * rpmh_write: Write a set of RPMH commands and block until response * @@ -99,7 +133,7 @@ int rpmh_write(const struct udevice *dev, enum rpmh_state state, DEFINE_RPMH_MSG_ONSTACK(dev, state, rpm_msg); int ret; - ret = __fill_rpmh_msg(&rpm_msg, state, cmd, n); + ret = __fill_rpmh_msg(&rpm_msg, state, cmd, n, false); if (ret) return ret; diff --git a/drivers/spmi/spmi-msm.c b/drivers/spmi/spmi-msm.c index faae54e9fef..f3cd98c3db8 100644 --- a/drivers/spmi/spmi-msm.c +++ b/drivers/spmi/spmi-msm.c @@ -274,10 +274,25 @@ static void msm_spmi_channel_map_v5(struct msm_spmi_priv *priv, unsigned int i, 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 */ + + } else if (owner == priv->owner) { + /* + * Found a channel owned by our EE - ALWAYS switch to it! + * even if we already have a mapping, we must prefer the one + * owned by our EE to avoid hardware access violations. + */ priv->channel_map[slave_id][pid] = i | SPMI_CHANNEL_VALID; + /* Clear READ_ONLY flag since we own this channel */ + + } else if (prev_read_only) { + /* + * Previous mapping was read-only and this one is also not ours. + * Update to this channel. + */ + priv->channel_map[slave_id][pid] = i | SPMI_CHANNEL_VALID | SPMI_CHANNEL_READ_ONLY; + } + /* else: Previous was writable and owned by us, this one isn't - keep previous */ } static int msm_spmi_probe(struct udevice *dev) diff --git a/drivers/usb/dwc3/dwc3-generic.c b/drivers/usb/dwc3/dwc3-generic.c index bb11613a587..22b9ef0b24e 100644 --- a/drivers/usb/dwc3/dwc3-generic.c +++ b/drivers/usb/dwc3/dwc3-generic.c @@ -461,9 +461,13 @@ static void dwc3_qcom_select_utmi_clk(void __iomem *qscratch_base) setbits_le32(qscratch_base + QSCRATCH_GENERAL_CFG, PIPE_UTMI_CLK_DIS); + udelay(100); + setbits_le32(qscratch_base + QSCRATCH_GENERAL_CFG, PIPE_UTMI_CLK_SEL | PIPE3_PHYSTATUS_SW); + udelay(100); + clrbits_le32(qscratch_base + QSCRATCH_GENERAL_CFG, PIPE_UTMI_CLK_DIS); } @@ -472,7 +476,14 @@ static void dwc3_qcom_glue_configure(struct udevice *dev, int index, enum usb_dr_mode mode) { struct dwc3_glue_data *glue = dev_get_plat(dev); - void __iomem *qscratch_base = map_physmem(glue->regs, 0x400, MAP_NOCACHE); + fdt_addr_t regs = glue->regs; + void __iomem *qscratch_base; + + /* Offset for qscratch base when using flat DT */ + if (device_is_compatible(dev, "qcom,snps-dwc3")) + regs += SDM845_QSCRATCH_BASE_OFFSET; + + qscratch_base = map_physmem(regs, 0x400, MAP_NOCACHE); if (IS_ERR_OR_NULL(qscratch_base)) { log_err("%s: Invalid qscratch base address\n", dev->name); return; @@ -485,11 +496,8 @@ static void dwc3_qcom_glue_configure(struct udevice *dev, int index, dwc3_qcom_vbus_override_enable(qscratch_base, true); } -struct dwc3_glue_ops qcom_ops = { - .glue_configure = dwc3_qcom_glue_configure, -}; - -static int dwc3_rk_glue_get_ctrl_dev(struct udevice *dev, ofnode *node) +/* In cases where there is no dwc3 node and it's flattened into the glue node */ +static int dwc3_flat_dt_get_ctrl_dev(struct udevice *dev, ofnode *node) { *node = dev_ofnode(dev); if (!ofnode_valid(*node)) @@ -498,8 +506,17 @@ static int dwc3_rk_glue_get_ctrl_dev(struct udevice *dev, ofnode *node) return 0; } +struct dwc3_glue_ops qcom_ops = { + .glue_configure = dwc3_qcom_glue_configure, +}; + +struct dwc3_glue_ops qcom_flat_dt_ops = { + .glue_configure = dwc3_qcom_glue_configure, + .glue_get_ctrl_dev = dwc3_flat_dt_get_ctrl_dev, +}; + struct dwc3_glue_ops rk_ops = { - .glue_get_ctrl_dev = dwc3_rk_glue_get_ctrl_dev, + .glue_get_ctrl_dev = dwc3_flat_dt_get_ctrl_dev, }; static int dwc3_glue_bind_common(struct udevice *parent, ofnode node) @@ -708,6 +725,7 @@ static const struct udevice_id dwc3_glue_ids[] = { { .compatible = "rockchip,rk3576-dwc3", .data = (ulong)&rk_ops }, { .compatible = "rockchip,rk3588-dwc3", .data = (ulong)&rk_ops }, { .compatible = "qcom,dwc3", .data = (ulong)&qcom_ops }, + { .compatible = "qcom,snps-dwc3", .data = (ulong)&qcom_flat_dt_ops }, { .compatible = "fsl,imx8mp-dwc3", .data = (ulong)&imx8mp_ops }, { .compatible = "fsl,imx8mq-dwc3" }, { .compatible = "intel,tangier-dwc3" }, diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index 7e08aeab904..ebb306852a6 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -61,7 +61,7 @@ config USB_GADGET_VENDOR_NUM default 0x0955 if ARCH_TEGRA default 0x1f3a if ARCH_SUNXI default 0x2207 if ARCH_ROCKCHIP - default 0x18d1 if ARCH_QCOM + default 0x18d1 if ARCH_SNAPDRAGON default 0x0 help Vendor ID of the USB device emulated, reported to the host device. @@ -89,7 +89,7 @@ config USB_GADGET_PRODUCT_NUM default 0x350b if ROCKCHIP_RK3588 default 0x350c if ROCKCHIP_RK3528 default 0x350e if ROCKCHIP_RK3576 - default 0x4ee0 if ARCH_QCOM + default 0x4ee0 if ARCH_SNAPDRAGON default 0x0 help Product ID of the USB device emulated, reported to the host device. diff --git a/drivers/watchdog/qcom-wdt.c b/drivers/watchdog/qcom-wdt.c index 4b972cff72c..e4ebb1f31d4 100644 --- a/drivers/watchdog/qcom-wdt.c +++ b/drivers/watchdog/qcom-wdt.c @@ -17,6 +17,9 @@ #include +/* Maximum allowed timeout value in Qcom SoCs*/ +#define QCOM_WDT_MAX_TIMEOUT 0xfffff + enum wdt_reg { WDT_RST, WDT_EN, @@ -55,8 +58,24 @@ static void __iomem *wdt_addr(struct qcom_wdt *wdt, enum wdt_reg reg) int qcom_wdt_start(struct udevice *dev, u64 timeout_ms, ulong flags) { struct qcom_wdt *wdt = dev_get_priv(dev); - ulong bark_timeout_s = ((timeout_ms - 1) * wdt->clk_rate) / 1000; - ulong bite_timeout_s = (timeout_ms * wdt->clk_rate) / 1000; + u64 tmp_timeout; + u32 bark_timeout_s, bite_timeout_s; + + /* Compute timeout in watchdog ticks */ + tmp_timeout = (timeout_ms * (u64)wdt->clk_rate) / 1000; + if (tmp_timeout > QCOM_WDT_MAX_TIMEOUT) { + dev_warn(dev, + "Requested timeout (%llu ms) exceeds maximum allowed value (%llu ms). " + "Using max timeout instead.\n", + timeout_ms, + ((u64)QCOM_WDT_MAX_TIMEOUT * 1000) / wdt->clk_rate); + tmp_timeout = (u32)QCOM_WDT_MAX_TIMEOUT; + timeout_ms = (tmp_timeout * 1000) / wdt->clk_rate; + } + + bite_timeout_s = (u32)tmp_timeout; + tmp_timeout = ((timeout_ms - 1) * (u64)wdt->clk_rate) / 1000; + bark_timeout_s = (u32)tmp_timeout; writel(0, wdt_addr(wdt, WDT_EN)); writel(BIT(0), wdt_addr(wdt, WDT_RST)); diff --git a/include/configs/dragonboard820c.h b/include/configs/dragonboard820c.h index c6d9182ccc9..8e408d8aec3 100644 --- a/include/configs/dragonboard820c.h +++ b/include/configs/dragonboard820c.h @@ -27,7 +27,6 @@ #define CFG_EXTRA_ENV_SETTINGS \ "loadaddr=0x95000000\0" \ - "fdt_high=0xffffffffffffffff\0" \ "initrd_high=0xffffffffffffffff\0" \ "linux_image=uImage\0" \ "kernel_addr_r=0x95000000\0"\ diff --git a/include/soc/qcom/rpmh.h b/include/soc/qcom/rpmh.h index 3421fbf1ee3..40812a315bc 100644 --- a/include/soc/qcom/rpmh.h +++ b/include/soc/qcom/rpmh.h @@ -13,12 +13,14 @@ #if IS_ENABLED(CONFIG_QCOM_RPMH) int rpmh_write(const struct udevice *dev, enum rpmh_state state, const struct tcs_cmd *cmd, u32 n); - +int rpmh_read(const struct udevice *dev, enum rpmh_state state, struct tcs_cmd *cmd); #else static inline int rpmh_write(const struct device *dev, enum rpmh_state state, const struct tcs_cmd *cmd, u32 n) { return -ENODEV; } +static inline int rpmh_read(const struct udevice *dev, struct tcs_cmd *cmd) +{ return -ENODEV; } #endif /* CONFIG_QCOM_RPMH */ diff --git a/include/soc/qcom/tcs.h b/include/soc/qcom/tcs.h index 3acca067c72..22bafe2598a 100644 --- a/include/soc/qcom/tcs.h +++ b/include/soc/qcom/tcs.h @@ -55,6 +55,7 @@ struct tcs_cmd { */ struct tcs_request { enum rpmh_state state; + bool is_read; u32 wait_for_compl; u32 num_cmds; struct tcs_cmd *cmds;