From 5ae15415c12c330ef3cd5d8c13bdadf5afb3db7a Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Thu, 10 Sep 2020 16:00:00 +0200 Subject: IPQ40xx: clk: Use dt-bindings instead of hardcoding Its common to use dt-bindings instead of hard-coding clocks or resets. So lets use the imported Linux GCC bindings on IPQ40xx target. Signed-off-by: Robert Marko Cc: Luka Perkov --- arch/arm/dts/qcom-ipq4019.dtsi | 3 ++- arch/arm/mach-ipq40xx/clock-ipq4019.c | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/arch/arm/dts/qcom-ipq4019.dtsi b/arch/arm/dts/qcom-ipq4019.dtsi index 5f78bc5..7b3b5e0 100644 --- a/arch/arm/dts/qcom-ipq4019.dtsi +++ b/arch/arm/dts/qcom-ipq4019.dtsi @@ -10,6 +10,7 @@ #include "skeleton.dtsi" #include #include +#include / { #address-cells = <1>; @@ -61,7 +62,7 @@ blsp1_uart1: serial@78af000 { compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm"; reg = <0x78af000 0x200>; - clock = <&gcc 26>; + clock = <&gcc GCC_BLSP1_UART1_APPS_CLK>; bit-rate = <0xFF>; status = "disabled"; u-boot,dm-pre-reloc; diff --git a/arch/arm/mach-ipq40xx/clock-ipq4019.c b/arch/arm/mach-ipq40xx/clock-ipq4019.c index 7cf98a2..83a688e 100644 --- a/arch/arm/mach-ipq40xx/clock-ipq4019.c +++ b/arch/arm/mach-ipq40xx/clock-ipq4019.c @@ -13,6 +13,8 @@ #include #include +#include + struct msm_clk_priv { phys_addr_t base; }; @@ -20,7 +22,7 @@ struct msm_clk_priv { ulong msm_set_rate(struct clk *clk, ulong rate) { switch (clk->id) { - case 26: /*UART1*/ + case GCC_BLSP1_UART1_APPS_CLK: /*UART1*/ /* This clock is already initialized by SBL1 */ return 0; break; -- cgit v1.1 From 6ef099b29e153f664b1de829020b4410b9ec709d Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Thu, 10 Sep 2020 16:00:01 +0200 Subject: IPQ40xx: Add SMEM support There is already existing driver for SMEM so lets enable it for IPQ40xx as well. Signed-off-by: Robert Marko Cc: Luka Perkov --- arch/arm/Kconfig | 2 ++ arch/arm/dts/qcom-ipq4019.dtsi | 5 +++++ drivers/smem/Kconfig | 2 +- 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 80702c2..ee378f0 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -767,8 +767,10 @@ config ARCH_IPQ40XX select DM select DM_GPIO select DM_SERIAL + select MSM_SMEM select PINCTRL select CLK + select SMEM select OF_CONTROL imply CMD_DM diff --git a/arch/arm/dts/qcom-ipq4019.dtsi b/arch/arm/dts/qcom-ipq4019.dtsi index 7b3b5e0..dd69d0a 100644 --- a/arch/arm/dts/qcom-ipq4019.dtsi +++ b/arch/arm/dts/qcom-ipq4019.dtsi @@ -39,6 +39,11 @@ }; }; + smem { + compatible = "qcom,smem"; + memory-region = <&smem_mem>; + }; + soc: soc { #address-cells = <1>; #size-cells = <1>; diff --git a/drivers/smem/Kconfig b/drivers/smem/Kconfig index 7169d0f..73d51b3 100644 --- a/drivers/smem/Kconfig +++ b/drivers/smem/Kconfig @@ -15,7 +15,7 @@ config SANDBOX_SMEM config MSM_SMEM bool "Qualcomm Shared Memory Manager (SMEM)" depends on DM - depends on ARCH_SNAPDRAGON + depends on ARCH_SNAPDRAGON || ARCH_IPQ40XX help Enable support for the Qualcomm Shared Memory Manager. The driver provides an interface to items in a heap shared among all -- cgit v1.1 From 8ef7df5df39edbeb1367409cc340646810d2369b Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Thu, 10 Sep 2020 16:00:02 +0200 Subject: reset: Add IPQ40xx reset controller driver On Qualcomm IPQ40xx SoC series, GCC clock IP also handles the resets. So since this will be needed by further drivers, lets add a driver for the reset controller. Signed-off-by: Robert Marko Cc: Luka Perkov --- MAINTAINERS | 2 + drivers/reset/Kconfig | 8 ++ drivers/reset/Makefile | 1 + drivers/reset/reset-ipq4019.c | 173 +++++++++++++++++++++++++ include/dt-bindings/reset/qcom,ipq4019-reset.h | 92 +++++++++++++ 5 files changed, 276 insertions(+) create mode 100644 drivers/reset/reset-ipq4019.c create mode 100644 include/dt-bindings/reset/qcom,ipq4019-reset.h diff --git a/MAINTAINERS b/MAINTAINERS index 80e6e54..fcad3e4 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -238,6 +238,8 @@ M: Luka Perkov S: Maintained F: arch/arm/mach-ipq40xx/ F: include/dt-bindings/clock/qcom,ipq4019-gcc.h +F: include/dt-bindings/reset/qcom,ipq4019-reset.h +F: drivers/reset/reset-ipq4019.c ARM MARVELL KIRKWOOD ARMADA-XP ARMADA-38X ARMADA-37XX ARMADA-7K/8K M: Stefan Roese diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig index 253902f..3fdfe4a 100644 --- a/drivers/reset/Kconfig +++ b/drivers/reset/Kconfig @@ -148,6 +148,14 @@ config RESET_IMX7 help Support for reset controller on i.MX7/8 SoCs. +config RESET_IPQ419 + bool "Reset driver for Qualcomm IPQ40xx SoCs" + depends on DM_RESET && ARCH_IPQ40XX + default y + help + Support for reset controller on Qualcomm + IPQ40xx SoCs. + config RESET_SIFIVE bool "Reset Driver for SiFive SoC's" depends on DM_RESET && CLK_SIFIVE_FU540_PRCI && TARGET_SIFIVE_FU540 diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile index 3c7f066..5176da5 100644 --- a/drivers/reset/Makefile +++ b/drivers/reset/Makefile @@ -23,6 +23,7 @@ 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_IPQ419) += reset-ipq4019.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-ipq4019.c b/drivers/reset/reset-ipq4019.c new file mode 100644 index 0000000..f216db4 --- /dev/null +++ b/drivers/reset/reset-ipq4019.c @@ -0,0 +1,173 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2020 Sartura Ltd. + * + * Author: Robert Marko + * + * Based on Linux driver + */ + +#include +#include +#include +#include +#include +#include +#include + +struct ipq4019_reset_priv { + phys_addr_t base; +}; + +struct qcom_reset_map { + unsigned int reg; + u8 bit; +}; + +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 int ipq4019_reset_assert(struct reset_ctl *rst) +{ + struct ipq4019_reset_priv *priv = dev_get_priv(rst->dev); + const struct qcom_reset_map *reset_map = gcc_ipq4019_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 ipq4019_reset_deassert(struct reset_ctl *rst) +{ + struct ipq4019_reset_priv *priv = dev_get_priv(rst->dev); + const struct qcom_reset_map *reset_map = gcc_ipq4019_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 ipq4019_reset_free(struct reset_ctl *rst) +{ + return 0; +} + +static int ipq4019_reset_request(struct reset_ctl *rst) +{ + return 0; +} + +static const struct reset_ops ipq4019_reset_ops = { + .request = ipq4019_reset_request, + .rfree = ipq4019_reset_free, + .rst_assert = ipq4019_reset_assert, + .rst_deassert = ipq4019_reset_deassert, +}; + +static const struct udevice_id ipq4019_reset_ids[] = { + { .compatible = "qcom,gcc-reset-ipq4019" }, + { } +}; + +static int ipq4019_reset_probe(struct udevice *dev) +{ + struct ipq4019_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(ipq4019_reset) = { + .name = "ipq4019_reset", + .id = UCLASS_RESET, + .of_match = ipq4019_reset_ids, + .ops = &ipq4019_reset_ops, + .probe = ipq4019_reset_probe, + .priv_auto_alloc_size = sizeof(struct ipq4019_reset_priv), +}; diff --git a/include/dt-bindings/reset/qcom,ipq4019-reset.h b/include/dt-bindings/reset/qcom,ipq4019-reset.h new file mode 100644 index 0000000..ed047d7 --- /dev/null +++ b/include/dt-bindings/reset/qcom,ipq4019-reset.h @@ -0,0 +1,92 @@ +/* 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 -- cgit v1.1 From 496a3aa5ff864ac0346b7013b2fcf94a5ea9da93 Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Thu, 10 Sep 2020 16:00:03 +0200 Subject: IPQ40xx: Add reset controller support Since we have a driver for the reset controller, lets add the necessary node. Signed-off-by: Robert Marko Cc: Luka Perkov --- arch/arm/Kconfig | 1 + arch/arm/dts/qcom-ipq4019.dtsi | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index ee378f0..68d6d1a 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -767,6 +767,7 @@ config ARCH_IPQ40XX select DM select DM_GPIO select DM_SERIAL + select DM_RESET select MSM_SMEM select PINCTRL select CLK diff --git a/arch/arm/dts/qcom-ipq4019.dtsi b/arch/arm/dts/qcom-ipq4019.dtsi index dd69d0a..7b15df3 100644 --- a/arch/arm/dts/qcom-ipq4019.dtsi +++ b/arch/arm/dts/qcom-ipq4019.dtsi @@ -11,6 +11,7 @@ #include #include #include +#include / { #address-cells = <1>; @@ -58,6 +59,14 @@ u-boot,dm-pre-reloc; }; + reset: gcc-reset@1800000 { + compatible = "qcom,gcc-reset-ipq4019"; + reg = <0x1800000 0x60000>; + #clock-cells = <1>; + #reset-cells = <1>; + u-boot,dm-pre-reloc; + }; + pinctrl: qcom,tlmm@1000000 { compatible = "qcom,tlmm-ipq4019"; reg = <0x1000000 0x300000>; -- cgit v1.1 From dec042028e8aff9a4f12d1b2ae48a373ab4c4ff9 Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Thu, 10 Sep 2020 16:00:04 +0200 Subject: phy: add driver for Qualcomm IPQ40xx USB PHY Add a driver to setup the USB PHY-s on Qualcomm IPQ40xx series SoCs. The driver sets up HS and SS phys. Signed-off-by: Robert Marko Cc: Luka Perkov --- MAINTAINERS | 1 + drivers/phy/Kconfig | 6 ++ drivers/phy/Makefile | 1 + drivers/phy/phy-qcom-ipq4019-usb.c | 145 +++++++++++++++++++++++++++++++++++++ 4 files changed, 153 insertions(+) create mode 100644 drivers/phy/phy-qcom-ipq4019-usb.c diff --git a/MAINTAINERS b/MAINTAINERS index fcad3e4..1ba7109 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -240,6 +240,7 @@ F: arch/arm/mach-ipq40xx/ F: include/dt-bindings/clock/qcom,ipq4019-gcc.h F: include/dt-bindings/reset/qcom,ipq4019-reset.h F: drivers/reset/reset-ipq4019.c +F: drivers/phy/phy-qcom-ipq4019-usb.c ARM MARVELL KIRKWOOD ARMADA-XP ARMADA-38X ARMADA-37XX ARMADA-7K/8K M: Stefan Roese diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index 9c77510..8da00a2 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig @@ -125,6 +125,12 @@ config STI_USB_PHY used by USB2 and USB3 Host controllers available on STiH407 SoC families. +config PHY_QCOM_IPQ4019_USB + tristate "Qualcomm IPQ4019 USB PHY driver" + depends on PHY && ARCH_IPQ40XX + help + Support for the USB PHY-s on Qualcomm IPQ40xx SoC-s. + config PHY_RCAR_GEN2 tristate "Renesas R-Car Gen2 USB PHY" depends on PHY && RCAR_GEN2 diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile index 74e8d93..009f353 100644 --- a/drivers/phy/Makefile +++ b/drivers/phy/Makefile @@ -13,6 +13,7 @@ obj-$(CONFIG_PHY_SANDBOX) += sandbox-phy.o obj-$(CONFIG_$(SPL_)PIPE3_PHY) += ti-pipe3-phy.o obj-$(CONFIG_AM654_PHY) += phy-ti-am654.o obj-$(CONFIG_STI_USB_PHY) += sti_usb_phy.o +obj-$(CONFIG_PHY_QCOM_IPQ4019_USB) += phy-qcom-ipq4019-usb.o obj-$(CONFIG_PHY_RCAR_GEN2) += phy-rcar-gen2.o obj-$(CONFIG_PHY_RCAR_GEN3) += phy-rcar-gen3.o obj-$(CONFIG_PHY_STM32_USBPHYC) += phy-stm32-usbphyc.o diff --git a/drivers/phy/phy-qcom-ipq4019-usb.c b/drivers/phy/phy-qcom-ipq4019-usb.c new file mode 100644 index 0000000..465f0d3 --- /dev/null +++ b/drivers/phy/phy-qcom-ipq4019-usb.c @@ -0,0 +1,145 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2019 Sartura Ltd. + * + * Author: Robert Marko + * + * Based on Linux driver + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +struct ipq4019_usb_phy { + phys_addr_t base; + struct reset_ctl por_rst; + struct reset_ctl srif_rst; +}; + +static int ipq4019_ss_phy_power_off(struct phy *_phy) +{ + struct ipq4019_usb_phy *phy = dev_get_priv(_phy->dev); + + reset_assert(&phy->por_rst); + mdelay(10); + + return 0; +} + +static int ipq4019_ss_phy_power_on(struct phy *_phy) +{ + struct ipq4019_usb_phy *phy = dev_get_priv(_phy->dev); + + ipq4019_ss_phy_power_off(_phy); + + reset_deassert(&phy->por_rst); + + return 0; +} + +static struct phy_ops ipq4019_usb_ss_phy_ops = { + .power_on = ipq4019_ss_phy_power_on, + .power_off = ipq4019_ss_phy_power_off, +}; + +static int ipq4019_usb_ss_phy_probe(struct udevice *dev) +{ + struct ipq4019_usb_phy *phy = dev_get_priv(dev); + int ret; + + phy->base = dev_read_addr(dev); + if (phy->base == FDT_ADDR_T_NONE) + return -EINVAL; + + ret = reset_get_by_name(dev, "por_rst", &phy->por_rst); + if (ret) + return ret; + + return 0; +} + +static const struct udevice_id ipq4019_usb_ss_phy_ids[] = { + { .compatible = "qcom,usb-ss-ipq4019-phy" }, + { } +}; + +U_BOOT_DRIVER(ipq4019_usb_ss_phy) = { + .name = "ipq4019-usb-ss-phy", + .id = UCLASS_PHY, + .of_match = ipq4019_usb_ss_phy_ids, + .ops = &ipq4019_usb_ss_phy_ops, + .probe = ipq4019_usb_ss_phy_probe, + .priv_auto_alloc_size = sizeof(struct ipq4019_usb_phy), +}; + +static int ipq4019_hs_phy_power_off(struct phy *_phy) +{ + struct ipq4019_usb_phy *phy = dev_get_priv(_phy->dev); + + reset_assert(&phy->por_rst); + mdelay(10); + + reset_assert(&phy->srif_rst); + mdelay(10); + + return 0; +} + +static int ipq4019_hs_phy_power_on(struct phy *_phy) +{ + struct ipq4019_usb_phy *phy = dev_get_priv(_phy->dev); + + ipq4019_hs_phy_power_off(_phy); + + reset_deassert(&phy->srif_rst); + mdelay(10); + + reset_deassert(&phy->por_rst); + + return 0; +} + +static struct phy_ops ipq4019_usb_hs_phy_ops = { + .power_on = ipq4019_hs_phy_power_on, + .power_off = ipq4019_hs_phy_power_off, +}; + +static int ipq4019_usb_hs_phy_probe(struct udevice *dev) +{ + struct ipq4019_usb_phy *phy = dev_get_priv(dev); + int ret; + + phy->base = dev_read_addr(dev); + if (phy->base == FDT_ADDR_T_NONE) + return -EINVAL; + + ret = reset_get_by_name(dev, "por_rst", &phy->por_rst); + if (ret) + return ret; + + ret = reset_get_by_name(dev, "srif_rst", &phy->srif_rst); + if (ret) + return ret; + + return 0; +} + +static const struct udevice_id ipq4019_usb_hs_phy_ids[] = { + { .compatible = "qcom,usb-hs-ipq4019-phy" }, + { } +}; + +U_BOOT_DRIVER(ipq4019_usb_hs_phy) = { + .name = "ipq4019-usb-hs-phy", + .id = UCLASS_PHY, + .of_match = ipq4019_usb_hs_phy_ids, + .ops = &ipq4019_usb_hs_phy_ops, + .probe = ipq4019_usb_hs_phy_probe, + .priv_auto_alloc_size = sizeof(struct ipq4019_usb_phy), +}; -- cgit v1.1 From 74a703a8aded58dac2ed3373447c6a4fc2d467c9 Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Thu, 10 Sep 2020 16:00:05 +0200 Subject: usb: dwc3: Add Qualcomm DWC3 compatible string Lot of Qualcomm SoC-s use DWC3 controller for both USB2.0 and USB3.0 ports. Qualcomm has some custom config registers on top of the generic ones, but for host mode these are not needed. So lets add the neccessary compatible string. Signed-off-by: Robert Marko Cc: Luka Perkov --- drivers/usb/dwc3/dwc3-generic.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/dwc3/dwc3-generic.c b/drivers/usb/dwc3/dwc3-generic.c index 551f682..7fbf250 100644 --- a/drivers/usb/dwc3/dwc3-generic.c +++ b/drivers/usb/dwc3/dwc3-generic.c @@ -449,6 +449,7 @@ static const struct udevice_id dwc3_glue_ids[] = { { .compatible = "ti,am654-dwc3" }, { .compatible = "rockchip,rk3328-dwc3" }, { .compatible = "rockchip,rk3399-dwc3" }, + { .compatible = "qcom,dwc3" }, { } }; -- cgit v1.1 From 430e1dcfa46bf43fde7406940e471caa513d9933 Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Thu, 10 Sep 2020 16:00:06 +0200 Subject: IPQ40xx: Add USB nodes There are drivers to support built in USB controller and PHY-s now, so lets add the USB nodes to DTSI. Signed-off-by: Robert Marko Cc: Luka Perkov --- arch/arm/dts/qcom-ipq4019.dtsi | 76 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/arch/arm/dts/qcom-ipq4019.dtsi b/arch/arm/dts/qcom-ipq4019.dtsi index 7b15df3..e0e4188 100644 --- a/arch/arm/dts/qcom-ipq4019.dtsi +++ b/arch/arm/dts/qcom-ipq4019.dtsi @@ -90,5 +90,81 @@ gpio-bank-name="soc"; #gpio-cells = <2>; }; + + usb3_ss_phy: ssphy@9a000 { + compatible = "qcom,usb-ss-ipq4019-phy"; + #phy-cells = <0>; + reg = <0x9a000 0x800>; + reg-names = "phy_base"; + resets = <&reset USB3_UNIPHY_PHY_ARES>; + reset-names = "por_rst"; + status = "disabled"; + }; + + usb3_hs_phy: hsphy@a6000 { + compatible = "qcom,usb-hs-ipq4019-phy"; + #phy-cells = <0>; + reg = <0xa6000 0x40>; + reg-names = "phy_base"; + resets = <&reset USB3_HSPHY_POR_ARES>, <&reset USB3_HSPHY_S_ARES>; + reset-names = "por_rst", "srif_rst"; + status = "disabled"; + }; + + usb3: usb3@8af8800 { + compatible = "qcom,dwc3"; + reg = <0x8af8800 0x100>; + #address-cells = <1>; + #size-cells = <1>; + clocks = <&gcc GCC_USB3_MASTER_CLK>, + <&gcc GCC_USB3_SLEEP_CLK>, + <&gcc GCC_USB3_MOCK_UTMI_CLK>; + clock-names = "master", "sleep", "mock_utmi"; + ranges; + status = "disabled"; + + dwc3@8a00000 { + compatible = "snps,dwc3"; + reg = <0x8a00000 0xf8000>; + phys = <&usb3_hs_phy>, <&usb3_ss_phy>; + phy-names = "usb2-phy", "usb3-phy"; + dr_mode = "host"; + maximum-speed = "super-speed"; + snps,dis_u2_susphy_quirk; + }; + }; + + usb2_hs_phy: hsphy@a8000 { + compatible = "qcom,usb-hs-ipq4019-phy"; + #phy-cells = <0>; + reg = <0xa8000 0x40>; + reg-names = "phy_base"; + resets = <&reset USB2_HSPHY_POR_ARES>, <&reset USB2_HSPHY_S_ARES>; + reset-names = "por_rst", "srif_rst"; + status = "disabled"; + }; + + usb2: usb2@60f8800 { + compatible = "qcom,dwc3"; + reg = <0x60f8800 0x100>; + #address-cells = <1>; + #size-cells = <1>; + clocks = <&gcc GCC_USB2_MASTER_CLK>, + <&gcc GCC_USB2_SLEEP_CLK>, + <&gcc GCC_USB2_MOCK_UTMI_CLK>; + clock-names = "master", "sleep", "mock_utmi"; + ranges; + status = "disabled"; + + dwc3@6000000 { + compatible = "snps,dwc3"; + reg = <0x6000000 0xf8000>; + phys = <&usb2_hs_phy>; + phy-names = "usb2-phy"; + dr_mode = "host"; + maximum-speed = "high-speed"; + snps,dis_u2_susphy_quirk; + }; + }; }; }; -- cgit v1.1