diff options
Diffstat (limited to 'drivers/clk')
28 files changed, 1040 insertions, 132 deletions
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index e6483ddc88b..b884a02bdeb 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -131,7 +131,7 @@ config CLK_BOSTON config CLK_CDCE9XX bool "Enable CDCD9XX clock driver" - depends on CLK + depends on CLK && ARCH_OMAP2PLUS help Enable the clock synthesizer driver for CDCE913/925/937/949 series of chips. @@ -169,7 +169,7 @@ config CLK_K210_SET_RATE config CLK_MPC83XX bool "Enable MPC83xx clock driver" - depends on CLK + depends on CLK && MPC83xx help Support for the clock driver of the MPC83xx series of SoCs. diff --git a/drivers/clk/airoha/clk-airoha.c b/drivers/clk/airoha/clk-airoha.c index 1b2c4c98de5..49dbca82135 100644 --- a/drivers/clk/airoha/clk-airoha.c +++ b/drivers/clk/airoha/clk-airoha.c @@ -16,7 +16,7 @@ #include <dm/device_compat.h> #include <dm/lists.h> #include <regmap.h> -#include <syscon.h> +#include <asm/arch/scu-regmap.h> #include <dt-bindings/clock/en7523-clk.h> @@ -26,6 +26,7 @@ #define REG_SPI_CLK_DIV_SEL 0x1c4 #define REG_SPI_CLK_FREQ_SEL 0x1c8 #define REG_NPU_CLK_DIV_SEL 0x1fc +#define REG_CRYPTO_CLKSRC 0x200 #define REG_NP_SCU_PCIC 0x88 #define REG_NP_SCU_SSTR 0x9c @@ -33,6 +34,7 @@ #define REG_PCIE_XSI1_SEL_MASK GENMASK(12, 11) #define REG_CRYPTO_CLKSRC2 0x20c +#define EN7523_MAX_CLKS 8 #define EN7581_MAX_CLKS 9 struct airoha_clk_desc { @@ -66,14 +68,119 @@ struct airoha_clk_soc_data { }; static const u32 gsw_base[] = { 400000000, 500000000 }; +static const u32 emi_base[] = { 333000000, 400000000 }; +static const u32 bus_base[] = { 500000000, 540000000 }; static const u32 slic_base[] = { 100000000, 3125000 }; - +static const u32 npu_base[] = { 333000000, 400000000, 500000000 }; +/* EN7581 */ static const u32 emi7581_base[] = { 540000000, 480000000, 400000000, 300000000 }; static const u32 bus7581_base[] = { 600000000, 540000000 }; static const u32 npu7581_base[] = { 800000000, 750000000, 720000000, 600000000 }; static const u32 crypto_base[] = { 540000000, 480000000 }; static const u32 emmc7581_base[] = { 200000000, 150000000 }; +static const struct airoha_clk_desc en7523_base_clks[EN7523_MAX_CLKS] = { + [EN7523_CLK_GSW] = { + .id = EN7523_CLK_GSW, + .name = "gsw", + + .base_reg = REG_GSW_CLK_DIV_SEL, + .base_bits = 1, + .base_shift = 8, + .base_values = gsw_base, + .n_base_values = ARRAY_SIZE(gsw_base), + + .div_bits = 3, + .div_shift = 0, + .div_step = 1, + .div_offset = 1, + }, + [EN7523_CLK_EMI] = { + .id = EN7523_CLK_EMI, + .name = "emi", + + .base_reg = REG_EMI_CLK_DIV_SEL, + .base_bits = 1, + .base_shift = 8, + .base_values = emi_base, + .n_base_values = ARRAY_SIZE(emi_base), + + .div_bits = 3, + .div_shift = 0, + .div_step = 1, + .div_offset = 1, + }, + [EN7523_CLK_BUS] = { + .id = EN7523_CLK_BUS, + .name = "bus", + + .base_reg = REG_BUS_CLK_DIV_SEL, + .base_bits = 1, + .base_shift = 8, + .base_values = bus_base, + .n_base_values = ARRAY_SIZE(bus_base), + + .div_bits = 3, + .div_shift = 0, + .div_step = 1, + .div_offset = 1, + }, + [EN7523_CLK_SLIC] = { + .id = EN7523_CLK_SLIC, + .name = "slic", + + .base_reg = REG_SPI_CLK_FREQ_SEL, + .base_bits = 1, + .base_shift = 0, + .base_values = slic_base, + .n_base_values = ARRAY_SIZE(slic_base), + + .div_reg = REG_SPI_CLK_DIV_SEL, + .div_bits = 5, + .div_shift = 24, + .div_val0 = 20, + .div_step = 2, + }, + [EN7523_CLK_SPI] = { + .id = EN7523_CLK_SPI, + .name = "spi", + + .base_reg = REG_SPI_CLK_DIV_SEL, + + .base_value = 400000000, + + .div_bits = 5, + .div_shift = 8, + .div_val0 = 40, + .div_step = 2, + }, + [EN7523_CLK_NPU] = { + .id = EN7523_CLK_NPU, + .name = "npu", + + .base_reg = REG_NPU_CLK_DIV_SEL, + .base_bits = 2, + .base_shift = 8, + .base_values = npu_base, + .n_base_values = ARRAY_SIZE(npu_base), + + .div_bits = 3, + .div_shift = 0, + .div_step = 1, + .div_offset = 1, + }, + [EN7523_CLK_CRYPTO] = { + .id = EN7523_CLK_CRYPTO, + .name = "crypto", + + .base_reg = REG_CRYPTO_CLKSRC, + .base_bits = 1, + .base_shift = 0, + .base_values = emi_base, + .n_base_values = ARRAY_SIZE(emi_base), + } +}; + static const struct airoha_clk_desc en7581_base_clks[EN7581_MAX_CLKS] = { [EN7523_CLK_GSW] = { .id = EN7523_CLK_GSW, @@ -400,14 +507,8 @@ const struct clk_ops airoha_clk_ops = { static int airoha_clk_probe(struct udevice *dev) { struct airoha_clk_priv *priv = dev_get_priv(dev); - ofnode chip_scu_node; - - chip_scu_node = ofnode_by_compatible(ofnode_null(), - "airoha,en7581-chip-scu"); - if (!ofnode_valid(chip_scu_node)) - return -EINVAL; - priv->chip_scu_map = syscon_node_to_regmap(chip_scu_node); + priv->chip_scu_map = airoha_get_chip_scu_regmap(); if (IS_ERR(priv->chip_scu_map)) return PTR_ERR(priv->chip_scu_map); @@ -431,12 +532,20 @@ static int airoha_clk_bind(struct udevice *dev) return ret; } +static const struct airoha_clk_soc_data en7523_data = { + .num_clocks = ARRAY_SIZE(en7523_base_clks), + .descs = en7523_base_clks, +}; + static const struct airoha_clk_soc_data en7581_data = { .num_clocks = ARRAY_SIZE(en7581_base_clks), .descs = en7581_base_clks, }; static const struct udevice_id airoha_clk_ids[] = { + { .compatible = "airoha,en7523-scu", + .data = (ulong)&en7523_data, + }, { .compatible = "airoha,en7581-scu", .data = (ulong)&en7581_data, }, diff --git a/drivers/clk/altera/clk-agilex.c b/drivers/clk/altera/clk-agilex.c index 242740a4b00..fdbf834bb2f 100644 --- a/drivers/clk/altera/clk-agilex.c +++ b/drivers/clk/altera/clk-agilex.c @@ -14,6 +14,7 @@ #include <dm/lists.h> #include <dm/util.h> #include <dt-bindings/clock/agilex-clock.h> +#include <linux/bitfield.h> #include <linux/bitops.h> #include <asm/arch/clock_manager.h> @@ -22,6 +23,8 @@ DECLARE_GLOBAL_DATA_PTR; struct socfpga_clk_plat { void __iomem *regs; + int pllgrp; + int bitmask; }; /* @@ -544,14 +547,11 @@ static u32 clk_get_emac_clk_hz(struct socfpga_clk_plat *plat, u32 emac_id) /* Get EMAC clock source */ ctl = CM_REG_READL(plat, CLKMGR_PERPLL_EMACCTL); if (emac_id == AGILEX_EMAC0_CLK) - ctl = (ctl >> CLKMGR_PERPLLGRP_EMACCTL_EMAC0SELB_OFFSET) & - CLKMGR_PERPLLGRP_EMACCTL_EMAC0SELB_MASK; + ctl = FIELD_GET(CLKMGR_PERPLLGRP_EMACCTL_EMAC0SELB_MASK, ctl); else if (emac_id == AGILEX_EMAC1_CLK) - ctl = (ctl >> CLKMGR_PERPLLGRP_EMACCTL_EMAC1SELB_OFFSET) & - CLKMGR_PERPLLGRP_EMACCTL_EMAC1SELB_MASK; + ctl = FIELD_GET(CLKMGR_PERPLLGRP_EMACCTL_EMAC1SELB_MASK, ctl); else if (emac_id == AGILEX_EMAC2_CLK) - ctl = (ctl >> CLKMGR_PERPLLGRP_EMACCTL_EMAC2SELB_OFFSET) & - CLKMGR_PERPLLGRP_EMACCTL_EMAC2SELB_MASK; + ctl = FIELD_GET(CLKMGR_PERPLLGRP_EMACCTL_EMAC2SELB_MASK, ctl); else return 0; @@ -643,8 +643,125 @@ static ulong socfpga_clk_get_rate(struct clk *clk) } } +static int bitmask_from_clk_id(struct clk *clk) +{ + struct socfpga_clk_plat *plat = dev_get_plat(clk->dev); + + switch (clk->id) { + case AGILEX_MPU_CLK: + plat->pllgrp = CLKMGR_MAINPLL_EN; + plat->bitmask = CLKMGR_MAINPLLGRP_EN_MPUCLK_MASK; + break; + case AGILEX_L4_MAIN_CLK: + plat->pllgrp = CLKMGR_MAINPLL_EN; + plat->bitmask = CLKMGR_MAINPLLGRP_EN_L4MAINCLK_MASK; + break; + case AGILEX_L4_MP_CLK: + plat->pllgrp = CLKMGR_MAINPLL_EN; + plat->bitmask = CLKMGR_MAINPLLGRP_EN_L4MPCLK_MASK; + break; + case AGILEX_L4_SP_CLK: + plat->pllgrp = CLKMGR_MAINPLL_EN; + plat->bitmask = CLKMGR_MAINPLLGRP_EN_L4SPCLK_MASK; + break; + case AGILEX_CS_AT_CLK: + plat->pllgrp = CLKMGR_MAINPLL_EN; + plat->bitmask = CLKMGR_MAINPLLGRP_EN_CSCLK_MASK; + break; + case AGILEX_CS_TRACE_CLK: + plat->pllgrp = CLKMGR_MAINPLL_EN; + plat->bitmask = CLKMGR_MAINPLLGRP_EN_CSCLK_MASK; + break; + case AGILEX_CS_PDBG_CLK: + plat->pllgrp = CLKMGR_MAINPLL_EN; + plat->bitmask = CLKMGR_MAINPLLGRP_EN_CSCLK_MASK; + break; + case AGILEX_CS_TIMER_CLK: + plat->pllgrp = CLKMGR_MAINPLL_EN; + plat->bitmask = CLKMGR_MAINPLLGRP_EN_CSTIMERCLK_MASK; + break; + case AGILEX_S2F_USER0_CLK: + plat->pllgrp = CLKMGR_MAINPLL_EN; + plat->bitmask = CLKMGR_MAINPLLGRP_EN_S2FUSER0CLK_MASK; + break; + case AGILEX_EMAC0_CLK: + plat->pllgrp = CLKMGR_PERPLL_EN; + plat->bitmask = CLKMGR_PERPLLGRP_EN_EMAC0CLK_MASK; + break; + case AGILEX_EMAC1_CLK: + plat->pllgrp = CLKMGR_PERPLL_EN; + plat->bitmask = CLKMGR_PERPLLGRP_EN_EMAC1CLK_MASK; + break; + case AGILEX_EMAC2_CLK: + plat->pllgrp = CLKMGR_PERPLL_EN; + plat->bitmask = CLKMGR_PERPLLGRP_EN_EMAC2CLK_MASK; + break; + case AGILEX_EMAC_PTP_CLK: + plat->pllgrp = CLKMGR_PERPLL_EN; + plat->bitmask = CLKMGR_PERPLLGRP_EN_EMACPTPCLK_MASK; + break; + case AGILEX_GPIO_DB_CLK: + plat->pllgrp = CLKMGR_PERPLL_EN; + plat->bitmask = CLKMGR_PERPLLGRP_EN_GPIODBCLK_MASK; + break; + case AGILEX_SDMMC_CLK: + plat->pllgrp = CLKMGR_PERPLL_EN; + plat->bitmask = CLKMGR_PERPLLGRP_EN_SDMMCCLK_MASK; + break; + case AGILEX_S2F_USER1_CLK: + plat->pllgrp = CLKMGR_PERPLL_EN; + plat->bitmask = CLKMGR_PERPLLGRP_EN_S2FUSER1CLK_MASK; + break; + case AGILEX_PSI_REF_CLK: + plat->pllgrp = CLKMGR_PERPLL_EN; + plat->bitmask = CLKMGR_PERPLLGRP_EN_PSIREFCLK_MASK; + break; + case AGILEX_USB_CLK: + plat->pllgrp = CLKMGR_PERPLL_EN; + plat->bitmask = CLKMGR_PERPLLGRP_EN_USBCLK_MASK; + break; + case AGILEX_SPI_M_CLK: + plat->pllgrp = CLKMGR_PERPLL_EN; + plat->bitmask = CLKMGR_PERPLLGRP_EN_SPIMCLK_MASK; + break; + case AGILEX_NAND_CLK: + plat->pllgrp = CLKMGR_PERPLL_EN; + plat->bitmask = CLKMGR_PERPLLGRP_EN_NANDCLK_MASK; + break; + default: + return -ENXIO; + } + + return 0; +} + static int socfpga_clk_enable(struct clk *clk) { + struct socfpga_clk_plat *plat = dev_get_plat(clk->dev); + uintptr_t base_addr = (uintptr_t)plat->regs; + int ret; + + ret = bitmask_from_clk_id(clk); + if (ret) + return ret; + + setbits_le32(base_addr + plat->pllgrp, plat->bitmask); + + return 0; +} + +static int socfpga_clk_disable(struct clk *clk) +{ + struct socfpga_clk_plat *plat = dev_get_plat(clk->dev); + uintptr_t base_addr = (uintptr_t)plat->regs; + int ret; + + ret = bitmask_from_clk_id(clk); + if (ret) + return ret; + + clrbits_le32(base_addr + plat->pllgrp, plat->bitmask); + return 0; } @@ -672,6 +789,7 @@ static int socfpga_clk_of_to_plat(struct udevice *dev) static struct clk_ops socfpga_clk_ops = { .enable = socfpga_clk_enable, + .disable = socfpga_clk_disable, .get_rate = socfpga_clk_get_rate, }; diff --git a/drivers/clk/altera/clk-agilex.h b/drivers/clk/altera/clk-agilex.h index b3e8841a512..be639957940 100644 --- a/drivers/clk/altera/clk-agilex.h +++ b/drivers/clk/altera/clk-agilex.h @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* * Copyright (C) 2019 Intel Corporation <www.intel.com> + * Copyright (C) 2025 Altera Corporation <www.altera.com> */ #ifndef _CLK_AGILEX_ @@ -210,7 +211,26 @@ struct cm_config { #define CLKMGR_LOSTLOCK_SET_MASK BIT(0) +#define CLKMGR_MAINPLLGRP_EN_MPUCLK_MASK BIT(0) +#define CLKMGR_MAINPLLGRP_EN_L4MAINCLK_MASK BIT(1) +#define CLKMGR_MAINPLLGRP_EN_L4MPCLK_MASK BIT(2) +#define CLKMGR_MAINPLLGRP_EN_L4SPCLK_MASK BIT(3) +#define CLKMGR_MAINPLLGRP_EN_CSCLK_MASK BIT(4) +#define CLKMGR_MAINPLLGRP_EN_CSTIMERCLK_MASK BIT(5) +#define CLKMGR_MAINPLLGRP_EN_S2FUSER0CLK_MASK BIT(6) + +#define CLKMGR_PERPLLGRP_EN_EMAC0CLK_MASK BIT(0) +#define CLKMGR_PERPLLGRP_EN_EMAC1CLK_MASK BIT(1) +#define CLKMGR_PERPLLGRP_EN_EMAC2CLK_MASK BIT(2) +#define CLKMGR_PERPLLGRP_EN_EMACPTPCLK_MASK BIT(3) +#define CLKMGR_PERPLLGRP_EN_GPIODBCLK_MASK BIT(4) #define CLKMGR_PERPLLGRP_EN_SDMMCCLK_MASK BIT(5) +#define CLKMGR_PERPLLGRP_EN_S2FUSER1CLK_MASK BIT(6) +#define CLKMGR_PERPLLGRP_EN_PSIREFCLK_MASK BIT(7) +#define CLKMGR_PERPLLGRP_EN_USBCLK_MASK BIT(8) +#define CLKMGR_PERPLLGRP_EN_SPIMCLK_MASK BIT(9) +#define CLKMGR_PERPLLGRP_EN_NANDCLK_MASK BIT(10) + #define CLKMGR_PERPLLGRP_EMACCTL_EMAC0SELB_OFFSET 26 #define CLKMGR_PERPLLGRP_EMACCTL_EMAC0SELB_MASK BIT(26) #define CLKMGR_PERPLLGRP_EMACCTL_EMAC1SELB_OFFSET 27 diff --git a/drivers/clk/at91/Kconfig b/drivers/clk/at91/Kconfig index 4563892647b..faeaa2808b0 100644 --- a/drivers/clk/at91/Kconfig +++ b/drivers/clk/at91/Kconfig @@ -1,6 +1,6 @@ config CLK_AT91 bool "AT91 clock drivers" - depends on CLK + depends on CLK && ARCH_AT91 select MISC help This option is used to enable the AT91 clock driver. diff --git a/drivers/clk/at91/clk-sam9x60-pll.c b/drivers/clk/at91/clk-sam9x60-pll.c index 65be2775ac3..66f01472739 100644 --- a/drivers/clk/at91/clk-sam9x60-pll.c +++ b/drivers/clk/at91/clk-sam9x60-pll.c @@ -183,11 +183,8 @@ static int sam9x60_frac_pll_enable(struct clk *clk) AT91_PMC_PLL_UPDT_ID_MSK, AT91_PMC_PLL_UPDT_STUPTIM(0x3f) | pll->id); - /* Recommended value for AT91_PMC_PLL_ACR */ - if (pll->characteristics->upll) - val = AT91_PMC_PLL_ACR_DEFAULT_UPLL; - else - val = AT91_PMC_PLL_ACR_DEFAULT_PLLA; + /* Load recommended value for PMC_PLL_ACR */ + val = pll->characteristics->acr; pmc_write(base, AT91_PMC_PLL_ACR, val); if (pll->characteristics->upll) { diff --git a/drivers/clk/at91/pmc.h b/drivers/clk/at91/pmc.h index 580c9964ff4..f38868d1665 100644 --- a/drivers/clk/at91/pmc.h +++ b/drivers/clk/at91/pmc.h @@ -42,6 +42,7 @@ struct clk_pll_characteristics { u16 *icpll; u8 *out; u8 upll : 1; + u32 acr; }; struct clk_pll_layout { diff --git a/drivers/clk/at91/sam9x60.c b/drivers/clk/at91/sam9x60.c index e04266a2be2..2251e2846fa 100644 --- a/drivers/clk/at91/sam9x60.c +++ b/drivers/clk/at91/sam9x60.c @@ -123,6 +123,7 @@ static const struct clk_pll_characteristics apll_characteristics = { .num_output = ARRAY_SIZE(plla_outputs), .output = plla_outputs, .core_output = core_outputs, + .acr = 0x00020010UL, }; static const struct clk_pll_characteristics upll_characteristics = { @@ -131,6 +132,7 @@ static const struct clk_pll_characteristics upll_characteristics = { .output = upll_outputs, .core_output = core_outputs, .upll = true, + .acr = 0x12023010UL, /* fIN = [18 MHz, 32 MHz]*/ }; /* Layout for fractional PLLs. */ diff --git a/drivers/clk/at91/sam9x7.c b/drivers/clk/at91/sam9x7.c index ad9865feff0..9ea253e6ff8 100644 --- a/drivers/clk/at91/sam9x7.c +++ b/drivers/clk/at91/sam9x7.c @@ -164,6 +164,7 @@ static const struct clk_pll_characteristics plla_characteristics = { .num_output = ARRAY_SIZE(plla_outputs), .output = plla_outputs, .core_output = plla_core_outputs, + .acr = 0x00020010UL, /* Old ACR_DEFAULT_PLLA value */ }; static const struct clk_pll_characteristics upll_characteristics = { @@ -172,6 +173,7 @@ static const struct clk_pll_characteristics upll_characteristics = { .output = upll_outputs, .core_output = upll_core_outputs, .upll = true, + .acr = 0x12023010UL, /* fIN=[20 MHz, 32 MHz] */ }; static const struct clk_pll_characteristics lvdspll_characteristics = { @@ -179,6 +181,7 @@ static const struct clk_pll_characteristics lvdspll_characteristics = { .num_output = ARRAY_SIZE(lvdspll_outputs), .output = lvdspll_outputs, .core_output = lvdspll_core_outputs, + .acr = 0x12023010UL, /* fIN=[20 MHz, 32 MHz] */ }; static const struct clk_pll_characteristics audiopll_characteristics = { @@ -186,6 +189,7 @@ static const struct clk_pll_characteristics audiopll_characteristics = { .num_output = ARRAY_SIZE(audiopll_outputs), .output = audiopll_outputs, .core_output = audiopll_core_outputs, + .acr = 0x12023010UL, /* fIN=[20 MHz, 32 MHz] */ }; static const struct clk_pll_characteristics plladiv2_characteristics = { @@ -193,6 +197,7 @@ static const struct clk_pll_characteristics plladiv2_characteristics = { .num_output = ARRAY_SIZE(plladiv2_outputs), .output = plladiv2_outputs, .core_output = plladiv2_core_outputs, + .acr = 0x00020010UL, /* Old ACR_DEFAULT_PLLA value */ }; /* Layout for fractional PLLs. */ diff --git a/drivers/clk/at91/sama7d65.c b/drivers/clk/at91/sama7d65.c index 8d2c25e6fa9..9f0b394543b 100644 --- a/drivers/clk/at91/sama7d65.c +++ b/drivers/clk/at91/sama7d65.c @@ -184,6 +184,7 @@ static const struct clk_pll_characteristics pll_characteristics = { .num_output = ARRAY_SIZE(pll_outputs), .output = pll_outputs, .core_output = core_outputs, + .acr = 0x00070010UL, }; /* Layout for fractional PLLs. */ diff --git a/drivers/clk/at91/sama7g5.c b/drivers/clk/at91/sama7g5.c index c0e27828b1a..f24d251857f 100644 --- a/drivers/clk/at91/sama7g5.c +++ b/drivers/clk/at91/sama7g5.c @@ -169,6 +169,7 @@ static const struct clk_pll_characteristics pll_characteristics = { .num_output = ARRAY_SIZE(pll_outputs), .output = pll_outputs, .core_output = core_outputs, + .acr = 0x00070010UL, }; /* Layout for fractional PLLs. */ diff --git a/drivers/clk/clk-stub.c b/drivers/clk/clk-stub.c index 5f5aca41d5b..117266ac778 100644 --- a/drivers/clk/clk-stub.c +++ b/drivers/clk/clk-stub.c @@ -50,8 +50,11 @@ static struct clk_ops stub_clk_ops = { static const struct udevice_id stub_clk_ids[] = { { .compatible = "qcom,rpmcc" }, + { .compatible = "qcom,sdm670-rpmh-clk" }, { .compatible = "qcom,sdm845-rpmh-clk" }, + { .compatible = "qcom,sc7180-rpmh-clk" }, { .compatible = "qcom,sc7280-rpmh-clk" }, + { .compatible = "qcom,sm6350-rpmh-clk" }, { .compatible = "qcom,sm8150-rpmh-clk" }, { .compatible = "qcom,sm8250-rpmh-clk" }, { .compatible = "qcom,sm8550-rpmh-clk" }, diff --git a/drivers/clk/clk_scmi.c b/drivers/clk/clk_scmi.c index a7d89f32cd7..683ac822a01 100644 --- a/drivers/clk/clk_scmi.c +++ b/drivers/clk/clk_scmi.c @@ -8,6 +8,7 @@ #include <clk-uclass.h> #include <dm.h> #include <dm/device_compat.h> +#include <dm/device-internal.h> #include <scmi_agent.h> #include <scmi_agent-uclass.h> #include <scmi_protocols.h> @@ -16,7 +17,9 @@ struct clk_scmi { struct clk clk; + char name[SCMI_CLOCK_NAME_LENGTH_MAX]; u32 ctrl_flags; + bool attrs_resolved; }; struct scmi_clock_priv { @@ -84,7 +87,7 @@ static int scmi_clk_get_num_clock(struct udevice *dev, size_t *num_clocks) return 0; } -static int scmi_clk_get_attibute(struct udevice *dev, int clkid, char **name, +static int scmi_clk_get_attibute(struct udevice *dev, int clkid, char *name, u32 *attr) { struct scmi_clock_priv *priv = dev_get_priv(dev); @@ -108,7 +111,7 @@ static int scmi_clk_get_attibute(struct udevice *dev, int clkid, char **name, if (ret) return ret; - *name = strdup(out.clock_name); + strncpy(name, out.clock_name, SCMI_CLOCK_NAME_LENGTH_MAX); *attr = out.attributes; } else { struct scmi_clk_attribute_out out; @@ -125,7 +128,7 @@ static int scmi_clk_get_attibute(struct udevice *dev, int clkid, char **name, if (ret) return ret; - *name = strdup(out.clock_name); + strncpy(name, out.clock_name, SCMI_CLOCK_NAME_LENGTH_MAX); *attr = out.attributes; } @@ -134,39 +137,93 @@ static int scmi_clk_get_attibute(struct udevice *dev, int clkid, char **name, static int scmi_clk_gate(struct clk *clk, int enable) { - struct scmi_clk_state_in in = { + struct scmi_clock_priv *priv = dev_get_parent_priv(clk->dev); + struct scmi_clk_state_in_v1 in_v1 = { + .clock_id = clk_get_id(clk), + .attributes = enable, + }; + /* Valid only from SCMI clock v2.1 */ + struct scmi_clk_state_in_v2 in_v2 = { .clock_id = clk_get_id(clk), .attributes = enable, }; struct scmi_clk_state_out out; - struct scmi_msg msg = SCMI_MSG_IN(SCMI_PROTOCOL_ID_CLOCK, - SCMI_CLOCK_CONFIG_SET, - in, out); + struct scmi_msg msg_v1 = SCMI_MSG_IN(SCMI_PROTOCOL_ID_CLOCK, + SCMI_CLOCK_CONFIG_SET, + in_v1, out); + struct scmi_msg msg_v2 = SCMI_MSG_IN(SCMI_PROTOCOL_ID_CLOCK, + SCMI_CLOCK_CONFIG_SET, + in_v2, out); int ret; - ret = devm_scmi_process_msg(clk->dev, &msg); + ret = devm_scmi_process_msg(clk->dev, + (priv->version < CLOCK_PROTOCOL_VERSION_2_1) ? + &msg_v1 : &msg_v2); if (ret) return ret; return scmi_to_linux_errno(out.status); } -static int scmi_clk_enable(struct clk *clk) +static int scmi_clk_get_ctrl_flags(struct clk *clk, u32 *ctrl_flags) { struct clk_scmi *clkscmi; + struct udevice *dev; + u32 attributes; struct clk *c; int ret; - if (!CONFIG_IS_ENABLED(CLK_CCF)) - return scmi_clk_gate(clk, 1); - ret = clk_get_by_id(clk->id, &c); if (ret) return ret; + dev = c->dev->parent; + clkscmi = container_of(c, struct clk_scmi, clk); - if (clkscmi->ctrl_flags & SUPPORT_CLK_STAT_CONTROL) + if (!clkscmi->attrs_resolved) { + char name[SCMI_CLOCK_NAME_LENGTH_MAX]; + ret = scmi_clk_get_attibute(dev, clk->id & CLK_ID_MSK, + name, &attributes); + if (ret) + return ret; + + strncpy(clkscmi->name, name, SCMI_CLOCK_NAME_LENGTH_MAX); + if (CLK_HAS_RESTRICTIONS(attributes)) { + u32 perm; + + ret = scmi_clk_get_permissions(dev, clk->id & CLK_ID_MSK, &perm); + if (ret < 0) + clkscmi->ctrl_flags = 0; + else + clkscmi->ctrl_flags = perm; + } else { + clkscmi->ctrl_flags = SUPPORT_CLK_STAT_CONTROL | + SUPPORT_CLK_PARENT_CONTROL | + SUPPORT_CLK_RATE_CONTROL; + } + + clkscmi->attrs_resolved = true; + } + + *ctrl_flags = clkscmi->ctrl_flags; + + return 0; +} + +static int scmi_clk_enable(struct clk *clk) +{ + u32 ctrl_flags; + int ret; + + if (!CONFIG_IS_ENABLED(CLK_CCF)) + return scmi_clk_gate(clk, 1); + + ret = scmi_clk_get_ctrl_flags(clk, &ctrl_flags); + if (ret) + return ret; + + if (ctrl_flags & SUPPORT_CLK_STAT_CONTROL) return scmi_clk_gate(clk, 1); /* Following Linux drivers/clk/clk-scmi.c, directly return 0 if agent has no permission. */ @@ -176,20 +233,17 @@ static int scmi_clk_enable(struct clk *clk) static int scmi_clk_disable(struct clk *clk) { - struct clk_scmi *clkscmi; - struct clk *c; + u32 ctrl_flags; int ret; if (!CONFIG_IS_ENABLED(CLK_CCF)) return scmi_clk_gate(clk, 0); - ret = clk_get_by_id(clk->id, &c); + ret = scmi_clk_get_ctrl_flags(clk, &ctrl_flags); if (ret) return ret; - clkscmi = container_of(c, struct clk_scmi, clk); - - if (clkscmi->ctrl_flags & SUPPORT_CLK_STAT_CONTROL) + if (ctrl_flags & SUPPORT_CLK_STAT_CONTROL) return scmi_clk_gate(clk, 0); /* Following Linux drivers/clk/clk-scmi.c, directly return 0 if agent has no permission. */ @@ -247,20 +301,17 @@ static ulong __scmi_clk_set_rate(struct clk *clk, ulong rate) static ulong scmi_clk_set_rate(struct clk *clk, ulong rate) { - struct clk_scmi *clkscmi; - struct clk *c; + u32 ctrl_flags; int ret; if (!CONFIG_IS_ENABLED(CLK_CCF)) return __scmi_clk_set_rate(clk, rate); - ret = clk_get_by_id(clk->id, &c); + ret = scmi_clk_get_ctrl_flags(clk, &ctrl_flags); if (ret) return ret; - clkscmi = container_of(c, struct clk_scmi, clk); - - if (clkscmi->ctrl_flags & SUPPORT_CLK_RATE_CONTROL) + if (ctrl_flags & SUPPORT_CLK_RATE_CONTROL) return __scmi_clk_set_rate(clk, rate); /* Following Linux drivers/clk/clk-scmi.c, directly return 0 if agent has no permission. */ @@ -271,7 +322,7 @@ static ulong scmi_clk_set_rate(struct clk *clk, ulong rate) static int scmi_clk_probe(struct udevice *dev) { - struct clk_scmi *clk_scmi; + struct clk_scmi *clk_scmi_bulk, *clk_scmi; struct scmi_clock_priv *priv = dev_get_priv(dev); size_t num_clocks, i; int ret; @@ -300,39 +351,23 @@ static int scmi_clk_probe(struct udevice *dev) return ret; } + clk_scmi_bulk = kzalloc(num_clocks * sizeof(*clk_scmi), GFP_KERNEL); + if (!clk_scmi_bulk) + return -ENOMEM; + for (i = 0; i < num_clocks; i++) { - char *clock_name; - u32 attributes; + clk_scmi = clk_scmi_bulk + i; + char *clock_name = clk_scmi->name; - if (!scmi_clk_get_attibute(dev, i, &clock_name, &attributes)) { - clk_scmi = kzalloc(sizeof(*clk_scmi), GFP_KERNEL); - if (!clk_scmi || !clock_name) - ret = -ENOMEM; - else - ret = clk_register(&clk_scmi->clk, dev->driver->name, - clock_name, dev->name); - - if (ret) { - free(clk_scmi); - free(clock_name); - return ret; - } - - dev_clk_dm(dev, i, &clk_scmi->clk); - - if (CLK_HAS_RESTRICTIONS(attributes)) { - u32 perm; - - ret = scmi_clk_get_permissions(dev, i, &perm); - if (ret < 0) - clk_scmi->ctrl_flags = 0; - else - clk_scmi->ctrl_flags = perm; - } else { - clk_scmi->ctrl_flags = SUPPORT_CLK_STAT_CONTROL | SUPPORT_CLK_PARENT_CONTROL | - SUPPORT_CLK_RATE_CONTROL; - } - } + snprintf(clock_name, SCMI_CLOCK_NAME_LENGTH_MAX, "scmi-%zu", i); + + ret = clk_register(&clk_scmi->clk, dev->driver->name, + clock_name, dev->name); + if (ret) + return ret; + + dev_clk_dm(dev, i, &clk_scmi->clk); + dev_set_parent_priv(clk_scmi->clk.dev, priv); } return 0; @@ -359,20 +394,17 @@ static int __scmi_clk_set_parent(struct clk *clk, struct clk *parent) static int scmi_clk_set_parent(struct clk *clk, struct clk *parent) { - struct clk_scmi *clkscmi; - struct clk *c; + u32 ctrl_flags; int ret; if (!CONFIG_IS_ENABLED(CLK_CCF)) - return -ENOTSUPP; + return __scmi_clk_set_parent(clk, parent); - ret = clk_get_by_id(clk->id, &c); + ret = scmi_clk_get_ctrl_flags(clk, &ctrl_flags); if (ret) return ret; - clkscmi = container_of(c, struct clk_scmi, clk); - - if (clkscmi->ctrl_flags & SUPPORT_CLK_PARENT_CONTROL) + if (ctrl_flags & SUPPORT_CLK_PARENT_CONTROL) return __scmi_clk_set_parent(clk, parent); /* Following Linux drivers/clk/clk-scmi.c, directly return 0 if agent has no permission. */ diff --git a/drivers/clk/clk_versaclock.c b/drivers/clk/clk_versaclock.c index 9ccaf13d242..19a787eaf0c 100644 --- a/drivers/clk/clk_versaclock.c +++ b/drivers/clk/clk_versaclock.c @@ -850,7 +850,7 @@ static char *versaclock_get_name(const char *dev_name, const char *clk_name, int buf = malloc(length); if (!buf) - ERR_PTR(-ENOMEM); + return ERR_PTR(-ENOMEM); if (index < 0) snprintf(buf, length, "%s.%s", dev_name, clk_name); @@ -904,12 +904,12 @@ int versaclock_probe(struct udevice *dev) if (IS_ERR(mux_name)) return PTR_ERR(mux_name); - clk_register(&vc5->clk_mux, "versaclock-mux", mux_name, vc5->pin_xin->dev->name); - - if (!IS_ERR(vc5->pin_xin)) + if (!IS_ERR(vc5->pin_xin)) { + clk_register(&vc5->clk_mux, "versaclock-mux", mux_name, vc5->pin_xin->dev->name); vc5_mux_set_parent(&vc5->clk_mux, 1); - else + } else { vc5_mux_set_parent(&vc5->clk_mux, 0); + } /* Configure Optional Loading Capacitance for external XTAL */ if (!(vc5->chip_info->flags & VC5_HAS_INTERNAL_XTAL)) { diff --git a/drivers/clk/clk_versal.c b/drivers/clk/clk_versal.c index cb98f34b5ec..c62a747036d 100644 --- a/drivers/clk/clk_versal.c +++ b/drivers/clk/clk_versal.c @@ -121,25 +121,19 @@ static unsigned int clock_max_idx __section(".data"); #define PM_QUERY_DATA 35 -static int versal_pm_query(struct versal_pm_query_data qdata, u32 *ret_payload) -{ - struct pt_regs regs; - - regs.regs[0] = PM_SIP_SVC | PM_QUERY_DATA; - regs.regs[1] = ((u64)qdata.arg1 << 32) | qdata.qid; - regs.regs[2] = ((u64)qdata.arg3 << 32) | qdata.arg2; +typedef int (*versal_pm_query_t)(struct versal_pm_query_data qdata, + u32 *ret_payload); +static versal_pm_query_t __data versal_pm_query; - smc_call(®s); +static int versal_pm_query_legacy(struct versal_pm_query_data qdata, + u32 *ret_payload) +{ + int ret; - if (ret_payload) { - ret_payload[0] = (u32)regs.regs[0]; - ret_payload[1] = upper_32_bits(regs.regs[0]); - ret_payload[2] = (u32)regs.regs[1]; - ret_payload[3] = upper_32_bits(regs.regs[1]); - ret_payload[4] = (u32)regs.regs[2]; - } + ret = smc_call_handler(PM_QUERY_DATA, qdata.qid, qdata.arg1, qdata.arg2, + qdata.arg3, 0, 0, ret_payload); - return qdata.qid == PM_QID_CLOCK_GET_NAME ? 0 : regs.regs[0]; + return qdata.qid == PM_QID_CLOCK_GET_NAME ? 0 : ret; } static inline int versal_is_valid_clock(u32 clk_id) @@ -356,7 +350,8 @@ static u32 versal_clock_get_div(u32 clk_id) u32 ret_payload[PAYLOAD_ARG_CNT]; u32 div; - xilinx_pm_request(PM_CLOCK_GETDIVIDER, clk_id, 0, 0, 0, ret_payload); + xilinx_pm_request(PM_CLOCK_GETDIVIDER, clk_id, 0, 0, 0, 0, 0, + ret_payload); div = ret_payload[1]; return div; @@ -366,7 +361,8 @@ static u32 versal_clock_set_div(u32 clk_id, u32 div) { u32 ret_payload[PAYLOAD_ARG_CNT]; - xilinx_pm_request(PM_CLOCK_SETDIVIDER, clk_id, div, 0, 0, ret_payload); + xilinx_pm_request(PM_CLOCK_SETDIVIDER, clk_id, div, 0, 0, 0, 0, + ret_payload); return div; } @@ -424,7 +420,7 @@ static u32 versal_clock_get_parentid(u32 clk_id) if (versal_clock_mux(clk_id)) { xilinx_pm_request(PM_CLOCK_GETPARENT, clk_id, 0, 0, 0, - ret_payload); + 0, 0, ret_payload); parent_id = ret_payload[1]; } @@ -442,7 +438,8 @@ static u64 versal_clock_get_pll_rate(u32 clk_id) u32 parent_rate, parent_id, parent_ref_clk_id; u32 id = clk_id & 0xFFF; - xilinx_pm_request(PM_CLOCK_GETSTATE, clk_id, 0, 0, 0, ret_payload); + xilinx_pm_request(PM_CLOCK_GETSTATE, clk_id, 0, 0, 0, 0, 0, + ret_payload); res = ret_payload[1]; if (!res) { printf("0%x PLL not enabled\n", clk_id); @@ -453,9 +450,11 @@ static u64 versal_clock_get_pll_rate(u32 clk_id) parent_ref_clk_id = versal_clock_get_parentid(parent_id); parent_rate = versal_clock_get_ref_rate(parent_ref_clk_id); - xilinx_pm_request(PM_CLOCK_GETDIVIDER, clk_id, 0, 0, 0, ret_payload); + xilinx_pm_request(PM_CLOCK_GETDIVIDER, clk_id, 0, 0, 0, 0, 0, + ret_payload); fbdiv = ret_payload[1]; - xilinx_pm_request(PM_CLOCK_PLL_GETPARAM, clk_id, 2, 0, 0, ret_payload); + xilinx_pm_request(PM_CLOCK_PLL_GETPARAM, clk_id, 2, 0, 0, 0, 0, + ret_payload); frac = ret_payload[1]; freq = (fbdiv * parent_rate) >> (1 << frac); @@ -679,6 +678,10 @@ static int versal_clk_probe(struct udevice *dev) debug("%s\n", __func__); + versal_pm_query = (versal_pm_query_t)dev_get_driver_data(dev); + if (!versal_pm_query) + return -EINVAL; + ret = versal_clock_get_freq_by_name("pl_alt_ref", dev, &pl_alt_ref_clk); if (ret == -ENODATA) { @@ -767,8 +770,10 @@ static int versal_clk_enable(struct clk *clk) clk_id = priv->clk[clk->id].clk_id; - if (versal_clock_gate(clk_id)) - return xilinx_pm_request(PM_CLOCK_ENABLE, clk_id, 0, 0, 0, NULL); + if (versal_clock_gate(clk_id)) { + return xilinx_pm_request(PM_CLOCK_ENABLE, clk_id, 0, 0, 0, + 0, 0, NULL); + } return 0; } @@ -783,7 +788,7 @@ static struct clk_ops versal_clk_ops = { }; static const struct udevice_id versal_clk_ids[] = { - { .compatible = "xlnx,versal-clk" }, + { .compatible = "xlnx,versal-clk", .data = (ulong)versal_pm_query_legacy }, { } }; diff --git a/drivers/clk/meson/g12a.c b/drivers/clk/meson/g12a.c index 5d7faaa3eab..a7a42b2edb6 100644 --- a/drivers/clk/meson/g12a.c +++ b/drivers/clk/meson/g12a.c @@ -916,8 +916,6 @@ static ulong meson_clk_set_rate_by_id(struct clk *clk, unsigned long id, return -EINVAL; case CLKID_PCIE_PLL: return meson_pcie_pll_set_rate(clk, rate); - - return 0; case CLKID_VPU: return meson_clk_set_rate_by_id(clk, meson_mux_get_parent(clk, CLKID_VPU), rate, diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index 34e41461e72..8504ed5d656 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -103,6 +103,21 @@ config CLK_QCOM_SM6115 on the Snapdragon SM6115 SoC. This driver supports the clocks and resets exposed by the GCC hardware block. +config CLK_QCOM_SM6350 + bool "Qualcomm SM6350 GCC" + select CLK_QCOM + help + Say Y here to enable support for the Global Clock Controller + on the Snapdragon SM6350 SoC. This driver supports the clocks + +config CLK_QCOM_SM7150 + bool "Qualcomm SM7150 GCC" + select CLK_QCOM + help + Say Y here to enable support for the Global Clock Controller + on the Snapdragon SM7150 SoC. This driver supports the clocks + and resets exposed by the GCC hardware block. + config CLK_QCOM_SM8150 bool "Qualcomm SM8150 GCC" select CLK_QCOM diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile index b3d95b0faa3..82a5b166196 100644 --- a/drivers/clk/qcom/Makefile +++ b/drivers/clk/qcom/Makefile @@ -16,6 +16,8 @@ obj-$(CONFIG_CLK_QCOM_QCS615) += clock-qcs615.o obj-$(CONFIG_CLK_QCOM_SA8775P) += clock-sa8775p.o obj-$(CONFIG_CLK_QCOM_SC7280) += clock-sc7280.o obj-$(CONFIG_CLK_QCOM_SM6115) += clock-sm6115.o +obj-$(CONFIG_CLK_QCOM_SM6350) += clock-sm6350.o +obj-$(CONFIG_CLK_QCOM_SM7150) += clock-sm7150.o obj-$(CONFIG_CLK_QCOM_SM8150) += clock-sm8150.o obj-$(CONFIG_CLK_QCOM_SM8250) += clock-sm8250.o obj-$(CONFIG_CLK_QCOM_SM8550) += clock-sm8550.o diff --git a/drivers/clk/qcom/clock-sc7280.c b/drivers/clk/qcom/clock-sc7280.c index 47e0ca5f0e5..55a233df394 100644 --- a/drivers/clk/qcom/clock-sc7280.c +++ b/drivers/clk/qcom/clock-sc7280.c @@ -38,6 +38,22 @@ static const struct freq_tbl ftbl_gcc_usb30_sec_master_clk_src[] = { { } }; +static const struct freq_tbl ftbl_gcc_qupv3_wrap0_s2_clk_src[] = { + F(7372800, CFG_CLK_SRC_GPLL0_EVEN, 1, 384, 15625), + F(14745600, CFG_CLK_SRC_GPLL0_EVEN, 1, 768, 15625), + F(19200000, CFG_CLK_SRC_CXO, 1, 0, 0), + F(29491200, CFG_CLK_SRC_GPLL0_EVEN, 1, 1536, 15625), + F(32000000, CFG_CLK_SRC_GPLL0_EVEN, 1, 8, 75), + F(48000000, CFG_CLK_SRC_GPLL0_EVEN, 1, 4, 25), + F(52174000, CFG_CLK_SRC_GPLL0, 1, 2, 23), + F(64000000, CFG_CLK_SRC_GPLL0_EVEN, 1, 16, 75), + F(75000000, CFG_CLK_SRC_GPLL0_EVEN, 4, 0, 0), + F(80000000, CFG_CLK_SRC_GPLL0_EVEN, 1, 4, 15), + F(96000000, CFG_CLK_SRC_GPLL0_EVEN, 1, 8, 25), + F(100000000, CFG_CLK_SRC_GPLL0, 6, 0, 0), + { } +}; + static ulong sc7280_set_rate(struct clk *clk, ulong rate) { struct msm_clk_priv *priv = dev_get_priv(clk->dev); @@ -47,6 +63,16 @@ static ulong sc7280_set_rate(struct clk *clk, ulong rate) debug("%s: %s, requested rate=%ld\n", __func__, priv->data->clks[clk->id].name, rate); switch (clk->id) { + case GCC_QUPV3_WRAP0_S5_CLK: /* UART5 */ + freq = qcom_find_freq(ftbl_gcc_qupv3_wrap0_s2_clk_src, rate); + clk_rcg_set_rate_mnd(priv->base, 0x17600, + freq->pre_div, freq->m, freq->n, freq->src, 16); + return freq->freq; + case GCC_QUPV3_WRAP0_S7_CLK: /* UART7 */ + freq = qcom_find_freq(ftbl_gcc_qupv3_wrap0_s2_clk_src, rate); + clk_rcg_set_rate_mnd(priv->base, 0x17860, + freq->pre_div, freq->m, freq->n, freq->src, 16); + return freq->freq; case GCC_USB30_PRIM_MASTER_CLK: freq = qcom_find_freq(ftbl_gcc_usb30_prim_master_clk_src, rate); clk_rcg_set_rate_mnd(priv->base, USB30_PRIM_MASTER_CLK_CMD_RCGR, @@ -107,6 +133,8 @@ static const struct gate_clk sc7280_clks[] = { GATE_CLK(GCC_QUPV3_WRAP0_S0_CLK, 0x52008, BIT(10)), GATE_CLK(GCC_QUPV3_WRAP0_S1_CLK, 0x52008, BIT(11)), GATE_CLK(GCC_QUPV3_WRAP0_S3_CLK, 0x52008, BIT(13)), + GATE_CLK(GCC_QUPV3_WRAP0_S5_CLK, 0x52008, BIT(15)), + GATE_CLK(GCC_QUPV3_WRAP0_S7_CLK, 0x52008, BIT(17)), GATE_CLK(GCC_UFS_PHY_AXI_CLK, 0x77010, BIT(0)), GATE_CLK(GCC_AGGRE_UFS_PHY_AXI_CLK, 0x770cc, BIT(0)), GATE_CLK(GCC_UFS_PHY_AHB_CLK, 0x77018, BIT(0)), diff --git a/drivers/clk/qcom/clock-sdm845.c b/drivers/clk/qcom/clock-sdm845.c index 5c8702ef2fe..c9a057cf6f9 100644 --- a/drivers/clk/qcom/clock-sdm845.c +++ b/drivers/clk/qcom/clock-sdm845.c @@ -23,6 +23,7 @@ #define USB30_PRIM_MASTER_CLK_CMD_RCGR 0xf018 #define USB30_PRIM_MOCK_UTMI_CLK_CMD_RCGR 0xf030 #define USB3_PRIM_PHY_AUX_CMD_RCGR 0xf05c +#define SDCC1_APPS_CLK_CMD_RCGR 0x26028 #define SDCC2_APPS_CLK_CMD_RCGR 0x1400c static const struct freq_tbl ftbl_gcc_qupv3_wrap0_s0_clk_src[] = { @@ -44,6 +45,18 @@ static const struct freq_tbl ftbl_gcc_qupv3_wrap0_s0_clk_src[] = { { } }; +static const struct freq_tbl ftbl_gcc_sdcc1_apps_clk_src[] = { + F(144000, CFG_CLK_SRC_CXO, 16, 3, 25), + F(400000, CFG_CLK_SRC_CXO, 12, 1, 4), + F(20000000, CFG_CLK_SRC_GPLL0_EVEN, 5, 1, 3), + F(25000000, CFG_CLK_SRC_GPLL0_EVEN, 6, 1, 2), + F(50000000, CFG_CLK_SRC_GPLL0_EVEN, 6, 0, 0), + F(100000000, CFG_CLK_SRC_GPLL0, 6, 0, 0), + F(192000000, CFG_CLK_SRC_GPLL6, 2, 0, 0), + F(384000000, CFG_CLK_SRC_GPLL6, 1, 0, 0), + { } +}; + static const struct freq_tbl ftbl_gcc_sdcc2_apps_clk_src[] = { F(400000, CFG_CLK_SRC_CXO, 12, 1, 4), F(9600000, CFG_CLK_SRC_CXO, 2, 0, 0), @@ -55,6 +68,22 @@ static const struct freq_tbl ftbl_gcc_sdcc2_apps_clk_src[] = { { } }; +static ulong sdm670_clk_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_SDCC1_APPS_CLK: + freq = qcom_find_freq(ftbl_gcc_sdcc1_apps_clk_src, rate); + clk_rcg_set_rate_mnd(priv->base, SDCC1_APPS_CLK_CMD_RCGR, + freq->pre_div, freq->m, freq->n, freq->src, 8); + return freq->freq; + default: + return 0; + } +} + static ulong sdm845_clk_set_rate(struct clk *clk, ulong rate) { struct msm_clk_priv *priv = dev_get_priv(clk->dev); @@ -76,6 +105,54 @@ static ulong sdm845_clk_set_rate(struct clk *clk, ulong rate) } } +static const struct gate_clk sdm670_clks[] = { + GATE_CLK(GCC_AGGRE_USB3_PRIM_AXI_CLK, 0x8201c, 0x00000001), + GATE_CLK(GCC_CFG_NOC_USB3_PRIM_AXI_CLK, 0x0502c, 0x00000001), + 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_SDCC1_AHB_CLK, 0x26008, 0x00000001), + GATE_CLK(GCC_SDCC1_APPS_CLK, 0x26004, 0x00000001), + GATE_CLK(GCC_SDCC1_ICE_CORE_CLK, 0x2600c, 0x00000001), + 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_MEM_CLKREF_CLK, 0x8c000, 0x00000001), + GATE_CLK(GCC_AGGRE_UFS_PHY_AXI_CLK, 0x82024, 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_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_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_USB_PHY_CFG_AHB2PHY_CLK, 0x6a004, 0x00000001), +}; + static const struct gate_clk sdm845_clks[] = { GATE_CLK(GCC_AGGRE_USB3_PRIM_AXI_CLK, 0x8201c, 0x00000001), GATE_CLK(GCC_AGGRE_USB3_SEC_AXI_CLK, 0x82020, 0x00000001), @@ -140,6 +217,28 @@ static const struct gate_clk sdm845_clks[] = { GATE_CLK(GCC_USB_PHY_CFG_AHB2PHY_CLK, 0x6a004, 0x00000001), }; +static int sdm670_clk_enable(struct clk *clk) +{ + struct msm_clk_priv *priv = dev_get_priv(clk->dev); + + debug("%s: clk %s\n", __func__, sdm670_clks[clk->id].name); + + switch (clk->id) { + case GCC_USB30_PRIM_MASTER_CLK: + qcom_gate_clk_en(priv, GCC_USB_PHY_CFG_AHB2PHY_CLK); + /* These numbers are just pulled from the frequency tables in the Linux driver */ + clk_rcg_set_rate_mnd(priv->base, USB30_PRIM_MASTER_CLK_CMD_RCGR, + (4.5 * 2) - 1, 0, 0, 1 << 8, 8); + clk_rcg_set_rate_mnd(priv->base, USB30_PRIM_MOCK_UTMI_CLK_CMD_RCGR, + 1, 0, 0, 0, 8); + clk_rcg_set_rate_mnd(priv->base, USB3_PRIM_PHY_AUX_CMD_RCGR, + 1, 0, 0, 0, 8); + break; + } + + return qcom_gate_clk_en(priv, clk->id); +} + static int sdm845_clk_enable(struct clk *clk) { struct msm_clk_priv *priv = dev_get_priv(clk->dev); @@ -188,6 +287,17 @@ static const struct qcom_reset_map sdm845_gcc_resets[] = { [GCC_USB_PHY_CFG_AHB2PHY_BCR] = { 0x6a000 }, }; +static const struct qcom_power_map sdm670_gdscs[] = { + [UFS_PHY_GDSC] = { 0x77004 }, + [USB30_PRIM_GDSC] = { 0xf004 }, + [HLOS1_VOTE_AGGRE_NOC_MMU_AUDIO_TBU_GDSC] = { 0x7d030 }, + [HLOS1_VOTE_AGGRE_NOC_MMU_TBU1_GDSC] = { 0x7d034 }, + [HLOS1_VOTE_AGGRE_NOC_MMU_TBU2_GDSC] = { 0x7d038 }, + [HLOS1_VOTE_MMNOC_MMU_TBU_HF0_GDSC] = { 0x7d040 }, + [HLOS1_VOTE_MMNOC_MMU_TBU_HF1_GDSC] = { 0x7d048 }, + [HLOS1_VOTE_MMNOC_MMU_TBU_SF_GDSC] = { 0x7d044 }, +}; + static const struct qcom_power_map sdm845_gdscs[] = { [PCIE_0_GDSC] = { 0x6b004 }, [PCIE_1_GDSC] = { 0x8d004 }, @@ -292,6 +402,19 @@ static const char *const sdm845_rcg_names[] = { "GCC_UFS_PHY_PHY_AUX", }; +static struct msm_clk_data sdm670_clk_data = { + /* Snapdragon 670 can function without its own exclusive resets. */ + .resets = sdm845_gcc_resets, + .num_resets = ARRAY_SIZE(sdm845_gcc_resets), + .clks = sdm670_clks, + .num_clks = ARRAY_SIZE(sdm670_clks), + .power_domains = sdm670_gdscs, + .num_power_domains = ARRAY_SIZE(sdm670_gdscs), + + .enable = sdm670_clk_enable, + .set_rate = sdm670_clk_set_rate, +}; + static struct msm_clk_data sdm845_clk_data = { .resets = sdm845_gcc_resets, .num_resets = ARRAY_SIZE(sdm845_gcc_resets), @@ -311,6 +434,10 @@ static struct msm_clk_data sdm845_clk_data = { static const struct udevice_id gcc_sdm845_of_match[] = { { + .compatible = "qcom,gcc-sdm670", + .data = (ulong)&sdm670_clk_data, + }, + { .compatible = "qcom,gcc-sdm845", .data = (ulong)&sdm845_clk_data, }, diff --git a/drivers/clk/qcom/clock-sm6350.c b/drivers/clk/qcom/clock-sm6350.c new file mode 100644 index 00000000000..ee6653848c7 --- /dev/null +++ b/drivers/clk/qcom/clock-sm6350.c @@ -0,0 +1,193 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Clock drivers for Qualcomm sm6350 + * + * (C) Copyright 2024 Linaro Ltd. + * (C) Copyright 2025 Luca Weiss <luca.weiss@fairphone.com> + */ + +#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,gcc-sm6350.h> + +#include "clock-qcom.h" + +#undef CFG_CLK_SRC_GPLL0_ODD +#define CFG_CLK_SRC_GPLL0_ODD (2 << 8) +#define CFG_CLK_SRC_GPLL6_EVEN (2 << 8) + +#define GCC_SE12_UART_RCG_REG 0x223a8 +#define GCC_SDCC2_APPS_CLK_SRC_REG 0x2000c + +#define APCS_GPLL7_STATUS 0x7000 +#define APCS_GPLLX_ENA_REG 0x52010 + +static const struct freq_tbl ftbl_gcc_qupv3_wrap1_s3_clk_src[] = { + F(7372800, CFG_CLK_SRC_GPLL0_EVEN, 1, 384, 15625), + F(14745600, CFG_CLK_SRC_GPLL0_EVEN, 1, 768, 15625), + F(19200000, CFG_CLK_SRC_CXO, 1, 0, 0), + F(29491200, CFG_CLK_SRC_GPLL0_EVEN, 1, 1536, 15625), + F(32000000, CFG_CLK_SRC_GPLL0_EVEN, 1, 8, 75), + F(48000000, CFG_CLK_SRC_GPLL0_EVEN, 1, 4, 25), + F(64000000, CFG_CLK_SRC_GPLL0_EVEN, 1, 16, 75), + F(75000000, CFG_CLK_SRC_GPLL0_EVEN, 4, 0, 0), + F(80000000, CFG_CLK_SRC_GPLL0_EVEN, 1, 4, 15), + F(96000000, CFG_CLK_SRC_GPLL0_EVEN, 1, 8, 25), + F(100000000, CFG_CLK_SRC_GPLL0_EVEN, 3, 0, 0), + F(102400000, CFG_CLK_SRC_GPLL0_EVEN, 1, 128, 375), + F(112000000, CFG_CLK_SRC_GPLL0_EVEN, 1, 28, 75), + F(117964800, CFG_CLK_SRC_GPLL0_EVEN, 1, 6144, 15625), + F(120000000, CFG_CLK_SRC_GPLL0_EVEN, 2.5, 0, 0), + F(128000000, CFG_CLK_SRC_GPLL6_EVEN, 3, 0, 0), + {} +}; + +static const struct freq_tbl ftbl_gcc_sdcc2_apps_clk_src[] = { + F(400000, CFG_CLK_SRC_CXO, 12, 1, 4), + F(9600000, CFG_CLK_SRC_CXO, 2, 0, 0), + F(19200000, CFG_CLK_SRC_CXO, 1, 0, 0), + F(25000000, CFG_CLK_SRC_GPLL0_ODD, 8, 0, 0), + F(50000000, CFG_CLK_SRC_GPLL0_ODD, 4, 0, 0), + F(100000000, CFG_CLK_SRC_GPLL0_ODD, 2, 0, 0), + F(202000000, CFG_CLK_SRC_GPLL7, 4, 0, 0), + {} +}; + +static struct pll_vote_clk gpll7_vote_clk = { + .status = APCS_GPLL7_STATUS, + .status_bit = BIT(31), + .ena_vote = APCS_GPLLX_ENA_REG, + .vote_bit = BIT(7), +}; + +static ulong sm6350_set_rate(struct clk *clk, ulong rate) +{ + struct msm_clk_priv *priv = dev_get_priv(clk->dev); + const struct freq_tbl *freq; + + if (clk->id < priv->data->num_clks) + debug("%s: %s, requested rate=%ld\n", __func__, + priv->data->clks[clk->id].name, rate); + + switch (clk->id) { + case GCC_QUPV3_WRAP1_S3_CLK: /*UART9*/ + freq = qcom_find_freq(ftbl_gcc_qupv3_wrap1_s3_clk_src, rate); + clk_rcg_set_rate_mnd(priv->base, GCC_SE12_UART_RCG_REG, + freq->pre_div, freq->m, freq->n, freq->src, + 16); + + return freq->freq; + case GCC_SDCC2_APPS_CLK: + /* Enable GPLL7 so that we can point SDCC2_APPS_CLK_SRC at it */ + clk_enable_gpll0(priv->base, &gpll7_vote_clk); + freq = qcom_find_freq(ftbl_gcc_sdcc2_apps_clk_src, rate); + WARN(freq->src != CFG_CLK_SRC_GPLL7, + "SDCC2_APPS_CLK_SRC not set to GPLL7, requested rate %lu\n", + rate); + clk_rcg_set_rate_mnd(priv->base, GCC_SDCC2_APPS_CLK_SRC_REG, + freq->pre_div, freq->m, freq->n, + CFG_CLK_SRC_GPLL7, 8); + + return rate; + default: + return 0; + } +} + +static const struct gate_clk sm6350_clks[] = { + GATE_CLK(GCC_AGGRE_UFS_PHY_AXI_CLK, 0x3e014, 0x00000001), + GATE_CLK(GCC_AGGRE_USB3_PRIM_AXI_CLK, 0x3e010, 0x00000001), + GATE_CLK(GCC_CFG_NOC_USB3_PRIM_AXI_CLK, 0x1101c, 0x00000001), + GATE_CLK(GCC_QUPV3_WRAP1_S3_CLK, 0x52000, 0x00800000), + GATE_CLK(GCC_QUPV3_WRAP_1_M_AHB_CLK, 0x52000, 0x00040000), + GATE_CLK(GCC_QUPV3_WRAP_1_S_AHB_CLK, 0x52000, 0x00080000), + GATE_CLK(GCC_SDCC2_AHB_CLK, 0x20008, 0x00000001), + GATE_CLK(GCC_SDCC2_APPS_CLK, 0x20004, 0x00000001), + GATE_CLK(GCC_UFS_MEM_CLKREF_CLK, 0x8c000, 0x00000001), + GATE_CLK(GCC_UFS_PHY_AHB_CLK, 0x3a00c, 0x00000001), + GATE_CLK(GCC_UFS_PHY_AXI_CLK, 0x3a034, 0x00000001), + GATE_CLK(GCC_UFS_PHY_ICE_CORE_CLK, 0x3a0a4, 0x00000001), + GATE_CLK(GCC_UFS_PHY_PHY_AUX_CLK, 0x3a0ac, 0x00000001), + GATE_CLK(GCC_UFS_PHY_RX_SYMBOL_0_CLK, 0x3a014, 0x00000001), + GATE_CLK(GCC_UFS_PHY_RX_SYMBOL_1_CLK, 0x3a018, 0x00000001), + GATE_CLK(GCC_UFS_PHY_TX_SYMBOL_0_CLK, 0x3a010, 0x00000001), + GATE_CLK(GCC_UFS_PHY_UNIPRO_CORE_CLK, 0x3a09c, 0x00000001), + GATE_CLK(GCC_USB30_PRIM_MASTER_CLK, 0x1a00c, 0x00000001), + GATE_CLK(GCC_USB30_PRIM_MOCK_UTMI_CLK, 0x1a018, 0x00000001), + GATE_CLK(GCC_USB30_PRIM_SLEEP_CLK, 0x1a014, 0x00000001), + GATE_CLK(GCC_USB3_PRIM_CLKREF_CLK, 0x8c010, 0x00000001), + GATE_CLK(GCC_USB3_PRIM_PHY_AUX_CLK, 0x1a050, 0x00000001), + GATE_CLK(GCC_USB3_PRIM_PHY_COM_AUX_CLK, 0x1a054, 0x00000001), + GATE_CLK(GCC_USB3_PRIM_PHY_PIPE_CLK, 0x1a058, 0x00000001), +}; + +static int sm6350_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 %s\n", __func__, sm6350_clks[clk->id].name); + + switch (clk->id) { + case GCC_USB30_PRIM_MASTER_CLK: + qcom_gate_clk_en(priv, GCC_USB3_PRIM_PHY_AUX_CLK); + qcom_gate_clk_en(priv, GCC_USB3_PRIM_PHY_COM_AUX_CLK); + break; + } + + return qcom_gate_clk_en(priv, clk->id); +} + +static const struct qcom_reset_map sm6350_gcc_resets[] = { + [GCC_QUSB2PHY_PRIM_BCR] = { 0x1d000 }, + [GCC_QUSB2PHY_SEC_BCR] = { 0x1e000 }, + [GCC_SDCC1_BCR] = { 0x4b000 }, + [GCC_SDCC2_BCR] = { 0x20000 }, + [GCC_UFS_PHY_BCR] = { 0x3a000 }, + [GCC_USB30_PRIM_BCR] = { 0x1a000 }, + [GCC_USB3_PHY_PRIM_BCR] = { 0x1c000 }, + [GCC_USB3_DP_PHY_PRIM_BCR] = { 0x1c008 }, +}; + +static const struct qcom_power_map sm6350_gdscs[] = { + [USB30_PRIM_GDSC] = { 0x1a004 }, + [UFS_PHY_GDSC] = { 0x3a004 }, + [HLOS1_VOTE_MMNOC_MMU_TBU_HF0_GDSC] = { 0xb7040 }, + [HLOS1_VOTE_MMNOC_MMU_TBU_HF1_GDSC] = { 0xb7044 }, +}; + +static struct msm_clk_data sm6350_gcc_data = { + .resets = sm6350_gcc_resets, + .num_resets = ARRAY_SIZE(sm6350_gcc_resets), + .clks = sm6350_clks, + .num_clks = ARRAY_SIZE(sm6350_clks), + .power_domains = sm6350_gdscs, + .num_power_domains = ARRAY_SIZE(sm6350_gdscs), + + .enable = sm6350_enable, + .set_rate = sm6350_set_rate, +}; + +static const struct udevice_id gcc_sm6350_of_match[] = { + { + .compatible = "qcom,gcc-sm6350", + .data = (ulong)&sm6350_gcc_data, + }, + {} +}; + +U_BOOT_DRIVER(gcc_sm6350) = { + .name = "gcc_sm6350", + .id = UCLASS_NOP, + .of_match = gcc_sm6350_of_match, + .bind = qcom_cc_bind, + .flags = DM_FLAG_PRE_RELOC, +}; diff --git a/drivers/clk/qcom/clock-sm7150.c b/drivers/clk/qcom/clock-sm7150.c new file mode 100644 index 00000000000..8fe2076e55e --- /dev/null +++ b/drivers/clk/qcom/clock-sm7150.c @@ -0,0 +1,250 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Clock drivers for Qualcomm SM7150 + * + * (C) Copyright 2025 Danila Tikhonov <danila@jiaxyga.com> + * (C) Copyright 2025 Jens Reidel <adrian@mainlining.org> + * + * Based on Linux Kernel driver + */ + +#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,sm7150-gcc.h> + +#include "clock-qcom.h" + +#define USB30_PRIM_MASTER_CLK_CMD_RCGR 0xf01c +#define USB30_PRIM_MOCK_UTMI_CLK_CMD_RCGR 0xf034 +#define USB3_PRIM_PHY_AUX_CLK_CMD_RCGR 0xf060 + +#define SE8_UART_APPS_CMD_RCGR 0x18278 +#define GCC_SDCC2_APPS_CLK_SRC_REG 0x1400c + +#define APCS_GPLL7_STATUS 0x27000 +#define APCS_GPLLX_ENA_REG 0x52000 + +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), + F(19200000, CFG_CLK_SRC_CXO, 1, 0, 0), + F(29491200, CFG_CLK_SRC_GPLL0_EVEN, 1, 1536, 15625), + F(32000000, CFG_CLK_SRC_GPLL0_EVEN, 1, 8, 75), + F(48000000, CFG_CLK_SRC_GPLL0_EVEN, 1, 4, 25), + F(64000000, CFG_CLK_SRC_GPLL0_EVEN, 1, 16, 75), + F(80000000, CFG_CLK_SRC_GPLL0_EVEN, 1, 4, 15), + F(96000000, CFG_CLK_SRC_GPLL0_EVEN, 1, 8, 25), + F(100000000, CFG_CLK_SRC_GPLL0_EVEN, 3, 0, 0), + F(102400000, CFG_CLK_SRC_GPLL0_EVEN, 1, 128, 375), + F(112000000, CFG_CLK_SRC_GPLL0_EVEN, 1, 28, 75), + F(117964800, CFG_CLK_SRC_GPLL0_EVEN, 1, 6144, 15625), + F(120000000, CFG_CLK_SRC_GPLL0_EVEN, 2.5, 0, 0), + F(128000000, CFG_CLK_SRC_GPLL0, 1, 16, 75), + { } +}; + +static const struct freq_tbl ftbl_gcc_sdcc2_apps_clk_src[] = { + F(400000, CFG_CLK_SRC_CXO, 12, 1, 4), + F(9600000, CFG_CLK_SRC_CXO, 2, 0, 0), + F(19200000, CFG_CLK_SRC_CXO, 1, 0, 0), + F(25000000, CFG_CLK_SRC_GPLL0_EVEN, 12, 0, 0), + F(50000000, CFG_CLK_SRC_GPLL0_EVEN, 6, 0, 0), + F(100000000, CFG_CLK_SRC_GPLL0, 6, 0, 0), + F(208000000, CFG_CLK_SRC_GPLL7, 4, 0, 0), + { } +}; + +static const struct freq_tbl ftbl_gcc_usb30_prim_master_clk_src[] = { + F(66666667, CFG_CLK_SRC_GPLL0, 4.5, 0, 0), + F(133333333, CFG_CLK_SRC_GPLL0_EVEN, 4.5, 0, 0), + F(200000000, CFG_CLK_SRC_GPLL0, 3, 0, 0), + F(240000000, CFG_CLK_SRC_GPLL0, 2.5, 0, 0), + { } +}; + +static const struct freq_tbl ftbl_gcc_usb30_prim_mock_utmi_clk_src[] = { + F(19200000, CFG_CLK_SRC_CXO, 1, 0, 0), + F(20000000, CFG_CLK_SRC_GPLL0_EVEN, 15, 0, 0), + F(40000000, CFG_CLK_SRC_GPLL0_EVEN, 7.5, 0, 0), + F(60000000, CFG_CLK_SRC_GPLL0, 10, 0, 0), + { } +}; + +static const struct freq_tbl ftbl_gcc_usb3_prim_phy_aux_clk_src[] = { + F(19200000, CFG_CLK_SRC_CXO, 1, 0, 0), + { } +}; + +static ulong sm7150_clk_set_rate(struct clk *clk, ulong rate) +{ + struct msm_clk_priv *priv = dev_get_priv(clk->dev); + const struct freq_tbl *freq; + + if (clk->id < priv->data->num_clks) + debug("%s: %s, requested rate=%ld\n", __func__, priv->data->clks[clk->id].name, rate); + + switch (clk->id) { + case GCC_QUPV3_WRAP1_S2_CLK: /* UART8 */ + freq = qcom_find_freq(ftbl_gcc_qupv3_wrap0_s0_clk_src, rate); + clk_rcg_set_rate_mnd(priv->base, SE8_UART_APPS_CMD_RCGR, + freq->pre_div, freq->m, freq->n, freq->src, 16); + return freq->freq; + case GCC_USB30_PRIM_MASTER_CLK: + freq = qcom_find_freq(ftbl_gcc_usb30_prim_master_clk_src, rate); + clk_rcg_set_rate_mnd(priv->base, USB30_PRIM_MASTER_CLK_CMD_RCGR, + freq->pre_div, freq->m, freq->n, freq->src, 8); + return freq->freq; + case GCC_USB30_PRIM_MOCK_UTMI_CLK: + freq = qcom_find_freq(ftbl_gcc_usb30_prim_mock_utmi_clk_src, rate); + clk_rcg_set_rate_mnd(priv->base, USB30_PRIM_MOCK_UTMI_CLK_CMD_RCGR, + freq->pre_div, freq->m, freq->n, freq->src, 0); + return freq->freq; + case GCC_USB3_PRIM_PHY_AUX_CLK_SRC: + freq = qcom_find_freq(ftbl_gcc_usb3_prim_phy_aux_clk_src, rate); + clk_rcg_set_rate_mnd(priv->base, USB3_PRIM_PHY_AUX_CLK_CMD_RCGR, + freq->pre_div, freq->m, freq->n, freq->src, 0); + return freq->freq; + case GCC_SDCC2_APPS_CLK: + freq = qcom_find_freq(ftbl_gcc_sdcc2_apps_clk_src, rate); + clk_rcg_set_rate_mnd(priv->base, GCC_SDCC2_APPS_CLK_SRC_REG, + freq->pre_div, freq->m, freq->n, freq->src, 8); + return freq->freq; + default: + return 0; + } +} + +static const struct gate_clk sm7150_clks[] = { + GATE_CLK(GCC_AGGRE_UFS_PHY_AXI_CLK, 0x82024, BIT(0)), + GATE_CLK(GCC_AGGRE_USB3_PRIM_AXI_CLK, 0x8201c, BIT(0)), + GATE_CLK(GCC_CFG_NOC_USB3_PRIM_AXI_CLK, 0x502c, BIT(0)), + GATE_CLK(GCC_QUPV3_WRAP0_S0_CLK, 0x5200c, BIT(10)), + GATE_CLK(GCC_QUPV3_WRAP0_S1_CLK, 0x5200c, BIT(11)), + GATE_CLK(GCC_QUPV3_WRAP0_S2_CLK, 0x5200c, BIT(12)), + GATE_CLK(GCC_QUPV3_WRAP0_S3_CLK, 0x5200c, BIT(13)), + GATE_CLK(GCC_QUPV3_WRAP0_S4_CLK, 0x5200c, BIT(14)), + GATE_CLK(GCC_QUPV3_WRAP0_S5_CLK, 0x5200c, BIT(15)), + GATE_CLK(GCC_QUPV3_WRAP0_S6_CLK, 0x5200c, BIT(16)), + GATE_CLK(GCC_QUPV3_WRAP0_S7_CLK, 0x5200c, BIT(17)), + GATE_CLK(GCC_QUPV3_WRAP1_S0_CLK, 0x5200c, BIT(22)), + GATE_CLK(GCC_QUPV3_WRAP1_S1_CLK, 0x5200c, BIT(23)), + GATE_CLK(GCC_QUPV3_WRAP1_S2_CLK, 0x5200c, BIT(24)), + GATE_CLK(GCC_QUPV3_WRAP1_S3_CLK, 0x5200c, BIT(25)), + GATE_CLK(GCC_QUPV3_WRAP1_S4_CLK, 0x5200c, BIT(26)), + GATE_CLK(GCC_QUPV3_WRAP1_S5_CLK, 0x5200c, BIT(27)), + GATE_CLK(GCC_QUPV3_WRAP1_S6_CLK, 0x5200c, BIT(28)), + GATE_CLK(GCC_QUPV3_WRAP1_S7_CLK, 0x5200c, BIT(29)), + GATE_CLK(GCC_QUPV3_WRAP_0_M_AHB_CLK, 0x5200c, BIT(6)), + GATE_CLK(GCC_QUPV3_WRAP_0_S_AHB_CLK, 0x5200c, BIT(7)), + GATE_CLK(GCC_QUPV3_WRAP_1_M_AHB_CLK, 0x5200c, BIT(20)), + GATE_CLK(GCC_QUPV3_WRAP_1_S_AHB_CLK, 0x5200c, BIT(21)), + GATE_CLK(GCC_SDCC1_AHB_CLK, 0x12008, BIT(0)), + GATE_CLK(GCC_SDCC1_APPS_CLK, 0x1200c, BIT(0)), + GATE_CLK(GCC_SDCC1_ICE_CORE_CLK, 0x12040, BIT(0)), + GATE_CLK(GCC_SDCC2_AHB_CLK, 0x14008, BIT(0)), + GATE_CLK(GCC_SDCC2_APPS_CLK, 0x14004, BIT(0)), + GATE_CLK(GCC_SDCC4_AHB_CLK, 0x16008, BIT(0)), + GATE_CLK(GCC_SDCC4_APPS_CLK, 0x16004, BIT(0)), + GATE_CLK(GCC_UFS_MEM_CLKREF_CLK, 0x8c000, BIT(0)), + GATE_CLK(GCC_UFS_PHY_AHB_CLK, 0x77014, BIT(0)), + GATE_CLK(GCC_UFS_PHY_AXI_CLK, 0x77038, BIT(0)), + GATE_CLK(GCC_UFS_PHY_ICE_CORE_CLK, 0x77090, BIT(0)), + GATE_CLK(GCC_UFS_PHY_PHY_AUX_CLK, 0x77094, BIT(0)), + GATE_CLK(GCC_UFS_PHY_RX_SYMBOL_0_CLK, 0x7701c, BIT(0)), + GATE_CLK(GCC_UFS_PHY_TX_SYMBOL_0_CLK, 0x77018, BIT(0)), + GATE_CLK(GCC_UFS_PHY_UNIPRO_CORE_CLK, 0x7708c, BIT(0)), + GATE_CLK(GCC_USB30_PRIM_MASTER_CLK, 0x0f010, BIT(0)), + GATE_CLK(GCC_USB30_PRIM_MOCK_UTMI_CLK, 0x0f018, BIT(0)), + GATE_CLK(GCC_USB30_PRIM_SLEEP_CLK, 0x0f014, BIT(0)), + GATE_CLK(GCC_USB3_PRIM_CLKREF_CLK, 0x8c010, BIT(0)), + GATE_CLK(GCC_USB3_PRIM_PHY_AUX_CLK, 0x0f050, BIT(0)), + GATE_CLK(GCC_USB3_PRIM_PHY_COM_AUX_CLK, 0x0f054, BIT(0)), + GATE_CLK(GCC_USB3_PRIM_PHY_PIPE_CLK, 0x0f058, BIT(0)), + GATE_CLK(GCC_USB_PHY_CFG_AHB2PHY_CLK, 0x6a004, BIT(0)), +}; + +static int sm7150_clk_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 %s\n", __func__, sm7150_clks[clk->id].name); + + switch (clk->id) { + case GCC_AGGRE_USB3_PRIM_AXI_CLK: + qcom_gate_clk_en(priv, GCC_USB30_PRIM_MASTER_CLK); + fallthrough; + case GCC_USB30_PRIM_MASTER_CLK: + qcom_gate_clk_en(priv, GCC_USB3_PRIM_PHY_AUX_CLK); + qcom_gate_clk_en(priv, GCC_USB3_PRIM_PHY_COM_AUX_CLK); + break; + } + + return qcom_gate_clk_en(priv, clk->id); +} + +static const struct qcom_reset_map sm7150_gcc_resets[] = { + [GCC_UFS_PHY_BCR] = { 0x77000 }, + [GCC_USB30_PRIM_BCR] = { 0xf000 }, + [GCC_USB3_DP_PHY_PRIM_BCR] = { 0x50008 }, + [GCC_USB3_DP_PHY_SEC_BCR] = { 0x50014 }, + [GCC_USB3_PHY_PRIM_BCR] = { 0x50000 }, + [GCC_USB3_PHY_SEC_BCR] = { 0x5000c }, + [GCC_QUSB2PHY_PRIM_BCR] = { 0x26000 }, +}; + +static const struct qcom_power_map sm7150_gdscs[] = { + [PCIE_0_GDSC] = { 0x6b004 }, + [UFS_PHY_GDSC] = { 0x77004 }, + [USB30_PRIM_GDSC] = { 0xf004 }, +}; + +static const phys_addr_t sm7150_rcg_addrs[] = { + 0x10f01c, // USB30_PRIM_MASTER_CLK_CMD_RCGR + 0x10f034, // USB30_PRIM_MOCK_UTMI_CLK_CMD_RCGR + 0x10f060, // USB3_PRIM_PHY_AUX_CLK_CMD_RCGR, +}; + +static const char *const sm7150_rcg_names[] = { + "USB30_PRIM_MASTER_CLK", + "USB30_PRIM_MOCK_UTMI_CLK", + "USB3_PRIM_PHY_AUX_CLK", +}; + +static struct msm_clk_data sm7150_gcc_data = { + .resets = sm7150_gcc_resets, + .num_resets = ARRAY_SIZE(sm7150_gcc_resets), + .clks = sm7150_clks, + .num_clks = ARRAY_SIZE(sm7150_clks), + + .power_domains = sm7150_gdscs, + .num_power_domains = ARRAY_SIZE(sm7150_gdscs), + + .enable = sm7150_clk_enable, + .set_rate = sm7150_clk_set_rate, + + .dbg_rcg_addrs = sm7150_rcg_addrs, + .num_rcgs = ARRAY_SIZE(sm7150_rcg_addrs), + .dbg_rcg_names = sm7150_rcg_names, +}; + +static const struct udevice_id gcc_sm7150_of_match[] = { + { .compatible = "qcom,sm7150-gcc", .data = (ulong)&sm7150_gcc_data, }, + { /* sentinel */ } +}; + +U_BOOT_DRIVER(gcc_sm7150) = { + .name = "gcc_sm7150", + .id = UCLASS_NOP, + .of_match = gcc_sm7150_of_match, + .bind = qcom_cc_bind, + .flags = DM_FLAG_PRE_RELOC | DM_FLAG_DEFAULT_PD_CTRL_OFF, +}; diff --git a/drivers/clk/qcom/clock-sm8250.c b/drivers/clk/qcom/clock-sm8250.c index cc481258d22..37268c4eaf5 100644 --- a/drivers/clk/qcom/clock-sm8250.c +++ b/drivers/clk/qcom/clock-sm8250.c @@ -18,14 +18,9 @@ #define GCC_SE12_UART_RCG_REG 0x184D0 #define GCC_SDCC2_APPS_CLK_SRC_REG 0x1400c -#define APCS_GPLL0_ENA_VOTE 0x79000 #define APCS_GPLL9_STATUS 0x1c000 #define APCS_GPLLX_ENA_REG 0x52018 -#define USB30_PRIM_MASTER_CLK_CMD_RCGR 0xf020 -#define USB30_PRIM_MOCK_UTMI_CLK_CMD_RCGR 0xf038 -#define USB3_PRIM_PHY_AUX_CMD_RCGR 0xf064 - static const struct freq_tbl ftbl_gcc_qupv3_wrap1_s4_clk_src[] = { F(7372800, CFG_CLK_SRC_GPLL0_EVEN, 1, 384, 15625), F(14745600, CFG_CLK_SRC_GPLL0_EVEN, 1, 768, 15625), diff --git a/drivers/clk/renesas/Kconfig b/drivers/clk/renesas/Kconfig index 12966d02a22..51c87cc3606 100644 --- a/drivers/clk/renesas/Kconfig +++ b/drivers/clk/renesas/Kconfig @@ -51,8 +51,8 @@ config CLK_R8A7794 Enable this to support the clocks on Renesas R8A7794 SoC. config CLK_RCAR_GEN3 - bool "Renesas R-Car Gen3 and Gen4 clock driver" - def_bool y if RCAR_64 + bool "Renesas R-Car Gen3, Gen4, RZ/G2L clock driver" + def_bool y if RCAR_GEN3 || RCAR_GEN4 || RZG2L depends on CLK_RENESAS select CLK_RCAR select CLK_RCAR_CPG_LIB diff --git a/drivers/clk/rockchip/clk_px30.c b/drivers/clk/rockchip/clk_px30.c index ad7e1c0f246..b5054e84c32 100644 --- a/drivers/clk/rockchip/clk_px30.c +++ b/drivers/clk/rockchip/clk_px30.c @@ -1360,6 +1360,9 @@ static ulong px30_clk_set_rate(struct clk *clk, ulong rate) case SCLK_GMAC_RMII: ret = px30_mac_set_speed_clk(priv, rate); break; + /* Might occur in cru assigned-clocks, can be ignored here */ + case SCLK_GPU: + break; #endif default: return -ENOENT; @@ -1726,6 +1729,9 @@ static ulong px30_pmuclk_set_rate(struct clk *clk, ulong rate) case SCLK_UART0_PMU: ret = px30_pmu_uart0_set_clk(priv, rate); break; + /* Might occur in pmucru assigned-clocks, can be ignored here */ + case SCLK_WIFI_PMU: + break; default: return -ENOENT; } diff --git a/drivers/clk/sifive/Kconfig b/drivers/clk/sifive/Kconfig index 20fc004b59e..01e4f33415e 100644 --- a/drivers/clk/sifive/Kconfig +++ b/drivers/clk/sifive/Kconfig @@ -2,7 +2,7 @@ config CLK_SIFIVE bool "SiFive SoC driver support" - depends on CLK + depends on CLK && RISCV help SoC drivers for SiFive Linux-capable SoCs. diff --git a/drivers/clk/sophgo/clk-common.h b/drivers/clk/sophgo/clk-common.h index a9e83d0d689..a18673f397c 100644 --- a/drivers/clk/sophgo/clk-common.h +++ b/drivers/clk/sophgo/clk-common.h @@ -70,7 +70,7 @@ cv1800b_clk_setfield(void *base, struct cv1800b_clk_regfield *field, u32 val) u32 new_val = (readl(base + field->offset) & ~mask) | ((val << field->shift) & mask); - return writel(new_val, base + field->offset); + writel(new_val, base + field->offset); } #endif /* __CLK_SOPHGO_COMMON_H__ */ diff --git a/drivers/clk/ti/Kconfig b/drivers/clk/ti/Kconfig index fbcdefd889a..fdda283d6d3 100644 --- a/drivers/clk/ti/Kconfig +++ b/drivers/clk/ti/Kconfig @@ -5,14 +5,14 @@ config CLK_TI_AM3_DPLL bool "TI AM33XX Digital Phase-Locked Loop (DPLL) clock drivers" - depends on CLK && OF_CONTROL + depends on CLK && OF_CONTROL && ARCH_OMAP2PLUS help This enables the DPLL clock drivers support on AM33XX SoCs. The DPLL provides all interface clocks and functional clocks to the processor. config CLK_TI_CTRL bool "TI OMAP4 clock controller" - depends on CLK && OF_CONTROL + depends on CLK && OF_CONTROL && ARCH_OMAP2PLUS help This enables the clock controller driver support on TI's SoCs. @@ -49,7 +49,7 @@ config CLK_K3_PLL Enables PLL clock support for K3 SoC family of devices. config SPL_CLK_K3_PLL - bool "PLL clock support for K3 SoC family of devices" + bool "PLL clock support for K3 SoC family of devices in SPL" depends on CLK && LIB_RATIONAL && SPL help Enables PLL clock support for K3 SoC family of devices. @@ -61,7 +61,7 @@ config CLK_K3 Enables the clock translation layer from DT to device clocks. config SPL_CLK_K3 - bool "Clock support for K3 SoC family of devices" + bool "Clock support for K3 SoC family of devices in SPL" depends on CLK && SPL help Enables the clock translation layer from DT to device clocks. |
