[PATCH v1 04/14] clk: qcom: add SEGCC driver for nord
Aswin Murugan via U-Boot <[email protected]>
| Newsgroups | gmane.comp.boot-loaders.u-boot.general,gmane.comp.boot-loaders.u-boot |
|---|---|
| Message-ID | <[email protected]> |
Add support for the nord SE Global Clock Controller (SEGCC). Implement the qcom,nord-segcc driver to provide clocks, resets and power domains required by nord peripherals during boot. Signed-off-by: Aswin Murugan <[email protected]> --- drivers/clk/qcom/Kconfig | 9 ++ drivers/clk/qcom/Makefile | 1 + drivers/clk/qcom/clock-nord-segcc.c | 146 ++++++++++++++++++++++++++++ 3 files changed, 156 insertions(+) create mode 100644 drivers/clk/qcom/clock-nord-segcc.c diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index 4dff30928ca..c10bb8186e9 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -72,6 +72,15 @@ config CLK_QCOM_NORD_NEGCC UFS, USB, and QUPv3 clocks and resets exposed by the NEGCC hardware block. +config CLK_QCOM_NORD_SEGCC + bool "Qualcomm Nord SEGCC" + select CLK_QCOM + help + Say Y here to enable support for the South-East Global Clock + Controller on the Snapdragon Nord SoC. This driver supports the + EMAC and QUPv3 clocks and resets exposed by the SEGCC hardware + block. + config CLK_QCOM_QCM2290 bool "Qualcomm QCM2290 GCC" select CLK_QCOM diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile index 03bf25cbcc2..e7c6e5fe35b 100644 --- a/drivers/clk/qcom/Makefile +++ b/drivers/clk/qcom/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_CLK_QCOM_IPQ9574) += clock-ipq9574.o obj-$(CONFIG_CLK_QCOM_MILOS) += clock-milos.o obj-$(CONFIG_CLK_QCOM_NORD) += clock-nord-gcc.o obj-$(CONFIG_CLK_QCOM_NORD_NEGCC) += clock-nord-negcc.o +obj-$(CONFIG_CLK_QCOM_NORD_SEGCC) += clock-nord-segcc.o obj-$(CONFIG_CLK_QCOM_QCM2290) += clock-qcm2290.o obj-$(CONFIG_CLK_QCOM_QCS404) += clock-qcs404.o obj-$(CONFIG_CLK_QCOM_QCS8300) += clock-qcs8300.o diff --git a/drivers/clk/qcom/clock-nord-segcc.c b/drivers/clk/qcom/clock-nord-segcc.c new file mode 100644 index 00000000000..79fdfa148f9 --- /dev/null +++ b/drivers/clk/qcom/clock-nord-segcc.c @@ -0,0 +1,146 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * + */ + +#include <linux/types.h> +#include <clk-uclass.h> +#include <dm.h> +#include <linux/delay.h> +#include <asm/io.h> +#include <linux/bug.h> +#include <linux/bitops.h> +#include <dt-bindings/clock/qcom,nord-segcc.h> +#include "clock-qcom.h" + +#define SE_GCC_QUPV3_WRAP0_S4_CLK_CMD_RCGR 0x2665c + +static ulong nord_segcc_set_rate(struct clk *clk, ulong rate) +{ + struct msm_clk_priv *priv = dev_get_priv(clk->dev); + + if (clk->id < priv->data->num_clks) + debug("%s: %s, requested rate=%ld\n", __func__, + priv->data->clks[clk->id].name, rate); + + switch (clk->id) { + case SE_GCC_QUPV3_WRAP0_S4_CLK: + WARN(rate != 14745600, + "Unexpected rate for SE_GCC_QUPV3_WRAP0_S4_CLK: %lu\n", rate); + clk_rcg_set_rate_mnd(priv->base, SE_GCC_QUPV3_WRAP0_S4_CLK_CMD_RCGR, + 1, 384, 15625, CFG_CLK_SRC_GPLL0, 16); + return rate; + default: + return 0; + } +} + +static const struct gate_clk nord_segcc_clks[] = { + GATE_CLK_POLLED(SE_GCC_EMAC0_AXI_CLK, 0x2401c, BIT(0), 0x2401c), + GATE_CLK_POLLED(SE_GCC_EMAC1_AXI_CLK, 0x2501c, BIT(0), 0x2501c), + GATE_CLK_POLLED(SE_GCC_MMU_2_TCU_VOTE_CLK, 0x57040, BIT(0), 0x57040), + GATE_CLK_POLLED(SE_GCC_QUPV3_WRAP0_CORE_2X_CLK, 0x57000, BIT(15), 0x26020), + GATE_CLK_POLLED(SE_GCC_QUPV3_WRAP0_CORE_CLK, 0x57000, BIT(14), 0x2600c), + GATE_CLK_POLLED(SE_GCC_QUPV3_WRAP0_M_AHB_CLK, 0x57000, BIT(12), 0x26004), + GATE_CLK_POLLED(SE_GCC_QUPV3_WRAP0_S0_CLK, 0x57000, BIT(16), 0x2615c), + GATE_CLK_POLLED(SE_GCC_QUPV3_WRAP0_S1_CLK, 0x57000, BIT(17), 0x26298), + GATE_CLK_POLLED(SE_GCC_QUPV3_WRAP0_S2_CLK, 0x57000, BIT(18), 0x263d4), + GATE_CLK_POLLED(SE_GCC_QUPV3_WRAP0_S3_CLK, 0x57000, BIT(19), 0x26510), + GATE_CLK_POLLED(SE_GCC_QUPV3_WRAP0_S4_CLK, 0x57000, BIT(20), 0x2664c), + GATE_CLK_POLLED(SE_GCC_QUPV3_WRAP0_S5_CLK, 0x57000, BIT(21), 0x26788), + GATE_CLK_POLLED(SE_GCC_QUPV3_WRAP0_S6_CLK, 0x57000, BIT(22), 0x268c4), + GATE_CLK_POLLED(SE_GCC_QUPV3_WRAP0_S_AHB_CLK, 0x57000, BIT(13), 0x26008), + GATE_CLK_POLLED(SE_GCC_QUPV3_WRAP1_CORE_2X_CLK, 0x57000, BIT(26), 0x27020), + GATE_CLK_POLLED(SE_GCC_QUPV3_WRAP1_CORE_CLK, 0x57000, BIT(25), 0x2700c), + GATE_CLK_POLLED(SE_GCC_QUPV3_WRAP1_M_AHB_CLK, 0x57000, BIT(23), 0x27004), + GATE_CLK_POLLED(SE_GCC_QUPV3_WRAP1_S0_CLK, 0x57000, BIT(27), 0x2715c), + GATE_CLK_POLLED(SE_GCC_QUPV3_WRAP1_S1_CLK, 0x57000, BIT(28), 0x27298), + GATE_CLK_POLLED(SE_GCC_QUPV3_WRAP1_S2_CLK, 0x57000, BIT(29), 0x273d4), + GATE_CLK_POLLED(SE_GCC_QUPV3_WRAP1_S3_CLK, 0x57000, BIT(30), 0x27510), + GATE_CLK_POLLED(SE_GCC_QUPV3_WRAP1_S4_CLK, 0x57000, BIT(31), 0x2764c), + GATE_CLK_POLLED(SE_GCC_QUPV3_WRAP1_S5_CLK, 0x57008, BIT(0), 0x27788), + GATE_CLK_POLLED(SE_GCC_QUPV3_WRAP1_S6_CLK, 0x57008, BIT(1), 0x278c4), + GATE_CLK_POLLED(SE_GCC_QUPV3_WRAP1_S_AHB_CLK, 0x57000, BIT(24), 0x27008), + + GATE_CLK(SE_GCC_EEE_EMAC0_CLK, 0x240b4, BIT(0)), + GATE_CLK(SE_GCC_EEE_EMAC1_CLK, 0x250b4, BIT(0)), + GATE_CLK(SE_GCC_EMAC0_CC_SGMIIPHY_RX_CLK, 0x24064, BIT(0)), + GATE_CLK(SE_GCC_EMAC0_CC_SGMIIPHY_TX_CLK, 0x2405c, BIT(0)), + GATE_CLK(SE_GCC_EMAC0_PHY_AUX_CLK, 0x2402c, BIT(0)), + GATE_CLK(SE_GCC_EMAC0_PTP_CLK, 0x24048, BIT(0)), + GATE_CLK(SE_GCC_EMAC0_RGMII_CLK, 0x24058, BIT(0)), + GATE_CLK(SE_GCC_EMAC0_RPCS_RX_CLK, 0x240a8, BIT(0)), + GATE_CLK(SE_GCC_EMAC0_RPCS_TX_CLK, 0x240a4, BIT(0)), + GATE_CLK(SE_GCC_EMAC0_XGXS_RX_CLK, 0x240b0, BIT(0)), + GATE_CLK(SE_GCC_EMAC0_XGXS_TX_CLK, 0x240ac, BIT(0)), + GATE_CLK(SE_GCC_EMAC1_CC_SGMIIPHY_RX_CLK, 0x25064, BIT(0)), + GATE_CLK(SE_GCC_EMAC1_CC_SGMIIPHY_TX_CLK, 0x2505c, BIT(0)), + GATE_CLK(SE_GCC_EMAC1_PHY_AUX_CLK, 0x2502c, BIT(0)), + GATE_CLK(SE_GCC_EMAC1_PTP_CLK, 0x25048, BIT(0)), + GATE_CLK(SE_GCC_EMAC1_RGMII_CLK, 0x25058, BIT(0)), + GATE_CLK(SE_GCC_EMAC1_RPCS_RX_CLK, 0x250a8, BIT(0)), + GATE_CLK(SE_GCC_EMAC1_RPCS_TX_CLK, 0x250a4, BIT(0)), + GATE_CLK(SE_GCC_EMAC1_XGXS_RX_CLK, 0x250b0, BIT(0)), + GATE_CLK(SE_GCC_EMAC1_XGXS_TX_CLK, 0x250ac, BIT(0)), + GATE_CLK(SE_GCC_FRQ_MEASURE_REF_CLK, 0x18008, BIT(0)), + GATE_CLK(SE_GCC_GP1_CLK, 0x19000, BIT(0)), + GATE_CLK(SE_GCC_GP2_CLK, 0x1a000, BIT(0)), +}; + +static int nord_segcc_enable(struct clk *clk) +{ + struct msm_clk_priv *priv = dev_get_priv(clk->dev); + + if (priv->data->num_clks < clk->id) { + debug("%s: unknown clk id %lu\n", __func__, clk->id); + return 0; + } + + debug("%s: clk %ld: %s\n", __func__, clk->id, nord_segcc_clks[clk->id].name); + + qcom_gate_clk_en(priv, clk->id); + + return 0; +} + +static const struct qcom_reset_map nord_segcc_resets[] = { + [SE_GCC_EMAC0_BCR] = { 0x24000 }, + [SE_GCC_EMAC1_BCR] = { 0x25000 }, + [SE_GCC_QUPV3_WRAPPER_0_BCR] = { 0x26000 }, + [SE_GCC_QUPV3_WRAPPER_1_BCR] = { 0x27000 }, +}; + +static const struct qcom_power_map nord_segcc_gdscs[] = { + [SE_GCC_EMAC0_GDSC] = { 0x24004 }, + [SE_GCC_EMAC1_GDSC] = { 0x25004 }, +}; + +static struct msm_clk_data nord_segcc_data = { + .resets = nord_segcc_resets, + .num_resets = ARRAY_SIZE(nord_segcc_resets), + .clks = nord_segcc_clks, + .num_clks = ARRAY_SIZE(nord_segcc_clks), + + .power_domains = nord_segcc_gdscs, + .num_power_domains = ARRAY_SIZE(nord_segcc_gdscs), + + .enable = nord_segcc_enable, + .set_rate = nord_segcc_set_rate, +}; + +static const struct udevice_id gcc_nord_segcc_of_match[] = { + { + .compatible = "qcom,nord-segcc", + .data = (ulong)&nord_segcc_data, + }, + { } +}; + +U_BOOT_DRIVER(gcc_nord_segcc) = { + .name = "gcc_nord_segcc", + .id = UCLASS_NOP, + .of_match = gcc_nord_segcc_of_match, + .bind = qcom_cc_bind, + .flags = DM_FLAG_PRE_RELOC | DM_FLAG_DEFAULT_PD_CTRL_OFF, +}; -- 2.34.1