From a623c14f43d065a24e9ff7a1dfcbe38e5f9fed7e Mon Sep 17 00:00:00 2001 From: Caleb Connolly Date: Tue, 7 Nov 2023 12:40:59 +0000 Subject: [PATCH 01/24] clk/qcom: move from mach-snapdragon Clock drivers don't belong here, move them to the right place and declutter mach-snapdragon a bit. To de-couple these drivers from specific "target" platforms, add additional config options to enable each clock driver gated behind a common CLK_QCOM option and enable them by default for the respective targets. This will make future work easier as we move towards a generic Qualcomm target. Reviewed-by: Sumit Garg Signed-off-by: Caleb Connolly --- MAINTAINERS | 1 + arch/arm/mach-snapdragon/Kconfig | 4 ++ arch/arm/mach-snapdragon/Makefile | 5 --- drivers/clk/Kconfig | 1 + drivers/clk/Makefile | 1 + drivers/clk/qcom/Kconfig | 44 +++++++++++++++++++ drivers/clk/qcom/Makefile | 9 ++++ .../clk/qcom}/clock-apq8016.c | 2 +- .../clk/qcom}/clock-apq8096.c | 3 +- .../clk/qcom/clock-qcom.c | 2 +- .../clk/qcom/clock-qcom.h | 0 .../clk/qcom}/clock-qcs404.c | 2 +- .../clk/qcom}/clock-sdm845.c | 2 +- 13 files changed, 66 insertions(+), 10 deletions(-) create mode 100644 drivers/clk/qcom/Kconfig create mode 100644 drivers/clk/qcom/Makefile rename {arch/arm/mach-snapdragon => drivers/clk/qcom}/clock-apq8016.c (98%) rename {arch/arm/mach-snapdragon => drivers/clk/qcom}/clock-apq8096.c (98%) rename arch/arm/mach-snapdragon/clock-snapdragon.c => drivers/clk/qcom/clock-qcom.c (99%) rename arch/arm/mach-snapdragon/clock-snapdragon.h => drivers/clk/qcom/clock-qcom.h (100%) rename {arch/arm/mach-snapdragon => drivers/clk/qcom}/clock-qcs404.c (99%) rename {arch/arm/mach-snapdragon => drivers/clk/qcom}/clock-sdm845.c (98%) diff --git a/MAINTAINERS b/MAINTAINERS index 4fec063a242..185f5ebbb17 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -575,6 +575,7 @@ M: Neil Armstrong R: Sumit Garg S: Maintained F: arch/arm/mach-snapdragon/ +F: drivers/clk/qcom/ F: drivers/gpio/msm_gpio.c F: drivers/mmc/msm_sdhci.c F: drivers/phy/msm8916-usbh-phy.c diff --git a/arch/arm/mach-snapdragon/Kconfig b/arch/arm/mach-snapdragon/Kconfig index 2fc1521e2d3..dde37eccc55 100644 --- a/arch/arm/mach-snapdragon/Kconfig +++ b/arch/arm/mach-snapdragon/Kconfig @@ -15,6 +15,7 @@ config SPL_SYS_MALLOC_F_LEN config SDM845 bool "Qualcomm Snapdragon 845 SoC" select LINUX_KERNEL_IMAGE_HEADER + imply CLK_QCOM_SDM845 config LNX_KRNL_IMG_TEXT_OFFSET_BASE default 0x80000000 @@ -26,6 +27,7 @@ config TARGET_DRAGONBOARD410C bool "96Boards Dragonboard 410C" select BOARD_LATE_INIT select ENABLE_ARM_SOC_BOOT0_HOOK + imply CLK_QCOM_APQ8016 help Support for 96Boards Dragonboard 410C. This board complies with 96Board Open Platform Specifications. Features: @@ -39,6 +41,7 @@ config TARGET_DRAGONBOARD410C config TARGET_DRAGONBOARD820C bool "96Boards Dragonboard 820C" + imply CLK_QCOM_APQ8096 help Support for 96Boards Dragonboard 820C. This board complies with 96Board Open Platform Specifications. Features: @@ -72,6 +75,7 @@ config TARGET_STARQLTECHN config TARGET_QCS404EVB bool "Qualcomm Technologies, Inc. QCS404 EVB" select LINUX_KERNEL_IMAGE_HEADER + imply CLK_QCOM_QCS404 help Support for Qualcomm Technologies, Inc. QCS404 evaluation board. Features: diff --git a/arch/arm/mach-snapdragon/Makefile b/arch/arm/mach-snapdragon/Makefile index cbaaf23f6b5..497ee35cf7d 100644 --- a/arch/arm/mach-snapdragon/Makefile +++ b/arch/arm/mach-snapdragon/Makefile @@ -2,20 +2,15 @@ # # (C) Copyright 2015 Mateusz Kulikowski -obj-$(CONFIG_SDM845) += clock-sdm845.o obj-$(CONFIG_SDM845) += sysmap-sdm845.o obj-$(CONFIG_SDM845) += init_sdm845.o -obj-$(CONFIG_TARGET_DRAGONBOARD820C) += clock-apq8096.o obj-$(CONFIG_TARGET_DRAGONBOARD820C) += sysmap-apq8096.o -obj-$(CONFIG_TARGET_DRAGONBOARD410C) += clock-apq8016.o obj-$(CONFIG_TARGET_DRAGONBOARD410C) += sysmap-apq8016.o obj-y += misc.o -obj-y += clock-snapdragon.o obj-y += dram.o obj-y += pinctrl-snapdragon.o obj-y += pinctrl-apq8016.o obj-y += pinctrl-apq8096.o obj-y += pinctrl-qcs404.o obj-y += pinctrl-sdm845.o -obj-$(CONFIG_TARGET_QCS404EVB) += clock-qcs404.o obj-$(CONFIG_TARGET_QCS404EVB) += sysmap-qcs404.o diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index bfd23a99046..017dd260a54 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -254,6 +254,7 @@ source "drivers/clk/meson/Kconfig" source "drivers/clk/microchip/Kconfig" source "drivers/clk/mvebu/Kconfig" source "drivers/clk/owl/Kconfig" +source "drivers/clk/qcom/Kconfig" source "drivers/clk/renesas/Kconfig" source "drivers/clk/sunxi/Kconfig" source "drivers/clk/sifive/Kconfig" diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index af27ceb27da..638ad04baeb 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -39,6 +39,7 @@ obj-$(CONFIG_CLK_MPFS) += microchip/ obj-$(CONFIG_CLK_MVEBU) += mvebu/ obj-$(CONFIG_CLK_OCTEON) += clk_octeon.o obj-$(CONFIG_CLK_OWL) += owl/ +obj-$(CONFIG_CLK_QCOM) += qcom/ obj-$(CONFIG_CLK_RENESAS) += renesas/ obj-$(CONFIG_$(SPL_TPL_)CLK_SCMI) += clk_scmi.o obj-$(CONFIG_CLK_SIFIVE) += sifive/ diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig new file mode 100644 index 00000000000..a884f077d9b --- /dev/null +++ b/drivers/clk/qcom/Kconfig @@ -0,0 +1,44 @@ +if ARCH_SNAPDRAGON || ARCH_IPQ40XX + +config CLK_QCOM + bool + depends on CLK && DM_RESET + def_bool n + +menu "Qualcomm clock drivers" + +config CLK_QCOM_APQ8016 + bool "Qualcomm APQ8016 GCC" + select CLK_QCOM + help + Say Y here to enable support for the Global Clock Controller + on the Snapdragon APQ8016 SoC. This driver supports the clocks + and resets exposed by the GCC hardware block. + +config CLK_QCOM_APQ8096 + bool "Qualcomm APQ8096 GCC" + select CLK_QCOM + help + Say Y here to enable support for the Global Clock Controller + on the Snapdragon APQ8096 SoC. This driver supports the clocks + and resets exposed by the GCC hardware block. + +config CLK_QCOM_QCS404 + bool "Qualcomm QCS404 GCC" + select CLK_QCOM + help + Say Y here to enable support for the Global Clock Controller + on the Snapdragon QCS404 SoC. This driver supports the clocks + and resets exposed by the GCC hardware block. + +config CLK_QCOM_SDM845 + bool "Qualcomm SDM845 GCC" + select CLK_QCOM + help + Say Y here to enable support for the Global Clock Controller + on the Snapdragon 845 SoC. This driver supports the clocks + and resets exposed by the GCC hardware block. + +endmenu + +endif diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile new file mode 100644 index 00000000000..44d55583596 --- /dev/null +++ b/drivers/clk/qcom/Makefile @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# (C) Copyright 2023 Linaro + +obj-y += clock-qcom.o +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_QCS404) += clock-qcs404.o diff --git a/arch/arm/mach-snapdragon/clock-apq8016.c b/drivers/clk/qcom/clock-apq8016.c similarity index 98% rename from arch/arm/mach-snapdragon/clock-apq8016.c rename to drivers/clk/qcom/clock-apq8016.c index 23a37a1714d..90f2a93d9ed 100644 --- a/arch/arm/mach-snapdragon/clock-apq8016.c +++ b/drivers/clk/qcom/clock-apq8016.c @@ -13,7 +13,7 @@ #include #include #include -#include "clock-snapdragon.h" +#include "clock-qcom.h" /* GPLL0 clock control registers */ #define GPLL0_STATUS_ACTIVE BIT(17) diff --git a/arch/arm/mach-snapdragon/clock-apq8096.c b/drivers/clk/qcom/clock-apq8096.c similarity index 98% rename from arch/arm/mach-snapdragon/clock-apq8096.c rename to drivers/clk/qcom/clock-apq8096.c index 66184596d56..d5388c69aef 100644 --- a/arch/arm/mach-snapdragon/clock-apq8096.c +++ b/drivers/clk/qcom/clock-apq8096.c @@ -13,7 +13,8 @@ #include #include #include -#include "clock-snapdragon.h" + +#include "clock-qcom.h" /* GPLL0 clock control registers */ #define GPLL0_STATUS_ACTIVE BIT(30) diff --git a/arch/arm/mach-snapdragon/clock-snapdragon.c b/drivers/clk/qcom/clock-qcom.c similarity index 99% rename from arch/arm/mach-snapdragon/clock-snapdragon.c rename to drivers/clk/qcom/clock-qcom.c index 0ac45dce9a9..5667abeb89a 100644 --- a/arch/arm/mach-snapdragon/clock-snapdragon.c +++ b/drivers/clk/qcom/clock-qcom.c @@ -13,7 +13,7 @@ #include #include #include -#include "clock-snapdragon.h" +#include "clock-qcom.h" /* CBCR register fields */ #define CBCR_BRANCH_ENABLE_BIT BIT(0) diff --git a/arch/arm/mach-snapdragon/clock-snapdragon.h b/drivers/clk/qcom/clock-qcom.h similarity index 100% rename from arch/arm/mach-snapdragon/clock-snapdragon.h rename to drivers/clk/qcom/clock-qcom.h diff --git a/arch/arm/mach-snapdragon/clock-qcs404.c b/drivers/clk/qcom/clock-qcs404.c similarity index 99% rename from arch/arm/mach-snapdragon/clock-qcs404.c rename to drivers/clk/qcom/clock-qcs404.c index 3357b54c30c..80218af73ef 100644 --- a/arch/arm/mach-snapdragon/clock-qcs404.c +++ b/drivers/clk/qcom/clock-qcs404.c @@ -11,7 +11,7 @@ #include #include #include -#include "clock-snapdragon.h" +#include "clock-qcom.h" #include diff --git a/arch/arm/mach-snapdragon/clock-sdm845.c b/drivers/clk/qcom/clock-sdm845.c similarity index 98% rename from arch/arm/mach-snapdragon/clock-sdm845.c rename to drivers/clk/qcom/clock-sdm845.c index d6df0365afc..95a057b8298 100644 --- a/arch/arm/mach-snapdragon/clock-sdm845.c +++ b/drivers/clk/qcom/clock-sdm845.c @@ -15,7 +15,7 @@ #include #include #include -#include "clock-snapdragon.h" +#include "clock-qcom.h" #define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n) } From fac2121a47fe5fe6af45af0f5acfa5b8bd369b52 Mon Sep 17 00:00:00 2001 From: Caleb Connolly Date: Tue, 7 Nov 2023 12:41:00 +0000 Subject: [PATCH 02/24] clk/qcom: move ipq4019 driver from mach-ipq40xx This driver is just a stub, but it's necessary to support the upcoming reset driver changes. Reviewed-by: Sumit Garg Signed-off-by: Caleb Connolly --- arch/arm/Kconfig | 1 + arch/arm/mach-ipq40xx/Makefile | 1 - drivers/clk/qcom/Kconfig | 8 ++++ drivers/clk/qcom/Makefile | 1 + .../clk/qcom}/clock-ipq4019.c | 41 +------------------ drivers/clk/qcom/clock-qcom.c | 1 + 6 files changed, 13 insertions(+), 40 deletions(-) rename {arch/arm/mach-ipq40xx => drivers/clk/qcom}/clock-ipq4019.c (56%) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 2d4458b7b56..294ab9d0a3f 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -776,6 +776,7 @@ config ARCH_IPQ40XX select CLK select SMEM select OF_CONTROL + select CLK_QCOM_IPQ4019 imply CMD_DM config ARCH_KEYSTONE diff --git a/arch/arm/mach-ipq40xx/Makefile b/arch/arm/mach-ipq40xx/Makefile index 08a65b8854d..b36a935c6f9 100644 --- a/arch/arm/mach-ipq40xx/Makefile +++ b/arch/arm/mach-ipq40xx/Makefile @@ -4,6 +4,5 @@ # # Author: Robert Marko -obj-y += clock-ipq4019.o obj-y += pinctrl-snapdragon.o obj-y += pinctrl-ipq4019.o diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index a884f077d9b..0df0d1881a4 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -23,6 +23,14 @@ config CLK_QCOM_APQ8096 on the Snapdragon APQ8096 SoC. This driver supports the clocks and resets exposed by the GCC hardware block. +config CLK_QCOM_IPQ4019 + bool "Qualcomm IPQ4019 GCC" + select CLK_QCOM + help + Say Y here to enable support for the Global Clock Controller + on the Snapdragon IPQ4019 SoC. This driver supports the clocks + and resets exposed by the GCC hardware block. + config CLK_QCOM_QCS404 bool "Qualcomm QCS404 GCC" select CLK_QCOM diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile index 44d55583596..cb179fdac58 100644 --- a/drivers/clk/qcom/Makefile +++ b/drivers/clk/qcom/Makefile @@ -6,4 +6,5 @@ obj-y += clock-qcom.o 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_QCS404) += clock-qcs404.o diff --git a/arch/arm/mach-ipq40xx/clock-ipq4019.c b/drivers/clk/qcom/clock-ipq4019.c similarity index 56% rename from arch/arm/mach-ipq40xx/clock-ipq4019.c rename to drivers/clk/qcom/clock-ipq4019.c index c1d5c4ecdd8..04c99964df1 100644 --- a/arch/arm/mach-ipq40xx/clock-ipq4019.c +++ b/drivers/clk/qcom/clock-ipq4019.c @@ -12,12 +12,9 @@ #include #include #include - #include -struct msm_clk_priv { - phys_addr_t base; -}; +#include "clock-qcom.h" ulong msm_set_rate(struct clk *clk, ulong rate) { @@ -30,23 +27,7 @@ ulong msm_set_rate(struct clk *clk, ulong rate) } } -static int msm_clk_probe(struct udevice *dev) -{ - struct msm_clk_priv *priv = dev_get_priv(dev); - - priv->base = dev_read_addr(dev); - if (priv->base == FDT_ADDR_T_NONE) - return -EINVAL; - - return 0; -} - -static ulong msm_clk_set_rate(struct clk *clk, ulong rate) -{ - return msm_set_rate(clk, rate); -} - -static int msm_enable(struct clk *clk) +int msm_enable(struct clk *clk) { switch (clk->id) { case GCC_BLSP1_QUP1_SPI_APPS_CLK: /*SPI1*/ @@ -68,21 +49,3 @@ static int msm_enable(struct clk *clk) } } -static struct clk_ops msm_clk_ops = { - .set_rate = msm_clk_set_rate, - .enable = msm_enable, -}; - -static const struct udevice_id msm_clk_ids[] = { - { .compatible = "qcom,gcc-ipq4019" }, - { } -}; - -U_BOOT_DRIVER(clk_msm) = { - .name = "clk_msm", - .id = UCLASS_CLK, - .of_match = msm_clk_ids, - .ops = &msm_clk_ops, - .priv_auto = sizeof(struct msm_clk_priv), - .probe = msm_clk_probe, -}; diff --git a/drivers/clk/qcom/clock-qcom.c b/drivers/clk/qcom/clock-qcom.c index 5667abeb89a..5914616fba5 100644 --- a/drivers/clk/qcom/clock-qcom.c +++ b/drivers/clk/qcom/clock-qcom.c @@ -166,6 +166,7 @@ static const struct udevice_id msm_clk_ids[] = { { .compatible = "qcom,gcc-apq8016" }, { .compatible = "qcom,gcc-msm8996" }, { .compatible = "qcom,gcc-apq8096" }, + { .compatible = "qcom,gcc-ipq4019" }, { .compatible = "qcom,gcc-sdm845" }, { .compatible = "qcom,gcc-qcs404" }, { } From 3ead661633293413e9af6d1e20c0a1a362d08ee8 Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Tue, 7 Nov 2023 12:41:01 +0000 Subject: [PATCH 03/24] clk/qcom: handle resets and clocks in one device Qualcomm's clock controller blocks actually do much more than it says on the tin.. They provide clocks, resets and power domains. Currently, U-Boot requires one to spawn 2 separate devices for controlling clocks and resets, both spanning the same register space. Refactor the code to make it work with just a single DT node, making it compatible with upstream Linux bindings and dropping the dedicated reset driver in favour of including it in the clock driver. Heavily inspired by Renesas code for a similar hw block. [caleb: moved drivers to clk/qcom, added reset driver and adjusted bind logic. Imported qcom,gcc-ipq4019.h from Linux] Signed-off-by: Konrad Dybcio Reviewed-by: Sumit Garg Signed-off-by: Caleb Connolly --- arch/arm/Kconfig | 1 + arch/arm/dts/qcom-ipq4019.dtsi | 14 +- arch/arm/dts/qcs404-evb.dts | 19 +- drivers/clk/qcom/clock-apq8016.c | 17 ++ drivers/clk/qcom/clock-apq8096.c | 16 ++ drivers/clk/qcom/clock-ipq4019.c | 96 ++++++++- drivers/clk/qcom/clock-qcom.c | 119 +++++++++-- drivers/clk/qcom/clock-qcom.h | 22 +- drivers/clk/qcom/clock-qcs404.c | 50 ++++- drivers/clk/qcom/clock-sdm845.c | 42 ++++ drivers/reset/Kconfig | 7 - drivers/reset/Makefile | 1 - drivers/reset/reset-qcom.c | 195 ------------------ ...{qcom,ipq4019-gcc.h => qcom,gcc-ipq4019.h} | 73 +++++++ .../dt-bindings/reset/qcom,ipq4019-reset.h | 92 --------- 15 files changed, 422 insertions(+), 342 deletions(-) delete mode 100644 drivers/reset/reset-qcom.c rename include/dt-bindings/clock/{qcom,ipq4019-gcc.h => qcom,gcc-ipq4019.h} (58%) delete mode 100644 include/dt-bindings/reset/qcom,ipq4019-reset.h diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 294ab9d0a3f..2eef266e1d1 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1077,6 +1077,7 @@ config ARCH_SNAPDRAGON select DM select DM_GPIO select DM_SERIAL + select DM_RESET select GPIO_EXTRA_HEADER select MSM_SMEM select OF_CONTROL diff --git a/arch/arm/dts/qcom-ipq4019.dtsi b/arch/arm/dts/qcom-ipq4019.dtsi index 0850ae56e9a..f9489e42ea2 100644 --- a/arch/arm/dts/qcom-ipq4019.dtsi +++ b/arch/arm/dts/qcom-ipq4019.dtsi @@ -66,14 +66,6 @@ status = "disabled"; }; - reset: gcc-reset@1800000 { - compatible = "qcom,gcc-reset-ipq4019"; - reg = <0x1800000 0x60000>; - #clock-cells = <1>; - #reset-cells = <1>; - bootph-all; - }; - soc_gpios: pinctrl@1000000 { compatible = "qcom,ipq4019-pinctrl"; reg = <0x1000000 0x300000>; @@ -136,7 +128,7 @@ #phy-cells = <0>; reg = <0x9a000 0x800>; reg-names = "phy_base"; - resets = <&reset USB3_UNIPHY_PHY_ARES>; + resets = <&gcc USB3_UNIPHY_PHY_ARES>; reset-names = "por_rst"; status = "disabled"; }; @@ -146,7 +138,7 @@ #phy-cells = <0>; reg = <0xa6000 0x40>; reg-names = "phy_base"; - resets = <&reset USB3_HSPHY_POR_ARES>, <&reset USB3_HSPHY_S_ARES>; + resets = <&gcc USB3_HSPHY_POR_ARES>, <&gcc USB3_HSPHY_S_ARES>; reset-names = "por_rst", "srif_rst"; status = "disabled"; }; @@ -179,7 +171,7 @@ #phy-cells = <0>; reg = <0xa8000 0x40>; reg-names = "phy_base"; - resets = <&reset USB2_HSPHY_POR_ARES>, <&reset USB2_HSPHY_S_ARES>; + resets = <&gcc USB2_HSPHY_POR_ARES>, <&gcc USB2_HSPHY_S_ARES>; reset-names = "por_rst", "srif_rst"; status = "disabled"; }; diff --git a/arch/arm/dts/qcs404-evb.dts b/arch/arm/dts/qcs404-evb.dts index 8d7893c1169..84224a8a3d3 100644 --- a/arch/arm/dts/qcs404-evb.dts +++ b/arch/arm/dts/qcs404-evb.dts @@ -208,11 +208,6 @@ #address-cells = <0x1>; #size-cells = <0x0>; #clock-cells = <1>; - }; - - reset: gcc-reset@1800000 { - compatible = "qcom,gcc-reset-qcs404"; - reg = <0x1800000 0x80000>; #reset-cells = <1>; }; @@ -245,8 +240,8 @@ clocks = <&gcc GCC_USB_HS_PHY_CFG_AHB_CLK>, <&gcc GCC_USB3_PHY_PIPE_CLK>; clock-names = "ahb", "pipe"; - resets = <&reset GCC_USB3_PHY_BCR>, - <&reset GCC_USB3PHY_PHY_BCR>; + resets = <&gcc GCC_USB3_PHY_BCR>, + <&gcc GCC_USB3PHY_PHY_BCR>; reset-names = "com", "phy"; }; @@ -257,8 +252,8 @@ clocks = <&gcc GCC_USB_HS_PHY_CFG_AHB_CLK>, <&gcc GCC_USB2A_PHY_SLEEP_CLK>; clock-names = "ahb", "sleep"; - resets = <&reset GCC_USB_HS_PHY_CFG_AHB_BCR>, - <&reset GCC_USB2A_PHY_BCR>; + resets = <&gcc GCC_USB_HS_PHY_CFG_AHB_BCR>, + <&gcc GCC_USB2A_PHY_BCR>; reset-names = "phy", "por"; }; @@ -269,8 +264,8 @@ clocks = <&gcc GCC_USB_HS_PHY_CFG_AHB_CLK>, <&gcc GCC_USB2A_PHY_SLEEP_CLK>; clock-names = "ahb", "sleep"; - resets = <&reset GCC_QUSB2_PHY_BCR>, - <&reset GCC_USB2_HS_PHY_ONLY_BCR>; + resets = <&gcc GCC_QUSB2_PHY_BCR>, + <&gcc GCC_USB2_HS_PHY_ONLY_BCR>; reset-names = "phy", "por"; }; @@ -335,7 +330,7 @@ <&gcc GCC_ETH_PTP_CLK>, <&gcc GCC_ETH_RGMII_CLK>; - resets = <&reset GCC_EMAC_BCR>; + resets = <&gcc GCC_EMAC_BCR>; reset-names = "emac"; snps,tso; diff --git a/drivers/clk/qcom/clock-apq8016.c b/drivers/clk/qcom/clock-apq8016.c index 90f2a93d9ed..3bddbd27590 100644 --- a/drivers/clk/qcom/clock-apq8016.c +++ b/drivers/clk/qcom/clock-apq8016.c @@ -13,6 +13,7 @@ #include #include #include + #include "clock-qcom.h" /* GPLL0 clock control registers */ @@ -116,3 +117,19 @@ int msm_enable(struct clk *clk) { return 0; } + +static const struct udevice_id gcc_apq8016_of_match[] = { + { + .compatible = "qcom,gcc-apq8016", + /* TODO: add reset map */ + }, + { } +}; + +U_BOOT_DRIVER(gcc_apq8016) = { + .name = "gcc_apq8016", + .id = UCLASS_NOP, + .of_match = gcc_apq8016_of_match, + .bind = qcom_cc_bind, + .flags = DM_FLAG_PRE_RELOC, +}; diff --git a/drivers/clk/qcom/clock-apq8096.c b/drivers/clk/qcom/clock-apq8096.c index d5388c69aef..64b8cdf4c54 100644 --- a/drivers/clk/qcom/clock-apq8096.c +++ b/drivers/clk/qcom/clock-apq8096.c @@ -99,3 +99,19 @@ int msm_enable(struct clk *clk) { return 0; } + +static const struct udevice_id gcc_apq8096_of_match[] = { + { + .compatible = "qcom,gcc-apq8096", + /* TODO: add reset map */ + }, + { } +}; + +U_BOOT_DRIVER(gcc_apq8096) = { + .name = "gcc_apq8096", + .id = UCLASS_NOP, + .of_match = gcc_apq8096_of_match, + .bind = qcom_cc_bind, + .flags = DM_FLAG_PRE_RELOC, +}; diff --git a/drivers/clk/qcom/clock-ipq4019.c b/drivers/clk/qcom/clock-ipq4019.c index 04c99964df1..db869f87421 100644 --- a/drivers/clk/qcom/clock-ipq4019.c +++ b/drivers/clk/qcom/clock-ipq4019.c @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include "clock-qcom.h" @@ -49,3 +49,97 @@ int msm_enable(struct clk *clk) } } +static const struct qcom_reset_map gcc_ipq4019_resets[] = { + [WIFI0_CPU_INIT_RESET] = { 0x1f008, 5 }, + [WIFI0_RADIO_SRIF_RESET] = { 0x1f008, 4 }, + [WIFI0_RADIO_WARM_RESET] = { 0x1f008, 3 }, + [WIFI0_RADIO_COLD_RESET] = { 0x1f008, 2 }, + [WIFI0_CORE_WARM_RESET] = { 0x1f008, 1 }, + [WIFI0_CORE_COLD_RESET] = { 0x1f008, 0 }, + [WIFI1_CPU_INIT_RESET] = { 0x20008, 5 }, + [WIFI1_RADIO_SRIF_RESET] = { 0x20008, 4 }, + [WIFI1_RADIO_WARM_RESET] = { 0x20008, 3 }, + [WIFI1_RADIO_COLD_RESET] = { 0x20008, 2 }, + [WIFI1_CORE_WARM_RESET] = { 0x20008, 1 }, + [WIFI1_CORE_COLD_RESET] = { 0x20008, 0 }, + [USB3_UNIPHY_PHY_ARES] = { 0x1e038, 5 }, + [USB3_HSPHY_POR_ARES] = { 0x1e038, 4 }, + [USB3_HSPHY_S_ARES] = { 0x1e038, 2 }, + [USB2_HSPHY_POR_ARES] = { 0x1e01c, 4 }, + [USB2_HSPHY_S_ARES] = { 0x1e01c, 2 }, + [PCIE_PHY_AHB_ARES] = { 0x1d010, 11 }, + [PCIE_AHB_ARES] = { 0x1d010, 10 }, + [PCIE_PWR_ARES] = { 0x1d010, 9 }, + [PCIE_PIPE_STICKY_ARES] = { 0x1d010, 8 }, + [PCIE_AXI_M_STICKY_ARES] = { 0x1d010, 7 }, + [PCIE_PHY_ARES] = { 0x1d010, 6 }, + [PCIE_PARF_XPU_ARES] = { 0x1d010, 5 }, + [PCIE_AXI_S_XPU_ARES] = { 0x1d010, 4 }, + [PCIE_AXI_M_VMIDMT_ARES] = { 0x1d010, 3 }, + [PCIE_PIPE_ARES] = { 0x1d010, 2 }, + [PCIE_AXI_S_ARES] = { 0x1d010, 1 }, + [PCIE_AXI_M_ARES] = { 0x1d010, 0 }, + [ESS_RESET] = { 0x12008, 0}, + [GCC_BLSP1_BCR] = {0x01000, 0}, + [GCC_BLSP1_QUP1_BCR] = {0x02000, 0}, + [GCC_BLSP1_UART1_BCR] = {0x02038, 0}, + [GCC_BLSP1_QUP2_BCR] = {0x03008, 0}, + [GCC_BLSP1_UART2_BCR] = {0x03028, 0}, + [GCC_BIMC_BCR] = {0x04000, 0}, + [GCC_TLMM_BCR] = {0x05000, 0}, + [GCC_IMEM_BCR] = {0x0E000, 0}, + [GCC_ESS_BCR] = {0x12008, 0}, + [GCC_PRNG_BCR] = {0x13000, 0}, + [GCC_BOOT_ROM_BCR] = {0x13008, 0}, + [GCC_CRYPTO_BCR] = {0x16000, 0}, + [GCC_SDCC1_BCR] = {0x18000, 0}, + [GCC_SEC_CTRL_BCR] = {0x1A000, 0}, + [GCC_AUDIO_BCR] = {0x1B008, 0}, + [GCC_QPIC_BCR] = {0x1C000, 0}, + [GCC_PCIE_BCR] = {0x1D000, 0}, + [GCC_USB2_BCR] = {0x1E008, 0}, + [GCC_USB2_PHY_BCR] = {0x1E018, 0}, + [GCC_USB3_BCR] = {0x1E024, 0}, + [GCC_USB3_PHY_BCR] = {0x1E034, 0}, + [GCC_SYSTEM_NOC_BCR] = {0x21000, 0}, + [GCC_PCNOC_BCR] = {0x2102C, 0}, + [GCC_DCD_BCR] = {0x21038, 0}, + [GCC_SNOC_BUS_TIMEOUT0_BCR] = {0x21064, 0}, + [GCC_SNOC_BUS_TIMEOUT1_BCR] = {0x2106C, 0}, + [GCC_SNOC_BUS_TIMEOUT2_BCR] = {0x21074, 0}, + [GCC_SNOC_BUS_TIMEOUT3_BCR] = {0x2107C, 0}, + [GCC_PCNOC_BUS_TIMEOUT0_BCR] = {0x21084, 0}, + [GCC_PCNOC_BUS_TIMEOUT1_BCR] = {0x2108C, 0}, + [GCC_PCNOC_BUS_TIMEOUT2_BCR] = {0x21094, 0}, + [GCC_PCNOC_BUS_TIMEOUT3_BCR] = {0x2109C, 0}, + [GCC_PCNOC_BUS_TIMEOUT4_BCR] = {0x210A4, 0}, + [GCC_PCNOC_BUS_TIMEOUT5_BCR] = {0x210AC, 0}, + [GCC_PCNOC_BUS_TIMEOUT6_BCR] = {0x210B4, 0}, + [GCC_PCNOC_BUS_TIMEOUT7_BCR] = {0x210BC, 0}, + [GCC_PCNOC_BUS_TIMEOUT8_BCR] = {0x210C4, 0}, + [GCC_PCNOC_BUS_TIMEOUT9_BCR] = {0x210CC, 0}, + [GCC_TCSR_BCR] = {0x22000, 0}, + [GCC_MPM_BCR] = {0x24000, 0}, + [GCC_SPDM_BCR] = {0x25000, 0}, +}; + +static struct msm_clk_data ipq4019_data = { + .resets = gcc_ipq4019_resets, + .num_resets = ARRAY_SIZE(gcc_ipq4019_resets), +}; + +static const struct udevice_id gcc_ipq4019_of_match[] = { + { + .compatible = "qcom,gcc-ipq4019", + .data = (ulong)&ipq4019_data, + }, + { } +}; + +U_BOOT_DRIVER(gcc_ipq4019) = { + .name = "gcc_ipq4019", + .id = UCLASS_NOP, + .of_match = gcc_ipq4019_of_match, + .bind = qcom_cc_bind, + .flags = DM_FLAG_PRE_RELOC, +}; diff --git a/drivers/clk/qcom/clock-qcom.c b/drivers/clk/qcom/clock-qcom.c index 5914616fba5..a661837e4e1 100644 --- a/drivers/clk/qcom/clock-qcom.c +++ b/drivers/clk/qcom/clock-qcom.c @@ -1,8 +1,13 @@ -// SPDX-License-Identifier: BSD-3-Clause +// SPDX-License-Identifier: BSD-3-Clause AND GPL-2.0 /* - * Clock drivers for Qualcomm APQ8016, APQ8096 + * Clock and reset drivers for Qualcomm platforms Global Clock + * Controller (GCC). * * (C) Copyright 2015 Mateusz Kulikowski + * (C) Copyright 2020 Sartura Ltd. (reset driver) + * Author: Robert Marko + * (C) Copyright 2022 Linaro Ltd. (reset driver) + * Author: Sumit Garg * * Based on Little Kernel driver, simplified */ @@ -10,9 +15,13 @@ #include #include #include +#include +#include #include #include #include +#include + #include "clock-qcom.h" /* CBCR register fields */ @@ -137,12 +146,15 @@ void clk_rcg_set_rate(phys_addr_t base, const struct bcr_regs *regs, int div, static int msm_clk_probe(struct udevice *dev) { + struct msm_clk_data *data = (struct msm_clk_data *)dev_get_driver_data(dev); struct msm_clk_priv *priv = dev_get_priv(dev); priv->base = dev_read_addr(dev); if (priv->base == FDT_ADDR_T_NONE) return -EINVAL; + priv->data = data; + return 0; } @@ -161,22 +173,97 @@ static struct clk_ops msm_clk_ops = { .enable = msm_clk_enable, }; -static const struct udevice_id msm_clk_ids[] = { - { .compatible = "qcom,gcc-msm8916" }, - { .compatible = "qcom,gcc-apq8016" }, - { .compatible = "qcom,gcc-msm8996" }, - { .compatible = "qcom,gcc-apq8096" }, - { .compatible = "qcom,gcc-ipq4019" }, - { .compatible = "qcom,gcc-sdm845" }, - { .compatible = "qcom,gcc-qcs404" }, - { } -}; - -U_BOOT_DRIVER(clk_msm) = { - .name = "clk_msm", +U_BOOT_DRIVER(qcom_clk) = { + .name = "qcom_clk", .id = UCLASS_CLK, - .of_match = msm_clk_ids, .ops = &msm_clk_ops, .priv_auto = sizeof(struct msm_clk_priv), .probe = msm_clk_probe, }; + +int qcom_cc_bind(struct udevice *parent) +{ + struct msm_clk_data *data = (struct msm_clk_data *)dev_get_driver_data(parent); + struct udevice *clkdev, *rstdev; + struct driver *drv; + int ret; + + /* Get a handle to the common clk handler */ + drv = lists_driver_lookup_name("qcom_clk"); + if (!drv) + return -ENOENT; + + /* Register the clock controller */ + ret = device_bind_with_driver_data(parent, drv, "qcom_clk", (ulong)data, + dev_ofnode(parent), &clkdev); + if (ret) + return ret; + + /* Bail out early if resets are not specified for this platform */ + if (!data->resets) + return ret; + + /* Get a handle to the common reset handler */ + drv = lists_driver_lookup_name("qcom_reset"); + if (!drv) + return -ENOENT; + + /* Register the reset controller */ + ret = device_bind_with_driver_data(parent, drv, "qcom_reset", (ulong)data, + dev_ofnode(parent), &rstdev); + if (ret) + device_unbind(clkdev); + + return ret; +} + +static int qcom_reset_set(struct reset_ctl *rst, bool assert) +{ + struct msm_clk_data *data = (struct msm_clk_data *)dev_get_driver_data(rst->dev); + void __iomem *base = dev_get_priv(rst->dev); + const struct qcom_reset_map *map; + u32 value; + + map = &data->resets[rst->id]; + + value = readl(base + map->reg); + + if (assert) + value |= BIT(map->bit); + else + value &= ~BIT(map->bit); + + writel(value, base + map->reg); + + return 0; +} + +static int qcom_reset_assert(struct reset_ctl *rst) +{ + return qcom_reset_set(rst, true); +} + +static int qcom_reset_deassert(struct reset_ctl *rst) +{ + return qcom_reset_set(rst, false); +} + +static const struct reset_ops qcom_reset_ops = { + .rst_assert = qcom_reset_assert, + .rst_deassert = qcom_reset_deassert, +}; + +static int qcom_reset_probe(struct udevice *dev) +{ + /* Set our priv pointer to the base address */ + dev_set_priv(dev, (void *)dev_read_addr(dev)); + + return 0; +} + +U_BOOT_DRIVER(qcom_reset) = { + .name = "qcom_reset", + .id = UCLASS_RESET, + .ops = &qcom_reset_ops, + .probe = qcom_reset_probe, +}; diff --git a/drivers/clk/qcom/clock-qcom.h b/drivers/clk/qcom/clock-qcom.h index c90bbefa588..a9f895c2422 100644 --- a/drivers/clk/qcom/clock-qcom.h +++ b/drivers/clk/qcom/clock-qcom.h @@ -1,11 +1,9 @@ /* SPDX-License-Identifier: GPL-2.0+ */ /* - * Qualcomm APQ8016, APQ8096, SDM845 - * * (C) Copyright 2017 Jorge Ramirez-Ortiz */ -#ifndef _CLOCK_SNAPDRAGON_H -#define _CLOCK_SNAPDRAGON_H +#ifndef _CLOCK_QCOM_H +#define _CLOCK_QCOM_H #define CFG_CLK_SRC_CXO (0 << 8) #define CFG_CLK_SRC_GPLL0 (1 << 8) @@ -32,10 +30,22 @@ struct bcr_regs { uintptr_t D; }; -struct msm_clk_priv { - phys_addr_t base; +struct qcom_reset_map { + unsigned int reg; + u8 bit; }; +struct msm_clk_data { + const struct qcom_reset_map *resets; + unsigned long num_resets; +}; + +struct msm_clk_priv { + phys_addr_t base; + struct msm_clk_data *data; +}; + +int qcom_cc_bind(struct udevice *parent); void clk_enable_gpll0(phys_addr_t base, const struct pll_vote_clk *gpll0); void clk_bcr_update(phys_addr_t apps_cmd_rgcr); void clk_enable_cbc(phys_addr_t cbcr); diff --git a/drivers/clk/qcom/clock-qcs404.c b/drivers/clk/qcom/clock-qcs404.c index 80218af73ef..10ac3609be4 100644 --- a/drivers/clk/qcom/clock-qcs404.c +++ b/drivers/clk/qcom/clock-qcs404.c @@ -11,9 +11,10 @@ #include #include #include +#include + #include "clock-qcom.h" -#include /* GPLL0 clock control registers */ #define GPLL0_STATUS_ACTIVE BIT(31) @@ -235,3 +236,50 @@ int msm_enable(struct clk *clk) return 0; } + +static const struct qcom_reset_map qcs404_gcc_resets[] = { + [GCC_GENI_IR_BCR] = { 0x0F000 }, + [GCC_CDSP_RESTART] = { 0x18000 }, + [GCC_USB_HS_BCR] = { 0x41000 }, + [GCC_USB2_HS_PHY_ONLY_BCR] = { 0x41034 }, + [GCC_QUSB2_PHY_BCR] = { 0x4103c }, + [GCC_USB_HS_PHY_CFG_AHB_BCR] = { 0x0000c, 1 }, + [GCC_USB2A_PHY_BCR] = { 0x0000c, 0 }, + [GCC_USB3_PHY_BCR] = { 0x39004 }, + [GCC_USB_30_BCR] = { 0x39000 }, + [GCC_USB3PHY_PHY_BCR] = { 0x39008 }, + [GCC_PCIE_0_BCR] = { 0x3e000 }, + [GCC_PCIE_0_PHY_BCR] = { 0x3e004 }, + [GCC_PCIE_0_LINK_DOWN_BCR] = { 0x3e038 }, + [GCC_PCIEPHY_0_PHY_BCR] = { 0x3e03c }, + [GCC_PCIE_0_AXI_MASTER_STICKY_ARES] = { 0x3e040, 6}, + [GCC_PCIE_0_AHB_ARES] = { 0x3e040, 5 }, + [GCC_PCIE_0_AXI_SLAVE_ARES] = { 0x3e040, 4 }, + [GCC_PCIE_0_AXI_MASTER_ARES] = { 0x3e040, 3 }, + [GCC_PCIE_0_CORE_STICKY_ARES] = { 0x3e040, 2 }, + [GCC_PCIE_0_SLEEP_ARES] = { 0x3e040, 1 }, + [GCC_PCIE_0_PIPE_ARES] = { 0x3e040, 0 }, + [GCC_EMAC_BCR] = { 0x4e000 }, + [GCC_WDSP_RESTART] = {0x19000}, +}; + +static const struct msm_clk_data qcs404_gcc_data = { + .resets = qcs404_gcc_resets, + .num_resets = ARRAY_SIZE(qcs404_gcc_resets), +}; + +static const struct udevice_id gcc_qcs404_of_match[] = { + { + .compatible = "qcom,gcc-qcs404", + .data = (ulong)&qcs404_gcc_data + }, + { } +}; + +U_BOOT_DRIVER(gcc_qcs404) = { + .name = "gcc_qcs404", + .id = UCLASS_NOP, + .of_match = gcc_qcs404_of_match, + .bind = qcom_cc_bind, + .flags = DM_FLAG_PRE_RELOC, +}; diff --git a/drivers/clk/qcom/clock-sdm845.c b/drivers/clk/qcom/clock-sdm845.c index 95a057b8298..a7a43f69b9b 100644 --- a/drivers/clk/qcom/clock-sdm845.c +++ b/drivers/clk/qcom/clock-sdm845.c @@ -15,6 +15,7 @@ #include #include #include + #include "clock-qcom.h" #define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n) } @@ -96,3 +97,44 @@ int msm_enable(struct clk *clk) { return 0; } + +static const struct qcom_reset_map sdm845_gcc_resets[] = { + [GCC_QUPV3_WRAPPER_0_BCR] = { 0x17000 }, + [GCC_QUPV3_WRAPPER_1_BCR] = { 0x18000 }, + [GCC_QUSB2PHY_PRIM_BCR] = { 0x12000 }, + [GCC_QUSB2PHY_SEC_BCR] = { 0x12004 }, + [GCC_SDCC2_BCR] = { 0x14000 }, + [GCC_SDCC4_BCR] = { 0x16000 }, + [GCC_UFS_CARD_BCR] = { 0x75000 }, + [GCC_UFS_PHY_BCR] = { 0x77000 }, + [GCC_USB30_PRIM_BCR] = { 0xf000 }, + [GCC_USB30_SEC_BCR] = { 0x10000 }, + [GCC_USB3_PHY_PRIM_BCR] = { 0x50000 }, + [GCC_USB3PHY_PHY_PRIM_BCR] = { 0x50004 }, + [GCC_USB3_DP_PHY_PRIM_BCR] = { 0x50008 }, + [GCC_USB3_PHY_SEC_BCR] = { 0x5000c }, + [GCC_USB3PHY_PHY_SEC_BCR] = { 0x50010 }, + [GCC_USB3_DP_PHY_SEC_BCR] = { 0x50014 }, + [GCC_USB_PHY_CFG_AHB2PHY_BCR] = { 0x6a000 }, +}; + +static const struct msm_clk_data qcs404_gcc_data = { + .resets = sdm845_gcc_resets, + .num_resets = ARRAY_SIZE(sdm845_gcc_resets), +}; + +static const struct udevice_id gcc_sdm845_of_match[] = { + { + .compatible = "qcom,gcc-sdm845", + .data = (ulong)&qcs404_gcc_data, + }, + { } +}; + +U_BOOT_DRIVER(gcc_sdm845) = { + .name = "gcc_sdm845", + .id = UCLASS_NOP, + .of_match = gcc_sdm845_of_match, + .bind = qcom_cc_bind, + .flags = DM_FLAG_PRE_RELOC, +}; diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig index 73bbd306925..88e04d93f2a 100644 --- a/drivers/reset/Kconfig +++ b/drivers/reset/Kconfig @@ -156,13 +156,6 @@ config RESET_IMX7 help Support for reset controller on i.MX7/8 SoCs. -config RESET_QCOM - bool "Reset driver for Qualcomm SoCs" - depends on DM_RESET && (ARCH_SNAPDRAGON || ARCH_IPQ40XX) - default y - help - Support for reset controller on Qualcomm SoCs. - config RESET_SIFIVE bool "Reset Driver for SiFive SoC's" depends on DM_RESET && CLK_SIFIVE_PRCI && (TARGET_SIFIVE_UNLEASHED || TARGET_SIFIVE_UNMATCHED) diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile index e2239a250a3..7b0066f8018 100644 --- a/drivers/reset/Makefile +++ b/drivers/reset/Makefile @@ -24,7 +24,6 @@ obj-$(CONFIG_RESET_MTMIPS) += reset-mtmips.o obj-$(CONFIG_RESET_SUNXI) += reset-sunxi.o obj-$(CONFIG_RESET_HISILICON) += reset-hisilicon.o obj-$(CONFIG_RESET_IMX7) += reset-imx7.o -obj-$(CONFIG_RESET_QCOM) += reset-qcom.o obj-$(CONFIG_RESET_SIFIVE) += reset-sifive.o obj-$(CONFIG_RESET_SYSCON) += reset-syscon.o obj-$(CONFIG_RESET_RASPBERRYPI) += reset-raspberrypi.o diff --git a/drivers/reset/reset-qcom.c b/drivers/reset/reset-qcom.c deleted file mode 100644 index 94315e76d54..00000000000 --- a/drivers/reset/reset-qcom.c +++ /dev/null @@ -1,195 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (c) 2020 Sartura Ltd. - * Copyright (c) 2022 Linaro Ltd. - * - * Author: Robert Marko - * Sumit Garg - * - * Based on Linux driver - */ - -#include -#include -#include -#include -#include -#include - -struct qcom_reset_priv { - phys_addr_t base; -}; - -struct qcom_reset_map { - unsigned int reg; - u8 bit; -}; - -#ifdef CONFIG_ARCH_IPQ40XX -#include -static const struct qcom_reset_map gcc_qcom_resets[] = { - [WIFI0_CPU_INIT_RESET] = { 0x1f008, 5 }, - [WIFI0_RADIO_SRIF_RESET] = { 0x1f008, 4 }, - [WIFI0_RADIO_WARM_RESET] = { 0x1f008, 3 }, - [WIFI0_RADIO_COLD_RESET] = { 0x1f008, 2 }, - [WIFI0_CORE_WARM_RESET] = { 0x1f008, 1 }, - [WIFI0_CORE_COLD_RESET] = { 0x1f008, 0 }, - [WIFI1_CPU_INIT_RESET] = { 0x20008, 5 }, - [WIFI1_RADIO_SRIF_RESET] = { 0x20008, 4 }, - [WIFI1_RADIO_WARM_RESET] = { 0x20008, 3 }, - [WIFI1_RADIO_COLD_RESET] = { 0x20008, 2 }, - [WIFI1_CORE_WARM_RESET] = { 0x20008, 1 }, - [WIFI1_CORE_COLD_RESET] = { 0x20008, 0 }, - [USB3_UNIPHY_PHY_ARES] = { 0x1e038, 5 }, - [USB3_HSPHY_POR_ARES] = { 0x1e038, 4 }, - [USB3_HSPHY_S_ARES] = { 0x1e038, 2 }, - [USB2_HSPHY_POR_ARES] = { 0x1e01c, 4 }, - [USB2_HSPHY_S_ARES] = { 0x1e01c, 2 }, - [PCIE_PHY_AHB_ARES] = { 0x1d010, 11 }, - [PCIE_AHB_ARES] = { 0x1d010, 10 }, - [PCIE_PWR_ARES] = { 0x1d010, 9 }, - [PCIE_PIPE_STICKY_ARES] = { 0x1d010, 8 }, - [PCIE_AXI_M_STICKY_ARES] = { 0x1d010, 7 }, - [PCIE_PHY_ARES] = { 0x1d010, 6 }, - [PCIE_PARF_XPU_ARES] = { 0x1d010, 5 }, - [PCIE_AXI_S_XPU_ARES] = { 0x1d010, 4 }, - [PCIE_AXI_M_VMIDMT_ARES] = { 0x1d010, 3 }, - [PCIE_PIPE_ARES] = { 0x1d010, 2 }, - [PCIE_AXI_S_ARES] = { 0x1d010, 1 }, - [PCIE_AXI_M_ARES] = { 0x1d010, 0 }, - [ESS_RESET] = { 0x12008, 0}, - [GCC_BLSP1_BCR] = {0x01000, 0}, - [GCC_BLSP1_QUP1_BCR] = {0x02000, 0}, - [GCC_BLSP1_UART1_BCR] = {0x02038, 0}, - [GCC_BLSP1_QUP2_BCR] = {0x03008, 0}, - [GCC_BLSP1_UART2_BCR] = {0x03028, 0}, - [GCC_BIMC_BCR] = {0x04000, 0}, - [GCC_TLMM_BCR] = {0x05000, 0}, - [GCC_IMEM_BCR] = {0x0E000, 0}, - [GCC_ESS_BCR] = {0x12008, 0}, - [GCC_PRNG_BCR] = {0x13000, 0}, - [GCC_BOOT_ROM_BCR] = {0x13008, 0}, - [GCC_CRYPTO_BCR] = {0x16000, 0}, - [GCC_SDCC1_BCR] = {0x18000, 0}, - [GCC_SEC_CTRL_BCR] = {0x1A000, 0}, - [GCC_AUDIO_BCR] = {0x1B008, 0}, - [GCC_QPIC_BCR] = {0x1C000, 0}, - [GCC_PCIE_BCR] = {0x1D000, 0}, - [GCC_USB2_BCR] = {0x1E008, 0}, - [GCC_USB2_PHY_BCR] = {0x1E018, 0}, - [GCC_USB3_BCR] = {0x1E024, 0}, - [GCC_USB3_PHY_BCR] = {0x1E034, 0}, - [GCC_SYSTEM_NOC_BCR] = {0x21000, 0}, - [GCC_PCNOC_BCR] = {0x2102C, 0}, - [GCC_DCD_BCR] = {0x21038, 0}, - [GCC_SNOC_BUS_TIMEOUT0_BCR] = {0x21064, 0}, - [GCC_SNOC_BUS_TIMEOUT1_BCR] = {0x2106C, 0}, - [GCC_SNOC_BUS_TIMEOUT2_BCR] = {0x21074, 0}, - [GCC_SNOC_BUS_TIMEOUT3_BCR] = {0x2107C, 0}, - [GCC_PCNOC_BUS_TIMEOUT0_BCR] = {0x21084, 0}, - [GCC_PCNOC_BUS_TIMEOUT1_BCR] = {0x2108C, 0}, - [GCC_PCNOC_BUS_TIMEOUT2_BCR] = {0x21094, 0}, - [GCC_PCNOC_BUS_TIMEOUT3_BCR] = {0x2109C, 0}, - [GCC_PCNOC_BUS_TIMEOUT4_BCR] = {0x210A4, 0}, - [GCC_PCNOC_BUS_TIMEOUT5_BCR] = {0x210AC, 0}, - [GCC_PCNOC_BUS_TIMEOUT6_BCR] = {0x210B4, 0}, - [GCC_PCNOC_BUS_TIMEOUT7_BCR] = {0x210BC, 0}, - [GCC_PCNOC_BUS_TIMEOUT8_BCR] = {0x210C4, 0}, - [GCC_PCNOC_BUS_TIMEOUT9_BCR] = {0x210CC, 0}, - [GCC_TCSR_BCR] = {0x22000, 0}, - [GCC_MPM_BCR] = {0x24000, 0}, - [GCC_SPDM_BCR] = {0x25000, 0}, -}; -#endif - -#ifdef CONFIG_TARGET_QCS404EVB -#include -static const struct qcom_reset_map gcc_qcom_resets[] = { - [GCC_GENI_IR_BCR] = { 0x0F000 }, - [GCC_CDSP_RESTART] = { 0x18000 }, - [GCC_USB_HS_BCR] = { 0x41000 }, - [GCC_USB2_HS_PHY_ONLY_BCR] = { 0x41034 }, - [GCC_QUSB2_PHY_BCR] = { 0x4103c }, - [GCC_USB_HS_PHY_CFG_AHB_BCR] = { 0x0000c, 1 }, - [GCC_USB2A_PHY_BCR] = { 0x0000c, 0 }, - [GCC_USB3_PHY_BCR] = { 0x39004 }, - [GCC_USB_30_BCR] = { 0x39000 }, - [GCC_USB3PHY_PHY_BCR] = { 0x39008 }, - [GCC_PCIE_0_BCR] = { 0x3e000 }, - [GCC_PCIE_0_PHY_BCR] = { 0x3e004 }, - [GCC_PCIE_0_LINK_DOWN_BCR] = { 0x3e038 }, - [GCC_PCIEPHY_0_PHY_BCR] = { 0x3e03c }, - [GCC_PCIE_0_AXI_MASTER_STICKY_ARES] = { 0x3e040, 6}, - [GCC_PCIE_0_AHB_ARES] = { 0x3e040, 5 }, - [GCC_PCIE_0_AXI_SLAVE_ARES] = { 0x3e040, 4 }, - [GCC_PCIE_0_AXI_MASTER_ARES] = { 0x3e040, 3 }, - [GCC_PCIE_0_CORE_STICKY_ARES] = { 0x3e040, 2 }, - [GCC_PCIE_0_SLEEP_ARES] = { 0x3e040, 1 }, - [GCC_PCIE_0_PIPE_ARES] = { 0x3e040, 0 }, - [GCC_EMAC_BCR] = { 0x4e000 }, - [GCC_WDSP_RESTART] = {0x19000}, -}; -#endif - -static int qcom_reset_assert(struct reset_ctl *rst) -{ - struct qcom_reset_priv *priv = dev_get_priv(rst->dev); - const struct qcom_reset_map *reset_map = gcc_qcom_resets; - const struct qcom_reset_map *map; - u32 value; - - map = &reset_map[rst->id]; - - value = readl(priv->base + map->reg); - value |= BIT(map->bit); - writel(value, priv->base + map->reg); - - return 0; -} - -static int qcom_reset_deassert(struct reset_ctl *rst) -{ - struct qcom_reset_priv *priv = dev_get_priv(rst->dev); - const struct qcom_reset_map *reset_map = gcc_qcom_resets; - const struct qcom_reset_map *map; - u32 value; - - map = &reset_map[rst->id]; - - value = readl(priv->base + map->reg); - value &= ~BIT(map->bit); - writel(value, priv->base + map->reg); - - return 0; -} - -static const struct reset_ops qcom_reset_ops = { - .rst_assert = qcom_reset_assert, - .rst_deassert = qcom_reset_deassert, -}; - -static const struct udevice_id qcom_reset_ids[] = { - { .compatible = "qcom,gcc-reset-ipq4019" }, - { .compatible = "qcom,gcc-reset-qcs404" }, - { } -}; - -static int qcom_reset_probe(struct udevice *dev) -{ - struct qcom_reset_priv *priv = dev_get_priv(dev); - - priv->base = dev_read_addr(dev); - if (priv->base == FDT_ADDR_T_NONE) - return -EINVAL; - - return 0; -} - -U_BOOT_DRIVER(qcom_reset) = { - .name = "qcom_reset", - .id = UCLASS_RESET, - .of_match = qcom_reset_ids, - .ops = &qcom_reset_ops, - .probe = qcom_reset_probe, - .priv_auto = sizeof(struct qcom_reset_priv), -}; diff --git a/include/dt-bindings/clock/qcom,ipq4019-gcc.h b/include/dt-bindings/clock/qcom,gcc-ipq4019.h similarity index 58% rename from include/dt-bindings/clock/qcom,ipq4019-gcc.h rename to include/dt-bindings/clock/qcom,gcc-ipq4019.h index 7130e222e41..7e8a7be6dcd 100644 --- a/include/dt-bindings/clock/qcom,ipq4019-gcc.h +++ b/include/dt-bindings/clock/qcom,gcc-ipq4019.h @@ -93,4 +93,77 @@ #define GCC_APSS_CPU_PLLDIV_CLK 74 #define GCC_PCNOC_AHB_CLK_SRC 75 +#define WIFI0_CPU_INIT_RESET 0 +#define WIFI0_RADIO_SRIF_RESET 1 +#define WIFI0_RADIO_WARM_RESET 2 +#define WIFI0_RADIO_COLD_RESET 3 +#define WIFI0_CORE_WARM_RESET 4 +#define WIFI0_CORE_COLD_RESET 5 +#define WIFI1_CPU_INIT_RESET 6 +#define WIFI1_RADIO_SRIF_RESET 7 +#define WIFI1_RADIO_WARM_RESET 8 +#define WIFI1_RADIO_COLD_RESET 9 +#define WIFI1_CORE_WARM_RESET 10 +#define WIFI1_CORE_COLD_RESET 11 +#define USB3_UNIPHY_PHY_ARES 12 +#define USB3_HSPHY_POR_ARES 13 +#define USB3_HSPHY_S_ARES 14 +#define USB2_HSPHY_POR_ARES 15 +#define USB2_HSPHY_S_ARES 16 +#define PCIE_PHY_AHB_ARES 17 +#define PCIE_AHB_ARES 18 +#define PCIE_PWR_ARES 19 +#define PCIE_PIPE_STICKY_ARES 20 +#define PCIE_AXI_M_STICKY_ARES 21 +#define PCIE_PHY_ARES 22 +#define PCIE_PARF_XPU_ARES 23 +#define PCIE_AXI_S_XPU_ARES 24 +#define PCIE_AXI_M_VMIDMT_ARES 25 +#define PCIE_PIPE_ARES 26 +#define PCIE_AXI_S_ARES 27 +#define PCIE_AXI_M_ARES 28 +#define ESS_RESET 29 +#define GCC_BLSP1_BCR 30 +#define GCC_BLSP1_QUP1_BCR 31 +#define GCC_BLSP1_UART1_BCR 32 +#define GCC_BLSP1_QUP2_BCR 33 +#define GCC_BLSP1_UART2_BCR 34 +#define GCC_BIMC_BCR 35 +#define GCC_TLMM_BCR 36 +#define GCC_IMEM_BCR 37 +#define GCC_ESS_BCR 38 +#define GCC_PRNG_BCR 39 +#define GCC_BOOT_ROM_BCR 40 +#define GCC_CRYPTO_BCR 41 +#define GCC_SDCC1_BCR 42 +#define GCC_SEC_CTRL_BCR 43 +#define GCC_AUDIO_BCR 44 +#define GCC_QPIC_BCR 45 +#define GCC_PCIE_BCR 46 +#define GCC_USB2_BCR 47 +#define GCC_USB2_PHY_BCR 48 +#define GCC_USB3_BCR 49 +#define GCC_USB3_PHY_BCR 50 +#define GCC_SYSTEM_NOC_BCR 51 +#define GCC_PCNOC_BCR 52 +#define GCC_DCD_BCR 53 +#define GCC_SNOC_BUS_TIMEOUT0_BCR 54 +#define GCC_SNOC_BUS_TIMEOUT1_BCR 55 +#define GCC_SNOC_BUS_TIMEOUT2_BCR 56 +#define GCC_SNOC_BUS_TIMEOUT3_BCR 57 +#define GCC_PCNOC_BUS_TIMEOUT0_BCR 58 +#define GCC_PCNOC_BUS_TIMEOUT1_BCR 59 +#define GCC_PCNOC_BUS_TIMEOUT2_BCR 60 +#define GCC_PCNOC_BUS_TIMEOUT3_BCR 61 +#define GCC_PCNOC_BUS_TIMEOUT4_BCR 62 +#define GCC_PCNOC_BUS_TIMEOUT5_BCR 63 +#define GCC_PCNOC_BUS_TIMEOUT6_BCR 64 +#define GCC_PCNOC_BUS_TIMEOUT7_BCR 65 +#define GCC_PCNOC_BUS_TIMEOUT8_BCR 66 +#define GCC_PCNOC_BUS_TIMEOUT9_BCR 67 +#define GCC_TCSR_BCR 68 +#define GCC_QDSS_BCR 69 +#define GCC_MPM_BCR 70 +#define GCC_SPDM_BCR 71 + #endif diff --git a/include/dt-bindings/reset/qcom,ipq4019-reset.h b/include/dt-bindings/reset/qcom,ipq4019-reset.h deleted file mode 100644 index ed047d7402d..00000000000 --- a/include/dt-bindings/reset/qcom,ipq4019-reset.h +++ /dev/null @@ -1,92 +0,0 @@ -/* Copyright (c) 2015 The Linux Foundation. All rights reserved. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ -#ifndef __QCOM_RESET_IPQ4019_H__ -#define __QCOM_RESET_IPQ4019_H__ - -#define WIFI0_CPU_INIT_RESET 0 -#define WIFI0_RADIO_SRIF_RESET 1 -#define WIFI0_RADIO_WARM_RESET 2 -#define WIFI0_RADIO_COLD_RESET 3 -#define WIFI0_CORE_WARM_RESET 4 -#define WIFI0_CORE_COLD_RESET 5 -#define WIFI1_CPU_INIT_RESET 6 -#define WIFI1_RADIO_SRIF_RESET 7 -#define WIFI1_RADIO_WARM_RESET 8 -#define WIFI1_RADIO_COLD_RESET 9 -#define WIFI1_CORE_WARM_RESET 10 -#define WIFI1_CORE_COLD_RESET 11 -#define USB3_UNIPHY_PHY_ARES 12 -#define USB3_HSPHY_POR_ARES 13 -#define USB3_HSPHY_S_ARES 14 -#define USB2_HSPHY_POR_ARES 15 -#define USB2_HSPHY_S_ARES 16 -#define PCIE_PHY_AHB_ARES 17 -#define PCIE_AHB_ARES 18 -#define PCIE_PWR_ARES 19 -#define PCIE_PIPE_STICKY_ARES 20 -#define PCIE_AXI_M_STICKY_ARES 21 -#define PCIE_PHY_ARES 22 -#define PCIE_PARF_XPU_ARES 23 -#define PCIE_AXI_S_XPU_ARES 24 -#define PCIE_AXI_M_VMIDMT_ARES 25 -#define PCIE_PIPE_ARES 26 -#define PCIE_AXI_S_ARES 27 -#define PCIE_AXI_M_ARES 28 -#define ESS_RESET 29 -#define GCC_BLSP1_BCR 30 -#define GCC_BLSP1_QUP1_BCR 31 -#define GCC_BLSP1_UART1_BCR 32 -#define GCC_BLSP1_QUP2_BCR 33 -#define GCC_BLSP1_UART2_BCR 34 -#define GCC_BIMC_BCR 35 -#define GCC_TLMM_BCR 36 -#define GCC_IMEM_BCR 37 -#define GCC_ESS_BCR 38 -#define GCC_PRNG_BCR 39 -#define GCC_BOOT_ROM_BCR 40 -#define GCC_CRYPTO_BCR 41 -#define GCC_SDCC1_BCR 42 -#define GCC_SEC_CTRL_BCR 43 -#define GCC_AUDIO_BCR 44 -#define GCC_QPIC_BCR 45 -#define GCC_PCIE_BCR 46 -#define GCC_USB2_BCR 47 -#define GCC_USB2_PHY_BCR 48 -#define GCC_USB3_BCR 49 -#define GCC_USB3_PHY_BCR 50 -#define GCC_SYSTEM_NOC_BCR 51 -#define GCC_PCNOC_BCR 52 -#define GCC_DCD_BCR 53 -#define GCC_SNOC_BUS_TIMEOUT0_BCR 54 -#define GCC_SNOC_BUS_TIMEOUT1_BCR 55 -#define GCC_SNOC_BUS_TIMEOUT2_BCR 56 -#define GCC_SNOC_BUS_TIMEOUT3_BCR 57 -#define GCC_PCNOC_BUS_TIMEOUT0_BCR 58 -#define GCC_PCNOC_BUS_TIMEOUT1_BCR 59 -#define GCC_PCNOC_BUS_TIMEOUT2_BCR 60 -#define GCC_PCNOC_BUS_TIMEOUT3_BCR 61 -#define GCC_PCNOC_BUS_TIMEOUT4_BCR 62 -#define GCC_PCNOC_BUS_TIMEOUT5_BCR 63 -#define GCC_PCNOC_BUS_TIMEOUT6_BCR 64 -#define GCC_PCNOC_BUS_TIMEOUT7_BCR 65 -#define GCC_PCNOC_BUS_TIMEOUT8_BCR 66 -#define GCC_PCNOC_BUS_TIMEOUT9_BCR 67 -#define GCC_TCSR_BCR 68 -#define GCC_QDSS_BCR 69 -#define GCC_MPM_BCR 70 -#define GCC_SPDM_BCR 71 - -#endif From 0e7fec02ce49556da2f045a8d04c69f2ae9fbd93 Mon Sep 17 00:00:00 2001 From: Caleb Connolly Date: Tue, 7 Nov 2023 12:41:02 +0000 Subject: [PATCH 04/24] clk/qcom: sdm845: add register map for simple gate clocks Many gate clocks can be enabled with a single register write, add support for defining these simple gate clocks and add the ones found on SDM845. While we're here, inline clk_init_uart() into msm_set_rate(). Reviewed-by: Sumit Garg Signed-off-by: Caleb Connolly --- drivers/clk/qcom/clock-qcom.h | 26 ++++++++++ drivers/clk/qcom/clock-sdm845.c | 87 ++++++++++++++++++++++++++++----- 2 files changed, 101 insertions(+), 12 deletions(-) diff --git a/drivers/clk/qcom/clock-qcom.h b/drivers/clk/qcom/clock-qcom.h index a9f895c2422..6d399db987b 100644 --- a/drivers/clk/qcom/clock-qcom.h +++ b/drivers/clk/qcom/clock-qcom.h @@ -5,6 +5,8 @@ #ifndef _CLOCK_QCOM_H #define _CLOCK_QCOM_H +#include + #define CFG_CLK_SRC_CXO (0 << 8) #define CFG_CLK_SRC_GPLL0 (1 << 8) #define CFG_CLK_SRC_GPLL0_EVEN (6 << 8) @@ -30,6 +32,18 @@ struct bcr_regs { uintptr_t D; }; +struct gate_clk { + uintptr_t reg; + u32 en_val; + const char *name; +}; + +#ifdef DEBUG +#define GATE_CLK(clk, reg, val) [clk] = { reg, val, #clk } +#else +#define GATE_CLK(clk, reg, val) [clk] = { reg, val, NULL } +#endif + struct qcom_reset_map { unsigned int reg; u8 bit; @@ -38,6 +52,8 @@ struct qcom_reset_map { struct msm_clk_data { const struct qcom_reset_map *resets; unsigned long num_resets; + const struct gate_clk *clks; + unsigned long num_clks; }; struct msm_clk_priv { @@ -55,4 +71,14 @@ void clk_rcg_set_rate_mnd(phys_addr_t base, const struct bcr_regs *regs, void clk_rcg_set_rate(phys_addr_t base, const struct bcr_regs *regs, int div, int source); +static inline void 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; + + val = readl(priv->base + priv->data->clks[id].reg); + writel(val | priv->data->clks[id].en_val, priv->base + priv->data->clks[id].reg); +} + #endif diff --git a/drivers/clk/qcom/clock-sdm845.c b/drivers/clk/qcom/clock-sdm845.c index a7a43f69b9b..57124e2a661 100644 --- a/drivers/clk/qcom/clock-sdm845.c +++ b/drivers/clk/qcom/clock-sdm845.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -71,30 +72,90 @@ const struct freq_tbl *qcom_find_freq(const struct freq_tbl *f, uint rate) return f - 1; } -static int clk_init_uart(struct msm_clk_priv *priv, uint rate) -{ - const struct freq_tbl *freq = qcom_find_freq(ftbl_gcc_qupv3_wrap0_s0_clk_src, rate); - - clk_rcg_set_rate_mnd(priv->base, &uart2_regs, - freq->pre_div, freq->m, freq->n, freq->src); - - return 0; -} - ulong msm_set_rate(struct clk *clk, ulong rate) { struct msm_clk_priv *priv = dev_get_priv(clk->dev); + const struct freq_tbl *freq; switch (clk->id) { - case GCC_QUPV3_WRAP1_S1_CLK: /*UART2*/ - return clk_init_uart(priv, rate); + case GCC_QUPV3_WRAP1_S1_CLK: /* UART9 */ + freq = qcom_find_freq(ftbl_gcc_qupv3_wrap0_s0_clk_src, rate); + clk_rcg_set_rate_mnd(priv->base, &uart2_regs, + freq->pre_div, freq->m, freq->n, freq->src); + + return freq->freq; default: return 0; } } +static const struct gate_clk sdm845_clks[] = { + GATE_CLK(GCC_QUPV3_WRAP0_S0_CLK, 0x5200c, 0x00000400), + GATE_CLK(GCC_QUPV3_WRAP0_S1_CLK, 0x5200c, 0x00000800), + GATE_CLK(GCC_QUPV3_WRAP0_S2_CLK, 0x5200c, 0x00001000), + GATE_CLK(GCC_QUPV3_WRAP0_S3_CLK, 0x5200c, 0x00002000), + GATE_CLK(GCC_QUPV3_WRAP0_S4_CLK, 0x5200c, 0x00004000), + GATE_CLK(GCC_QUPV3_WRAP0_S5_CLK, 0x5200c, 0x00008000), + GATE_CLK(GCC_QUPV3_WRAP0_S6_CLK, 0x5200c, 0x00010000), + GATE_CLK(GCC_QUPV3_WRAP0_S7_CLK, 0x5200c, 0x00020000), + GATE_CLK(GCC_QUPV3_WRAP1_S0_CLK, 0x5200c, 0x00400000), + GATE_CLK(GCC_QUPV3_WRAP1_S1_CLK, 0x5200c, 0x00800000), + GATE_CLK(GCC_QUPV3_WRAP1_S3_CLK, 0x5200c, 0x02000000), + GATE_CLK(GCC_QUPV3_WRAP1_S4_CLK, 0x5200c, 0x04000000), + GATE_CLK(GCC_QUPV3_WRAP1_S5_CLK, 0x5200c, 0x08000000), + GATE_CLK(GCC_QUPV3_WRAP1_S6_CLK, 0x5200c, 0x10000000), + GATE_CLK(GCC_QUPV3_WRAP1_S7_CLK, 0x5200c, 0x20000000), + GATE_CLK(GCC_QUPV3_WRAP_0_M_AHB_CLK, 0x5200c, 0x00000040), + GATE_CLK(GCC_QUPV3_WRAP_0_S_AHB_CLK, 0x5200c, 0x00000080), + GATE_CLK(GCC_QUPV3_WRAP_1_M_AHB_CLK, 0x5200c, 0x00100000), + GATE_CLK(GCC_QUPV3_WRAP_1_S_AHB_CLK, 0x5200c, 0x00200000), + GATE_CLK(GCC_SDCC2_AHB_CLK, 0x14008, 0x00000001), + GATE_CLK(GCC_SDCC2_APPS_CLK, 0x14004, 0x00000001), + GATE_CLK(GCC_SDCC4_AHB_CLK, 0x16008, 0x00000001), + GATE_CLK(GCC_SDCC4_APPS_CLK, 0x16004, 0x00000001), + GATE_CLK(GCC_UFS_CARD_AHB_CLK, 0x75010, 0x00000001), + GATE_CLK(GCC_UFS_CARD_AXI_CLK, 0x7500c, 0x00000001), + GATE_CLK(GCC_UFS_CARD_CLKREF_CLK, 0x8c004, 0x00000001), + GATE_CLK(GCC_UFS_CARD_ICE_CORE_CLK, 0x75058, 0x00000001), + GATE_CLK(GCC_UFS_CARD_PHY_AUX_CLK, 0x7508c, 0x00000001), + GATE_CLK(GCC_UFS_CARD_RX_SYMBOL_0_CLK, 0x75018, 0x00000001), + GATE_CLK(GCC_UFS_CARD_RX_SYMBOL_1_CLK, 0x750a8, 0x00000001), + GATE_CLK(GCC_UFS_CARD_TX_SYMBOL_0_CLK, 0x75014, 0x00000001), + GATE_CLK(GCC_UFS_CARD_UNIPRO_CORE_CLK, 0x75054, 0x00000001), + GATE_CLK(GCC_UFS_MEM_CLKREF_CLK, 0x8c000, 0x00000001), + GATE_CLK(GCC_UFS_PHY_AHB_CLK, 0x77010, 0x00000001), + GATE_CLK(GCC_UFS_PHY_AXI_CLK, 0x7700c, 0x00000001), + GATE_CLK(GCC_UFS_PHY_ICE_CORE_CLK, 0x77058, 0x00000001), + GATE_CLK(GCC_UFS_PHY_PHY_AUX_CLK, 0x7708c, 0x00000001), + GATE_CLK(GCC_UFS_PHY_RX_SYMBOL_0_CLK, 0x77018, 0x00000001), + GATE_CLK(GCC_UFS_PHY_RX_SYMBOL_1_CLK, 0x770a8, 0x00000001), + GATE_CLK(GCC_UFS_PHY_TX_SYMBOL_0_CLK, 0x77014, 0x00000001), + GATE_CLK(GCC_UFS_PHY_UNIPRO_CORE_CLK, 0x77054, 0x00000001), + GATE_CLK(GCC_USB30_PRIM_MASTER_CLK, 0x0f00c, 0x00000001), + GATE_CLK(GCC_USB30_PRIM_MOCK_UTMI_CLK, 0x0f014, 0x00000001), + GATE_CLK(GCC_USB30_PRIM_SLEEP_CLK, 0x0f010, 0x00000001), + GATE_CLK(GCC_USB30_SEC_MASTER_CLK, 0x1000c, 0x00000001), + GATE_CLK(GCC_USB30_SEC_MOCK_UTMI_CLK, 0x10014, 0x00000001), + GATE_CLK(GCC_USB30_SEC_SLEEP_CLK, 0x10010, 0x00000001), + GATE_CLK(GCC_USB3_PRIM_CLKREF_CLK, 0x8c008, 0x00000001), + GATE_CLK(GCC_USB3_PRIM_PHY_AUX_CLK, 0x0f04c, 0x00000001), + GATE_CLK(GCC_USB3_PRIM_PHY_COM_AUX_CLK, 0x0f050, 0x00000001), + GATE_CLK(GCC_USB3_PRIM_PHY_PIPE_CLK, 0x0f054, 0x00000001), + GATE_CLK(GCC_USB3_SEC_CLKREF_CLK, 0x8c028, 0x00000001), + GATE_CLK(GCC_USB3_SEC_PHY_AUX_CLK, 0x1004c, 0x00000001), + GATE_CLK(GCC_USB3_SEC_PHY_PIPE_CLK, 0x10054, 0x00000001), + GATE_CLK(GCC_USB3_SEC_PHY_COM_AUX_CLK, 0x10050, 0x00000001), + GATE_CLK(GCC_USB_PHY_CFG_AHB2PHY_CLK, 0x6a004, 0x00000001), +}; + int msm_enable(struct clk *clk) { + struct msm_clk_priv *priv = dev_get_priv(clk->dev); + + debug("%s: clk %s\n", __func__, sdm845_clks[clk->id].name); + + qcom_gate_clk_en(priv, clk->id); + return 0; } @@ -121,6 +182,8 @@ static const struct qcom_reset_map sdm845_gcc_resets[] = { static const struct msm_clk_data qcs404_gcc_data = { .resets = sdm845_gcc_resets, .num_resets = ARRAY_SIZE(sdm845_gcc_resets), + .clks = sdm845_clks, + .num_clks = ARRAY_SIZE(sdm845_clks), }; static const struct udevice_id gcc_sdm845_of_match[] = { From 37ea1343ac92e614d40279273e35920a4827c310 Mon Sep 17 00:00:00 2001 From: Caleb Connolly Date: Tue, 7 Nov 2023 12:41:03 +0000 Subject: [PATCH 05/24] clk/qcom: use function pointers for enable and set_rate Currently, it isn't possible to build clock drivers for more than one platform due to how the msm_enable() and msm_set_rate() callbacks are implemented. Extend qcom_clk_data to include function pointers for these and convert all platforms to use them. Previously, clock drivers relied on include/configs/ to include the board specific sysmap header, however as most of the header contents are clock driver related, import the contents directly into each clock driver and remove the header. The only exception here is the dragonboard820c board file which includes some pinctrl macros, those are also inlined. Reviewed-by: Sumit Garg Signed-off-by: Caleb Connolly [caleb: remove additional sysmap-sdm845.h mention] --- .../include/mach/sysmap-apq8016.h | 39 -------- .../include/mach/sysmap-apq8096.h | 37 -------- .../include/mach/sysmap-qcs404.h | 88 ------------------- .../include/mach/sysmap-sdm845.h | 42 --------- .../dragonboard820c/dragonboard820c.c | 6 +- drivers/clk/qcom/clock-apq8016.c | 37 ++++++-- drivers/clk/qcom/clock-apq8096.c | 33 +++++-- drivers/clk/qcom/clock-ipq4019.c | 10 ++- drivers/clk/qcom/clock-qcom.c | 17 ++-- drivers/clk/qcom/clock-qcom.h | 5 ++ drivers/clk/qcom/clock-qcs404.c | 85 +++++++++++++++++- drivers/clk/qcom/clock-sdm845.c | 19 +++- include/configs/dragonboard410c.h | 1 - include/configs/dragonboard820c.h | 1 - include/configs/dragonboard845c.h | 1 - include/configs/qcs404-evb.h | 1 - include/configs/sdm845.h | 1 - 17 files changed, 182 insertions(+), 241 deletions(-) delete mode 100644 arch/arm/mach-snapdragon/include/mach/sysmap-apq8016.h delete mode 100644 arch/arm/mach-snapdragon/include/mach/sysmap-apq8096.h delete mode 100644 arch/arm/mach-snapdragon/include/mach/sysmap-qcs404.h delete mode 100644 arch/arm/mach-snapdragon/include/mach/sysmap-sdm845.h diff --git a/arch/arm/mach-snapdragon/include/mach/sysmap-apq8016.h b/arch/arm/mach-snapdragon/include/mach/sysmap-apq8016.h deleted file mode 100644 index d9a3b1af986..00000000000 --- a/arch/arm/mach-snapdragon/include/mach/sysmap-apq8016.h +++ /dev/null @@ -1,39 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Qualcomm APQ8916 sysmap - * - * (C) Copyright 2015 Mateusz Kulikowski - */ -#ifndef _MACH_SYSMAP_APQ8016_H -#define _MACH_SYSMAP_APQ8016_H - -#define GICD_BASE (0x0b000000) -#define GICC_BASE (0x0b002000) - -/* Clocks: (from CLK_CTL_BASE) */ -#define GPLL0_STATUS (0x2101C) -#define APCS_GPLL_ENA_VOTE (0x45000) -#define APCS_CLOCK_BRANCH_ENA_VOTE (0x45004) - -#define SDCC_BCR(n) ((n * 0x1000) + 0x41000) -#define SDCC_CMD_RCGR(n) ((n * 0x1000) + 0x41004) -#define SDCC_CFG_RCGR(n) ((n * 0x1000) + 0x41008) -#define SDCC_M(n) ((n * 0x1000) + 0x4100C) -#define SDCC_N(n) ((n * 0x1000) + 0x41010) -#define SDCC_D(n) ((n * 0x1000) + 0x41014) -#define SDCC_APPS_CBCR(n) ((n * 0x1000) + 0x41018) -#define SDCC_AHB_CBCR(n) ((n * 0x1000) + 0x4101C) - -/* BLSP1 AHB clock (root clock for BLSP) */ -#define BLSP1_AHB_CBCR 0x1008 - -/* Uart clock control registers */ -#define BLSP1_UART2_BCR (0x3028) -#define BLSP1_UART2_APPS_CBCR (0x302C) -#define BLSP1_UART2_APPS_CMD_RCGR (0x3034) -#define BLSP1_UART2_APPS_CFG_RCGR (0x3038) -#define BLSP1_UART2_APPS_M (0x303C) -#define BLSP1_UART2_APPS_N (0x3040) -#define BLSP1_UART2_APPS_D (0x3044) - -#endif diff --git a/arch/arm/mach-snapdragon/include/mach/sysmap-apq8096.h b/arch/arm/mach-snapdragon/include/mach/sysmap-apq8096.h deleted file mode 100644 index 36a902bd929..00000000000 --- a/arch/arm/mach-snapdragon/include/mach/sysmap-apq8096.h +++ /dev/null @@ -1,37 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Qualcomm APQ8096 sysmap - * - * (C) Copyright 2017 Jorge Ramirez-Ortiz - */ -#ifndef _MACH_SYSMAP_APQ8096_H -#define _MACH_SYSMAP_APQ8096_H - -#define TLMM_BASE_ADDR (0x1010000) - -/* Strength (sdc1) */ -#define SDC1_HDRV_PULL_CTL_REG (TLMM_BASE_ADDR + 0x0012D000) - -/* Clocks: (from CLK_CTL_BASE) */ -#define GPLL0_STATUS (0x0000) -#define APCS_GPLL_ENA_VOTE (0x52000) -#define APCS_CLOCK_BRANCH_ENA_VOTE (0x52004) - -#define SDCC2_BCR (0x14000) /* block reset */ -#define SDCC2_APPS_CBCR (0x14004) /* branch control */ -#define SDCC2_AHB_CBCR (0x14008) -#define SDCC2_CMD_RCGR (0x14010) -#define SDCC2_CFG_RCGR (0x14014) -#define SDCC2_M (0x14018) -#define SDCC2_N (0x1401C) -#define SDCC2_D (0x14020) - -#define BLSP2_AHB_CBCR (0x25004) -#define BLSP2_UART2_APPS_CBCR (0x29004) -#define BLSP2_UART2_APPS_CMD_RCGR (0x2900C) -#define BLSP2_UART2_APPS_CFG_RCGR (0x29010) -#define BLSP2_UART2_APPS_M (0x29014) -#define BLSP2_UART2_APPS_N (0x29018) -#define BLSP2_UART2_APPS_D (0x2901C) - -#endif diff --git a/arch/arm/mach-snapdragon/include/mach/sysmap-qcs404.h b/arch/arm/mach-snapdragon/include/mach/sysmap-qcs404.h deleted file mode 100644 index 5768fb13775..00000000000 --- a/arch/arm/mach-snapdragon/include/mach/sysmap-qcs404.h +++ /dev/null @@ -1,88 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Qualcomm QCS404 sysmap - * - * (C) Copyright 2022 Sumit Garg - */ -#ifndef _MACH_SYSMAP_QCS404_H -#define _MACH_SYSMAP_QCS404_H - -#define GICD_BASE (0x0b000000) -#define GICC_BASE (0x0b002000) - -/* Clocks: (from CLK_CTL_BASE) */ -#define GPLL0_STATUS (0x21000) -#define GPLL1_STATUS (0x20000) -#define APCS_GPLL_ENA_VOTE (0x45000) -#define APCS_CLOCK_BRANCH_ENA_VOTE (0x45004) - -/* BLSP1 AHB clock (root clock for BLSP) */ -#define BLSP1_AHB_CBCR 0x1008 - -/* Uart clock control registers */ -#define BLSP1_UART2_BCR (0x3028) -#define BLSP1_UART2_APPS_CBCR (0x302C) -#define BLSP1_UART2_APPS_CMD_RCGR (0x3034) -#define BLSP1_UART2_APPS_CFG_RCGR (0x3038) -#define BLSP1_UART2_APPS_M (0x303C) -#define BLSP1_UART2_APPS_N (0x3040) -#define BLSP1_UART2_APPS_D (0x3044) - -/* I2C controller clock control registerss */ -#define BLSP1_QUP0_I2C_APPS_CBCR (0x6028) -#define BLSP1_QUP0_I2C_APPS_CMD_RCGR (0x602C) -#define BLSP1_QUP0_I2C_APPS_CFG_RCGR (0x6030) -#define BLSP1_QUP1_I2C_APPS_CBCR (0x2008) -#define BLSP1_QUP1_I2C_APPS_CMD_RCGR (0x200C) -#define BLSP1_QUP1_I2C_APPS_CFG_RCGR (0x2010) -#define BLSP1_QUP2_I2C_APPS_CBCR (0x3010) -#define BLSP1_QUP2_I2C_APPS_CMD_RCGR (0x3000) -#define BLSP1_QUP2_I2C_APPS_CFG_RCGR (0x3004) -#define BLSP1_QUP3_I2C_APPS_CBCR (0x4020) -#define BLSP1_QUP3_I2C_APPS_CMD_RCGR (0x4000) -#define BLSP1_QUP3_I2C_APPS_CFG_RCGR (0x4004) -#define BLSP1_QUP4_I2C_APPS_CBCR (0x5020) -#define BLSP1_QUP4_I2C_APPS_CMD_RCGR (0x5000) -#define BLSP1_QUP4_I2C_APPS_CFG_RCGR (0x5004) - -/* SD controller clock control registers */ -#define SDCC_BCR(n) (((n) * 0x1000) + 0x41000) -#define SDCC_CMD_RCGR(n) (((n) * 0x1000) + 0x41004) -#define SDCC_CFG_RCGR(n) (((n) * 0x1000) + 0x41008) -#define SDCC_M(n) (((n) * 0x1000) + 0x4100C) -#define SDCC_N(n) (((n) * 0x1000) + 0x41010) -#define SDCC_D(n) (((n) * 0x1000) + 0x41014) -#define SDCC_APPS_CBCR(n) (((n) * 0x1000) + 0x41018) -#define SDCC_AHB_CBCR(n) (((n) * 0x1000) + 0x4101C) - -/* USB-3.0 controller clock control registers */ -#define SYS_NOC_USB3_CBCR (0x26014) -#define USB30_BCR (0x39000) -#define USB3PHY_BCR (0x39008) -#define USB30_MASTER_CBCR (0x3900C) -#define USB30_SLEEP_CBCR (0x39010) -#define USB30_MOCK_UTMI_CBCR (0x39014) -#define USB30_MOCK_UTMI_CMD_RCGR (0x3901C) -#define USB30_MOCK_UTMI_CFG_RCGR (0x39020) -#define USB30_MASTER_CMD_RCGR (0x39028) -#define USB30_MASTER_CFG_RCGR (0x3902C) -#define USB30_MASTER_M (0x39030) -#define USB30_MASTER_N (0x39034) -#define USB30_MASTER_D (0x39038) -#define USB2A_PHY_SLEEP_CBCR (0x4102C) -#define USB_HS_PHY_CFG_AHB_CBCR (0x41030) - -/* ETH controller clock control registers */ -#define ETH_PTP_CBCR (0x4e004) -#define ETH_RGMII_CBCR (0x4e008) -#define ETH_SLAVE_AHB_CBCR (0x4e00c) -#define ETH_AXI_CBCR (0x4e010) -#define EMAC_PTP_CMD_RCGR (0x4e014) -#define EMAC_PTP_CFG_RCGR (0x4e018) -#define EMAC_CMD_RCGR (0x4e01c) -#define EMAC_CFG_RCGR (0x4e020) -#define EMAC_M (0x4e024) -#define EMAC_N (0x4e028) -#define EMAC_D (0x4e02c) - -#endif diff --git a/arch/arm/mach-snapdragon/include/mach/sysmap-sdm845.h b/arch/arm/mach-snapdragon/include/mach/sysmap-sdm845.h deleted file mode 100644 index 7165985bcd1..00000000000 --- a/arch/arm/mach-snapdragon/include/mach/sysmap-sdm845.h +++ /dev/null @@ -1,42 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Qualcomm SDM845 sysmap - * - * (C) Copyright 2021 Dzmitry Sankouski - */ -#ifndef _MACH_SYSMAP_SDM845_H -#define _MACH_SYSMAP_SDM845_H - -#define TLMM_BASE_ADDR (0x1010000) - -/* Strength (sdc1) */ -#define SDC1_HDRV_PULL_CTL_REG (TLMM_BASE_ADDR + 0x0012D000) - -/* Clocks: (from CLK_CTL_BASE) */ -#define GPLL0_STATUS (0x0000) -#define APCS_GPLL_ENA_VOTE (0x52000) -#define APCS_CLOCK_BRANCH_ENA_VOTE (0x52004) - -#define SDCC2_BCR (0x14000) /* block reset */ -#define SDCC2_APPS_CBCR (0x14004) /* branch control */ -#define SDCC2_AHB_CBCR (0x14008) -#define SDCC2_CMD_RCGR (0x1400c) -#define SDCC2_CFG_RCGR (0x14010) -#define SDCC2_M (0x14014) -#define SDCC2_N (0x14018) -#define SDCC2_D (0x1401C) - -#define RCG2_CFG_REG 0x4 -#define M_REG 0x8 -#define N_REG 0xc -#define D_REG 0x10 - -#define SE9_AHB_CBCR (0x25004) -#define SE9_UART_APPS_CBCR (0x29004) -#define SE9_UART_APPS_CMD_RCGR (0x18148) -#define SE9_UART_APPS_CFG_RCGR (0x1814C) -#define SE9_UART_APPS_M (0x18150) -#define SE9_UART_APPS_N (0x18154) -#define SE9_UART_APPS_D (0x18158) - -#endif diff --git a/board/qualcomm/dragonboard820c/dragonboard820c.c b/board/qualcomm/dragonboard820c/dragonboard820c.c index f9cc762a25c..6785bf58e94 100644 --- a/board/qualcomm/dragonboard820c/dragonboard820c.c +++ b/board/qualcomm/dragonboard820c/dragonboard820c.c @@ -7,7 +7,6 @@ #include #include -#include #include #include #include @@ -20,6 +19,11 @@ #include #include +#define TLMM_BASE_ADDR (0x1010000) + +/* Strength (sdc1) */ +#define SDC1_HDRV_PULL_CTL_REG (TLMM_BASE_ADDR + 0x0012D000) + DECLARE_GLOBAL_DATA_PTR; int dram_init(void) diff --git a/drivers/clk/qcom/clock-apq8016.c b/drivers/clk/qcom/clock-apq8016.c index 3bddbd27590..3f44252c453 100644 --- a/drivers/clk/qcom/clock-apq8016.c +++ b/drivers/clk/qcom/clock-apq8016.c @@ -16,6 +16,32 @@ #include "clock-qcom.h" +/* Clocks: (from CLK_CTL_BASE) */ +#define GPLL0_STATUS (0x2101C) +#define APCS_GPLL_ENA_VOTE (0x45000) +#define APCS_CLOCK_BRANCH_ENA_VOTE (0x45004) + +#define SDCC_BCR(n) ((n * 0x1000) + 0x41000) +#define SDCC_CMD_RCGR(n) ((n * 0x1000) + 0x41004) +#define SDCC_CFG_RCGR(n) ((n * 0x1000) + 0x41008) +#define SDCC_M(n) ((n * 0x1000) + 0x4100C) +#define SDCC_N(n) ((n * 0x1000) + 0x41010) +#define SDCC_D(n) ((n * 0x1000) + 0x41014) +#define SDCC_APPS_CBCR(n) ((n * 0x1000) + 0x41018) +#define SDCC_AHB_CBCR(n) ((n * 0x1000) + 0x4101C) + +/* BLSP1 AHB clock (root clock for BLSP) */ +#define BLSP1_AHB_CBCR 0x1008 + +/* Uart clock control registers */ +#define BLSP1_UART2_BCR (0x3028) +#define BLSP1_UART2_APPS_CBCR (0x302C) +#define BLSP1_UART2_APPS_CMD_RCGR (0x3034) +#define BLSP1_UART2_APPS_CFG_RCGR (0x3038) +#define BLSP1_UART2_APPS_M (0x303C) +#define BLSP1_UART2_APPS_N (0x3040) +#define BLSP1_UART2_APPS_D (0x3044) + /* GPLL0 clock control registers */ #define GPLL0_STATUS_ACTIVE BIT(17) @@ -94,7 +120,7 @@ static int clk_init_uart(struct msm_clk_priv *priv) return 0; } -ulong msm_set_rate(struct clk *clk, ulong rate) +static ulong apq8016_clk_set_rate(struct clk *clk, ulong rate) { struct msm_clk_priv *priv = dev_get_priv(clk->dev); @@ -113,15 +139,14 @@ ulong msm_set_rate(struct clk *clk, ulong rate) } } -int msm_enable(struct clk *clk) -{ - return 0; -} +static struct msm_clk_data apq8016_clk_data = { + .set_rate = apq8016_clk_set_rate, +}; static const struct udevice_id gcc_apq8016_of_match[] = { { .compatible = "qcom,gcc-apq8016", - /* TODO: add reset map */ + .data = (ulong)&apq8016_clk_data, }, { } }; diff --git a/drivers/clk/qcom/clock-apq8096.c b/drivers/clk/qcom/clock-apq8096.c index 64b8cdf4c54..75633a7c2af 100644 --- a/drivers/clk/qcom/clock-apq8096.c +++ b/drivers/clk/qcom/clock-apq8096.c @@ -16,6 +16,28 @@ #include "clock-qcom.h" +/* Clocks: (from CLK_CTL_BASE) */ +#define GPLL0_STATUS (0x0000) +#define APCS_GPLL_ENA_VOTE (0x52000) +#define APCS_CLOCK_BRANCH_ENA_VOTE (0x52004) + +#define SDCC2_BCR (0x14000) /* block reset */ +#define SDCC2_APPS_CBCR (0x14004) /* branch control */ +#define SDCC2_AHB_CBCR (0x14008) +#define SDCC2_CMD_RCGR (0x14010) +#define SDCC2_CFG_RCGR (0x14014) +#define SDCC2_M (0x14018) +#define SDCC2_N (0x1401C) +#define SDCC2_D (0x14020) + +#define BLSP2_AHB_CBCR (0x25004) +#define BLSP2_UART2_APPS_CBCR (0x29004) +#define BLSP2_UART2_APPS_CMD_RCGR (0x2900C) +#define BLSP2_UART2_APPS_CFG_RCGR (0x29010) +#define BLSP2_UART2_APPS_M (0x29014) +#define BLSP2_UART2_APPS_N (0x29018) +#define BLSP2_UART2_APPS_D (0x2901C) + /* GPLL0 clock control registers */ #define GPLL0_STATUS_ACTIVE BIT(30) #define APCS_GPLL_ENA_VOTE_GPLL0 BIT(0) @@ -80,7 +102,7 @@ static int clk_init_uart(struct msm_clk_priv *priv) return 0; } -ulong msm_set_rate(struct clk *clk, ulong rate) +static ulong apq8096_clk_set_rate(struct clk *clk, ulong rate) { struct msm_clk_priv *priv = dev_get_priv(clk->dev); @@ -95,15 +117,14 @@ ulong msm_set_rate(struct clk *clk, ulong rate) } } -int msm_enable(struct clk *clk) -{ - return 0; -} +static struct msm_clk_data apq8096_clk_data = { + .set_rate = apq8096_clk_set_rate, +}; static const struct udevice_id gcc_apq8096_of_match[] = { { .compatible = "qcom,gcc-apq8096", - /* TODO: add reset map */ + .data = (ulong)&apq8096_clk_data, }, { } }; diff --git a/drivers/clk/qcom/clock-ipq4019.c b/drivers/clk/qcom/clock-ipq4019.c index db869f87421..d693776d339 100644 --- a/drivers/clk/qcom/clock-ipq4019.c +++ b/drivers/clk/qcom/clock-ipq4019.c @@ -16,7 +16,7 @@ #include "clock-qcom.h" -ulong msm_set_rate(struct clk *clk, ulong rate) +static ulong ipq4019_clk_set_rate(struct clk *clk, ulong rate) { switch (clk->id) { case GCC_BLSP1_UART1_APPS_CLK: /*UART1*/ @@ -27,7 +27,7 @@ ulong msm_set_rate(struct clk *clk, ulong rate) } } -int msm_enable(struct clk *clk) +static int ipq4019_clk_enable(struct clk *clk) { switch (clk->id) { case GCC_BLSP1_QUP1_SPI_APPS_CLK: /*SPI1*/ @@ -123,7 +123,9 @@ static const struct qcom_reset_map gcc_ipq4019_resets[] = { [GCC_SPDM_BCR] = {0x25000, 0}, }; -static struct msm_clk_data ipq4019_data = { +static struct msm_clk_data ipq4019_clk_data = { + .enable = ipq4019_clk_enable, + .set_rate = ipq4019_clk_set_rate, .resets = gcc_ipq4019_resets, .num_resets = ARRAY_SIZE(gcc_ipq4019_resets), }; @@ -131,7 +133,7 @@ static struct msm_clk_data ipq4019_data = { static const struct udevice_id gcc_ipq4019_of_match[] = { { .compatible = "qcom,gcc-ipq4019", - .data = (ulong)&ipq4019_data, + .data = (ulong)&ipq4019_clk_data, }, { } }; diff --git a/drivers/clk/qcom/clock-qcom.c b/drivers/clk/qcom/clock-qcom.c index a661837e4e1..77bcaacd158 100644 --- a/drivers/clk/qcom/clock-qcom.c +++ b/drivers/clk/qcom/clock-qcom.c @@ -28,9 +28,6 @@ #define CBCR_BRANCH_ENABLE_BIT BIT(0) #define CBCR_BRANCH_OFF_BIT BIT(31) -extern ulong msm_set_rate(struct clk *clk, ulong rate); -extern int msm_enable(struct clk *clk); - /* Enable clock controlled by CBC soft macro */ void clk_enable_cbc(phys_addr_t cbcr) { @@ -160,12 +157,22 @@ static int msm_clk_probe(struct udevice *dev) static ulong msm_clk_set_rate(struct clk *clk, ulong rate) { - return msm_set_rate(clk, rate); + struct msm_clk_data *data = (struct msm_clk_data *)dev_get_driver_data(clk->dev); + + if (data->set_rate) + return data->set_rate(clk, rate); + + return 0; } static int msm_clk_enable(struct clk *clk) { - return msm_enable(clk); + struct msm_clk_data *data = (struct msm_clk_data *)dev_get_driver_data(clk->dev); + + if (data->enable) + return data->enable(clk); + + return 0; } static struct clk_ops msm_clk_ops = { diff --git a/drivers/clk/qcom/clock-qcom.h b/drivers/clk/qcom/clock-qcom.h index 6d399db987b..86f9ff6eb2f 100644 --- a/drivers/clk/qcom/clock-qcom.h +++ b/drivers/clk/qcom/clock-qcom.h @@ -49,11 +49,16 @@ struct qcom_reset_map { u8 bit; }; +struct clk; + struct msm_clk_data { const struct qcom_reset_map *resets; unsigned long num_resets; const struct gate_clk *clks; unsigned long num_clks; + + int (*enable)(struct clk *clk); + unsigned long (*set_rate)(struct clk *clk, unsigned long rate); }; struct msm_clk_priv { diff --git a/drivers/clk/qcom/clock-qcs404.c b/drivers/clk/qcom/clock-qcs404.c index 10ac3609be4..9ad580b50fc 100644 --- a/drivers/clk/qcom/clock-qcs404.c +++ b/drivers/clk/qcom/clock-qcs404.c @@ -15,6 +15,81 @@ #include "clock-qcom.h" +/* Clocks: (from CLK_CTL_BASE) */ +#define GPLL0_STATUS (0x21000) +#define GPLL1_STATUS (0x20000) +#define APCS_GPLL_ENA_VOTE (0x45000) +#define APCS_CLOCK_BRANCH_ENA_VOTE (0x45004) + +/* BLSP1 AHB clock (root clock for BLSP) */ +#define BLSP1_AHB_CBCR 0x1008 + +/* Uart clock control registers */ +#define BLSP1_UART2_BCR (0x3028) +#define BLSP1_UART2_APPS_CBCR (0x302C) +#define BLSP1_UART2_APPS_CMD_RCGR (0x3034) +#define BLSP1_UART2_APPS_CFG_RCGR (0x3038) +#define BLSP1_UART2_APPS_M (0x303C) +#define BLSP1_UART2_APPS_N (0x3040) +#define BLSP1_UART2_APPS_D (0x3044) + +/* I2C controller clock control registerss */ +#define BLSP1_QUP0_I2C_APPS_CBCR (0x6028) +#define BLSP1_QUP0_I2C_APPS_CMD_RCGR (0x602C) +#define BLSP1_QUP0_I2C_APPS_CFG_RCGR (0x6030) +#define BLSP1_QUP1_I2C_APPS_CBCR (0x2008) +#define BLSP1_QUP1_I2C_APPS_CMD_RCGR (0x200C) +#define BLSP1_QUP1_I2C_APPS_CFG_RCGR (0x2010) +#define BLSP1_QUP2_I2C_APPS_CBCR (0x3010) +#define BLSP1_QUP2_I2C_APPS_CMD_RCGR (0x3000) +#define BLSP1_QUP2_I2C_APPS_CFG_RCGR (0x3004) +#define BLSP1_QUP3_I2C_APPS_CBCR (0x4020) +#define BLSP1_QUP3_I2C_APPS_CMD_RCGR (0x4000) +#define BLSP1_QUP3_I2C_APPS_CFG_RCGR (0x4004) +#define BLSP1_QUP4_I2C_APPS_CBCR (0x5020) +#define BLSP1_QUP4_I2C_APPS_CMD_RCGR (0x5000) +#define BLSP1_QUP4_I2C_APPS_CFG_RCGR (0x5004) + +/* SD controller clock control registers */ +#define SDCC_BCR(n) (((n) * 0x1000) + 0x41000) +#define SDCC_CMD_RCGR(n) (((n) * 0x1000) + 0x41004) +#define SDCC_CFG_RCGR(n) (((n) * 0x1000) + 0x41008) +#define SDCC_M(n) (((n) * 0x1000) + 0x4100C) +#define SDCC_N(n) (((n) * 0x1000) + 0x41010) +#define SDCC_D(n) (((n) * 0x1000) + 0x41014) +#define SDCC_APPS_CBCR(n) (((n) * 0x1000) + 0x41018) +#define SDCC_AHB_CBCR(n) (((n) * 0x1000) + 0x4101C) + +/* USB-3.0 controller clock control registers */ +#define SYS_NOC_USB3_CBCR (0x26014) +#define USB30_BCR (0x39000) +#define USB3PHY_BCR (0x39008) +#define USB30_MASTER_CBCR (0x3900C) +#define USB30_SLEEP_CBCR (0x39010) +#define USB30_MOCK_UTMI_CBCR (0x39014) +#define USB30_MOCK_UTMI_CMD_RCGR (0x3901C) +#define USB30_MOCK_UTMI_CFG_RCGR (0x39020) +#define USB30_MASTER_CMD_RCGR (0x39028) +#define USB30_MASTER_CFG_RCGR (0x3902C) +#define USB30_MASTER_M (0x39030) +#define USB30_MASTER_N (0x39034) +#define USB30_MASTER_D (0x39038) +#define USB2A_PHY_SLEEP_CBCR (0x4102C) +#define USB_HS_PHY_CFG_AHB_CBCR (0x41030) + +/* ETH controller clock control registers */ +#define ETH_PTP_CBCR (0x4e004) +#define ETH_RGMII_CBCR (0x4e008) +#define ETH_SLAVE_AHB_CBCR (0x4e00c) +#define ETH_AXI_CBCR (0x4e010) +#define EMAC_PTP_CMD_RCGR (0x4e014) +#define EMAC_PTP_CFG_RCGR (0x4e018) +#define EMAC_CMD_RCGR (0x4e01c) +#define EMAC_CFG_RCGR (0x4e020) +#define EMAC_M (0x4e024) +#define EMAC_N (0x4e028) +#define EMAC_D (0x4e02c) + /* GPLL0 clock control registers */ #define GPLL0_STATUS_ACTIVE BIT(31) @@ -112,7 +187,7 @@ static const struct bcr_regs blsp1_qup4_i2c_apps_regs = { /* mnd_width = 0 */ }; -ulong msm_set_rate(struct clk *clk, ulong rate) +static ulong qcs404_clk_set_rate(struct clk *clk, ulong rate) { struct msm_clk_priv *priv = dev_get_priv(clk->dev); @@ -157,7 +232,7 @@ ulong msm_set_rate(struct clk *clk, ulong rate) return 0; } -int msm_enable(struct clk *clk) +static int qcs404_clk_enable(struct clk *clk) { struct msm_clk_priv *priv = dev_get_priv(clk->dev); @@ -263,15 +338,17 @@ static const struct qcom_reset_map qcs404_gcc_resets[] = { [GCC_WDSP_RESTART] = {0x19000}, }; -static const struct msm_clk_data qcs404_gcc_data = { +static const struct msm_clk_data qcs404_clk_gcc_data = { .resets = qcs404_gcc_resets, .num_resets = ARRAY_SIZE(qcs404_gcc_resets), + .enable = qcs404_clk_enable, + .set_rate = qcs404_clk_set_rate, }; static const struct udevice_id gcc_qcs404_of_match[] = { { .compatible = "qcom,gcc-qcs404", - .data = (ulong)&qcs404_gcc_data + .data = (ulong)&qcs404_clk_gcc_data }, { } }; diff --git a/drivers/clk/qcom/clock-sdm845.c b/drivers/clk/qcom/clock-sdm845.c index 57124e2a661..fc9a783f735 100644 --- a/drivers/clk/qcom/clock-sdm845.c +++ b/drivers/clk/qcom/clock-sdm845.c @@ -19,6 +19,14 @@ #include "clock-qcom.h" +#define SE9_AHB_CBCR 0x25004 +#define SE9_UART_APPS_CBCR 0x29004 +#define SE9_UART_APPS_CMD_RCGR 0x18148 +#define SE9_UART_APPS_CFG_RCGR 0x1814C +#define SE9_UART_APPS_M 0x18150 +#define SE9_UART_APPS_N 0x18154 +#define SE9_UART_APPS_D 0x18158 + #define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n) } struct freq_tbl { @@ -72,7 +80,7 @@ const struct freq_tbl *qcom_find_freq(const struct freq_tbl *f, uint rate) return f - 1; } -ulong msm_set_rate(struct clk *clk, ulong rate) +static ulong sdm845_clk_set_rate(struct clk *clk, ulong rate) { struct msm_clk_priv *priv = dev_get_priv(clk->dev); const struct freq_tbl *freq; @@ -148,7 +156,7 @@ static const struct gate_clk sdm845_clks[] = { GATE_CLK(GCC_USB_PHY_CFG_AHB2PHY_CLK, 0x6a004, 0x00000001), }; -int msm_enable(struct clk *clk) +static int sdm845_clk_enable(struct clk *clk) { struct msm_clk_priv *priv = dev_get_priv(clk->dev); @@ -179,17 +187,20 @@ static const struct qcom_reset_map sdm845_gcc_resets[] = { [GCC_USB_PHY_CFG_AHB2PHY_BCR] = { 0x6a000 }, }; -static const struct msm_clk_data qcs404_gcc_data = { +static struct msm_clk_data sdm845_clk_data = { .resets = sdm845_gcc_resets, .num_resets = ARRAY_SIZE(sdm845_gcc_resets), .clks = sdm845_clks, .num_clks = ARRAY_SIZE(sdm845_clks), + + .enable = sdm845_clk_enable, + .set_rate = sdm845_clk_set_rate, }; static const struct udevice_id gcc_sdm845_of_match[] = { { .compatible = "qcom,gcc-sdm845", - .data = (ulong)&qcs404_gcc_data, + .data = (ulong)&sdm845_clk_data, }, { } }; diff --git a/include/configs/dragonboard410c.h b/include/configs/dragonboard410c.h index 73aec348458..00102cd5c4f 100644 --- a/include/configs/dragonboard410c.h +++ b/include/configs/dragonboard410c.h @@ -9,7 +9,6 @@ #define __CONFIGS_DRAGONBOARD410C_H #include -#include /* Build new ELF image from u-boot.bin (U-Boot + appended DTB) */ diff --git a/include/configs/dragonboard820c.h b/include/configs/dragonboard820c.h index 49970837111..c6d9182ccc9 100644 --- a/include/configs/dragonboard820c.h +++ b/include/configs/dragonboard820c.h @@ -9,7 +9,6 @@ #define __CONFIGS_DRAGONBOARD820C_H #include -#include /* Physical Memory Map */ diff --git a/include/configs/dragonboard845c.h b/include/configs/dragonboard845c.h index c1e590fae2a..14a8a2ca049 100644 --- a/include/configs/dragonboard845c.h +++ b/include/configs/dragonboard845c.h @@ -9,7 +9,6 @@ #define __CONFIGS_SDM845_H #include -#include #define CFG_SYS_BAUDRATE_TABLE { 115200, 230400, 460800, 921600 } diff --git a/include/configs/qcs404-evb.h b/include/configs/qcs404-evb.h index 8ea59aa21ca..9501d43665e 100644 --- a/include/configs/qcs404-evb.h +++ b/include/configs/qcs404-evb.h @@ -9,7 +9,6 @@ #define __CONFIGS_QCS404EVB_H #include -#include #define CFG_SYS_BAUDRATE_TABLE { 115200, 230400, 460800, 921600 } diff --git a/include/configs/sdm845.h b/include/configs/sdm845.h index 673268dca98..5ad8569b215 100644 --- a/include/configs/sdm845.h +++ b/include/configs/sdm845.h @@ -9,7 +9,6 @@ #define __CONFIGS_SDM845_H #include -#include #define CFG_SYS_BAUDRATE_TABLE { 115200, 230400, 460800, 921600 } From 6acc44319bba5e4f5bcdacaa6412d617815472ed Mon Sep 17 00:00:00 2001 From: Caleb Connolly Date: Tue, 7 Nov 2023 12:41:04 +0000 Subject: [PATCH 06/24] clk/qcom: add mnd_width to clk_rcg_set_rate_mnd() This property is needed on some platforms to ensure that only the relevant bits are set in the M/N/D registers. Reviewed-by: Sumit Garg Signed-off-by: Caleb Connolly --- drivers/clk/qcom/clock-apq8016.c | 4 ++-- drivers/clk/qcom/clock-apq8096.c | 4 ++-- drivers/clk/qcom/clock-qcom.c | 11 +++++++---- drivers/clk/qcom/clock-qcom.h | 2 +- drivers/clk/qcom/clock-qcs404.c | 18 +++++++++--------- drivers/clk/qcom/clock-sdm845.c | 3 +-- 6 files changed, 22 insertions(+), 20 deletions(-) diff --git a/drivers/clk/qcom/clock-apq8016.c b/drivers/clk/qcom/clock-apq8016.c index 3f44252c453..498e8ef6780 100644 --- a/drivers/clk/qcom/clock-apq8016.c +++ b/drivers/clk/qcom/clock-apq8016.c @@ -86,7 +86,7 @@ static int clk_init_sdc(struct msm_clk_priv *priv, int slot, uint rate) clk_enable_cbc(priv->base + SDCC_AHB_CBCR(slot)); /* 800Mhz/div, gpll0 */ clk_rcg_set_rate_mnd(priv->base, &sdc_regs[slot], div, 0, 0, - CFG_CLK_SRC_GPLL0); + CFG_CLK_SRC_GPLL0, 8); clk_enable_gpll0(priv->base, &gpll0_vote_clk); clk_enable_cbc(priv->base + SDCC_APPS_CBCR(slot)); @@ -109,7 +109,7 @@ static int clk_init_uart(struct msm_clk_priv *priv) /* 7372800 uart block clock @ GPLL0 */ clk_rcg_set_rate_mnd(priv->base, &uart2_regs, 1, 144, 15625, - CFG_CLK_SRC_GPLL0); + CFG_CLK_SRC_GPLL0, 16); /* Vote for gpll0 clock */ clk_enable_gpll0(priv->base, &gpll0_vote_clk); diff --git a/drivers/clk/qcom/clock-apq8096.c b/drivers/clk/qcom/clock-apq8096.c index 75633a7c2af..367c0f06ae2 100644 --- a/drivers/clk/qcom/clock-apq8096.c +++ b/drivers/clk/qcom/clock-apq8096.c @@ -69,7 +69,7 @@ static int clk_init_sdc(struct msm_clk_priv *priv, uint rate) clk_enable_cbc(priv->base + SDCC2_AHB_CBCR); clk_rcg_set_rate_mnd(priv->base, &sdc_regs, div, 0, 0, - CFG_CLK_SRC_GPLL0); + CFG_CLK_SRC_GPLL0, 8); clk_enable_gpll0(priv->base, &gpll0_vote_clk); clk_enable_cbc(priv->base + SDCC2_APPS_CBCR); @@ -91,7 +91,7 @@ static int clk_init_uart(struct msm_clk_priv *priv) /* 7372800 uart block clock @ GPLL0 */ clk_rcg_set_rate_mnd(priv->base, &uart2_regs, 1, 192, 15625, - CFG_CLK_SRC_GPLL0); + CFG_CLK_SRC_GPLL0, 16); /* Vote for gpll0 clock */ clk_enable_gpll0(priv->base, &gpll0_vote_clk); diff --git a/drivers/clk/qcom/clock-qcom.c b/drivers/clk/qcom/clock-qcom.c index 77bcaacd158..fc478554f98 100644 --- a/drivers/clk/qcom/clock-qcom.c +++ b/drivers/clk/qcom/clock-qcom.c @@ -83,7 +83,7 @@ void clk_bcr_update(phys_addr_t apps_cmd_rcgr) /* root set rate for clocks with half integer and MND divider */ void clk_rcg_set_rate_mnd(phys_addr_t base, const struct bcr_regs *regs, - int div, int m, int n, int source) + int div, int m, int n, int source, u8 mnd_width) { u32 cfg; /* M value for MND divider. */ @@ -92,11 +92,14 @@ void clk_rcg_set_rate_mnd(phys_addr_t base, const struct bcr_regs *regs, u32 n_val = ~((n) - (m)) * !!(n); /* NOT 2D value for MND divider. */ u32 d_val = ~(n); + u32 mask = BIT(mnd_width) - 1; + + debug("m %#x n %#x d %#x div %#x mask %#x\n", m_val, n_val, d_val, div, mask); /* Program MND values */ - writel(m_val, base + regs->M); - writel(n_val, base + regs->N); - writel(d_val, base + regs->D); + writel(m_val & mask, base + regs->M); + writel(n_val & mask, base + regs->N); + writel(d_val & mask, base + regs->D); /* setup src select and divider */ cfg = readl(base + regs->cfg_rcgr); diff --git a/drivers/clk/qcom/clock-qcom.h b/drivers/clk/qcom/clock-qcom.h index 86f9ff6eb2f..24a32cb9666 100644 --- a/drivers/clk/qcom/clock-qcom.h +++ b/drivers/clk/qcom/clock-qcom.h @@ -72,7 +72,7 @@ void clk_bcr_update(phys_addr_t apps_cmd_rgcr); void clk_enable_cbc(phys_addr_t cbcr); void clk_enable_vote_clk(phys_addr_t base, const struct vote_clk *vclk); void clk_rcg_set_rate_mnd(phys_addr_t base, const struct bcr_regs *regs, - int div, int m, int n, int source); + int div, int m, int n, int source, u8 mnd_width); void clk_rcg_set_rate(phys_addr_t base, const struct bcr_regs *regs, int div, int source); diff --git a/drivers/clk/qcom/clock-qcs404.c b/drivers/clk/qcom/clock-qcs404.c index 9ad580b50fc..f234ab5d654 100644 --- a/drivers/clk/qcom/clock-qcs404.c +++ b/drivers/clk/qcom/clock-qcs404.c @@ -195,7 +195,7 @@ static ulong qcs404_clk_set_rate(struct clk *clk, ulong rate) case GCC_BLSP1_UART2_APPS_CLK: /* UART: 115200 */ clk_rcg_set_rate_mnd(priv->base, &uart2_regs, 0, 12, 125, - CFG_CLK_SRC_CXO); + CFG_CLK_SRC_CXO, 16); clk_enable_cbc(priv->base + BLSP1_UART2_APPS_CBCR); break; case GCC_BLSP1_AHB_CLK: @@ -204,7 +204,7 @@ static ulong qcs404_clk_set_rate(struct clk *clk, ulong rate) case GCC_SDCC1_APPS_CLK: /* SDCC1: 200MHz */ clk_rcg_set_rate_mnd(priv->base, &sdc_regs, 4, 0, 0, - CFG_CLK_SRC_GPLL0); + CFG_CLK_SRC_GPLL0, 8); clk_enable_gpll0(priv->base, &gpll0_vote_clk); clk_enable_cbc(priv->base + SDCC_APPS_CBCR(1)); break; @@ -214,16 +214,16 @@ static ulong qcs404_clk_set_rate(struct clk *clk, ulong rate) case GCC_ETH_RGMII_CLK: if (rate == 250000000) clk_rcg_set_rate_mnd(priv->base, &emac_regs, 2, 0, 0, - CFG_CLK_SRC_GPLL1); + CFG_CLK_SRC_GPLL1, 8); else if (rate == 125000000) clk_rcg_set_rate_mnd(priv->base, &emac_regs, 4, 0, 0, - CFG_CLK_SRC_GPLL1); + CFG_CLK_SRC_GPLL1, 8); else if (rate == 50000000) clk_rcg_set_rate_mnd(priv->base, &emac_regs, 10, 0, 0, - CFG_CLK_SRC_GPLL1); + CFG_CLK_SRC_GPLL1, 8); else if (rate == 5000000) clk_rcg_set_rate_mnd(priv->base, &emac_regs, 2, 1, 50, - CFG_CLK_SRC_GPLL1); + CFG_CLK_SRC_GPLL1, 8); break; default: return 0; @@ -240,7 +240,7 @@ static int qcs404_clk_enable(struct clk *clk) case GCC_USB30_MASTER_CLK: clk_enable_cbc(priv->base + USB30_MASTER_CBCR); clk_rcg_set_rate_mnd(priv->base, &usb30_master_regs, 4, 0, 0, - CFG_CLK_SRC_GPLL0); + CFG_CLK_SRC_GPLL0, 8); break; case GCC_SYS_NOC_USB3_CLK: clk_enable_cbc(priv->base + SYS_NOC_USB3_CBCR); @@ -262,14 +262,14 @@ static int qcs404_clk_enable(struct clk *clk) clk_enable_cbc(priv->base + ETH_PTP_CBCR); clk_enable_gpll0(priv->base, &gpll1_vote_clk); clk_rcg_set_rate_mnd(priv->base, &emac_ptp_regs, 2, 0, 0, - CFG_CLK_SRC_GPLL1); + CFG_CLK_SRC_GPLL1, 8); break; case GCC_ETH_RGMII_CLK: /* SPEED_1000: freq -> 250MHz */ clk_enable_cbc(priv->base + ETH_RGMII_CBCR); clk_enable_gpll0(priv->base, &gpll1_vote_clk); clk_rcg_set_rate_mnd(priv->base, &emac_regs, 2, 0, 0, - CFG_CLK_SRC_GPLL1); + CFG_CLK_SRC_GPLL1, 8); break; case GCC_ETH_SLAVE_AHB_CLK: clk_enable_cbc(priv->base + ETH_SLAVE_AHB_CBCR); diff --git a/drivers/clk/qcom/clock-sdm845.c b/drivers/clk/qcom/clock-sdm845.c index fc9a783f735..6af1f38302d 100644 --- a/drivers/clk/qcom/clock-sdm845.c +++ b/drivers/clk/qcom/clock-sdm845.c @@ -89,8 +89,7 @@ static ulong sdm845_clk_set_rate(struct clk *clk, ulong rate) case GCC_QUPV3_WRAP1_S1_CLK: /* UART9 */ freq = qcom_find_freq(ftbl_gcc_qupv3_wrap0_s0_clk_src, rate); clk_rcg_set_rate_mnd(priv->base, &uart2_regs, - freq->pre_div, freq->m, freq->n, freq->src); - + freq->pre_div, freq->m, freq->n, freq->src, 16); return freq->freq; default: return 0; From d5db46cf93fd19cbbd61ee34a5743c1c7e61f212 Mon Sep 17 00:00:00 2001 From: Caleb Connolly Date: Tue, 7 Nov 2023 12:41:05 +0000 Subject: [PATCH 07/24] clk/qcom: fix rcg divider value The RCG divider field takes a value of (2*h - 1) where h is the divisor. This allows fractional dividers to be supported by calculating them at compile time using a macro. However, the clk_rcg_set_rate_mnd() function was also performing the calculation. Clean this all up and consistently use the F() macro to calculate these at compile time and properly support fractional divisors. Additionally, improve clk_bcr_update() to timeout with a warning rather than hanging the board, and make the freq_tbl struct and helpers common so that they can be reused by future platforms. Reviewed-by: Sumit Garg Signed-off-by: Caleb Connolly --- drivers/clk/qcom/clock-apq8016.c | 2 +- drivers/clk/qcom/clock-apq8096.c | 2 +- drivers/clk/qcom/clock-qcom.c | 64 +++++++++++++++++++++++--------- drivers/clk/qcom/clock-qcom.h | 11 ++++++ drivers/clk/qcom/clock-qcs404.c | 16 ++++---- drivers/clk/qcom/clock-sdm845.c | 26 ------------- 6 files changed, 67 insertions(+), 54 deletions(-) diff --git a/drivers/clk/qcom/clock-apq8016.c b/drivers/clk/qcom/clock-apq8016.c index 498e8ef6780..c0ce570edc7 100644 --- a/drivers/clk/qcom/clock-apq8016.c +++ b/drivers/clk/qcom/clock-apq8016.c @@ -78,7 +78,7 @@ static struct vote_clk gcc_blsp1_ahb_clk = { /* SDHCI */ static int clk_init_sdc(struct msm_clk_priv *priv, int slot, uint rate) { - int div = 8; /* 100MHz default */ + int div = 15; /* 100MHz default */ if (rate == 200000000) div = 4; diff --git a/drivers/clk/qcom/clock-apq8096.c b/drivers/clk/qcom/clock-apq8096.c index 367c0f06ae2..cf1a347309a 100644 --- a/drivers/clk/qcom/clock-apq8096.c +++ b/drivers/clk/qcom/clock-apq8096.c @@ -65,7 +65,7 @@ static struct vote_clk gcc_blsp2_ahb_clk = { static int clk_init_sdc(struct msm_clk_priv *priv, uint rate) { - int div = 3; + int div = 5; clk_enable_cbc(priv->base + SDCC2_AHB_CBCR); clk_rcg_set_rate_mnd(priv->base, &sdc_regs, div, 0, 0, diff --git a/drivers/clk/qcom/clock-qcom.c b/drivers/clk/qcom/clock-qcom.c index fc478554f98..7c683e51922 100644 --- a/drivers/clk/qcom/clock-qcom.c +++ b/drivers/clk/qcom/clock-qcom.c @@ -19,6 +19,8 @@ #include #include #include +#include +#include #include #include @@ -68,30 +70,42 @@ void clk_enable_vote_clk(phys_addr_t base, const struct vote_clk *vclk) /* Update clock command via CMD_RCGR */ void clk_bcr_update(phys_addr_t apps_cmd_rcgr) { + u32 count; setbits_le32(apps_cmd_rcgr, APPS_CMD_RCGR_UPDATE); /* Wait for frequency to be updated. */ - while (readl(apps_cmd_rcgr) & APPS_CMD_RCGR_UPDATE) - ; + for (count = 0; count < 50000; count++) { + if (!(readl(apps_cmd_rcgr) & APPS_CMD_RCGR_UPDATE)) + break; + udelay(1); + } + WARN(count == 50000, "WARNING: RCG @ %#llx [%#010x] stuck at off\n", + apps_cmd_rcgr, readl(apps_cmd_rcgr)); } -#define CFG_MODE_DUAL_EDGE (0x2 << 12) /* Counter mode */ +#define CFG_SRC_DIV_MASK 0b11111 +#define CFG_SRC_SEL_SHIFT 8 +#define CFG_SRC_SEL_MASK (0x7 << CFG_SRC_SEL_SHIFT) +#define CFG_MODE_SHIFT 12 +#define CFG_MODE_MASK (0x3 << CFG_MODE_SHIFT) +#define CFG_MODE_DUAL_EDGE (0x2 << CFG_MODE_SHIFT) +#define CFG_HW_CLK_CTRL_MASK BIT(20) -#define CFG_MASK 0x3FFF - -#define CFG_DIVIDER_MASK 0x1F - -/* root set rate for clocks with half integer and MND divider */ +/* + * root set rate for clocks with half integer and MND divider + * div should be pre-calculated ((div * 2) - 1) + */ void clk_rcg_set_rate_mnd(phys_addr_t base, const struct bcr_regs *regs, int div, int m, int n, int source, u8 mnd_width) { u32 cfg; /* M value for MND divider. */ u32 m_val = m; + u32 n_minus_m = n - m; /* NOT(N-M) value for MND divider. */ - u32 n_val = ~((n) - (m)) * !!(n); + u32 n_val = ~n_minus_m * !!(n); /* NOT 2D value for MND divider. */ - u32 d_val = ~(n); + u32 d_val = ~(clamp_t(u32, n, m, n_minus_m)); u32 mask = BIT(mnd_width) - 1; debug("m %#x n %#x d %#x div %#x mask %#x\n", m_val, n_val, d_val, div, mask); @@ -103,15 +117,13 @@ void clk_rcg_set_rate_mnd(phys_addr_t base, const struct bcr_regs *regs, /* setup src select and divider */ cfg = readl(base + regs->cfg_rcgr); - cfg &= ~CFG_MASK; - cfg |= source & CFG_CLK_SRC_MASK; /* Select clock source */ + cfg &= ~(CFG_SRC_SEL_MASK | CFG_MODE_MASK | CFG_HW_CLK_CTRL_MASK); + cfg |= source & CFG_SRC_SEL_MASK; /* Select clock source */ - /* Set the divider; HW permits fraction dividers (+0.5), but - for simplicity, we will support integers only */ if (div) - cfg |= (2 * div - 1) & CFG_DIVIDER_MASK; + cfg |= div & CFG_SRC_DIV_MASK; - if (n_val) + if (n && n != m) cfg |= CFG_MODE_DUAL_EDGE; writel(cfg, base + regs->cfg_rcgr); /* Write new clock configuration */ @@ -128,7 +140,7 @@ void clk_rcg_set_rate(phys_addr_t base, const struct bcr_regs *regs, int div, /* setup src select and divider */ cfg = readl(base + regs->cfg_rcgr); - cfg &= ~CFG_MASK; + cfg &= ~(CFG_SRC_SEL_MASK | CFG_MODE_MASK | CFG_HW_CLK_CTRL_MASK); cfg |= source & CFG_CLK_SRC_MASK; /* Select clock source */ /* @@ -136,7 +148,7 @@ void clk_rcg_set_rate(phys_addr_t base, const struct bcr_regs *regs, int div, * for simplicity, we will support integers only */ if (div) - cfg |= (2 * div - 1) & CFG_DIVIDER_MASK; + cfg |= (2 * div - 1) & CFG_SRC_DIV_MASK; writel(cfg, base + regs->cfg_rcgr); /* Write new clock configuration */ @@ -144,6 +156,22 @@ void clk_rcg_set_rate(phys_addr_t base, const struct bcr_regs *regs, int div, clk_bcr_update(base + regs->cmd_rcgr); } +const struct freq_tbl *qcom_find_freq(const struct freq_tbl *f, uint rate) +{ + if (!f) + return NULL; + + if (!f->freq) + return f; + + for (; f->freq; f++) + if (rate <= f->freq) + return f; + + /* Default to our fastest rate */ + return f - 1; +} + static int msm_clk_probe(struct udevice *dev) { struct msm_clk_data *data = (struct msm_clk_data *)dev_get_driver_data(dev); diff --git a/drivers/clk/qcom/clock-qcom.h b/drivers/clk/qcom/clock-qcom.h index 24a32cb9666..01088c19015 100644 --- a/drivers/clk/qcom/clock-qcom.h +++ b/drivers/clk/qcom/clock-qcom.h @@ -32,6 +32,16 @@ struct bcr_regs { uintptr_t D; }; +struct freq_tbl { + uint freq; + uint src; + u8 pre_div; + u16 m; + u16 n; +}; + +#define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n) } + struct gate_clk { uintptr_t reg; u32 en_val; @@ -71,6 +81,7 @@ void clk_enable_gpll0(phys_addr_t base, const struct pll_vote_clk *gpll0); void clk_bcr_update(phys_addr_t apps_cmd_rgcr); void clk_enable_cbc(phys_addr_t cbcr); void clk_enable_vote_clk(phys_addr_t base, const struct vote_clk *vclk); +const struct freq_tbl *qcom_find_freq(const struct freq_tbl *f, uint rate); void clk_rcg_set_rate_mnd(phys_addr_t base, const struct bcr_regs *regs, int div, int m, int n, int source, u8 mnd_width); void clk_rcg_set_rate(phys_addr_t base, const struct bcr_regs *regs, int div, diff --git a/drivers/clk/qcom/clock-qcs404.c b/drivers/clk/qcom/clock-qcs404.c index f234ab5d654..f5b35280392 100644 --- a/drivers/clk/qcom/clock-qcs404.c +++ b/drivers/clk/qcom/clock-qcs404.c @@ -203,7 +203,7 @@ static ulong qcs404_clk_set_rate(struct clk *clk, ulong rate) break; case GCC_SDCC1_APPS_CLK: /* SDCC1: 200MHz */ - clk_rcg_set_rate_mnd(priv->base, &sdc_regs, 4, 0, 0, + clk_rcg_set_rate_mnd(priv->base, &sdc_regs, 7, 0, 0, CFG_CLK_SRC_GPLL0, 8); clk_enable_gpll0(priv->base, &gpll0_vote_clk); clk_enable_cbc(priv->base + SDCC_APPS_CBCR(1)); @@ -213,16 +213,16 @@ static ulong qcs404_clk_set_rate(struct clk *clk, ulong rate) break; case GCC_ETH_RGMII_CLK: if (rate == 250000000) - clk_rcg_set_rate_mnd(priv->base, &emac_regs, 2, 0, 0, + clk_rcg_set_rate_mnd(priv->base, &emac_regs, 3, 0, 0, CFG_CLK_SRC_GPLL1, 8); else if (rate == 125000000) - clk_rcg_set_rate_mnd(priv->base, &emac_regs, 4, 0, 0, + clk_rcg_set_rate_mnd(priv->base, &emac_regs, 7, 0, 0, CFG_CLK_SRC_GPLL1, 8); else if (rate == 50000000) - clk_rcg_set_rate_mnd(priv->base, &emac_regs, 10, 0, 0, + clk_rcg_set_rate_mnd(priv->base, &emac_regs, 19, 0, 0, CFG_CLK_SRC_GPLL1, 8); else if (rate == 5000000) - clk_rcg_set_rate_mnd(priv->base, &emac_regs, 2, 1, 50, + clk_rcg_set_rate_mnd(priv->base, &emac_regs, 3, 1, 50, CFG_CLK_SRC_GPLL1, 8); break; default: @@ -239,7 +239,7 @@ static int qcs404_clk_enable(struct clk *clk) switch (clk->id) { case GCC_USB30_MASTER_CLK: clk_enable_cbc(priv->base + USB30_MASTER_CBCR); - clk_rcg_set_rate_mnd(priv->base, &usb30_master_regs, 4, 0, 0, + clk_rcg_set_rate_mnd(priv->base, &usb30_master_regs, 7, 0, 0, CFG_CLK_SRC_GPLL0, 8); break; case GCC_SYS_NOC_USB3_CLK: @@ -261,14 +261,14 @@ static int qcs404_clk_enable(struct clk *clk) /* SPEED_1000: freq -> 250MHz */ clk_enable_cbc(priv->base + ETH_PTP_CBCR); clk_enable_gpll0(priv->base, &gpll1_vote_clk); - clk_rcg_set_rate_mnd(priv->base, &emac_ptp_regs, 2, 0, 0, + clk_rcg_set_rate_mnd(priv->base, &emac_ptp_regs, 3, 0, 0, CFG_CLK_SRC_GPLL1, 8); break; case GCC_ETH_RGMII_CLK: /* SPEED_1000: freq -> 250MHz */ clk_enable_cbc(priv->base + ETH_RGMII_CBCR); clk_enable_gpll0(priv->base, &gpll1_vote_clk); - clk_rcg_set_rate_mnd(priv->base, &emac_regs, 2, 0, 0, + clk_rcg_set_rate_mnd(priv->base, &emac_regs, 3, 0, 0, CFG_CLK_SRC_GPLL1, 8); break; case GCC_ETH_SLAVE_AHB_CLK: diff --git a/drivers/clk/qcom/clock-sdm845.c b/drivers/clk/qcom/clock-sdm845.c index 6af1f38302d..36ffee79d96 100644 --- a/drivers/clk/qcom/clock-sdm845.c +++ b/drivers/clk/qcom/clock-sdm845.c @@ -27,16 +27,6 @@ #define SE9_UART_APPS_N 0x18154 #define SE9_UART_APPS_D 0x18158 -#define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n) } - -struct freq_tbl { - uint freq; - uint src; - u8 pre_div; - u16 m; - u16 n; -}; - static const struct freq_tbl ftbl_gcc_qupv3_wrap0_s0_clk_src[] = { F(7372800, CFG_CLK_SRC_GPLL0_EVEN, 1, 384, 15625), F(14745600, CFG_CLK_SRC_GPLL0_EVEN, 1, 768, 15625), @@ -64,22 +54,6 @@ static const struct bcr_regs uart2_regs = { .D = SE9_UART_APPS_D, }; -const struct freq_tbl *qcom_find_freq(const struct freq_tbl *f, uint rate) -{ - if (!f) - return NULL; - - if (!f->freq) - return f; - - for (; f->freq; f++) - if (rate <= f->freq) - return f; - - /* Default to our fastest rate */ - return f - 1; -} - static ulong sdm845_clk_set_rate(struct clk *clk, ulong rate) { struct msm_clk_priv *priv = dev_get_priv(clk->dev); From 53b2c7af69464d06cc12fe96e8db6cabf201ba38 Mon Sep 17 00:00:00 2001 From: Caleb Connolly Date: Tue, 14 Nov 2023 12:55:40 +0000 Subject: [PATCH 08/24] pinctrl: qcom: move out of mach-snapdragon Move the Qualcomm pinctrl drivers out of mach-snapdragon and over to the rest of the pinctrl drivers, adjust the drivers so that support for each platform can be enabled/disabled individually and introduce platform specific configuration options. Reviewed-by: Sumit Garg Signed-off-by: Caleb Connolly --- MAINTAINERS | 1 + arch/arm/mach-snapdragon/Kconfig | 4 ++ arch/arm/mach-snapdragon/Makefile | 5 --- drivers/pinctrl/Kconfig | 1 + drivers/pinctrl/Makefile | 1 + drivers/pinctrl/qcom/Kconfig | 39 +++++++++++++++++++ drivers/pinctrl/qcom/Makefile | 9 +++++ .../pinctrl/qcom}/pinctrl-apq8016.c | 19 ++++++++- .../pinctrl/qcom}/pinctrl-apq8096.c | 19 ++++++++- .../pinctrl/qcom/pinctrl-qcom.c | 39 ++++++++++--------- .../pinctrl/qcom/pinctrl-qcom.h | 11 +++--- .../pinctrl/qcom}/pinctrl-qcs404.c | 19 ++++++++- .../pinctrl/qcom}/pinctrl-sdm845.c | 19 ++++++++- 13 files changed, 149 insertions(+), 37 deletions(-) create mode 100644 drivers/pinctrl/qcom/Kconfig create mode 100644 drivers/pinctrl/qcom/Makefile rename {arch/arm/mach-snapdragon => drivers/pinctrl/qcom}/pinctrl-apq8016.c (75%) rename {arch/arm/mach-snapdragon => drivers/pinctrl/qcom}/pinctrl-apq8096.c (74%) rename arch/arm/mach-snapdragon/pinctrl-snapdragon.c => drivers/pinctrl/qcom/pinctrl-qcom.c (85%) rename arch/arm/mach-snapdragon/pinctrl-snapdragon.h => drivers/pinctrl/qcom/pinctrl-qcom.h (68%) rename {arch/arm/mach-snapdragon => drivers/pinctrl/qcom}/pinctrl-qcs404.c (78%) rename {arch/arm/mach-snapdragon => drivers/pinctrl/qcom}/pinctrl-sdm845.c (70%) diff --git a/MAINTAINERS b/MAINTAINERS index 185f5ebbb17..b5ff9349294 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -579,6 +579,7 @@ F: drivers/clk/qcom/ F: drivers/gpio/msm_gpio.c F: drivers/mmc/msm_sdhci.c F: drivers/phy/msm8916-usbh-phy.c +F: drivers/pinctrl/qcom/ F: drivers/serial/serial_msm.c F: drivers/serial/serial_msm_geni.c F: drivers/smem/msm_smem.c diff --git a/arch/arm/mach-snapdragon/Kconfig b/arch/arm/mach-snapdragon/Kconfig index dde37eccc55..3c9f3bee3f1 100644 --- a/arch/arm/mach-snapdragon/Kconfig +++ b/arch/arm/mach-snapdragon/Kconfig @@ -16,6 +16,7 @@ config SDM845 bool "Qualcomm Snapdragon 845 SoC" select LINUX_KERNEL_IMAGE_HEADER imply CLK_QCOM_SDM845 + imply PINCTRL_QCOM_SDM845 config LNX_KRNL_IMG_TEXT_OFFSET_BASE default 0x80000000 @@ -28,6 +29,7 @@ config TARGET_DRAGONBOARD410C select BOARD_LATE_INIT select ENABLE_ARM_SOC_BOOT0_HOOK imply CLK_QCOM_APQ8016 + imply PINCTRL_QCOM_APQ8016 help Support for 96Boards Dragonboard 410C. This board complies with 96Board Open Platform Specifications. Features: @@ -42,6 +44,7 @@ config TARGET_DRAGONBOARD410C config TARGET_DRAGONBOARD820C bool "96Boards Dragonboard 820C" imply CLK_QCOM_APQ8096 + imply PINCTRL_QCOM_APQ8096 help Support for 96Boards Dragonboard 820C. This board complies with 96Board Open Platform Specifications. Features: @@ -76,6 +79,7 @@ config TARGET_QCS404EVB bool "Qualcomm Technologies, Inc. QCS404 EVB" select LINUX_KERNEL_IMAGE_HEADER imply CLK_QCOM_QCS404 + imply PINCTRL_QCOM_QCS404 help Support for Qualcomm Technologies, Inc. QCS404 evaluation board. Features: diff --git a/arch/arm/mach-snapdragon/Makefile b/arch/arm/mach-snapdragon/Makefile index 497ee35cf7d..3a3a297c176 100644 --- a/arch/arm/mach-snapdragon/Makefile +++ b/arch/arm/mach-snapdragon/Makefile @@ -8,9 +8,4 @@ obj-$(CONFIG_TARGET_DRAGONBOARD820C) += sysmap-apq8096.o obj-$(CONFIG_TARGET_DRAGONBOARD410C) += sysmap-apq8016.o obj-y += misc.o obj-y += dram.o -obj-y += pinctrl-snapdragon.o -obj-y += pinctrl-apq8016.o -obj-y += pinctrl-apq8096.o -obj-y += pinctrl-qcs404.o -obj-y += pinctrl-sdm845.o obj-$(CONFIG_TARGET_QCS404EVB) += sysmap-qcs404.o diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index fceafea24c2..a1d53cfbdbe 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -355,6 +355,7 @@ source "drivers/pinctrl/mvebu/Kconfig" source "drivers/pinctrl/nexell/Kconfig" source "drivers/pinctrl/nuvoton/Kconfig" source "drivers/pinctrl/nxp/Kconfig" +source "drivers/pinctrl/qcom/Kconfig" source "drivers/pinctrl/renesas/Kconfig" source "drivers/pinctrl/rockchip/Kconfig" source "drivers/pinctrl/sunxi/Kconfig" diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index 96a0516fe08..0e929d8ca04 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -13,6 +13,7 @@ obj-$(CONFIG_ARCH_ATH79) += ath79/ obj-$(CONFIG_PINCTRL_INTEL) += intel/ obj-$(CONFIG_ARCH_MTMIPS) += mtmips/ obj-$(CONFIG_ARCH_NPCM) += nuvoton/ +obj-$(CONFIG_PINCTRL_QCOM) += qcom/ obj-$(CONFIG_ARCH_RMOBILE) += renesas/ obj-$(CONFIG_ARCH_RZN1) += renesas/ obj-$(CONFIG_PINCTRL_SANDBOX) += pinctrl-sandbox.o diff --git a/drivers/pinctrl/qcom/Kconfig b/drivers/pinctrl/qcom/Kconfig new file mode 100644 index 00000000000..412925c4878 --- /dev/null +++ b/drivers/pinctrl/qcom/Kconfig @@ -0,0 +1,39 @@ +if ARCH_SNAPDRAGON + +config PINCTRL_QCOM + depends on PINCTRL_GENERIC + def_bool n + +menu "Qualcomm pinctrl drivers" + +config PINCTRL_QCOM_APQ8016 + bool "Qualcomm APQ8016 GCC" + 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" + 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_QCS404 + bool "Qualcomm QCS404 GCC" + 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_SDM845 + bool "Qualcomm SDM845 GCC" + select PINCTRL_QCOM + help + Say Y here to enable support for pinctrl on the Snapdragon 845 SoC, + as well as the associated GPIO driver. + +endmenu + +endif diff --git a/drivers/pinctrl/qcom/Makefile b/drivers/pinctrl/qcom/Makefile new file mode 100644 index 00000000000..86f50742730 --- /dev/null +++ b/drivers/pinctrl/qcom/Makefile @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (c) 2023 Linaro Ltd. + +obj-$(CONFIG_PINCTRL_QCOM) += pinctrl-qcom.o +obj-$(CONFIG_PINCTRL_QCOM_APQ8016) += pinctrl-apq8016.o +obj-$(CONFIG_PINCTRL_QCOM_APQ8096) += pinctrl-apq8096.o +obj-$(CONFIG_PINCTRL_QCOM_QCS404) += pinctrl-qcs404.o +obj-$(CONFIG_PINCTRL_QCOM_SDM845) += pinctrl-sdm845.o diff --git a/arch/arm/mach-snapdragon/pinctrl-apq8016.c b/drivers/pinctrl/qcom/pinctrl-apq8016.c similarity index 75% rename from arch/arm/mach-snapdragon/pinctrl-apq8016.c rename to drivers/pinctrl/qcom/pinctrl-apq8016.c index 70c0be0bca9..bcbc0df5071 100644 --- a/arch/arm/mach-snapdragon/pinctrl-apq8016.c +++ b/drivers/pinctrl/qcom/pinctrl-apq8016.c @@ -6,8 +6,10 @@ * */ -#include "pinctrl-snapdragon.h" #include +#include + +#include "pinctrl-qcom.h" #define MAX_PIN_NAME_LEN 32 static char pin_name[MAX_PIN_NAME_LEN] __section(".data"); @@ -52,10 +54,23 @@ static unsigned int apq8016_get_function_mux(unsigned int selector) return msm_pinctrl_functions[selector].val; } -struct msm_pinctrl_data apq8016_data = { +static const struct msm_pinctrl_data apq8016_data = { .pin_count = 133, .functions_count = ARRAY_SIZE(msm_pinctrl_functions), .get_function_name = apq8016_get_function_name, .get_function_mux = apq8016_get_function_mux, .get_pin_name = apq8016_get_pin_name, }; + +static const struct udevice_id msm_pinctrl_ids[] = { + { .compatible = "qcom,msm8916-pinctrl", .data = (ulong)&apq8016_data }, + { /* Sentinal */ } +}; + +U_BOOT_DRIVER(pinctrl_apq8016) = { + .name = "pinctrl_apq8016", + .id = UCLASS_NOP, + .of_match = msm_pinctrl_ids, + .ops = &msm_pinctrl_ops, + .bind = msm_pinctrl_bind, +}; diff --git a/arch/arm/mach-snapdragon/pinctrl-apq8096.c b/drivers/pinctrl/qcom/pinctrl-apq8096.c similarity index 74% rename from arch/arm/mach-snapdragon/pinctrl-apq8096.c rename to drivers/pinctrl/qcom/pinctrl-apq8096.c index 45462f01c2c..52508561768 100644 --- a/arch/arm/mach-snapdragon/pinctrl-apq8096.c +++ b/drivers/pinctrl/qcom/pinctrl-apq8096.c @@ -6,8 +6,10 @@ * */ -#include "pinctrl-snapdragon.h" #include +#include + +#include "pinctrl-qcom.h" #define MAX_PIN_NAME_LEN 32 static char pin_name[MAX_PIN_NAME_LEN] __section(".data"); @@ -47,10 +49,23 @@ static unsigned int apq8096_get_function_mux(unsigned int selector) return msm_pinctrl_functions[selector].val; } -struct msm_pinctrl_data apq8096_data = { +static const struct msm_pinctrl_data apq8096_data = { .pin_count = 157, .functions_count = ARRAY_SIZE(msm_pinctrl_functions), .get_function_name = apq8096_get_function_name, .get_function_mux = apq8096_get_function_mux, .get_pin_name = apq8096_get_pin_name, }; + +static const struct udevice_id msm_pinctrl_ids[] = { + { .compatible = "qcom,msm8996-pinctrl", .data = (ulong)&apq8096_data }, + { /* Sentinal */ } +}; + +U_BOOT_DRIVER(pinctrl_apq8096) = { + .name = "pinctrl_apq8096", + .id = UCLASS_NOP, + .of_match = msm_pinctrl_ids, + .ops = &msm_pinctrl_ops, + .bind = msm_pinctrl_bind, +}; diff --git a/arch/arm/mach-snapdragon/pinctrl-snapdragon.c b/drivers/pinctrl/qcom/pinctrl-qcom.c similarity index 85% rename from arch/arm/mach-snapdragon/pinctrl-snapdragon.c rename to drivers/pinctrl/qcom/pinctrl-qcom.c index 826dc514866..1cface7f610 100644 --- a/arch/arm/mach-snapdragon/pinctrl-snapdragon.c +++ b/drivers/pinctrl/qcom/pinctrl-qcom.c @@ -11,10 +11,11 @@ #include #include #include +#include #include #include #include -#include "pinctrl-snapdragon.h" +#include "pinctrl-qcom.h" struct msm_pinctrl_priv { phys_addr_t base; @@ -109,7 +110,7 @@ static int msm_pinconf_set(struct udevice *dev, unsigned int pin_selector, return 0; } -static struct pinctrl_ops msm_pinctrl_ops = { +struct pinctrl_ops msm_pinctrl_ops = { .get_pins_count = msm_get_pins_count, .get_pin_name = msm_get_pin_name, .set_state = pinctrl_generic_set_state, @@ -121,12 +122,24 @@ static struct pinctrl_ops msm_pinctrl_ops = { .get_function_name = msm_get_function_name, }; -static int msm_pinctrl_bind(struct udevice *dev) +int msm_pinctrl_bind(struct udevice *dev) { ofnode node = dev_ofnode(dev); + struct msm_pinctrl_data *data = (struct msm_pinctrl_data *)dev_get_driver_data(dev); + struct driver *drv; + struct udevice *pinctrl_dev; const char *name; int ret; + drv = lists_driver_lookup_name("pinctrl_qcom"); + if (!drv) + return -ENOENT; + + ret = device_bind_with_driver_data(dev_get_parent(dev), drv, ofnode_get_name(node), (ulong)data, + dev_ofnode(dev), &pinctrl_dev); + if (ret) + return ret; + ofnode_get_property(node, "gpio-controller", &ret); if (ret < 0) return 0; @@ -139,28 +152,18 @@ static int msm_pinctrl_bind(struct udevice *dev) /* Bind gpio node */ ret = device_bind_driver_to_node(dev, "gpio_msm", name, node, NULL); - if (ret) + if (ret) { + device_unbind(pinctrl_dev); return ret; - - dev_dbg(dev, "bind %s\n", name); + } return 0; } -static const struct udevice_id msm_pinctrl_ids[] = { - { .compatible = "qcom,msm8916-pinctrl", .data = (ulong)&apq8016_data }, - { .compatible = "qcom,msm8996-pinctrl", .data = (ulong)&apq8096_data }, - { .compatible = "qcom,sdm845-pinctrl", .data = (ulong)&sdm845_data }, - { .compatible = "qcom,qcs404-pinctrl", .data = (ulong)&qcs404_data }, - { } -}; - -U_BOOT_DRIVER(pinctrl_snapdraon) = { - .name = "pinctrl_msm", +U_BOOT_DRIVER(pinctrl_qcom) = { + .name = "pinctrl_qcom", .id = UCLASS_PINCTRL, - .of_match = msm_pinctrl_ids, .priv_auto = sizeof(struct msm_pinctrl_priv), .ops = &msm_pinctrl_ops, .probe = msm_pinctrl_probe, - .bind = msm_pinctrl_bind, }; diff --git a/arch/arm/mach-snapdragon/pinctrl-snapdragon.h b/drivers/pinctrl/qcom/pinctrl-qcom.h similarity index 68% rename from arch/arm/mach-snapdragon/pinctrl-snapdragon.h rename to drivers/pinctrl/qcom/pinctrl-qcom.h index 178ee01a41f..1edd9a43ffd 100644 --- a/arch/arm/mach-snapdragon/pinctrl-snapdragon.h +++ b/drivers/pinctrl/qcom/pinctrl-qcom.h @@ -5,8 +5,8 @@ * (C) Copyright 2018 Ramon Fried * */ -#ifndef _PINCTRL_SNAPDRAGON_H -#define _PINCTRL_SNAPDRAGON_H +#ifndef _PINCTRL_QCOM_H +#define _PINCTRL_QCOM_H struct udevice; @@ -25,9 +25,8 @@ struct pinctrl_function { int val; }; -extern struct msm_pinctrl_data apq8016_data; -extern struct msm_pinctrl_data apq8096_data; -extern struct msm_pinctrl_data sdm845_data; -extern struct msm_pinctrl_data qcs404_data; +extern struct pinctrl_ops msm_pinctrl_ops; + +int msm_pinctrl_bind(struct udevice *dev); #endif diff --git a/arch/arm/mach-snapdragon/pinctrl-qcs404.c b/drivers/pinctrl/qcom/pinctrl-qcs404.c similarity index 78% rename from arch/arm/mach-snapdragon/pinctrl-qcs404.c rename to drivers/pinctrl/qcom/pinctrl-qcs404.c index a6e53c4412e..272331c90b5 100644 --- a/arch/arm/mach-snapdragon/pinctrl-qcs404.c +++ b/drivers/pinctrl/qcom/pinctrl-qcs404.c @@ -5,8 +5,10 @@ * (C) Copyright 2022 Sumit Garg */ -#include "pinctrl-snapdragon.h" #include +#include + +#include "pinctrl-qcom.h" #define MAX_PIN_NAME_LEN 32 static char pin_name[MAX_PIN_NAME_LEN] __section(".data"); @@ -59,10 +61,23 @@ static unsigned int qcs404_get_function_mux(unsigned int selector) return msm_pinctrl_functions[selector].val; } -struct msm_pinctrl_data qcs404_data = { +static struct msm_pinctrl_data qcs404_data = { .pin_count = 126, .functions_count = ARRAY_SIZE(msm_pinctrl_functions), .get_function_name = qcs404_get_function_name, .get_function_mux = qcs404_get_function_mux, .get_pin_name = qcs404_get_pin_name, }; + +static const struct udevice_id msm_pinctrl_ids[] = { + { .compatible = "qcom,qcs404-pinctrl", .data = (ulong)&qcs404_data }, + { /* Sentinal */ } +}; + +U_BOOT_DRIVER(pinctrl_qcs404) = { + .name = "pinctrl_qcs404", + .id = UCLASS_NOP, + .of_match = msm_pinctrl_ids, + .ops = &msm_pinctrl_ops, + .bind = msm_pinctrl_bind, +}; diff --git a/arch/arm/mach-snapdragon/pinctrl-sdm845.c b/drivers/pinctrl/qcom/pinctrl-sdm845.c similarity index 70% rename from arch/arm/mach-snapdragon/pinctrl-sdm845.c rename to drivers/pinctrl/qcom/pinctrl-sdm845.c index 40f2f012fa0..1a09c5c81dc 100644 --- a/arch/arm/mach-snapdragon/pinctrl-sdm845.c +++ b/drivers/pinctrl/qcom/pinctrl-sdm845.c @@ -6,8 +6,10 @@ * */ -#include "pinctrl-snapdragon.h" #include +#include + +#include "pinctrl-qcom.h" #define MAX_PIN_NAME_LEN 32 static char pin_name[MAX_PIN_NAME_LEN] __section(".data"); @@ -35,10 +37,23 @@ static unsigned int sdm845_get_function_mux(unsigned int selector) return msm_pinctrl_functions[selector].val; } -struct msm_pinctrl_data sdm845_data = { +static struct msm_pinctrl_data sdm845_data = { .pin_count = 150, .functions_count = ARRAY_SIZE(msm_pinctrl_functions), .get_function_name = sdm845_get_function_name, .get_function_mux = sdm845_get_function_mux, .get_pin_name = sdm845_get_pin_name, }; + +static const struct udevice_id msm_pinctrl_ids[] = { + { .compatible = "qcom,sdm845-pinctrl", .data = (ulong)&sdm845_data }, + { /* Sentinal */ } +}; + +U_BOOT_DRIVER(pinctrl_sdm845) = { + .name = "pinctrl_sdm845", + .id = UCLASS_NOP, + .of_match = msm_pinctrl_ids, + .ops = &msm_pinctrl_ops, + .bind = msm_pinctrl_bind, +}; From 24d2908e987af6b435ac818eda44fe81152296fb Mon Sep 17 00:00:00 2001 From: Caleb Connolly Date: Tue, 14 Nov 2023 12:55:41 +0000 Subject: [PATCH 09/24] pinctrl: qcom: move ipq4019 driver from mach-ipq40xx Drop the duplicated pinctrl-snapdragon driver from mach-ipq40xx and add it to drivers/pinctrl/qcom. Acked-by: Sumit Garg Signed-off-by: Caleb Connolly --- arch/arm/Kconfig | 1 + arch/arm/mach-ipq40xx/Makefile | 8 - arch/arm/mach-ipq40xx/pinctrl-snapdragon.c | 166 ------------------ arch/arm/mach-ipq40xx/pinctrl-snapdragon.h | 28 --- drivers/pinctrl/qcom/Kconfig | 7 + drivers/pinctrl/qcom/Makefile | 1 + .../pinctrl/qcom}/pinctrl-ipq4019.c | 23 ++- 7 files changed, 27 insertions(+), 207 deletions(-) delete mode 100644 arch/arm/mach-ipq40xx/Makefile delete mode 100644 arch/arm/mach-ipq40xx/pinctrl-snapdragon.c delete mode 100644 arch/arm/mach-ipq40xx/pinctrl-snapdragon.h rename {arch/arm/mach-ipq40xx => drivers/pinctrl/qcom}/pinctrl-ipq4019.c (73%) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 2eef266e1d1..9e73b69f1e1 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -777,6 +777,7 @@ config ARCH_IPQ40XX select SMEM select OF_CONTROL select CLK_QCOM_IPQ4019 + select PINCTRL_QCOM_IPQ4019 imply CMD_DM config ARCH_KEYSTONE diff --git a/arch/arm/mach-ipq40xx/Makefile b/arch/arm/mach-ipq40xx/Makefile deleted file mode 100644 index b36a935c6f9..00000000000 --- a/arch/arm/mach-ipq40xx/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0+ -# -# Copyright (c) 2019 Sartura Ltd. -# -# Author: Robert Marko - -obj-y += pinctrl-snapdragon.o -obj-y += pinctrl-ipq4019.o diff --git a/arch/arm/mach-ipq40xx/pinctrl-snapdragon.c b/arch/arm/mach-ipq40xx/pinctrl-snapdragon.c deleted file mode 100644 index 036fec93d72..00000000000 --- a/arch/arm/mach-ipq40xx/pinctrl-snapdragon.c +++ /dev/null @@ -1,166 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * TLMM driver for Qualcomm IPQ40xx - * - * (C) Copyright 2018 Ramon Fried - * - * Copyright (c) 2020 Sartura Ltd. - * - * Author: Robert Marko - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include "pinctrl-snapdragon.h" - -struct msm_pinctrl_priv { - phys_addr_t base; - struct msm_pinctrl_data *data; -}; - -#define GPIO_CONFIG_OFFSET(x) ((x) * 0x1000) -#define TLMM_GPIO_PULL_MASK GENMASK(1, 0) -#define TLMM_FUNC_SEL_MASK GENMASK(5, 2) -#define TLMM_DRV_STRENGTH_MASK GENMASK(8, 6) -#define TLMM_GPIO_DISABLE BIT(9) - -static const struct pinconf_param msm_conf_params[] = { - { "drive-strength", PIN_CONFIG_DRIVE_STRENGTH, 2 }, - { "bias-disable", PIN_CONFIG_BIAS_DISABLE, 0 }, - { "bias-pull-up", PIN_CONFIG_BIAS_PULL_UP, 2 }, -}; - -static int msm_get_functions_count(struct udevice *dev) -{ - struct msm_pinctrl_priv *priv = dev_get_priv(dev); - - return priv->data->functions_count; -} - -static int msm_get_pins_count(struct udevice *dev) -{ - struct msm_pinctrl_priv *priv = dev_get_priv(dev); - - return priv->data->pin_count; -} - -static const char *msm_get_function_name(struct udevice *dev, - unsigned int selector) -{ - struct msm_pinctrl_priv *priv = dev_get_priv(dev); - - return priv->data->get_function_name(dev, selector); -} - -static int msm_pinctrl_probe(struct udevice *dev) -{ - struct msm_pinctrl_priv *priv = dev_get_priv(dev); - - priv->base = devfdt_get_addr(dev); - priv->data = (struct msm_pinctrl_data *)dev->driver_data; - - return priv->base == FDT_ADDR_T_NONE ? -EINVAL : 0; -} - -static const char *msm_get_pin_name(struct udevice *dev, unsigned int selector) -{ - struct msm_pinctrl_priv *priv = dev_get_priv(dev); - - return priv->data->get_pin_name(dev, selector); -} - -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); - - clrsetbits_le32(priv->base + GPIO_CONFIG_OFFSET(pin_selector), - TLMM_FUNC_SEL_MASK | TLMM_GPIO_DISABLE, - priv->data->get_function_mux(func_selector) << 2); - return 0; -} - -static int msm_pinconf_set(struct udevice *dev, unsigned int pin_selector, - unsigned int param, unsigned int argument) -{ - struct msm_pinctrl_priv *priv = dev_get_priv(dev); - - switch (param) { - case PIN_CONFIG_DRIVE_STRENGTH: - clrsetbits_le32(priv->base + GPIO_CONFIG_OFFSET(pin_selector), - TLMM_DRV_STRENGTH_MASK, argument << 6); - break; - case PIN_CONFIG_BIAS_DISABLE: - clrbits_le32(priv->base + GPIO_CONFIG_OFFSET(pin_selector), - TLMM_GPIO_PULL_MASK); - break; - case PIN_CONFIG_BIAS_PULL_UP: - clrsetbits_le32(priv->base + GPIO_CONFIG_OFFSET(pin_selector), - TLMM_GPIO_PULL_MASK, argument); - break; - default: - return 0; - } - - return 0; -} - -static int msm_pinctrl_bind(struct udevice *dev) -{ - ofnode node = dev_ofnode(dev); - const char *name; - int ret; - - ofnode_get_property(node, "gpio-controller", &ret); - if (ret < 0) - return 0; - - /* Get the name of gpio node */ - name = ofnode_get_name(node); - if (!name) - return -EINVAL; - - /* Bind gpio node */ - ret = device_bind_driver_to_node(dev, "gpio_msm", - name, node, NULL); - if (ret) - return ret; - - dev_dbg(dev, "bind %s\n", name); - - return 0; -} - -static struct pinctrl_ops msm_pinctrl_ops = { - .get_pins_count = msm_get_pins_count, - .get_pin_name = msm_get_pin_name, - .set_state = pinctrl_generic_set_state, - .pinmux_set = msm_pinmux_set, - .pinconf_num_params = ARRAY_SIZE(msm_conf_params), - .pinconf_params = msm_conf_params, - .pinconf_set = msm_pinconf_set, - .get_functions_count = msm_get_functions_count, - .get_function_name = msm_get_function_name, -}; - -static const struct udevice_id msm_pinctrl_ids[] = { - { .compatible = "qcom,ipq4019-pinctrl", .data = (ulong)&ipq4019_data }, - { } -}; - -U_BOOT_DRIVER(pinctrl_snapdraon) = { - .name = "pinctrl_msm", - .id = UCLASS_PINCTRL, - .of_match = msm_pinctrl_ids, - .priv_auto = sizeof(struct msm_pinctrl_priv), - .ops = &msm_pinctrl_ops, - .probe = msm_pinctrl_probe, - .bind = msm_pinctrl_bind, -}; diff --git a/arch/arm/mach-ipq40xx/pinctrl-snapdragon.h b/arch/arm/mach-ipq40xx/pinctrl-snapdragon.h deleted file mode 100644 index b4823a309fc..00000000000 --- a/arch/arm/mach-ipq40xx/pinctrl-snapdragon.h +++ /dev/null @@ -1,28 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Qualcomm Pin control - * - * (C) Copyright 2018 Ramon Fried - * - */ -#ifndef _PINCTRL_SNAPDRAGON_H -#define _PINCTRL_SNAPDRAGON_H - -struct msm_pinctrl_data { - int pin_count; - int functions_count; - const char *(*get_function_name)(struct udevice *dev, - unsigned int selector); - unsigned int (*get_function_mux)(unsigned int selector); - const char *(*get_pin_name)(struct udevice *dev, - unsigned int selector); -}; - -struct pinctrl_function { - const char *name; - int val; -}; - -extern struct msm_pinctrl_data ipq4019_data; - -#endif diff --git a/drivers/pinctrl/qcom/Kconfig b/drivers/pinctrl/qcom/Kconfig index 412925c4878..2fe63981478 100644 --- a/drivers/pinctrl/qcom/Kconfig +++ b/drivers/pinctrl/qcom/Kconfig @@ -20,6 +20,13 @@ config PINCTRL_QCOM_APQ8096 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" + 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_QCS404 bool "Qualcomm QCS404 GCC" select PINCTRL_QCOM diff --git a/drivers/pinctrl/qcom/Makefile b/drivers/pinctrl/qcom/Makefile index 86f50742730..6d9aca6d7b7 100644 --- a/drivers/pinctrl/qcom/Makefile +++ b/drivers/pinctrl/qcom/Makefile @@ -4,6 +4,7 @@ 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_APQ8096) += pinctrl-apq8096.o obj-$(CONFIG_PINCTRL_QCOM_QCS404) += pinctrl-qcs404.o obj-$(CONFIG_PINCTRL_QCOM_SDM845) += pinctrl-sdm845.o diff --git a/arch/arm/mach-ipq40xx/pinctrl-ipq4019.c b/drivers/pinctrl/qcom/pinctrl-ipq4019.c similarity index 73% rename from arch/arm/mach-ipq40xx/pinctrl-ipq4019.c rename to drivers/pinctrl/qcom/pinctrl-ipq4019.c index 3e365f8cc86..87058e21ce8 100644 --- a/arch/arm/mach-ipq40xx/pinctrl-ipq4019.c +++ b/drivers/pinctrl/qcom/pinctrl-ipq4019.c @@ -7,12 +7,13 @@ * Author: Robert Marko */ -#include "pinctrl-snapdragon.h" #include +#include + +#include "pinctrl-qcom.h" #define MAX_PIN_NAME_LEN 32 -static char pin_name[MAX_PIN_NAME_LEN]; - +static char pin_name[MAX_PIN_NAME_LEN] __section(".data"); static const struct pinctrl_function msm_pinctrl_functions[] = { {"gpio", 0}, {"blsp_uart0_0", 1}, /* Only for GPIO:16,17 */ @@ -26,7 +27,6 @@ static const struct pinctrl_function msm_pinctrl_functions[] = { {"mdc_0", 1}, /* Only for GPIO7 */ {"mdc_1", 2}, /* Only for GPIO52 */ }; - static const char *ipq4019_get_function_name(struct udevice *dev, unsigned int selector) { @@ -45,10 +45,23 @@ static unsigned int ipq4019_get_function_mux(unsigned int selector) return msm_pinctrl_functions[selector].val; } -struct msm_pinctrl_data ipq4019_data = { +static const struct msm_pinctrl_data ipq4019_data = { .pin_count = 100, .functions_count = ARRAY_SIZE(msm_pinctrl_functions), .get_function_name = ipq4019_get_function_name, .get_function_mux = ipq4019_get_function_mux, .get_pin_name = ipq4019_get_pin_name, }; + +static const struct udevice_id msm_pinctrl_ids[] = { + { .compatible = "qcom,ipq4019-pinctrl", .data = (ulong)&ipq4019_data }, + { /* Sentinal */ } +}; + +U_BOOT_DRIVER(pinctrl_ipq4019) = { + .name = "pinctrl_ipq4019", + .id = UCLASS_NOP, + .of_match = msm_pinctrl_ids, + .ops = &msm_pinctrl_ops, + .bind = msm_pinctrl_bind, +}; From 2c2cc3e9c0273d4ecfd33c17fc6fb50a8fb5bcf5 Mon Sep 17 00:00:00 2001 From: Caleb Connolly Date: Tue, 14 Nov 2023 12:55:42 +0000 Subject: [PATCH 10/24] pinctrl: qcom: make compatible with linux DTs The pinctrl and GPIO drivers are currently heavily incompatible with upstream. Most Qualcomm pinctrl blocks feature "tiles" of pins, each at it's own address. Introduce support for these by allowing the soc driver to specify per-pin register offsets similarly to the Linux driver. Adjust the GPIO driver to handle these too, and finally enable support for all pins with the same numbering as used in Linux. Reviewed-by: Sumit Garg Signed-off-by: Caleb Connolly --- arch/arm/dts/dragonboard845c-uboot.dtsi | 2 +- arch/arm/dts/sdm845.dtsi | 16 ++----- arch/arm/dts/starqltechn-uboot.dtsi | 5 +-- arch/arm/dts/starqltechn.dts | 16 +++---- arch/arm/mach-snapdragon/include/mach/gpio.h | 28 ++++++++++-- drivers/gpio/msm_gpio.c | 36 +++++++++------- drivers/pinctrl/qcom/pinctrl-apq8016.c | 2 +- drivers/pinctrl/qcom/pinctrl-apq8096.c | 2 +- drivers/pinctrl/qcom/pinctrl-ipq4019.c | 2 +- drivers/pinctrl/qcom/pinctrl-qcom.c | 31 +++++++++----- drivers/pinctrl/qcom/pinctrl-qcom.h | 5 ++- drivers/pinctrl/qcom/pinctrl-qcs404.c | 2 +- drivers/pinctrl/qcom/pinctrl-sdm845.c | 45 +++++++++++++++++++- 13 files changed, 130 insertions(+), 62 deletions(-) diff --git a/arch/arm/dts/dragonboard845c-uboot.dtsi b/arch/arm/dts/dragonboard845c-uboot.dtsi index 7106db8a734..7728f4f4a3e 100644 --- a/arch/arm/dts/dragonboard845c-uboot.dtsi +++ b/arch/arm/dts/dragonboard845c-uboot.dtsi @@ -19,7 +19,7 @@ bootph-all; }; - pinctrl_north@3900000 { + pinctrl@3400000 { bootph-all; }; }; diff --git a/arch/arm/dts/sdm845.dtsi b/arch/arm/dts/sdm845.dtsi index 3b86b9328fc..4798ace0ff8 100644 --- a/arch/arm/dts/sdm845.dtsi +++ b/arch/arm/dts/sdm845.dtsi @@ -26,23 +26,13 @@ #power-domain-cells = <1>; }; - gpio_north: gpio_north@3900000 { - #gpio-cells = <2>; + tlmm: pinctrl@3400000 { compatible = "qcom,sdm845-pinctrl"; - reg = <0x3900000 0x400000>; - gpio-count = <150>; - gpio-controller; - gpio-ranges = <&gpio_north 0 0 150>; - gpio-bank-name = "soc_north."; - }; - - tlmm_north: pinctrl_north@3900000 { - compatible = "qcom,sdm845-pinctrl"; - reg = <0x3900000 0x400000>; + reg = <0x3400000 0xc00000>; gpio-count = <150>; gpio-controller; #gpio-cells = <2>; - gpio-ranges = <&tlmm_north 0 0 150>; + gpio-ranges = <&tlmm 0 0 150>; /* DEBUG UART */ qup_uart9: qup-uart9-default { diff --git a/arch/arm/dts/starqltechn-uboot.dtsi b/arch/arm/dts/starqltechn-uboot.dtsi index d81a22ffe49..034d5c1c07e 100644 --- a/arch/arm/dts/starqltechn-uboot.dtsi +++ b/arch/arm/dts/starqltechn-uboot.dtsi @@ -19,10 +19,7 @@ clock-controller@100000 { bootph-all; }; - gpio_north@3900000 { - bootph-all; - }; - pinctrl_north@3900000 { + pinctrl@3400000 { bootph-all; }; }; diff --git a/arch/arm/dts/starqltechn.dts b/arch/arm/dts/starqltechn.dts index eec51d165f9..5b6372bee79 100644 --- a/arch/arm/dts/starqltechn.dts +++ b/arch/arm/dts/starqltechn.dts @@ -65,15 +65,15 @@ serial@a84000 { status = "okay"; }; + }; +}; - pinctrl_north@3900000 { - muic_i2c: muic_i2c { - pins = "GPIO_33", "GPIO_34"; - drive-strength = <0x2>; - function = "gpio"; - bias-disable; - }; - }; +&tlmm { + muic_i2c: muic-i2c-n { + pins = "GPIO_33", "GPIO_34"; + drive-strength = <0x2>; + function = "gpio"; + bias-disable; }; }; diff --git a/arch/arm/mach-snapdragon/include/mach/gpio.h b/arch/arm/mach-snapdragon/include/mach/gpio.h index bbc2bc16175..8dac62f870b 100644 --- a/arch/arm/mach-snapdragon/include/mach/gpio.h +++ b/arch/arm/mach-snapdragon/include/mach/gpio.h @@ -1,8 +1,28 @@ /* SPDX-License-Identifier: GPL-2.0+ */ /* - * Empty gpio.h + * Qualcomm common pin control data. * - * This file must stay as arch/arm/include/asm/gpio.h requires it. - * - * (C) Copyright 2015 Mateusz Kulikowski + * Copyright (C) 2023 Linaro Ltd. */ +#ifndef _QCOM_GPIO_H_ +#define _QCOM_GPIO_H_ + +#include +#include + +struct msm_pin_data { + int pin_count; + const unsigned int *pin_offsets; +}; + +static inline u32 qcom_pin_offset(const unsigned int *offs, unsigned int selector) +{ + u32 out = (selector * 0x1000); + + if (offs) + return out + offs[selector]; + + return out; +} + +#endif /* _QCOM_GPIO_H_ */ diff --git a/drivers/gpio/msm_gpio.c b/drivers/gpio/msm_gpio.c index 51670f26371..d9355ed4430 100644 --- a/drivers/gpio/msm_gpio.c +++ b/drivers/gpio/msm_gpio.c @@ -11,13 +11,10 @@ #include #include #include +#include DECLARE_GLOBAL_DATA_PTR; -/* Register offsets */ -#define GPIO_CONFIG_OFF(no) ((no) * 0x1000) -#define GPIO_IN_OUT_OFF(no) ((no) * 0x1000 + 0x4) - /* OE */ #define GPIO_OE_DISABLE (0x0 << 9) #define GPIO_OE_ENABLE (0x1 << 9) @@ -29,15 +26,22 @@ DECLARE_GLOBAL_DATA_PTR; struct msm_gpio_bank { phys_addr_t base; + const struct msm_pin_data *pin_data; }; +#define GPIO_CONFIG_REG(dev, x) \ + (qcom_pin_offset(((struct msm_gpio_bank *)dev_get_priv(dev))->pin_data->pin_offsets, x)) + +#define GPIO_IN_OUT_REG(dev, x) \ + (GPIO_CONFIG_REG(dev, x) + 0x4) + static int msm_gpio_direction_input(struct udevice *dev, unsigned int gpio) { struct msm_gpio_bank *priv = dev_get_priv(dev); - phys_addr_t reg = priv->base + GPIO_CONFIG_OFF(gpio); /* Disable OE bit */ - clrsetbits_le32(reg, GPIO_OE_MASK, GPIO_OE_DISABLE); + clrsetbits_le32(priv->base + GPIO_CONFIG_REG(dev, gpio), + GPIO_OE_MASK, GPIO_OE_DISABLE); return 0; } @@ -48,7 +52,7 @@ static int msm_gpio_set_value(struct udevice *dev, unsigned gpio, int value) value = !!value; /* set value */ - writel(value << GPIO_OUT, priv->base + GPIO_IN_OUT_OFF(gpio)); + writel(value << GPIO_OUT, priv->base + GPIO_IN_OUT_REG(dev, gpio)); return 0; } @@ -57,13 +61,13 @@ static int msm_gpio_direction_output(struct udevice *dev, unsigned gpio, int value) { struct msm_gpio_bank *priv = dev_get_priv(dev); - phys_addr_t reg = priv->base + GPIO_CONFIG_OFF(gpio); value = !!value; /* set value */ - writel(value << GPIO_OUT, priv->base + GPIO_IN_OUT_OFF(gpio)); + writel(value << GPIO_OUT, priv->base + GPIO_IN_OUT_REG(dev, gpio)); /* switch direction */ - clrsetbits_le32(reg, GPIO_OE_MASK, GPIO_OE_ENABLE); + clrsetbits_le32(priv->base + GPIO_CONFIG_REG(dev, gpio), + GPIO_OE_MASK, GPIO_OE_ENABLE); return 0; } @@ -72,14 +76,14 @@ static int msm_gpio_get_value(struct udevice *dev, unsigned gpio) { struct msm_gpio_bank *priv = dev_get_priv(dev); - return !!(readl(priv->base + GPIO_IN_OUT_OFF(gpio)) >> GPIO_IN); + return !!(readl(priv->base + GPIO_IN_OUT_REG(dev, gpio)) >> GPIO_IN); } -static int msm_gpio_get_function(struct udevice *dev, unsigned offset) +static int msm_gpio_get_function(struct udevice *dev, unsigned gpio) { struct msm_gpio_bank *priv = dev_get_priv(dev); - if (readl(priv->base + GPIO_CONFIG_OFF(offset)) & GPIO_OE_ENABLE) + if (readl(priv->base + GPIO_CONFIG_REG(dev, gpio)) & GPIO_OE_ENABLE) return GPIOF_OUTPUT; return GPIOF_INPUT; @@ -98,6 +102,7 @@ static int msm_gpio_probe(struct udevice *dev) struct msm_gpio_bank *priv = dev_get_priv(dev); priv->base = dev_read_addr(dev); + priv->pin_data = (struct msm_pin_data *)dev_get_driver_data(dev); return priv->base == FDT_ADDR_T_NONE ? -EINVAL : 0; } @@ -105,9 +110,10 @@ static int msm_gpio_probe(struct udevice *dev) static int msm_gpio_of_to_plat(struct udevice *dev) { struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); + const struct msm_pin_data *pin_data = (struct msm_pin_data *)dev_get_driver_data(dev); - uc_priv->gpio_count = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), - "gpio-count", 0); + /* Get the pin count from the pinctrl driver */ + uc_priv->gpio_count = pin_data->pin_count; uc_priv->bank_name = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "gpio-bank-name", NULL); if (uc_priv->bank_name == NULL) diff --git a/drivers/pinctrl/qcom/pinctrl-apq8016.c b/drivers/pinctrl/qcom/pinctrl-apq8016.c index bcbc0df5071..8149ffd83cc 100644 --- a/drivers/pinctrl/qcom/pinctrl-apq8016.c +++ b/drivers/pinctrl/qcom/pinctrl-apq8016.c @@ -55,7 +55,7 @@ static unsigned int apq8016_get_function_mux(unsigned int selector) } static const struct msm_pinctrl_data apq8016_data = { - .pin_count = 133, + .pin_data = { .pin_count = 133, }, .functions_count = ARRAY_SIZE(msm_pinctrl_functions), .get_function_name = apq8016_get_function_name, .get_function_mux = apq8016_get_function_mux, diff --git a/drivers/pinctrl/qcom/pinctrl-apq8096.c b/drivers/pinctrl/qcom/pinctrl-apq8096.c index 52508561768..d64ab1ff7be 100644 --- a/drivers/pinctrl/qcom/pinctrl-apq8096.c +++ b/drivers/pinctrl/qcom/pinctrl-apq8096.c @@ -50,7 +50,7 @@ static unsigned int apq8096_get_function_mux(unsigned int selector) } static const struct msm_pinctrl_data apq8096_data = { - .pin_count = 157, + .pin_data = { .pin_count = 157, }, .functions_count = ARRAY_SIZE(msm_pinctrl_functions), .get_function_name = apq8096_get_function_name, .get_function_mux = apq8096_get_function_mux, diff --git a/drivers/pinctrl/qcom/pinctrl-ipq4019.c b/drivers/pinctrl/qcom/pinctrl-ipq4019.c index 87058e21ce8..2d99f99e1e4 100644 --- a/drivers/pinctrl/qcom/pinctrl-ipq4019.c +++ b/drivers/pinctrl/qcom/pinctrl-ipq4019.c @@ -46,7 +46,7 @@ static unsigned int ipq4019_get_function_mux(unsigned int selector) } static const struct msm_pinctrl_data ipq4019_data = { - .pin_count = 100, + .pin_data = { .pin_count = 100, }, .functions_count = ARRAY_SIZE(msm_pinctrl_functions), .get_function_name = ipq4019_get_function_name, .get_function_mux = ipq4019_get_function_mux, diff --git a/drivers/pinctrl/qcom/pinctrl-qcom.c b/drivers/pinctrl/qcom/pinctrl-qcom.c index 1cface7f610..dc3d8c4d903 100644 --- a/drivers/pinctrl/qcom/pinctrl-qcom.c +++ b/drivers/pinctrl/qcom/pinctrl-qcom.c @@ -13,8 +13,11 @@ #include #include #include +#include #include #include +#include + #include "pinctrl-qcom.h" struct msm_pinctrl_priv { @@ -22,7 +25,9 @@ struct msm_pinctrl_priv { struct msm_pinctrl_data *data; }; -#define GPIO_CONFIG_OFFSET(x) ((x) * 0x1000) +#define GPIO_CONFIG_REG(priv, x) \ + (qcom_pin_offset((priv)->data->pin_data.pin_offsets, x)) + #define TLMM_GPIO_PULL_MASK GENMASK(1, 0) #define TLMM_FUNC_SEL_MASK GENMASK(5, 2) #define TLMM_DRV_STRENGTH_MASK GENMASK(8, 6) @@ -45,7 +50,7 @@ static int msm_get_pins_count(struct udevice *dev) { struct msm_pinctrl_priv *priv = dev_get_priv(dev); - return priv->data->pin_count; + return priv->data->pin_data.pin_count; } static const char *msm_get_function_name(struct udevice *dev, @@ -61,7 +66,7 @@ static int msm_pinctrl_probe(struct udevice *dev) struct msm_pinctrl_priv *priv = dev_get_priv(dev); priv->base = dev_read_addr(dev); - priv->data = (struct msm_pinctrl_data *)dev->driver_data; + priv->data = (struct msm_pinctrl_data *)dev_get_driver_data(dev); return priv->base == FDT_ADDR_T_NONE ? -EINVAL : 0; } @@ -78,7 +83,7 @@ static int msm_pinmux_set(struct udevice *dev, unsigned int pin_selector, { struct msm_pinctrl_priv *priv = dev_get_priv(dev); - clrsetbits_le32(priv->base + GPIO_CONFIG_OFFSET(pin_selector), + clrsetbits_le32(priv->base + GPIO_CONFIG_REG(priv, pin_selector), TLMM_FUNC_SEL_MASK | TLMM_GPIO_DISABLE, priv->data->get_function_mux(func_selector) << 2); return 0; @@ -92,15 +97,15 @@ static int msm_pinconf_set(struct udevice *dev, unsigned int pin_selector, switch (param) { case PIN_CONFIG_DRIVE_STRENGTH: argument = (argument / 2) - 1; - clrsetbits_le32(priv->base + GPIO_CONFIG_OFFSET(pin_selector), + clrsetbits_le32(priv->base + GPIO_CONFIG_REG(priv, pin_selector), TLMM_DRV_STRENGTH_MASK, argument << 6); break; case PIN_CONFIG_BIAS_DISABLE: - clrbits_le32(priv->base + GPIO_CONFIG_OFFSET(pin_selector), + clrbits_le32(priv->base + GPIO_CONFIG_REG(priv, pin_selector), TLMM_GPIO_PULL_MASK); break; case PIN_CONFIG_BIAS_PULL_UP: - clrsetbits_le32(priv->base + GPIO_CONFIG_OFFSET(pin_selector), + clrsetbits_le32(priv->base + GPIO_CONFIG_REG(priv, pin_selector), TLMM_GPIO_PULL_MASK, argument); break; default: @@ -149,9 +154,15 @@ int msm_pinctrl_bind(struct udevice *dev) if (!name) return -EINVAL; - /* Bind gpio node */ - ret = device_bind_driver_to_node(dev, "gpio_msm", - name, node, NULL); + drv = lists_driver_lookup_name("gpio_msm"); + if (!drv) { + printf("Can't find gpio_msm driver\n"); + return -ENODEV; + } + + /* Bind gpio device as a child of the pinctrl device */ + ret = device_bind_with_driver_data(pinctrl_dev, drv, + name, (ulong)&data->pin_data, node, NULL); if (ret) { device_unbind(pinctrl_dev); return ret; diff --git a/drivers/pinctrl/qcom/pinctrl-qcom.h b/drivers/pinctrl/qcom/pinctrl-qcom.h index 1edd9a43ffd..07f2eae9bae 100644 --- a/drivers/pinctrl/qcom/pinctrl-qcom.h +++ b/drivers/pinctrl/qcom/pinctrl-qcom.h @@ -8,10 +8,13 @@ #ifndef _PINCTRL_QCOM_H #define _PINCTRL_QCOM_H +#include +#include + struct udevice; struct msm_pinctrl_data { - int pin_count; + struct msm_pin_data pin_data; int functions_count; const char *(*get_function_name)(struct udevice *dev, unsigned int selector); diff --git a/drivers/pinctrl/qcom/pinctrl-qcs404.c b/drivers/pinctrl/qcom/pinctrl-qcs404.c index 272331c90b5..ac00afa2a1f 100644 --- a/drivers/pinctrl/qcom/pinctrl-qcs404.c +++ b/drivers/pinctrl/qcom/pinctrl-qcs404.c @@ -62,7 +62,7 @@ static unsigned int qcs404_get_function_mux(unsigned int selector) } static struct msm_pinctrl_data qcs404_data = { - .pin_count = 126, + .pin_data = { .pin_count = 126, }, .functions_count = ARRAY_SIZE(msm_pinctrl_functions), .get_function_name = qcs404_get_function_name, .get_function_mux = qcs404_get_function_mux, diff --git a/drivers/pinctrl/qcom/pinctrl-sdm845.c b/drivers/pinctrl/qcom/pinctrl-sdm845.c index 1a09c5c81dc..9f0f4085ce2 100644 --- a/drivers/pinctrl/qcom/pinctrl-sdm845.c +++ b/drivers/pinctrl/qcom/pinctrl-sdm845.c @@ -3,6 +3,7 @@ * Qualcomm SDM845 pinctrl * * (C) Copyright 2021 Dzmitry Sankouski + * (C) Copyright 2023 Linaro Ltd. * */ @@ -11,6 +12,10 @@ #include "pinctrl-qcom.h" +#define NORTH 0x00500000 +#define SOUTH 0x00900000 +#define EAST 0x00100000 + #define MAX_PIN_NAME_LEN 32 static char pin_name[MAX_PIN_NAME_LEN] __section(".data"); @@ -19,6 +24,39 @@ static const struct pinctrl_function msm_pinctrl_functions[] = { {"gpio", 0}, }; +static const unsigned int sdm845_pin_offsets[] = { + [0] = EAST, [1] = EAST, [2] = EAST, [3] = EAST, [4] = NORTH, + [5] = NORTH, [6] = NORTH, [7] = NORTH, [8] = EAST, [9] = EAST, + [10] = EAST, [11] = EAST, [12] = SOUTH, [13] = SOUTH, [14] = SOUTH, + [15] = SOUTH, [16] = SOUTH, [17] = SOUTH, [18] = SOUTH, [19] = SOUTH, + [20] = SOUTH, [21] = SOUTH, [22] = SOUTH, [23] = SOUTH, [24] = SOUTH, + [25] = SOUTH, [26] = SOUTH, [27] = EAST, [28] = EAST, [29] = EAST, + [30] = EAST, [31] = NORTH, [32] = NORTH, [33] = NORTH, [34] = NORTH, + [35] = SOUTH, [36] = SOUTH, [37] = SOUTH, [38] = NORTH, [39] = EAST, + [40] = SOUTH, [41] = EAST, [42] = EAST, [43] = EAST, [44] = EAST, + [45] = EAST, [46] = EAST, [47] = EAST, [48] = EAST, [49] = NORTH, + [50] = NORTH, [51] = NORTH, [52] = NORTH, [53] = NORTH, [54] = NORTH, + [55] = NORTH, [56] = NORTH, [57] = NORTH, [58] = NORTH, [59] = NORTH, + [60] = NORTH, [61] = NORTH, [62] = NORTH, [63] = NORTH, [64] = NORTH, + [65] = NORTH, [66] = NORTH, [67] = NORTH, [68] = NORTH, [69] = EAST, + [70] = EAST, [71] = EAST, [72] = EAST, [73] = EAST, [74] = EAST, + [75] = EAST, [76] = EAST, [77] = EAST, [78] = EAST, [79] = NORTH, + [80] = NORTH, [81] = NORTH, [82] = NORTH, [83] = NORTH, [84] = NORTH, + [85] = EAST, [86] = EAST, [87] = EAST, [88] = EAST, [89] = SOUTH, + [90] = SOUTH, [91] = SOUTH, [92] = SOUTH, [93] = SOUTH, [94] = SOUTH, + [95] = SOUTH, [96] = SOUTH, [97] = NORTH, [98] = NORTH, [99] = NORTH, + [100] = NORTH, [101] = NORTH, [102] = NORTH, [103] = NORTH, [104] = NORTH, + [105] = NORTH, [106] = NORTH, [107] = NORTH, [108] = NORTH, [109] = NORTH, + [110] = NORTH, [111] = NORTH, [112] = NORTH, [113] = NORTH, [114] = NORTH, + [115] = NORTH, [116] = NORTH, [117] = NORTH, [118] = NORTH, [119] = NORTH, + [120] = NORTH, [121] = NORTH, [122] = EAST, [123] = EAST, [124] = EAST, + [125] = EAST, [126] = EAST, [127] = NORTH, [128] = NORTH, [129] = NORTH, + [130] = NORTH, [131] = NORTH, [132] = NORTH, [133] = NORTH, [134] = NORTH, + [135] = NORTH, [136] = NORTH, [137] = NORTH, [138] = NORTH, [139] = NORTH, + [140] = NORTH, [141] = NORTH, [142] = NORTH, [143] = NORTH, [144] = NORTH, + [145] = NORTH, [146] = NORTH, [147] = NORTH, [148] = NORTH, [149] = NORTH, +}; + static const char *sdm845_get_function_name(struct udevice *dev, unsigned int selector) { @@ -28,7 +66,7 @@ static const char *sdm845_get_function_name(struct udevice *dev, static const char *sdm845_get_pin_name(struct udevice *dev, unsigned int selector) { - snprintf(pin_name, MAX_PIN_NAME_LEN, "GPIO_%u", selector); + snprintf(pin_name, MAX_PIN_NAME_LEN, "gpio%u", selector); return pin_name; } @@ -38,7 +76,10 @@ static unsigned int sdm845_get_function_mux(unsigned int selector) } static struct msm_pinctrl_data sdm845_data = { - .pin_count = 150, + .pin_data = { + .pin_offsets = sdm845_pin_offsets, + .pin_count = ARRAY_SIZE(sdm845_pin_offsets), + }, .functions_count = ARRAY_SIZE(msm_pinctrl_functions), .get_function_name = sdm845_get_function_name, .get_function_mux = sdm845_get_function_mux, From 6156e39e42cde73f7b8bbbad6105a10a4b188541 Mon Sep 17 00:00:00 2001 From: Caleb Connolly Date: Tue, 14 Nov 2023 12:55:43 +0000 Subject: [PATCH 11/24] msm_gpio: use unsigned int Replaces the uses of "unsigned" with "unsigned int". Reviewed-by: Sumit Garg Signed-off-by: Caleb Connolly --- drivers/gpio/msm_gpio.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpio/msm_gpio.c b/drivers/gpio/msm_gpio.c index d9355ed4430..80cd28bb231 100644 --- a/drivers/gpio/msm_gpio.c +++ b/drivers/gpio/msm_gpio.c @@ -46,7 +46,7 @@ static int msm_gpio_direction_input(struct udevice *dev, unsigned int gpio) return 0; } -static int msm_gpio_set_value(struct udevice *dev, unsigned gpio, int value) +static int msm_gpio_set_value(struct udevice *dev, unsigned int gpio, int value) { struct msm_gpio_bank *priv = dev_get_priv(dev); @@ -57,7 +57,7 @@ static int msm_gpio_set_value(struct udevice *dev, unsigned gpio, int value) return 0; } -static int msm_gpio_direction_output(struct udevice *dev, unsigned gpio, +static int msm_gpio_direction_output(struct udevice *dev, unsigned int gpio, int value) { struct msm_gpio_bank *priv = dev_get_priv(dev); @@ -72,14 +72,14 @@ static int msm_gpio_direction_output(struct udevice *dev, unsigned gpio, return 0; } -static int msm_gpio_get_value(struct udevice *dev, unsigned gpio) +static int msm_gpio_get_value(struct udevice *dev, unsigned int gpio) { struct msm_gpio_bank *priv = dev_get_priv(dev); return !!(readl(priv->base + GPIO_IN_OUT_REG(dev, gpio)) >> GPIO_IN); } -static int msm_gpio_get_function(struct udevice *dev, unsigned gpio) +static int msm_gpio_get_function(struct udevice *dev, unsigned int gpio) { struct msm_gpio_bank *priv = dev_get_priv(dev); From 836b7f447429960fa6ff8b6d25c11e39b8c00b94 Mon Sep 17 00:00:00 2001 From: Caleb Connolly Date: Tue, 14 Nov 2023 12:51:11 +0000 Subject: [PATCH 12/24] serial: msm-geni: don't rely on parent misc device commit 1b15483deb3f ("misc: add Qualcomm GENI SE QUP device driver") introduced support for platform-specific oversampling values, necessary to configure the UART clocks on all platforms at runtime. However it relies in probing a parent device. Despite the DM_FLAG_PRE_RELOC flag, this is not done consistently during boot. Instead, take another approach by relying on ofnode_ helpers to read the serial engine base address and do the read directly. This fixes early UART on boards with a non-default oversampling rate. Signed-off-by: Caleb Connolly --- drivers/misc/Kconfig | 7 ------ drivers/misc/Makefile | 1 - drivers/misc/qcom-geni-se.c | 41 -------------------------------- drivers/serial/Kconfig | 2 -- drivers/serial/serial_msm_geni.c | 27 +++++++++++++-------- 5 files changed, 17 insertions(+), 61 deletions(-) delete mode 100644 drivers/misc/qcom-geni-se.c diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index e8e4400516f..e85a0dd51ca 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -527,13 +527,6 @@ config WINBOND_W83627 legacy UART or other devices in the Winbond Super IO chips on X86 platforms. -config QCOM_GENI_SE - bool "Qualcomm GENI Serial Engine Driver" - depends on ARCH_SNAPDRAGON - help - The driver manages Generic Interface (GENI) firmware based - Qualcomm Technologies, Inc. Universal Peripheral (QUP) Wrapper. - config QFW bool help diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index cda701d38ec..6bf1e79f7e2 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -60,7 +60,6 @@ obj-$(CONFIG_NUVOTON_NCT6102D) += nuvoton_nct6102d.o obj-$(CONFIG_P2SB) += p2sb-uclass.o obj-$(CONFIG_PCA9551_LED) += pca9551_led.o obj-$(CONFIG_$(SPL_)PWRSEQ) += pwrseq-uclass.o -obj-$(CONFIG_QCOM_GENI_SE) += qcom-geni-se.o ifdef CONFIG_QFW obj-y += qfw.o obj-$(CONFIG_QFW_ACPI) += qfw_acpi.o diff --git a/drivers/misc/qcom-geni-se.c b/drivers/misc/qcom-geni-se.c deleted file mode 100644 index 281a5ec819a..00000000000 --- a/drivers/misc/qcom-geni-se.c +++ /dev/null @@ -1,41 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Qualcomm Generic Interface (GENI) Serial Engine (SE) Wrapper - * - * Copyright (C) 2023 Linaro Ltd. - */ - -#include -#include -#include -#include - -static int geni_se_qup_read(struct udevice *dev, int offset, - void *buf, int size) -{ - fdt_addr_t base = dev_read_addr(dev); - - if (size != sizeof(u32)) - return -EINVAL; - - *(u32 *)buf = readl(base + offset); - - return size; -} - -static struct misc_ops geni_se_qup_ops = { - .read = geni_se_qup_read, -}; - -static const struct udevice_id geni_se_qup_ids[] = { - { .compatible = "qcom,geni-se-qup" }, - {} -}; - -U_BOOT_DRIVER(geni_se_qup) = { - .name = "geni_se_qup", - .id = UCLASS_MISC, - .of_match = geni_se_qup_ids, - .ops = &geni_se_qup_ops, - .flags = DM_FLAG_PRE_RELOC, -}; diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 6628a887de7..26460c4e0ca 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -972,8 +972,6 @@ config MSM_SERIAL config MSM_GENI_SERIAL bool "Qualcomm on-chip GENI UART" - select MISC - imply QCOM_GENI_SE help Support UART based on Generic Interface (GENI) Serial Engine (SE), used on Qualcomm Snapdragon SoCs. Should support all qualcomm SOCs diff --git a/drivers/serial/serial_msm_geni.c b/drivers/serial/serial_msm_geni.c index b8bc61451a0..0e52e32ddf3 100644 --- a/drivers/serial/serial_msm_geni.c +++ b/drivers/serial/serial_msm_geni.c @@ -485,12 +485,12 @@ static const struct dm_serial_ops msm_serial_ops = { .setbrg = msm_serial_setbrg, }; -static void geni_set_oversampling(struct udevice *dev) +static int geni_set_oversampling(struct udevice *dev) { struct msm_serial_data *priv = dev_get_priv(dev); - struct udevice *parent_dev = dev_get_parent(dev); + ofnode parent_node = ofnode_get_parent(dev_ofnode(dev)); u32 geni_se_version; - int ret; + fdt_addr_t addr; priv->oversampling = UART_OVERSAMPLING; @@ -498,16 +498,20 @@ static void geni_set_oversampling(struct udevice *dev) * It could happen that GENI SE IP is missing in the board's device * tree or GENI UART node is a direct child of SoC device tree node. */ - if (device_get_uclass_id(parent_dev) != UCLASS_MISC) - return; + if (!ofnode_device_is_compatible(parent_node, "qcom,geni-se-qup")) { + pr_err("%s: UART node must be a child of geniqup node\n", + __func__); + return -ENODEV; + } - ret = misc_read(parent_dev, QUP_HW_VER_REG, - &geni_se_version, sizeof(geni_se_version)); - if (ret != sizeof(geni_se_version)) - return; + /* Read the HW_VER register relative to the parents address space */ + addr = ofnode_get_addr(parent_node); + geni_se_version = readl(addr + QUP_HW_VER_REG); if (geni_se_version >= QUP_SE_VERSION_2_5) priv->oversampling /= 2; + + return 0; } static inline void geni_serial_init(struct udevice *dev) @@ -552,8 +556,11 @@ static inline void geni_serial_init(struct udevice *dev) static int msm_serial_probe(struct udevice *dev) { struct msm_serial_data *priv = dev_get_priv(dev); + int ret; - geni_set_oversampling(dev); + ret = geni_set_oversampling(dev); + if (ret < 0) + return ret; /* No need to reinitialize the UART after relocation */ if (gd->flags & GD_FLG_RELOC) From a4ba2a66639ed5db672800a52e6d02b4e83573c2 Mon Sep 17 00:00:00 2001 From: Caleb Connolly Date: Tue, 14 Nov 2023 12:51:12 +0000 Subject: [PATCH 13/24] serial: msm-geni: handle devm_clk_get() errors devm_clk_get() returns an ERR_PTR on failure, not null. Fix the check to avoid the board crashing when the clock isn't available. Additionally, add the missing error handling for this function. Fixes: 324df15a292e ("serial: qcom: add support for GENI serial driver") Signed-off-by: Caleb Connolly --- drivers/serial/serial_msm_geni.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/serial/serial_msm_geni.c b/drivers/serial/serial_msm_geni.c index 0e52e32ddf3..e5c3dcffc1c 100644 --- a/drivers/serial/serial_msm_geni.c +++ b/drivers/serial/serial_msm_geni.c @@ -188,8 +188,8 @@ static int geni_serial_set_clock_rate(struct udevice *dev, u64 rate) int ret; clk = devm_clk_get(dev, NULL); - if (!clk) - return -EINVAL; + if (IS_ERR(clk)) + return PTR_ERR(clk); ret = clk_set_rate(clk, rate); return ret; @@ -248,11 +248,16 @@ static int msm_serial_setbrg(struct udevice *dev, int baud) struct msm_serial_data *priv = dev_get_priv(dev); u64 clk_rate; u32 clk_div; + int ret; priv->baud = baud; clk_rate = get_clk_div_rate(baud, priv->oversampling, &clk_div); - geni_serial_set_clock_rate(dev, clk_rate); + ret = geni_serial_set_clock_rate(dev, clk_rate); + if (ret < 0) { + pr_err("%s: Couldn't set clock rate: %d\n", __func__, ret); + return ret; + } geni_serial_baud(priv->base, clk_div, baud); return 0; From 033f09b4b460a676b6ce869d2ade97a3098fd312 Mon Sep 17 00:00:00 2001 From: Caleb Connolly Date: Tue, 5 Dec 2023 13:46:46 +0000 Subject: [PATCH 14/24] gpio: qcom_pmic: fix silent dev_read_addr downcast priv->pid is uint32_t, but dev_read_addr() returns a uint64_t on arm64, with the upper bits being used for error codes. Do error checking before downcasting to u32 to prevent errors being silently ignored. Reviewed-by: Sumit Garg Reviewed-by: Neil Armstrong Tested-by: Sumit Garg Reviewed-by: Simon Glass Signed-off-by: Caleb Connolly --- drivers/gpio/qcom_pmic_gpio.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/gpio/qcom_pmic_gpio.c b/drivers/gpio/qcom_pmic_gpio.c index 65feb453ebc..e5841f50295 100644 --- a/drivers/gpio/qcom_pmic_gpio.c +++ b/drivers/gpio/qcom_pmic_gpio.c @@ -221,11 +221,14 @@ static int qcom_gpio_probe(struct udevice *dev) { struct qcom_gpio_bank *priv = dev_get_priv(dev); int reg; + u64 pid; - priv->pid = dev_read_addr(dev); - if (priv->pid == FDT_ADDR_T_NONE) + pid = dev_read_addr(dev); + if (pid == FDT_ADDR_T_NONE) return log_msg_ret("bad address", -EINVAL); + priv->pid = pid; + /* Do a sanity check */ reg = pmic_reg_read(dev->parent, priv->pid + REG_TYPE); if (reg != REG_TYPE_VAL) @@ -328,11 +331,14 @@ static int qcom_pwrkey_probe(struct udevice *dev) { struct qcom_gpio_bank *priv = dev_get_priv(dev); int reg; + u64 pid; - priv->pid = dev_read_addr(dev); - if (priv->pid == FDT_ADDR_T_NONE) + pid = dev_read_addr(dev); + if (pid == FDT_ADDR_T_NONE) return log_msg_ret("bad address", -EINVAL); + priv->pid = pid; + /* Do a sanity check */ reg = pmic_reg_read(dev->parent, priv->pid + REG_TYPE); if (reg != 0x1) From 4e8aa0065d4bb15d039bb629dc8659bf97ef7cf0 Mon Sep 17 00:00:00 2001 From: Caleb Connolly Date: Tue, 5 Dec 2023 13:46:47 +0000 Subject: [PATCH 15/24] button: qcom-pmic: introduce Qualcomm PMIC button driver Qualcomm PMICs include a "pon" function which handles two buttons, the power button and "resin" button (usually volume down). Introduce a new driver following upstream Linux DT to enable these and map them to Enter and Down respectively to enable use in boot menus. Reviewed-by: Neil Armstrong Reviewed-by: Sumit Garg Tested-by: Sumit Garg Reviewed-by: Simon Glass Signed-off-by: Caleb Connolly --- MAINTAINERS | 1 + drivers/button/Kconfig | 9 ++ drivers/button/Makefile | 1 + drivers/button/button-qcom-pmic.c | 165 ++++++++++++++++++++++++++++++ 4 files changed, 176 insertions(+) create mode 100644 drivers/button/button-qcom-pmic.c diff --git a/MAINTAINERS b/MAINTAINERS index b5ff9349294..da477a4e6ad 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -575,6 +575,7 @@ M: Neil Armstrong R: Sumit Garg S: Maintained F: arch/arm/mach-snapdragon/ +F: drivers/button/button-qcom-pmic.c F: drivers/clk/qcom/ F: drivers/gpio/msm_gpio.c F: drivers/mmc/msm_sdhci.c diff --git a/drivers/button/Kconfig b/drivers/button/Kconfig index 8ce2de37d62..097b05f822e 100644 --- a/drivers/button/Kconfig +++ b/drivers/button/Kconfig @@ -27,4 +27,13 @@ config BUTTON_GPIO The GPIO driver must used driver model. Buttons are configured using the device tree. +config BUTTON_QCOM_PMIC + bool "Qualcomm power button" + depends on BUTTON + depends on PMIC_QCOM + help + Enable support for the power and "resin" (usually volume down) buttons + on Qualcomm SoCs. These will be configured as the Enter and Down keys + respectively, allowing navigation of bootmenu with buttons on device. + endmenu diff --git a/drivers/button/Makefile b/drivers/button/Makefile index bbd18af1494..68555081a47 100644 --- a/drivers/button/Makefile +++ b/drivers/button/Makefile @@ -5,3 +5,4 @@ obj-$(CONFIG_BUTTON) += button-uclass.o obj-$(CONFIG_BUTTON_ADC) += button-adc.o obj-$(CONFIG_BUTTON_GPIO) += button-gpio.o +obj-$(CONFIG_BUTTON_QCOM_PMIC) += button-qcom-pmic.o \ No newline at end of file diff --git a/drivers/button/button-qcom-pmic.c b/drivers/button/button-qcom-pmic.c new file mode 100644 index 00000000000..34a976d1e6c --- /dev/null +++ b/drivers/button/button-qcom-pmic.c @@ -0,0 +1,165 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Qualcomm generic pmic gpio driver + * + * (C) Copyright 2015 Mateusz Kulikowski + * (C) Copyright 2023 Linaro Ltd. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define REG_TYPE 0x4 +#define REG_SUBTYPE 0x5 + +struct qcom_pmic_btn_priv { + u32 base; + u32 status_bit; + int code; + struct udevice *pmic; +}; + +#define PON_INT_RT_STS 0x10 +#define KPDPWR_ON_INT_BIT 0 +#define RESIN_ON_INT_BIT 1 + +#define NODE_IS_PWRKEY(node) (!strncmp(ofnode_get_name(node), "pwrkey", strlen("pwrkey"))) +#define NODE_IS_RESIN(node) (!strncmp(ofnode_get_name(node), "resin", strlen("resin"))) + +static enum button_state_t qcom_pwrkey_get_state(struct udevice *dev) +{ + struct qcom_pmic_btn_priv *priv = dev_get_priv(dev); + + int reg = pmic_reg_read(priv->pmic, priv->base + PON_INT_RT_STS); + + if (reg < 0) + return 0; + + return (reg & BIT(priv->status_bit)) != 0; +} + +static int qcom_pwrkey_get_code(struct udevice *dev) +{ + struct qcom_pmic_btn_priv *priv = dev_get_priv(dev); + + return priv->code; +} + +static int qcom_pwrkey_probe(struct udevice *dev) +{ + struct button_uc_plat *uc_plat = dev_get_uclass_plat(dev); + struct qcom_pmic_btn_priv *priv = dev_get_priv(dev); + ofnode node = dev_ofnode(dev); + int ret; + u64 base; + + /* Ignore the top-level pon node */ + if (!uc_plat->label) + return 0; + + /* the pwrkey and resin nodes are children of the "pon" node, get the + * PMIC device to use in pmic_reg_* calls. + */ + priv->pmic = dev->parent->parent; + + /* Get the address of the parent pon node */ + base = dev_read_addr(dev->parent); + if (base == FDT_ADDR_T_NONE) { + printf("%s: Can't find address\n", dev->name); + return -EINVAL; + } + + priv->base = base; + + /* Do a sanity check */ + ret = pmic_reg_read(priv->pmic, priv->base + REG_TYPE); + if (ret != 0x1 && ret != 0xb) { + printf("%s: unexpected PMIC function type %d\n", dev->name, ret); + return -ENXIO; + } + + ret = pmic_reg_read(priv->pmic, priv->base + REG_SUBTYPE); + if ((ret & 0x7) == 0) { + printf("%s: unexpected PMCI function subtype %d\n", dev->name, ret); + return -ENXIO; + } + + if (NODE_IS_PWRKEY(node)) { + priv->status_bit = 0; + priv->code = KEY_ENTER; + } else if (NODE_IS_RESIN(node)) { + priv->status_bit = 1; + priv->code = KEY_DOWN; + } else { + /* Should not get here! */ + printf("Invalid pon node '%s' should be 'pwrkey' or 'resin'\n", + ofnode_get_name(node)); + return -EINVAL; + } + + return 0; +} + +static int button_qcom_pmic_bind(struct udevice *parent) +{ + struct udevice *dev; + ofnode node; + int ret; + + dev_for_each_subnode(node, parent) { + struct button_uc_plat *uc_plat; + const char *label; + + if (!ofnode_is_enabled(node)) + continue; + + ret = device_bind_driver_to_node(parent, "qcom_pwrkey", + ofnode_get_name(node), + node, &dev); + if (ret) { + printf("Failed to bind %s! %d\n", label, ret); + return ret; + } + uc_plat = dev_get_uclass_plat(dev); + if (NODE_IS_PWRKEY(node)) { + uc_plat->label = "pwrkey"; + } else if (NODE_IS_RESIN(node)) { + uc_plat->label = "vol_down"; + } else { + printf("Unknown button node '%s' should be 'pwrkey' or 'resin'\n", + ofnode_get_name(node)); + device_unbind(dev); + } + } + + return 0; +} + +static const struct button_ops button_qcom_pmic_ops = { + .get_state = qcom_pwrkey_get_state, + .get_code = qcom_pwrkey_get_code, +}; + +static const struct udevice_id qcom_pwrkey_ids[] = { + { .compatible = "qcom,pm8916-pon" }, + { .compatible = "qcom,pm8941-pon" }, + { .compatible = "qcom,pm8998-pon" }, + { } +}; + +U_BOOT_DRIVER(qcom_pwrkey) = { + .name = "qcom_pwrkey", + .id = UCLASS_BUTTON, + .of_match = qcom_pwrkey_ids, + .bind = button_qcom_pmic_bind, + .probe = qcom_pwrkey_probe, + .ops = &button_qcom_pmic_ops, + .priv_auto = sizeof(struct qcom_pmic_btn_priv), +}; From b7f189541e00ebf6687acc08e571a80a7b9f70c2 Mon Sep 17 00:00:00 2001 From: Caleb Connolly Date: Tue, 5 Dec 2023 13:46:48 +0000 Subject: [PATCH 16/24] mach-snapdragon: switch to PMIC button driver The PMIC button driver is a much better representation of the hardware here, adjust the boards to use upstream DT and the PMIC button driver instead of exposing the buttons as GPIOs and relying on the GPIO-button driver. Reviewed-by: Neil Armstrong Reviewed-by: Sumit Garg Tested-by: Sumit Garg Signed-off-by: Caleb Connolly --- arch/arm/dts/dragonboard410c-uboot.dtsi | 11 ----- arch/arm/dts/dragonboard410c.dts | 22 ++++++--- arch/arm/dts/dragonboard820c-uboot.dtsi | 12 ----- arch/arm/dts/dragonboard820c.dts | 23 +++++++--- arch/arm/dts/dragonboard845c-uboot.dtsi | 11 ----- arch/arm/dts/dragonboard845c.dts | 4 ++ arch/arm/dts/sdm845.dtsi | 23 +++++++--- arch/arm/dts/starqltechn-uboot.dtsi | 10 ----- arch/arm/dts/starqltechn.dts | 20 ++------- arch/arm/mach-snapdragon/Kconfig | 3 ++ arch/arm/mach-snapdragon/init_sdm845.c | 45 ++++--------------- .../dragonboard410c/dragonboard410c.c | 31 +++++-------- .../dragonboard820c/dragonboard820c.c | 29 ++++-------- 13 files changed, 91 insertions(+), 153 deletions(-) diff --git a/arch/arm/dts/dragonboard410c-uboot.dtsi b/arch/arm/dts/dragonboard410c-uboot.dtsi index 3b0bd0ed0a1..cec64bf80f9 100644 --- a/arch/arm/dts/dragonboard410c-uboot.dtsi +++ b/arch/arm/dts/dragonboard410c-uboot.dtsi @@ -42,14 +42,3 @@ gpios = <&pm8916_gpios 3 0>; }; }; - - -&pm8916_pon { - key_vol_down { - gpios = <&pm8916_pon 1 0>; - }; - - key_power { - gpios = <&pm8916_pon 0 0>; - }; -}; diff --git a/arch/arm/dts/dragonboard410c.dts b/arch/arm/dts/dragonboard410c.dts index 9230dd3fd96..c41fee97781 100644 --- a/arch/arm/dts/dragonboard410c.dts +++ b/arch/arm/dts/dragonboard410c.dts @@ -147,11 +147,23 @@ #address-cells = <0x1>; #size-cells = <0x1>; - pm8916_pon: pm8916_pon@800 { - compatible = "qcom,pm8916-pwrkey"; - reg = <0x800 0x96>; - #gpio-cells = <2>; - gpio-controller; + pon@800 { + compatible = "qcom,pm8916-pon"; + reg = <0x800 0x100>; + mode-bootloader = <0x2>; + mode-recovery = <0x1>; + + pwrkey { + compatible = "qcom,pm8941-pwrkey"; + debounce = <15625>; + bias-pull-up; + }; + + pm8916_resin: resin { + compatible = "qcom,pm8941-resin"; + debounce = <15625>; + bias-pull-up; + }; }; pm8916_gpios: pm8916_gpios@c000 { diff --git a/arch/arm/dts/dragonboard820c-uboot.dtsi b/arch/arm/dts/dragonboard820c-uboot.dtsi index 457728a43ec..d93c7c1fbde 100644 --- a/arch/arm/dts/dragonboard820c-uboot.dtsi +++ b/arch/arm/dts/dragonboard820c-uboot.dtsi @@ -30,15 +30,3 @@ }; }; }; - -&pm8994_pon { - key_vol_down { - gpios = <&pm8994_pon 1 0>; - label = "key_vol_down"; - }; - - key_power { - gpios = <&pm8994_pon 0 0>; - label = "key_power"; - }; -}; diff --git a/arch/arm/dts/dragonboard820c.dts b/arch/arm/dts/dragonboard820c.dts index ad201d48749..0d9c9f7a492 100644 --- a/arch/arm/dts/dragonboard820c.dts +++ b/arch/arm/dts/dragonboard820c.dts @@ -109,12 +109,23 @@ #address-cells = <0x1>; #size-cells = <0x1>; - pm8994_pon: pm8994_pon@800 { - compatible = "qcom,pm8994-pwrkey"; - reg = <0x800 0x96>; - #gpio-cells = <2>; - gpio-controller; - gpio-bank-name="pm8994_key."; + pm8994_pon: pon@800 { + compatible = "qcom,pm8916-pon"; + reg = <0x800 0x100>; + mode-bootloader = <0x2>; + mode-recovery = <0x1>; + + pwrkey { + compatible = "qcom,pm8941-pwrkey"; + debounce = <15625>; + bias-pull-up; + }; + + pm8994_resin: resin { + compatible = "qcom,pm8941-resin"; + debounce = <15625>; + bias-pull-up; + }; }; pm8994_gpios: pm8994_gpios@c000 { diff --git a/arch/arm/dts/dragonboard845c-uboot.dtsi b/arch/arm/dts/dragonboard845c-uboot.dtsi index 7728f4f4a3e..775f45c0149 100644 --- a/arch/arm/dts/dragonboard845c-uboot.dtsi +++ b/arch/arm/dts/dragonboard845c-uboot.dtsi @@ -24,14 +24,3 @@ }; }; }; - -&pm8998_pon { - key_vol_down { - gpios = <&pm8998_pon 1 0>; - label = "key_vol_down"; - }; - key_power { - gpios = <&pm8998_pon 0 0>; - label = "key_power"; - }; -}; diff --git a/arch/arm/dts/dragonboard845c.dts b/arch/arm/dts/dragonboard845c.dts index b4f057ac653..054f253eb32 100644 --- a/arch/arm/dts/dragonboard845c.dts +++ b/arch/arm/dts/dragonboard845c.dts @@ -41,4 +41,8 @@ }; }; +&pm8998_resin { + status = "okay"; +}; + #include "dragonboard845c-uboot.dtsi" diff --git a/arch/arm/dts/sdm845.dtsi b/arch/arm/dts/sdm845.dtsi index 4798ace0ff8..cd5d890e9a4 100644 --- a/arch/arm/dts/sdm845.dtsi +++ b/arch/arm/dts/sdm845.dtsi @@ -78,12 +78,25 @@ #address-cells = <0x1>; #size-cells = <0x1>; - pm8998_pon: pm8998_pon@800 { - compatible = "qcom,pm8998-pwrkey"; + pm8998_pon: pon@800 { + compatible = "qcom,pm8998-pon"; + reg = <0x800 0x100>; - #gpio-cells = <2>; - gpio-controller; - gpio-bank-name = "pm8998_key."; + mode-bootloader = <0x2>; + mode-recovery = <0x1>; + + pm8998_pwrkey: pwrkey { + compatible = "qcom,pm8941-pwrkey"; + debounce = <15625>; + bias-pull-up; + }; + + pm8998_resin: resin { + compatible = "qcom,pm8941-resin"; + debounce = <15625>; + bias-pull-up; + status = "disabled"; + }; }; pm8998_gpios: pm8998_gpios@c000 { diff --git a/arch/arm/dts/starqltechn-uboot.dtsi b/arch/arm/dts/starqltechn-uboot.dtsi index 034d5c1c07e..55c6d18412b 100644 --- a/arch/arm/dts/starqltechn-uboot.dtsi +++ b/arch/arm/dts/starqltechn-uboot.dtsi @@ -25,13 +25,3 @@ }; }; -&pm8998_pon { - key_vol_down { - gpios = <&pm8998_pon 1 0>; - label = "key_vol_down"; - }; - key_power { - gpios = <&pm8998_pon 0 0>; - label = "key_power"; - }; -}; diff --git a/arch/arm/dts/starqltechn.dts b/arch/arm/dts/starqltechn.dts index 5b6372bee79..0842e19adb6 100644 --- a/arch/arm/dts/starqltechn.dts +++ b/arch/arm/dts/starqltechn.dts @@ -45,22 +45,6 @@ format = "a8r8g8b8"; }; - gpio-keys { - compatible = "gpio-keys"; - - key-pwr { - label = "Power"; - linux,code = ; - gpios = <&pm8998_pon 0 GPIO_ACTIVE_LOW>; - }; - - key-vol-down { - label = "Volume Down"; - linux,code = ; - gpios = <&pm8998_pon 1 GPIO_ACTIVE_LOW>; - }; - }; - soc: soc { serial@a84000 { status = "okay"; @@ -68,6 +52,10 @@ }; }; +&pm8998_resin { + status = "okay"; +}; + &tlmm { muic_i2c: muic-i2c-n { pins = "GPIO_33", "GPIO_34"; diff --git a/arch/arm/mach-snapdragon/Kconfig b/arch/arm/mach-snapdragon/Kconfig index 3c9f3bee3f1..ad667108191 100644 --- a/arch/arm/mach-snapdragon/Kconfig +++ b/arch/arm/mach-snapdragon/Kconfig @@ -17,6 +17,7 @@ config SDM845 select LINUX_KERNEL_IMAGE_HEADER imply CLK_QCOM_SDM845 imply PINCTRL_QCOM_SDM845 + imply BUTTON_QCOM_PMIC config LNX_KRNL_IMG_TEXT_OFFSET_BASE default 0x80000000 @@ -30,6 +31,7 @@ config TARGET_DRAGONBOARD410C select ENABLE_ARM_SOC_BOOT0_HOOK imply CLK_QCOM_APQ8016 imply PINCTRL_QCOM_APQ8016 + imply BUTTON_QCOM_PMIC help Support for 96Boards Dragonboard 410C. This board complies with 96Board Open Platform Specifications. Features: @@ -45,6 +47,7 @@ config TARGET_DRAGONBOARD820C bool "96Boards Dragonboard 820C" imply CLK_QCOM_APQ8096 imply PINCTRL_QCOM_APQ8096 + imply BUTTON_QCOM_PMIC help Support for 96Boards Dragonboard 820C. This board complies with 96Board Open Platform Specifications. Features: diff --git a/arch/arm/mach-snapdragon/init_sdm845.c b/arch/arm/mach-snapdragon/init_sdm845.c index 1f885023943..067acc9a6f4 100644 --- a/arch/arm/mach-snapdragon/init_sdm845.c +++ b/arch/arm/mach-snapdragon/init_sdm845.c @@ -5,6 +5,7 @@ * (C) Copyright 2021 Dzmitry Sankouski */ +#include #include #include #include @@ -32,46 +33,18 @@ __weak int board_init(void) /* Check for vol- and power buttons */ __weak int misc_init_r(void) { - struct udevice *pon; - struct gpio_desc resin; - int node, ret; + struct udevice *btn; + int ret; + enum button_state_t state; - ret = uclass_get_device_by_name(UCLASS_GPIO, "pm8998_pon@800", &pon); + ret = button_get_by_label("pwrkey", &btn); if (ret < 0) { - printf("Failed to find PMIC pon node. Check device tree\n"); - return 0; + printf("Couldn't find power button!\n"); + return ret; } - node = fdt_subnode_offset(gd->fdt_blob, dev_of_offset(pon), - "key_vol_down"); - if (node < 0) { - printf("Failed to find key_vol_down node. Check device tree\n"); - return 0; - } - if (gpio_request_by_name_nodev(offset_to_ofnode(node), "gpios", 0, - &resin, 0)) { - printf("Failed to request key_vol_down button.\n"); - return 0; - } - if (dm_gpio_get_value(&resin)) { - env_set("key_vol_down", "1"); - printf("Volume down button pressed\n"); - } else { - env_set("key_vol_down", "0"); - } - - node = fdt_subnode_offset(gd->fdt_blob, dev_of_offset(pon), - "key_power"); - if (node < 0) { - printf("Failed to find key_power node. Check device tree\n"); - return 0; - } - if (gpio_request_by_name_nodev(offset_to_ofnode(node), "gpios", 0, - &resin, 0)) { - printf("Failed to request key_power button.\n"); - return 0; - } - if (dm_gpio_get_value(&resin)) { + state = button_get_state(btn); + if (state == BUTTON_ON) { env_set("key_power", "1"); printf("Power button pressed\n"); } else { diff --git a/board/qualcomm/dragonboard410c/dragonboard410c.c b/board/qualcomm/dragonboard410c/dragonboard410c.c index 371b3262f8c..350e0e9e20a 100644 --- a/board/qualcomm/dragonboard410c/dragonboard410c.c +++ b/board/qualcomm/dragonboard410c/dragonboard410c.c @@ -5,6 +5,7 @@ * (C) Copyright 2015 Mateusz Kulikowski */ +#include #include #include #include @@ -108,32 +109,20 @@ int board_usb_init(int index, enum usb_init_type init) /* Check for vol- button - if pressed - stop autoboot */ int misc_init_r(void) { - struct udevice *pon; - struct gpio_desc resin; - int node, ret; + struct udevice *btn; + int ret; + enum button_state_t state; - ret = uclass_get_device_by_name(UCLASS_GPIO, "pm8916_pon@800", &pon); + ret = button_get_by_label("vol_down", &btn); if (ret < 0) { - printf("Failed to find PMIC pon node. Check device tree\n"); - return 0; + printf("Couldn't find power button!\n"); + return ret; } - node = fdt_subnode_offset(gd->fdt_blob, dev_of_offset(pon), - "key_vol_down"); - if (node < 0) { - printf("Failed to find key_vol_down node. Check device tree\n"); - return 0; - } - - if (gpio_request_by_name_nodev(offset_to_ofnode(node), "gpios", 0, - &resin, 0)) { - printf("Failed to request key_vol_down button.\n"); - return 0; - } - - if (dm_gpio_get_value(&resin)) { + state = button_get_state(btn); + if (state == BUTTON_ON) { env_set("preboot", "setenv preboot; fastboot 0"); - printf("key_vol_down pressed - Starting fastboot.\n"); + printf("vol_down pressed - Starting fastboot.\n"); } return 0; diff --git a/board/qualcomm/dragonboard820c/dragonboard820c.c b/board/qualcomm/dragonboard820c/dragonboard820c.c index 6785bf58e94..2f0db628368 100644 --- a/board/qualcomm/dragonboard820c/dragonboard820c.c +++ b/board/qualcomm/dragonboard820c/dragonboard820c.c @@ -5,6 +5,7 @@ * (C) Copyright 2017 Jorge Ramirez-Ortiz */ +#include #include #include #include @@ -139,30 +140,18 @@ void reset_cpu(void) /* Check for vol- button - if pressed - stop autoboot */ int misc_init_r(void) { - struct udevice *pon; - struct gpio_desc resin; - int node, ret; + struct udevice *btn; + int ret; + enum button_state_t state; - ret = uclass_get_device_by_name(UCLASS_GPIO, "pm8994_pon@800", &pon); + ret = button_get_by_label("pwrkey", &btn); if (ret < 0) { - printf("Failed to find PMIC pon node. Check device tree\n"); - return 0; + printf("Couldn't find power button!\n"); + return ret; } - node = fdt_subnode_offset(gd->fdt_blob, dev_of_offset(pon), - "key_vol_down"); - if (node < 0) { - printf("Failed to find key_vol_down node. Check device tree\n"); - return 0; - } - - if (gpio_request_by_name_nodev(offset_to_ofnode(node), "gpios", 0, - &resin, 0)) { - printf("Failed to request key_vol_down button.\n"); - return 0; - } - - if (dm_gpio_get_value(&resin)) { + state = button_get_state(btn); + if (state == BUTTON_ON) { env_set("bootdelay", "-1"); printf("Power button pressed - dropping to console.\n"); } From 5415d5f0e70f4786d474f7870018213fcce0fd52 Mon Sep 17 00:00:00 2001 From: Caleb Connolly Date: Tue, 5 Dec 2023 13:46:49 +0000 Subject: [PATCH 17/24] gpio: qcom_pmic: drop pon GPIO driver Remove the (now unused) GPIO driver for the power and resin buttons on the PMIC. Reviewed-by: Neil Armstrong Reviewed-by: Sumit Garg Tested-by: Sumit Garg Signed-off-by: Caleb Connolly --- drivers/gpio/Kconfig | 5 +- drivers/gpio/qcom_pmic_gpio.c | 104 ---------------------------------- 2 files changed, 2 insertions(+), 107 deletions(-) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 63e62e1acd2..27df5d88d40 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -318,12 +318,11 @@ config CMD_PCA953X config QCOM_PMIC_GPIO bool "Qualcomm generic PMIC GPIO/keypad driver" depends on DM_GPIO && PMIC_QCOM + select BUTTON help Support for GPIO pins and power/reset buttons found on Qualcomm SoCs PMIC. - Default name for GPIO bank is "pm8916". - Power and reset buttons are placed in "pwkey_qcom" bank and - have gpio numbers 0 and 1 respectively. + The GPIO bank is called "pmic" config PCF8575_GPIO bool "PCF8575 I2C GPIO Expander driver" diff --git a/drivers/gpio/qcom_pmic_gpio.c b/drivers/gpio/qcom_pmic_gpio.c index e5841f50295..7b83c67fa46 100644 --- a/drivers/gpio/qcom_pmic_gpio.c +++ b/drivers/gpio/qcom_pmic_gpio.c @@ -275,107 +275,3 @@ U_BOOT_DRIVER(qcom_pmic_gpio) = { .priv_auto = sizeof(struct qcom_gpio_bank), }; - -/* Add pmic buttons as GPIO as well - there is no generic way for now */ -#define PON_INT_RT_STS 0x10 -#define KPDPWR_ON_INT_BIT 0 -#define RESIN_ON_INT_BIT 1 - -static int qcom_pwrkey_get_function(struct udevice *dev, unsigned offset) -{ - return GPIOF_INPUT; -} - -static int qcom_pwrkey_get_value(struct udevice *dev, unsigned offset) -{ - struct qcom_gpio_bank *priv = dev_get_priv(dev); - - int reg = pmic_reg_read(dev->parent, priv->pid + PON_INT_RT_STS); - - if (reg < 0) - return 0; - - switch (offset) { - case 0: /* Power button */ - return (reg & BIT(KPDPWR_ON_INT_BIT)) != 0; - break; - case 1: /* Reset button */ - default: - return (reg & BIT(RESIN_ON_INT_BIT)) != 0; - break; - } -} - -/* - * Since pmic buttons modelled as GPIO, we need empty direction functions - * to trick u-boot button driver - */ -static int qcom_pwrkey_direction_input(struct udevice *dev, unsigned int offset) -{ - return 0; -} - -static int qcom_pwrkey_direction_output(struct udevice *dev, unsigned int offset, int value) -{ - return -EOPNOTSUPP; -} - -static const struct dm_gpio_ops qcom_pwrkey_ops = { - .get_value = qcom_pwrkey_get_value, - .get_function = qcom_pwrkey_get_function, - .direction_input = qcom_pwrkey_direction_input, - .direction_output = qcom_pwrkey_direction_output, -}; - -static int qcom_pwrkey_probe(struct udevice *dev) -{ - struct qcom_gpio_bank *priv = dev_get_priv(dev); - int reg; - u64 pid; - - pid = dev_read_addr(dev); - if (pid == FDT_ADDR_T_NONE) - return log_msg_ret("bad address", -EINVAL); - - priv->pid = pid; - - /* Do a sanity check */ - reg = pmic_reg_read(dev->parent, priv->pid + REG_TYPE); - if (reg != 0x1) - return log_msg_ret("bad type", -ENXIO); - - reg = pmic_reg_read(dev->parent, priv->pid + REG_SUBTYPE); - if ((reg & 0x5) == 0) - return log_msg_ret("bad subtype", -ENXIO); - - return 0; -} - -static int qcom_pwrkey_of_to_plat(struct udevice *dev) -{ - struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); - - uc_priv->gpio_count = 2; - uc_priv->bank_name = dev_read_string(dev, "gpio-bank-name"); - if (uc_priv->bank_name == NULL) - uc_priv->bank_name = "pwkey_qcom"; - - return 0; -} - -static const struct udevice_id qcom_pwrkey_ids[] = { - { .compatible = "qcom,pm8916-pwrkey" }, - { .compatible = "qcom,pm8994-pwrkey" }, - { .compatible = "qcom,pm8998-pwrkey" }, - { } -}; - -U_BOOT_DRIVER(pwrkey_qcom) = { - .name = "pwrkey_qcom", - .id = UCLASS_GPIO, - .of_match = qcom_pwrkey_ids, - .of_to_plat = qcom_pwrkey_of_to_plat, - .probe = qcom_pwrkey_probe, - .ops = &qcom_pwrkey_ops, - .priv_auto = sizeof(struct qcom_gpio_bank), -}; From ab4214333d900bf68a202c988528ec6b553d00ff Mon Sep 17 00:00:00 2001 From: Caleb Connolly Date: Tue, 5 Dec 2023 13:46:50 +0000 Subject: [PATCH 18/24] gpio: qcom_pmic: support upstream DT Upstream uses the gpio-ranges property to define the number of GPIOs, support for parsing this when gpio-count is unspecified Additionally, drop the bank-name property as it isn't used in upstream, and we can just hardcode the bank name instead. Reviewed-by: Sumit Garg Tested-by: Sumit Garg Reviewed-by: Simon Glass Signed-off-by: Caleb Connolly --- drivers/gpio/qcom_pmic_gpio.c | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/drivers/gpio/qcom_pmic_gpio.c b/drivers/gpio/qcom_pmic_gpio.c index 7b83c67fa46..5221bd27825 100644 --- a/drivers/gpio/qcom_pmic_gpio.c +++ b/drivers/gpio/qcom_pmic_gpio.c @@ -245,14 +245,39 @@ static int qcom_gpio_probe(struct udevice *dev) return 0; } +/* + * Parse basic GPIO count specified via the gpio-ranges property + * as specified in Linux devicetrees + * Returns < 0 on error, otherwise gpio count + */ +static int qcom_gpio_of_parse_ranges(struct udevice *dev) +{ + int ret; + struct ofnode_phandle_args args; + + ret = ofnode_parse_phandle_with_args(dev_ofnode(dev), "gpio-ranges", + NULL, 3, 0, &args); + if (ret) + return log_msg_ret("gpio-ranges", ret); + + return args.args[2]; +} + static int qcom_gpio_of_to_plat(struct udevice *dev) { struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); + int ret; uc_priv->gpio_count = dev_read_u32_default(dev, "gpio-count", 0); - uc_priv->bank_name = dev_read_string(dev, "gpio-bank-name"); - if (uc_priv->bank_name == NULL) - uc_priv->bank_name = "qcom_pmic"; + if (!uc_priv->gpio_count) { + ret = qcom_gpio_of_parse_ranges(dev); + if (ret > 0) + uc_priv->gpio_count = ret; + else + return ret; + } + + uc_priv->bank_name = "pmic"; return 0; } From a712ececbd41f14e26dcfd0a794b0f2c86560eb5 Mon Sep 17 00:00:00 2001 From: Caleb Connolly Date: Tue, 5 Dec 2023 13:46:51 +0000 Subject: [PATCH 19/24] dts: qcom: adjust pmic gpio to use upstream bindings Use the upstream gpio-ranges property instead of gpio-count, and drop the bank-name property for Qualcomm boards. Reviewed-by: Neil Armstrong Reviewed-by: Sumit Garg Tested-by: Sumit Garg Signed-off-by: Caleb Connolly --- arch/arm/dts/dragonboard410c.dts | 3 +-- arch/arm/dts/dragonboard820c.dts | 3 +-- arch/arm/dts/qcs404-evb.dts | 3 +-- arch/arm/dts/sdm845.dtsi | 3 +-- 4 files changed, 4 insertions(+), 8 deletions(-) diff --git a/arch/arm/dts/dragonboard410c.dts b/arch/arm/dts/dragonboard410c.dts index c41fee97781..6a4e3ccf17b 100644 --- a/arch/arm/dts/dragonboard410c.dts +++ b/arch/arm/dts/dragonboard410c.dts @@ -170,9 +170,8 @@ compatible = "qcom,pm8916-gpio"; reg = <0xc000 0x400>; gpio-controller; - gpio-count = <4>; + gpio-ranges = <&pm8916_gpios 0 0 4>; #gpio-cells = <2>; - gpio-bank-name="pmic"; }; }; diff --git a/arch/arm/dts/dragonboard820c.dts b/arch/arm/dts/dragonboard820c.dts index 0d9c9f7a492..146a0af8aaf 100644 --- a/arch/arm/dts/dragonboard820c.dts +++ b/arch/arm/dts/dragonboard820c.dts @@ -132,9 +132,8 @@ compatible = "qcom,pm8994-gpio"; reg = <0xc000 0x400>; gpio-controller; - gpio-count = <24>; + gpio-ranges = <&pm8994_gpios 0 0 22>; #gpio-cells = <2>; - gpio-bank-name="pm8994."; }; }; diff --git a/arch/arm/dts/qcs404-evb.dts b/arch/arm/dts/qcs404-evb.dts index 84224a8a3d3..bd2e303e10f 100644 --- a/arch/arm/dts/qcs404-evb.dts +++ b/arch/arm/dts/qcs404-evb.dts @@ -378,9 +378,8 @@ compatible = "qcom,pms405-gpio"; reg = <0xc000 0x400>; gpio-controller; - gpio-count = <12>; + gpio-ranges = <&pms405_gpios 0 0 12>; #gpio-cells = <2>; - gpio-bank-name="pmic"; }; }; }; diff --git a/arch/arm/dts/sdm845.dtsi b/arch/arm/dts/sdm845.dtsi index cd5d890e9a4..a26e9f411ee 100644 --- a/arch/arm/dts/sdm845.dtsi +++ b/arch/arm/dts/sdm845.dtsi @@ -103,9 +103,8 @@ compatible = "qcom,pm8998-gpio"; reg = <0xc000 0x1a00>; gpio-controller; - gpio-count = <21>; + gpio-ranges = <&pm8998_gpios 0 0 26>; #gpio-cells = <2>; - gpio-bank-name = "pm8998."; }; }; From f1d66ed728c6eef6a91522ba989348b4a69939c1 Mon Sep 17 00:00:00 2001 From: Caleb Connolly Date: Tue, 5 Dec 2023 13:46:52 +0000 Subject: [PATCH 20/24] gpio: qcom_pmic: drop gpio-count property This property is not part of the dt bindings and all boards use the new gpio-ranges property instead. Drop support for this. Reviewed-by: Neil Armstrong Reviewed-by: Sumit Garg Tested-by: Sumit Garg Signed-off-by: Caleb Connolly --- doc/device-tree-bindings/gpio/pm8916_gpio.txt | 48 ------------------- drivers/gpio/qcom_pmic_gpio.c | 13 ++--- 2 files changed, 5 insertions(+), 56 deletions(-) delete mode 100644 doc/device-tree-bindings/gpio/pm8916_gpio.txt diff --git a/doc/device-tree-bindings/gpio/pm8916_gpio.txt b/doc/device-tree-bindings/gpio/pm8916_gpio.txt deleted file mode 100644 index 58185b83352..00000000000 --- a/doc/device-tree-bindings/gpio/pm8916_gpio.txt +++ /dev/null @@ -1,48 +0,0 @@ -Driver for part of pm8916 PMIC - gpio and power/reset keys - -This device should be child of SPMI pmic. - -1) GPIO driver - -Required properties: -- compatible: "qcom,pm8916-gpio" -- reg: peripheral ID, size of register block -- gpio-controller -- gpio-count: number of GPIOs -- #gpio-cells: 2 - -Optional properties: -- gpio-bank-name: name of bank (as default "pm8916" is used) - -Example: - -pmic_gpios: gpios@c000 { - compatible = "qcom,pm8916-gpio"; - reg = <0xc000 0x400>; - gpio-controller; - gpio-count = <4>; - #gpio-cells = <2>; - gpio-bank-name="pmic"; -}; - - -2) Power/Reset key driver - -Required properties: -- compatible: "qcom,pm8916-pwrkey" -- reg: peripheral ID, size of register block -- gpio-controller -- #gpio-cells: 2 - -Optional properties: -- gpio-bank-name: name of bank (as default "pm8916_key" is used) - - -Example: - -pmic_pon: pon@800 { - compatible = "qcom,pm8916-pwrkey"; - reg = <0x800 0x96>; - #gpio-cells = <2>; - gpio-controller; -}; diff --git a/drivers/gpio/qcom_pmic_gpio.c b/drivers/gpio/qcom_pmic_gpio.c index 5221bd27825..6167c841167 100644 --- a/drivers/gpio/qcom_pmic_gpio.c +++ b/drivers/gpio/qcom_pmic_gpio.c @@ -268,14 +268,11 @@ static int qcom_gpio_of_to_plat(struct udevice *dev) struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); int ret; - uc_priv->gpio_count = dev_read_u32_default(dev, "gpio-count", 0); - if (!uc_priv->gpio_count) { - ret = qcom_gpio_of_parse_ranges(dev); - if (ret > 0) - uc_priv->gpio_count = ret; - else - return ret; - } + ret = qcom_gpio_of_parse_ranges(dev); + if (ret > 0) + uc_priv->gpio_count = ret; + else + return ret; uc_priv->bank_name = "pmic"; From 92fe08921c769994817004b4b7e621d32f0431dd Mon Sep 17 00:00:00 2001 From: Caleb Connolly Date: Tue, 5 Dec 2023 13:46:53 +0000 Subject: [PATCH 21/24] spmi: msm: fix register range names The core and chnl register ranges were swapped on SDM845. Fix it, and fetch the register ranges by name instead of by index. Drop the cosmetic "version" variable and clean up the debug logging. Reviewed-by: Neil Armstrong Reviewed-by: Sumit Garg Tested-by: Sumit Garg Signed-off-by: Caleb Connolly --- arch/arm/dts/qcs404-evb.dts | 7 ++-- arch/arm/dts/sdm845.dtsi | 2 +- doc/device-tree-bindings/spmi/spmi-msm.txt | 26 ------------ drivers/spmi/spmi-msm.c | 46 +++++++++------------- 4 files changed, 23 insertions(+), 58 deletions(-) delete mode 100644 doc/device-tree-bindings/spmi/spmi-msm.txt diff --git a/arch/arm/dts/qcs404-evb.dts b/arch/arm/dts/qcs404-evb.dts index bd2e303e10f..07bf7dd0b32 100644 --- a/arch/arm/dts/qcs404-evb.dts +++ b/arch/arm/dts/qcs404-evb.dts @@ -362,9 +362,10 @@ spmi@200f000 { compatible = "qcom,spmi-pmic-arb"; - reg = <0x200f000 0x1000 - 0x2400000 0x400000 - 0x2c00000 0x400000>; + reg = <0x200f000 0x001000>, + <0x2400000 0x800000>, + <0x2c00000 0x800000>; + reg-names = "core", "chnls", "obsrvr"; #address-cells = <0x1>; #size-cells = <0x1>; diff --git a/arch/arm/dts/sdm845.dtsi b/arch/arm/dts/sdm845.dtsi index a26e9f411ee..96c9749a52c 100644 --- a/arch/arm/dts/sdm845.dtsi +++ b/arch/arm/dts/sdm845.dtsi @@ -63,7 +63,7 @@ reg = <0xc440000 0x1100>, <0xc600000 0x2000000>, <0xe600000 0x100000>; - reg-names = "cnfg", "core", "obsrvr"; + reg-names = "core", "chnls", "obsrvr"; #address-cells = <0x1>; #size-cells = <0x1>; diff --git a/doc/device-tree-bindings/spmi/spmi-msm.txt b/doc/device-tree-bindings/spmi/spmi-msm.txt deleted file mode 100644 index ae47673b768..00000000000 --- a/doc/device-tree-bindings/spmi/spmi-msm.txt +++ /dev/null @@ -1,26 +0,0 @@ -Qualcomm SPMI arbiter/bus driver - -This is bus driver for Qualcomm chips that use SPMI to communicate with PMICs. - -Required properties: -- compatible: "qcom,spmi-pmic-arb" -- reg: Register block adresses and sizes for various parts of device: - 1) PMIC arbiter channel mapping base (PMIC_ARB_REG_CHNLn) - 2) SPMI write command (master) registers (PMIC_ARB_CORE_SW_DEC_CHANNELS) - 3) SPMI read command (observer) registers (PMIC_ARB_CORE_REGISTERS_OBS) - -Optional properties (if not set by parent): -- #address-cells: 0x1 - childs slave ID address -- #size-cells: 0x1 - -All PMICs should be placed as a child nodes of bus arbiter. -Automatic detection of childs is currently not supported. - -Example: - -spmi@200f000 { - compatible = "qcom,spmi-pmic-arb"; - reg = <0x200f800 0x200 0x2400000 0x400000 0x2c00000 0x400000>; - #address-cells = <0x1>; - #size-cells = <0x1>; -}; diff --git a/drivers/spmi/spmi-msm.c b/drivers/spmi/spmi-msm.c index 27a035c0a59..5fe8a70abca 100644 --- a/drivers/spmi/spmi-msm.c +++ b/drivers/spmi/spmi-msm.c @@ -70,7 +70,7 @@ enum pmic_arb_channel { struct msm_spmi_priv { phys_addr_t arb_chnl; /* ARB channel mapping base */ - phys_addr_t spmi_core; /* SPMI core */ + phys_addr_t spmi_chnls; /* SPMI channels */ phys_addr_t spmi_obs; /* SPMI observer */ /* SPMI channel map */ uint8_t channel_map[SPMI_MAX_SLAVES][SPMI_MAX_PERIPH]; @@ -95,10 +95,10 @@ static int msm_spmi_write(struct udevice *dev, int usid, int pid, int off, /* Disable IRQ mode for the current channel*/ writel(0x0, - priv->spmi_core + SPMI_CH_OFFSET(channel) + SPMI_REG_CONFIG); + priv->spmi_chnls + SPMI_CH_OFFSET(channel) + SPMI_REG_CONFIG); /* Write single byte */ - writel(val, priv->spmi_core + SPMI_CH_OFFSET(channel) + SPMI_REG_WDATA); + writel(val, priv->spmi_chnls + SPMI_CH_OFFSET(channel) + SPMI_REG_WDATA); /* Prepare write command */ reg |= SPMI_CMD_EXT_REG_WRITE_LONG << SPMI_CMD_OPCODE_SHIFT; @@ -113,12 +113,12 @@ static int msm_spmi_write(struct udevice *dev, int usid, int pid, int off, ch_offset = SPMI_CH_OFFSET(channel); /* Send write command */ - writel(reg, priv->spmi_core + SPMI_CH_OFFSET(channel) + SPMI_REG_CMD0); + writel(reg, priv->spmi_chnls + SPMI_CH_OFFSET(channel) + SPMI_REG_CMD0); /* Wait till CMD DONE status */ reg = 0; while (!reg) { - reg = readl(priv->spmi_core + SPMI_CH_OFFSET(channel) + + reg = readl(priv->spmi_chnls + SPMI_CH_OFFSET(channel) + SPMI_REG_STATUS); } @@ -186,47 +186,37 @@ static struct dm_spmi_ops msm_spmi_ops = { static int msm_spmi_probe(struct udevice *dev) { struct msm_spmi_priv *priv = dev_get_priv(dev); - phys_addr_t config_addr; + phys_addr_t core_addr; u32 hw_ver; - u32 version; int i; - int err; - config_addr = dev_read_addr_index(dev, 0); - priv->spmi_core = dev_read_addr_index(dev, 1); - priv->spmi_obs = dev_read_addr_index(dev, 2); + core_addr = dev_read_addr_name(dev, "core"); + priv->spmi_chnls = dev_read_addr_name(dev, "chnls"); + priv->spmi_obs = dev_read_addr_name(dev, "obsrvr"); - hw_ver = readl(config_addr + PMIC_ARB_VERSION); + hw_ver = readl(core_addr + PMIC_ARB_VERSION); if (hw_ver < PMIC_ARB_VERSION_V3_MIN) { priv->arb_ver = V2; - version = 2; - priv->arb_chnl = config_addr + APID_MAP_OFFSET_V1_V2_V3; + priv->arb_chnl = core_addr + APID_MAP_OFFSET_V1_V2_V3; } else if (hw_ver < PMIC_ARB_VERSION_V5_MIN) { priv->arb_ver = V3; - version = 3; - priv->arb_chnl = config_addr + APID_MAP_OFFSET_V1_V2_V3; + priv->arb_chnl = core_addr + APID_MAP_OFFSET_V1_V2_V3; } else { priv->arb_ver = V5; - version = 5; - priv->arb_chnl = config_addr + APID_MAP_OFFSET_V5; - - if (err) { - dev_err(dev, "could not read APID->PPID mapping table, rc= %d\n", err); - return -1; - } + priv->arb_chnl = core_addr + APID_MAP_OFFSET_V5; } - dev_dbg(dev, "PMIC Arb Version-%d (0x%x)\n", version, hw_ver); + dev_dbg(dev, "PMIC Arb Version-%d (%#x)\n", hw_ver >> 28, hw_ver); if (priv->arb_chnl == FDT_ADDR_T_NONE || - priv->spmi_core == FDT_ADDR_T_NONE || + priv->spmi_chnls == FDT_ADDR_T_NONE || priv->spmi_obs == FDT_ADDR_T_NONE) return -EINVAL; - dev_dbg(dev, "priv->arb_chnl address (%llu)\n", priv->arb_chnl); - dev_dbg(dev, "priv->spmi_core address (%llu)\n", priv->spmi_core); - dev_dbg(dev, "priv->spmi_obs address (%llu)\n", priv->spmi_obs); + dev_dbg(dev, "priv->arb_chnl address (%#08llx)\n", priv->arb_chnl); + dev_dbg(dev, "priv->spmi_chnls address (%#08llx)\n", priv->spmi_chnls); + dev_dbg(dev, "priv->spmi_obs address (%#08llx)\n", priv->spmi_obs); /* Scan peripherals connected to each SPMI channel */ for (i = 0; i < SPMI_MAX_PERIPH; i++) { uint32_t periph = readl(priv->arb_chnl + ARB_CHANNEL_OFFSET(i)); From 64550c7f4d34def290d4952ed5c53357802626ec Mon Sep 17 00:00:00 2001 From: Caleb Connolly Date: Tue, 5 Dec 2023 13:46:54 +0000 Subject: [PATCH 22/24] pmic: qcom: dont use dev_read_addr to get USID Linux DTs stuff a value indicating if the USID is a USID or a GSID in the reg property, the Linux SPMI driver then reads the two address cells separately. U-boot's dev_read_addr() doesn't know how to handle this, so use ofnode_read_u32_index() to get just the USID. The Qcom pmic driver doesn't have support for GSID handling, so just ignore the second value for now. Reviewed-by: Neil Armstrong Reviewed-by: Sumit Garg Tested-by: Sumit Garg Signed-off-by: Caleb Connolly --- .../pmic/qcom,spmi-pmic.txt | 94 ------------------- drivers/power/pmic/pmic_qcom.c | 13 ++- 2 files changed, 10 insertions(+), 97 deletions(-) delete mode 100644 doc/device-tree-bindings/pmic/qcom,spmi-pmic.txt diff --git a/doc/device-tree-bindings/pmic/qcom,spmi-pmic.txt b/doc/device-tree-bindings/pmic/qcom,spmi-pmic.txt deleted file mode 100644 index eb78e3ae770..00000000000 --- a/doc/device-tree-bindings/pmic/qcom,spmi-pmic.txt +++ /dev/null @@ -1,94 +0,0 @@ - Qualcomm SPMI PMICs multi-function device bindings - -The Qualcomm SPMI series presently includes PM8941, PM8841 and PMA8084 -PMICs. These PMICs use a QPNP scheme through SPMI interface. -QPNP is effectively a partitioning scheme for dividing the SPMI extended -register space up into logical pieces, and set of fixed register -locations/definitions within these regions, with some of these regions -specifically used for interrupt handling. - -The QPNP PMICs are used with the Qualcomm Snapdragon series SoCs, and are -interfaced to the chip via the SPMI (System Power Management Interface) bus. -Support for multiple independent functions are implemented by splitting the -16-bit SPMI slave address space into 256 smaller fixed-size regions, 256 bytes -each. A function can consume one or more of these fixed-size register regions. - -Required properties: -- compatible: Should contain one of: - "qcom,pm660", - "qcom,pm660l", - "qcom,pm7325", - "qcom,pm8004", - "qcom,pm8005", - "qcom,pm8019", - "qcom,pm8028", - "qcom,pm8110", - "qcom,pm8150", - "qcom,pm8150b", - "qcom,pm8150c", - "qcom,pm8150l", - "qcom,pm8226", - "qcom,pm8350c", - "qcom,pm8841", - "qcom,pm8901", - "qcom,pm8909", - "qcom,pm8916", - "qcom,pm8941", - "qcom,pm8950", - "qcom,pm8953", - "qcom,pm8994", - "qcom,pm8998", - "qcom,pma8084", - "qcom,pmd9635", - "qcom,pmi8950", - "qcom,pmi8962", - "qcom,pmi8994", - "qcom,pmi8998", - "qcom,pmk8002", - "qcom,pmk8350", - "qcom,pmr735a", - "qcom,smb2351", - or generalized "qcom,spmi-pmic". -- reg: Specifies the SPMI USID slave address for this device. - For more information see: - Documentation/devicetree/bindings/spmi/spmi.yaml - -Required properties for peripheral child nodes: -- compatible: Should contain "qcom,xxx", where "xxx" is a peripheral name. - -Optional properties for peripheral child nodes: -- interrupts: Interrupts are specified as a 4-tuple. For more information - see: - Documentation/devicetree/bindings/spmi/qcom,spmi-pmic-arb.yaml -- interrupt-names: Corresponding interrupt name to the interrupts property - -Each child node of SPMI slave id represents a function of the PMIC. In the -example below the rtc device node represents a peripheral of pm8941 -SID = 0. The regulator device node represents a peripheral of pm8941 SID = 1. - -Example: - - spmi { - compatible = "qcom,spmi-pmic-arb"; - - pm8941@0 { - compatible = "qcom,pm8941", "qcom,spmi-pmic"; - reg = <0x0 SPMI_USID>; - - rtc { - compatible = "qcom,rtc"; - interrupts = <0x0 0x61 0x1 IRQ_TYPE_EDGE_RISING>; - interrupt-names = "alarm"; - }; - }; - - pm8941@1 { - compatible = "qcom,pm8941", "qcom,spmi-pmic"; - reg = <0x1 SPMI_USID>; - - regulator { - compatible = "qcom,regulator"; - regulator-name = "8941_boost"; - }; - }; - }; diff --git a/drivers/power/pmic/pmic_qcom.c b/drivers/power/pmic/pmic_qcom.c index ad8daf43f06..f2ac6494811 100644 --- a/drivers/power/pmic/pmic_qcom.c +++ b/drivers/power/pmic/pmic_qcom.c @@ -66,12 +66,19 @@ static const struct udevice_id pmic_qcom_ids[] = { static int pmic_qcom_probe(struct udevice *dev) { struct pmic_qcom_priv *priv = dev_get_priv(dev); + int ret; - priv->usid = dev_read_addr(dev); - - if (priv->usid == FDT_ADDR_T_NONE) + /* + * dev_read_addr() can't be used here because the reg property actually + * contains two discrete values, not a single 64-bit address. + * The address is the first value. + */ + ret = ofnode_read_u32_index(dev_ofnode(dev), "reg", 0, &priv->usid); + if (ret < 0) return -EINVAL; + debug("usid: %d\n", priv->usid); + return 0; } From 4d6d25be5f7bcdc2d722972bff977aff2f91223c Mon Sep 17 00:00:00 2001 From: Caleb Connolly Date: Mon, 8 Jan 2024 15:30:51 +0000 Subject: [PATCH 23/24] test: spmi: fix tests With the recent changes to the Qualcomm PMIC GPIO driver the sandbox tests for it no longer pass, update the DTS and tests to work with the changes. Signed-off-by: Caleb Connolly --- arch/sandbox/dts/test.dts | 2 +- test/dm/spmi.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index 4fe72664c4b..e264b29554c 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -1544,10 +1544,10 @@ spmi_gpios: gpios@c000 { compatible = "qcom,pm8916-gpio"; reg = <0xc000 0x400>; + gpio-ranges = <&spmi_gpios 0 0 4>; gpio-controller; gpio-count = <4>; #gpio-cells = <2>; - gpio-bank-name="spmi"; }; }; }; diff --git a/test/dm/spmi.c b/test/dm/spmi.c index 9cc284b98cb..97bb0eb30fc 100644 --- a/test/dm/spmi.c +++ b/test/dm/spmi.c @@ -81,7 +81,7 @@ static int dm_test_spmi_access_peripheral(struct unit_test_state *uts) int offset_count; /* Get second pin of PMIC GPIO */ - ut_assertok(gpio_lookup_name("spmi1", &dev, &offset, &gpio)); + ut_assertok(gpio_lookup_name("pmic1", &dev, &offset, &gpio)); /* Check if PMIC is parent */ ut_asserteq(device_get_uclass_id(dev->parent), UCLASS_PMIC); @@ -92,7 +92,7 @@ static int dm_test_spmi_access_peripheral(struct unit_test_state *uts) name = gpio_get_bank_info(dev, &offset_count); /* Check bank name */ - ut_asserteq_str("spmi", name); + ut_asserteq_str("pmic", name); /* Check pin count */ ut_asserteq(4, offset_count); From 4c3dfa1b8babf9fc0575ce08eed99f950d3bab84 Mon Sep 17 00:00:00 2001 From: Caleb Connolly Date: Mon, 15 Jan 2024 18:03:17 +0000 Subject: [PATCH 24/24] sandbox_flattree: enable button support sandbox_flattree enables QCOM_PMIC_GPIO which now depends on BUTTON. As a result the button tests now get run, but fail because the ADC and GPIO button drivers aren't enabled. Enable them to run the tests for sandbox_flattree. Reported-by: Neil Armstrong Reviewed-by: Neil Armstrong Signed-off-by: Caleb Connolly --- configs/sandbox_flattree_defconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/configs/sandbox_flattree_defconfig b/configs/sandbox_flattree_defconfig index 1bd91097a52..36f384b07d0 100644 --- a/configs/sandbox_flattree_defconfig +++ b/configs/sandbox_flattree_defconfig @@ -101,6 +101,9 @@ CONFIG_SYS_ATA_DATA_OFFSET=0 CONFIG_SYS_ATA_REG_OFFSET=1 CONFIG_SYS_ATA_ALT_OFFSET=2 CONFIG_SYS_ATA_IDE0_OFFSET=0 +CONFIG_BUTTON=y +CONFIG_BUTTON_ADC=y +CONFIG_BUTTON_GPIO=y CONFIG_CLK=y CONFIG_CLK_COMPOSITE_CCF=y CONFIG_CLK_K210=y